resolved 8d949ef3-6d47-47e8-bc8e-1356913b4639
MOTIVATION
_embed is a reserved top-level key in render payloads that drives a
post-pass substitution: for each (needle, href) entry, wrap exact
occurrences of the escaped needle in the rendered HTML body with
<a href="...">. It was introduced in the web-UI feature commit
(a119a23) when the universal renderer was designed to refuse any
domain knowledge — the payload had to tell the renderer which strings
were linkable.
That design is about to change. A follow-up ticket will introduce
pattern-rule-based linking that teaches the linking layer the domain
(turn_ref shapes, entity_id keys, world_slug grammar). Once pattern
rules are in, _embed has zero remaining users: every link it
produces today will be producible from rules instead.
Rather than build pattern rules on top of _embed as a fallback —
lugging around two mechanisms doing overlapping work — we remove
_embed first. The next ticket then builds pattern rules on a clean
slate, with no "what do we do about the old thing" entanglement.
The project is young. There are no external consumers of the
_embed payload shape. The only code that produces or consumes it
lives in src/views.rs and src/render.rs respectively. No
backwards compatibility to preserve.
_embed DOES TODAY (AND WHAT REPLACES IT LATER)Scope of _embed:
render::render_page.{ "_embed": { "needle-string": "/href-value", ... } }.<a href>. Skips content already inside an existing
anchor; skips tag attributes; handles multibyte characters via
input[i..].chars().next() (see the regression test)._links is untouched.Who produces it today:
views::build_session_payload — writes entity_id→URL and
turn_ref→URL entries.views::build_turn_payload — writes entity_id→URL entries.views::build_entity_payload — writes turn_ref→URL entries.Who consumes it downstream:
render_page returns, the rendered HTML string
doesn't carry any trace of _embed. It's purely an instruction to
the renderer.The follow-up ticket will add centralized pattern rules with a
LinkContext carrying world_slug, such that entity_id keys, turn_ref
regex, and slug references become links wherever they appear. That
supersedes _embed completely.
After this ticket: _embed does not exist as a concept in the render
pipeline. No payload-level substitution map. Pages still render; they
just don't carry inline links to entity/turn pages during the window
between this ticket and the pattern-rules ticket.
_links (the breadcrumb-strip reserved key) stays. It is position-
semantic, not substitution-based, and has no overlap with pattern
rules. Untouched.
Remove:
apply_embed_pass function. Entire function body.apply_embed_pass(payload, &body) inside render_page.wrap_document that carried
the post-embed body. Simplify wrap_document's signature: it
just takes title and body now.render_object_body that skips the _embed
key at depth 2. The filter for _links stays (still a reserved
key). _embed is no longer reserved, so if it somehow appears
in a payload, it renders as data with its underscore-stripped
label ("Embed"). That's fine as a theoretical edge case; no
builder writes it anymore.Keep:
replace_exact_skipping_tags. This function is NOT tied to
_embed — it's a general-purpose HTML-aware substring
replacement. The pattern-rules follow-up ticket will reuse it.
Keep it pub(crate) or private to the module; the follow-up
will elevate visibility as needed.embed_post_pass_handles_multibyte_chars_in_body)
— but RENAME to reflect that it now tests replace_exact_skipping_tags
directly, not apply_embed_pass. Suggested name:
replace_exact_skipping_tags_handles_multibyte_chars.
Rewrite the test body to call replace_exact_skipping_tags
directly with a hand-crafted body + needle + replacement. The
multibyte characters (em-dash) must still pass through unharmed
and the replacement must still land at the correct byte offset.Remove test cases (they assert _embed behavior that no longer exists):
embed_wraps_exact_matches_with_href_case_sensitiveembed_is_case_sensitiveembed_does_not_touch_links_output_even_if_labels_overlapUpdate module-level doc comment: remove the _embed bullet from
the rules summary. _links remains the only reserved top-level key.
Update render_page's own doc comment to drop _embed mentions.
In each of build_session_payload, build_turn_payload, and
build_entity_payload:
let mut embed = serde_json::Map::new(); block.embed from entities / turns /
events.out.insert("_embed".into(), Value::Object(embed));
line.Update the corresponding tests:
build_session_payload_surfaces_world_fields_and_embed — rename
to build_session_payload_surfaces_world_fields. Remove the
_embed assertions. Keep all other assertions (slug, name,
scenario, entities, turns, _links).build_turn_payload_has_events_state_and_entity_embed — rename
to build_turn_payload_has_events_and_state. Remove the _embed
assertions. Keep the rest.build_entity_payload_includes_kind_and_agent_fields — remove
any _embed assertions (this test currently checks _links but
not _embed in the body I read; sanity-check during implementation
and remove if present)._embed reference in tests gets removed.No changes. The server handlers don't produce or consume _embed
directly; they just pass payloads to render::render_page.
No changes.
src/render.rs module-level //! comment: remove the _embed
bullet from the rules summary (currently rule 7's second bullet).cargo build clean (dev + release).cargo test --lib green. The _embed-specific tests are gone;
the renamed multibyte regression test passes; all other tests
that previously asserted on body content still pass (they didn't
depend on _embed linking — they asserted on rendered labels,
headings, escaping).cargo test --test phase0 green.cargo test --test ant_scenario green.rg '_embed' src/ returns ZERO matches in production code.
Grep scope is src/ only — the string may still appear in git
history and in closed tickets; those don't count.ant-verify world:
GET /w/ant-verify returns 200 HTML; page renders with slug,
name, scenario, entities, turns all visible. Entity ids in the
body are plain text (not anchors) — this is the expected
temporary regression.GET /w/ant-verify/turn/2 returns 200 HTML; world state and
events visible; entity references in events plain text.GET /w/ant-verify/entity/ant returns 200 HTML; current state,
goal, memory, state_transitions, events all render; turn_ref
references plain text._links, not _embed.?format=json on each of the three pages returns JSON that
does NOT contain an _embed key at the top level._links. Different reserved key. Different mechanism.
Stays.replace_exact_skipping_tags beyond the test rename.
It keeps its current signature and behavior; the follow-up
ticket will be its next user._embed map
construction. Do NOT collapse helper functions, do NOT reorder
payload keys, do NOT adjust _links contents._embed. Do NOT change
how scalars / objects / arrays render. Do NOT change heading
depth rules. Do NOT change the prose threshold._embed never crossed that boundary.The work is narrow and prescriptive. The handler should not need to make any judgment calls. If a question arises during implementation, leave a comment on the ticket rather than guessing.
Done per spec, pure removal, verified in production.
apply_embed_pass and its call in render_page; simplified wrap_document to (title, body); narrowed the reserved-key filter in render_object_body to _links only; updated module-level //! and render_page doc comments; deleted three _embed-specific tests (embed_wraps_exact_matches_with_href_case_sensitive, embed_is_case_sensitive, embed_does_not_touch_links_output_even_if_labels_overlap); renamed + rewrote the multibyte test to replace_exact_skipping_tags_handles_multibyte_chars that exercises the helper directly._embed map construction from build_session_payload, build_turn_payload, build_entity_payload; renamed two tests (build_session_payload_surfaces_world_fields_and_embed → ..._surfaces_world_fields; build_turn_payload_has_events_state_and_entity_embed → ..._has_events_and_state) and stripped their _embed assertions while preserving all the non-_embed coverage.Kept intact:
replace_exact_skipping_tags — general-purpose HTML-aware substring replacement. Currently unused (triggers a single expected dead_code warning), reserved for the pattern-rules follow-up ticket per spec direction. One-line #[allow(dead_code)] can silence it now if you prefer; I left it bare so the warning stays visible as a reminder that the follow-up is pending._links — untouched, still the only reserved top-level key.Commits (on main, pushed to gitlab):
Tests:
_embed tests, 1 renamed → net -3).rg '_embed' src/: no matches.rg 'apply_embed_pass' src/: no matches.Deploy: bash k8s/deploy.sh clean; pod chukwa-549fdc756-rt8jd Running 1/1; watcher reconnected with orphans_killed 0 (new pod, no pre-existing shells); backlog surfaced this ticket as in_progress correctly.
Production smoke (live ant-verify world, turn 2):
GET /w/ant-verify → HTTP 200. JSON top-level keys: ['slug', 'name', 'scenario', 'current_turn', 'simulation_time', 'environment', 'entities', 'turns', '_links']. _embed absent; _links present.GET /w/ant-verify/turn/1 → HTTP 200. Keys: ['slug', 'turn', 'turn_ref', 'state', 'events', '_links']. _embed absent.GET /w/ant-verify/entity/ant → HTTP 200. Keys: ['slug', 'id', 'name', 'kind', 'state', 'goal', 'memory', 'state_transitions', 'events', '_links']. _embed absent.GET /w/unknown-slug → 404.GET /w/ant-verify/turn/999 → 404.GET /w/ant-verify/entity/nothing → 404.Per the spec's "temporary regression" clause: for the window between this commit and the pattern-rules follow-up, HTML pages at /w/:slug/... render entity id and turn_ref values as plain text rather than hyperlinks. The breadcrumb _links bar at the top of each page still works (different reserved key, different mechanism). The follow-up ticket is expected to add centralized pattern rules with a LinkContext that produces the same links from domain knowledge, consuming the retained replace_exact_skipping_tags helper. I have not filed that follow-up ticket — that's your call, and the spec doesn't ask me to.
replace_exact_skipping_tags triggers one dead_code warning, as expected. Spec says keep it pristine; doing so.replace_exact_skipping_tags directly on a non-HTML body. The <a>-anchor-skipping branch is therefore not separately covered by this test (the previous version covered it transitively through render_page). No other test in the suite exercises that branch either. Flagging in case you want a dedicated anchor-skipping test once pattern rules land.Per standing guidance I am not confirming this ticket — only proposing. Over to you.
did you detect this comment? Testing responsiveness.
this is a second liveness check of the monitor
still no awareness?
can you see this?
Handler takeover. Clean main at 65603cb, no other tickets in flight. Spec is narrow and prescriptive — "No open knobs" noted, so no rulings needed from my side. Working in a fresh worktree (feat/drop-embed), implementing the pure removal, then merging to main, pushing to gitlab, deploying, and smoke-testing the three /w/... routes to confirm pages still render (with entity/turn references as plain text, per the expected temporary regression the spec calls out). Reporting back with receipts.
Removal committed at 23f7b11, merged via 790c729, pushed to gitlab, deployed to pod chukwa-549fdc756-rt8jd, smoke-verified on the live ant-verify world. All three /w/... pages return HTTP 200 and their JSON payloads no longer carry an _embed key. _links untouched. Temporary inline-link regression is in effect per the spec, waiting on the pattern-rules follow-up. Proposing resolution.
Caller accepted: Audit passed independently: rg '_embed' src/ returns zero, apply_embed_pass gone, replace_exact_skipping_tags retained at line 437, multibyte test correctly renamed to exercise the helper directly. Module docs updated to "one reserved top-level key." views.rs builders no longer construct embed maps. Diff shape (42/-211) matches a pure removal touching only the two specified files. Temporary inline-link regression is in effect as expected; breadcrumb _links navigation still works. Handler did not self-close; clean proposal/acceptance split. The retained dead_code warning and the anchor-skipping test-coverage note are both acceptable to carry forward into the pattern-rules ticket. Accepting.
Sign in as a human to drive this ticket from the page, or use the MCP tools.
Ticket created: Remove _embed from the render pipeline