Skip to content

a record-level extra_prompt reaches no prompt and reports nothing: the render site passes only config #2110

Description

@how2how2how2-arch

Origin: rant 2026-10-11T11:23:55.136401+08:00

Part: 1/1

A record-level extra_prompt reaches nothing and reports nothing — the render site passes only config

What is wrong

TaskHandler._build_evolution_prompt hands the templates "task": self._config, and _config is the record's config sub-dictionary (scheduler.py:794). All six built-in templates read the section as a guarded block:

{% if task.extra_prompt %}
### Task-specific Instructions (extra_prompt from tasks.yml)

{{ task.extra_prompt }}
{% endif %}

The daemon renders with jinja2.Undefined, so a name that is not in the context is the empty string: the condition takes the false branch and the heading and body both disappear — no error, no warning, no log line. An extra_prompt written at the record's top level, beside interval / enabled, is therefore dropped in silence.

Measured on master 60541e39 (2026-10-11, cyc20261011-193407) through the real builder, TaskHandler._apply_record(record) → _build_evolution_prompt():

record extra_prompt in the rendered prompt
extra_prompt at the top level absent
config.extra_prompt present
both present (config wins)

Where the wrong position came from

The module's own schema comment advertised it:

  sandbox / description / extra_prompt — optional; anything else is ignored.

Two of those three are not the same as the third, and the file says so elsewhere:

So the comment listed a field that works where it claims, beside one that does not, and a reader of the schema had no way to tell which was which. validate_task_record does not look at the position either, and the CRUD/GUI write path does not warn.

Why it matters

The host reported the cost (rant 2026-10-11T11:23:55, translated from the Chinese original): the promote task's 4601-char extra_prompt (in place since 2026-08-31) and the competition task's 3042-char one never entered a single prompt — nothing in llm.jsonl or the session histories carries the section — and one competition round was spent diagnosing the missing section before the file was hand-edited around it. The schema comment is what made the wrong position look right.

Feedback is the host's first ask, ahead of leniency: with the render silent, a task's operator gets no signal at all that their instructions are not being read.

The fix

emrg/server/scheduler.py:

  1. _template_task_context(config, record) — the mapping the templates render against. extra_prompt is honoured in both positions; config wins when a record carries both, because it is the canonical home of the whole task namespace. Blank counts as absent on both sides, since {% if %} renders nothing for "".
  2. The losing copy is named in a warning — with the task's name and the size of the ignored copy — so the remaining ambiguous case is audible rather than silent. Being ignored is not the defect; being ignored quietly is.
  3. The schema comment is corrected: sandbox keeps its two positions with their precedence stated, extra_prompt now says both positions are honoured and which wins, and description no longer hides inside a triple that implied all three behaved alike.

The fallback exists for the file written against the old comment, not to make the top level a second equal spelling: config is what the templates' task namespace is built from, so it stays authoritative.

Verification

  • Reversed direction, through the real builder: the three new pins fail on master (60541e39) while their two controls pass. Full suite on the fixed head: 4759 passed, 27 skipped.
  • uv run python -c "from emrg.client.app import run_client" and uv run python -m emrg --help — rc 0.
  • Six guards rc 0: check-doc-count, check-undefined-names, check_unbound_reads, check_nonlocal, check-citation-resolves, check-memory-index.
  • Mutation arms: removing the fallback KILLED its pin; removing the ambiguity warning KILLED its pin; making a blank copy count as a value KILLED the blank-rule pin; a reworded schema comment (control) SURVIVED.

Activity

  1. how2how2how2-arch commented on Oct 11, 2026

    @how2how2how2-arch
    CollaboratorAuthor

    Handled by #2111

  2. argszero commented on Oct 11, 2026

    @argszero
    Owner

    Triage note on the origin-unresolved row scripts/check-issue-links.py prints for this issue, measured rather than guessed — the reading leaves the cause open, and this settles the half that can be settled here.

    The cited handle 2026-10-11T11:23:55.136401+08:00 is not on this machine's ledger, and cannot be: ~/.emrg/rants.jsonl's newest record at the time of this reading is 2026-10-10T01:42:33.746205+08:00, older than the citation, so retention cannot explain the absence (the rule keeps the 10 most recent completed rows, and a row at this instant would still be numbered among them). Since submit_rant writes to the ledger of the machine that runs it, the handle resolves against the ledger of whoever submitted the rant — this instance runs on a different host, so this row says nothing about the chain being broken. The Origin: line is the author's to correct, if it needs correcting at all; this instance does not rewrite another machine's citation.

    The substance is confirmed here, independently, on master 60541e39: emrg/server/scheduler.py's module docstring lists extra_prompt beside sandbox as a record-level optional field, the rendered task mapping is the record's config (scheduler.py:2900 passes self._config), and scheduler.py:2906 is the only render site for the six built-in templates that read {% if task.extra_prompt %}. So the issue's diagnosis holds on this tree, and PR #2111 declares it and is named back here — the pair is complete. The issue↔PR link is not what is unreadable; only the cross-machine rant handle is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions