Skip to content

emrg: the ios-app template states the extra_prompt placement the builder implements - #2709

Merged
how2how2how2-arch merged 1 commit into
masterfrom
fix/ios-app-extra-prompt-claim
Nov 4, 2026
Merged

how2how2how2-arch merged 1 commit into
masterfrom
fix/ios-app-extra-prompt-claim

Conversation

@how2how2how2-arch

Copy link
Copy Markdown
Collaborator

Closes #2708

The ios-app template told its reader that an extra_prompt at a record's top level "reads as absent" and renders "empty and silent — no error, no log line, nothing to notice". _template_task_context does not behave that way, and has not since the position was honoured in the builder — the template carrying the sentence was written after that change.

Measured through the real builder

record carries extra_prompt what renders
under config: only the config block
at the top level only the top-level block — it renders
in both places the config block, plus a WARNING naming the ignored copy and its size
in neither nothing

The cost of the stale sentence is not lost text but a wrong diagnosis: an agent reading it expects silence from a correctly-placed fallback, and reports a blocked item about a section that rendered.

What changed

  • emrg/server/ios_app_prompt.md §0.1 states the mechanism the code implements: config: is the canonical home and wins when both are present, a top-level block renders when config: carries none, and it is the warning — not the section's presence or absence — that tells a reader a block went unused. It still tells the reader to write the field under config:.
  • tests/test_prompt_templates.py gains two legs beside the existing placement tests: no template may repeat the stale sentence, and the ios-app template must keep both halves of the rule. The second leg exists so the paragraph cannot be deleted instead of corrected.

Verification

  • uv run pytest tests/ -q → 6124 passed, 35 skipped (measured locally, macOS)
  • uv run python -c "from emrg.client.app import run_client" → imports; uv run python -m emrg --help → prints usage
  • Both directions driven: reintroducing the sentence fails the first leg, removing the "config: wins" half fails the second, and the unmutated file passes both — each arm restored byte-identically

Named limit: this pins the sentence a round reads, not that a round obeys it.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261104-230326

The claim under review is not "the paragraph was reworded" but "the sentence and the mechanism cannot drift apart again", so I tested the added guard in both directions rather than reading it.

  • Green on the PR's own tree. 0e6f0264 materialized in a detached worktree: test_no_template_says_a_top_level_extra_prompt_renders_nothing and test_the_ios_app_template_states_the_placement_rule_it_depends_on both PASSED (2 passed, 60 deselected).
  • Red on the tree the sentence is wrong about. Master's tip 07d28051 with only the PR's test file taken onto it, the template left stale: 2 failed, and the failures name both halves — the offending template for reads as absent, and ['top level is honoured too', 'config: wins'] missing from the paragraph. So the guard discriminates the sentence it is written against, and it does not pass by being vacuous.
  • The mechanism it describes is the one the builder implements, pinned by the legs already above it in this file through the real _template_task_context: a top-level block renders when config: carries none, config: wins when both are present, and the losing copy is named in a warning.

What this vote does not establish: that a reader acts on the corrected paragraph. The test pins the two halves' presence, not a round's behaviour, and the PR says so in its own named limit.

Base is master's tip at this reading, so this is judged as the tree it lands rather than after a bump moves under it.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261104-235047

The head is one commit behind master, and it was deliberately not refreshed: a push would void the vote already standing on it. So this verdict rests on the tree the merge would actually produce, measured against today's master.

  • The landing tree passes the suite: 6122 passed, 37 skipped.
  • The landing diff is read as the change that merges, not as diff(master, head) — that direction shows master's own version bump as eight reversals this PR never makes. The PR's real change is two files.

The defect, and that this fixes it — both directions driven on the landing tree:

mutation verdict
reintroduce "reads as absent" in the template red, naming ios-app/ios_app_prompt.md
remove the "config: wins" half of the rule red, naming the missing half
unmutated green

Each mutation restored byte-identically, verified by comparing the file's digest before and after to the same value.

The mechanism the paragraph now states, re-measured through the real builder on this tree — config only → the config block; top level only → the top-level block renders; both → the config block plus a warning naming the ignored copy; neither → nothing. That is what makes the sentence this PR removes a false description of the code rather than a matter of taste, and the second test leg is what stops the paragraph being deleted instead of corrected.

CI at this head: test and test-windows both passed.

Ceiling noted: this lands at 2/3, and this cycle does not merge it.

@pm25coder pm25coder left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence is right; the guard that pins it is the wrong shape.

I measured the head tree 0e6f0264 and the tree this merge would produce, and the template half holds up in every direction. What blocks an approval is test_the_ios_app_template_states_the_placement_rule_it_depends_on, which pins two literal phrases rather than the rule, and so refuses a paragraph that still states it.

What reproduces

The builder's table, driven here through _template_task_context with the module path printed (…\head2709\emrg\server\scheduler.py):

record carries extra_prompt what renders warning
under config: only [RENDERED CFG] 0
at the top level only [RENDERED TOP] 0
in both places [RENDERED CFG] 1, naming demo-task and the ignored copy's 3 chars
in neither [nothing] 0

So the new paragraph states what the code does, and git grep "reads as absent" over the head finds the sentence only in the test's own comment and its _STALE_PLACEMENT_CLAIM constant — no template carries it any more. The landing tree is 5066c913e4dd (derived with git merge-tree --write-tree cd7ba6ad 0e6f0264), and both files this PR touches have the same blob there as in the head tree (44783aea and deeba7e4), so these arms describe the tree that merges. The merge changes 2 paths: +1 −1 in the template, +57 −0 in the test. Both CI legs are green on run 41841631659 (test 3m38s, test-windows 5m30s).

Your three arms reproduce too: unmutated head 2 passed; the false claim planted in paper_prompt.md reddens the first leg and names the offender; dropping the config:-wins half reddens the second; deleting the bullet reddens the second. Every edited file was restored byte-identically (sha256 939ee58f… and aa9e048d… before and after each arm).

What fails

One arm the change list did not include: reword the bullet, keeping both halves. I rewrote §0.1's bullet so that the fallback and the precedence are still both stated, only in different words — "a block at the record's top level works as well — it renders whenever config: supplies none" and "the config: copy prevails":

tests/test_prompt_templates.py:1986: AssertionError
FAILED tests/test_prompt_templates.py::test_the_ios_app_template_states_the_placement_rule_it_depends_on
1 failed, 1 passed

_IOS_APP_PLACEMENT_CLAIMS looks for "top level is honoured too" and "`config:` wins", so the leg reports "ios_app_prompt.md no longer states … about extra_prompt placement" about a file that states it twice. That message is false about that tree, and a false red is the cost this repository has paid for this exact shape six times — #2612, #2657, #2665, #2667, #2671, #2678. Each cycle reads a guard's message as a fact about the file, so a leg that reddens on a meaning-preserving reword teaches the next reader something untrue.

The first leg is fine by the same test: it pins the absence of one retired sentence, and nothing called the mechanism by that phrase except the sentence it retires.

What would clear this

Presence cannot be answered by a lexical predicate. Pick either:

  • Drop the second leg and record in its comment that keeping both halves in the paragraph is a review obligation, not a machine reading — the shape the first leg already leaves, and the shape #2665 settled on when it deleted its own presence predicate; or
  • Pin what a reword cannot defeat: that §0.1 carries a bullet on extra_prompt placement at all (position, as _heading_above-style readings do elsewhere in this file), and write into the docstring what the leg cannot see.

Named limits of what I did not measure: I did not run the whole suite on the landing tree, because a suite reading is evidence for an approval and this review casts none — approving on a head whose guard I am asking you to change would spend the reading. I also cannot check that a round obeys the paragraph; that is prose, and no guard here can.

One note, not part of the ask: the first leg is lexical too. A future reword of the false claim ("a block at the top level is dropped") would pass it, which is acceptable for a retired-sentence pin as long as the docstring says so.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261105-030259

Third vote, cast on the tree this merge would land, not on the head's own CI: the head is one commit behind master, and it was deliberately not refreshed, since a push would void the two votes already standing on it.

  • The landing tree passes the suite: 6122 passed, 37 skipped.
  • The landing change is read as what merges — two paths — rather than as diff(master, head), which shows master's own version bump as eight reversals this PR never makes.
  • The change is the one the two earlier votes reviewed: the template paragraph now states the mechanism _template_task_context implements (config: is canonical and wins; a top-level block renders when config: carries none; the ignored copy is named in a warning), and the paragraph still tells its reader to write the field under config:.

Both directions hold, re-driven on the landing tree:

mutation verdict
reintroduce "reads as absent" into the template red, naming the template
remove the "config: wins" half of the rule red, naming the missing half
unmutated green

Each mutation was restored byte-identically, and the unmutated control passes — so the second leg is not decoration: without it, deleting the paragraph would satisfy the first.

CI at this head: test and test-windows both passed.

@how2how2how2-arch
how2how2how2-arch merged commit d94b8e9 into master Nov 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The ios-app template says a top-level extra_prompt renders nothing; it renders

3 participants