Expand description
§Module: template
Template-mode support for in-place response documents. Parses structured patch blocks from agent responses and applies them to named component slots in the document, with boundary marker lifecycle management for CRDT-safe stream writes.
§Spec
parse_patches: Scans agent response text for<!-- patch:name -->...<!-- /patch:name -->blocks and returns a list ofPatchBlockvalues plus any unmatched text (content outside patch blocks). Markers inside fenced code blocks (``` or ~~~) and inline code spans are ignored so examples in responses are never mis-parsed as real patches.apply_patches: Delegates toapply_patches_with_overrideswith an empty override map. Applies parsed patches to matching<!-- agent:name -->components in the document.apply_patches_with_overrides: Core patch application pipeline:- Pre-patch: strips all existing boundary markers, inserts a fresh boundary at the end
of the
exchangecomponent (keyed to the file stem). - Applies each patch using mode resolution: stream overrides > inline attr (
patch=ormode=) >.agent-doc/config.toml ([components] section)> built-in defaults (exchange/findingsdefault toappend, all others toreplace). - For
appendmode, uses boundary-aware insertion when a boundary marker exists. - Patches targeting missing component names are routed as overflow to
exchange/output. - Unmatched text and overflow are merged and appended to
exchange/output(or an auto-createdexchangecomponent if none exists). - Post-patch: if the boundary was consumed, re-inserts a fresh one at the end of exchange.
- Pre-patch: strips all existing boundary markers, inserts a fresh boundary at the end
of the
reposition_boundary_to_end: Removes all boundaries and inserts a new one at the end ofexchange. Used by the IPC write path to keep boundary position current.reposition_boundary_to_end_with_summary: Same, with optional human-readable suffix on the boundary ID (e.g.a0cfeb34:agent-doc).template_info: Reads a document file, resolves its template mode flag, and returns a serializableTemplateInfowith per-component name, resolved mode, content, and line number. Used by editor plugins for rendering.is_template_mode(test-only): Legacy helper to detectmode = "template"string.
§Agentic Contracts
parse_patchesis pure and infallible for valid UTF-8; it returnsOkeven for empty or patch-free responses.- Patch markers inside fenced code blocks are never extracted as real patches. Agents may include example markers in code blocks without triggering unintended writes.
- Component patches are applied in reverse document order so earlier byte offsets remain valid throughout the operation.
- A boundary marker always exists at the end of
exchangeafterapply_patches_with_overridesreturns. Callers that perform incremental (CRDT/stream) writes may rely on this invariant. - Missing-component patches never cause errors; content is silently routed to
exchange/outputwith a diagnostic written to stderr. - Mode precedence is deterministic: stream override > inline attr (
patch=>mode=) >config.toml ([components] section)(patchkey >modekey) > built-in default. Callers can rely on this ordering when constructing overrides for stream mode. template_inforeads the document from disk; callers must ensure the file is flushed before calling (especially in the IPC write path).
§Evals
parse_single_patch: single patch block → onePatchBlock, empty unmatchedparse_multiple_patches: two sequential patch blocks → twoPatchBlocks in order, empty unmatchedparse_with_unmatched_content: text before and after patch block → unmatched contains both text segmentsparse_empty_response: empty string → zero patches, empty unmatchedparse_no_patches: plain text with no markers → zero patches, full text in unmatchedparse_patches_ignores_markers_in_fenced_code_block: agent:component markers inside ``` are preserved as contentparse_patches_ignores_patch_markers_in_fenced_code_block: nested patch markers inside ``` are not parsed as patchesparse_patches_ignores_markers_in_tilde_fence: patch markers inside ~~~ are ignoredparse_patches_ignores_closing_marker_in_code_block: closing marker inside code block is skipped; real close is foundparse_patches_normal_markers_still_work: sanity — two back-to-back patches parse correctlyapply_patches_replace: patch to non-exchange component replaces existing contentapply_patches_unmatched_creates_exchange: unmatched text auto-creates<!-- agent:exchange -->when absentapply_patches_unmatched_appends_to_existing_exchange: unmatched text appends to existing exchange; no duplicate componentapply_patches_missing_component_routes_to_exchange: patch targeting unknown component name appears in exchangeapply_patches_missing_component_creates_exchange: missing component + no exchange → auto-creates exchange with overflowinline_attr_mode_overrides_config:mode=replaceon tag wins overconfig.toml ([components] section)append configinline_attr_mode_overrides_default:mode=replaceon exchange wins over built-in append defaultno_inline_attr_falls_back_to_config: no inline attr →config.toml ([components] section)append config appliesno_inline_attr_no_config_falls_back_to_default: no attr, no config → exchange defaults to appendinline_patch_attr_overrides_config:patch=replaceon tag wins overconfig.toml ([components] section)append configtemplate_info_works: template-mode doc →TemplateInfo.template_mode = true, component list populatedtemplate_info_legacy_mode_works:response_mode: templatefrontmatter key recognizedtemplate_info_append_mode: non-template doc →template_mode = false, empty component listis_template_mode_detection:Some("template")→ true; other strings andNone→ false- (aspirational)
apply_patches_boundary_invariant: after any apply_patches call with an exchange component, a boundary marker exists at end of exchange - (aspirational)
reposition_boundary_removes_stale: multiple stale boundaries are reduced to exactly one at end of exchange
Structs§
- Component
Info - Per-component info for plugin rendering.
- Patch
Block - A parsed patch directive from an agent response.
- Template
Info - Template info output for plugins.
Functions§
- apply_
patches - Apply patch blocks to a document’s components.
- apply_
patches_ with_ overrides - Apply patches with per-component mode overrides (e.g., stream mode forces “replace” for cumulative buffers even on append-mode components like exchange).
- exchange_
baseline_ headings - Extract the set of stripped
### Re:heading lines from theexchangecomponent of a document. Used by the commit path to build a baseline of headings already present ingit HEADso the reposition step can mark all new-this-cycle headings (not just the last one) with(HEAD). - parse_
patches - Parse
<!-- patch:name -->...<!-- /patch:name -->blocks from an agent response. - reposition_
boundary_ to_ end - Reposition the boundary marker to the end of the exchange component.
- reposition_
boundary_ to_ end_ with_ baseline - Reposition boundary, with an optional set of baseline
### Re:headings (typically extracted from git HEAD). When a baseline is supplied, every### Re:heading in the current exchange whose normalized text is NOT in the baseline is treated as “new this cycle” and receives a(HEAD)suffix. Headings already present in the baseline are stripped of any stale(HEAD)suffix. When the baseline isNone, behavior matches the legacyannotate_latest_re_heading_with_headpath: only the last### Re:heading gets the marker. - reposition_
boundary_ to_ end_ with_ summary - Reposition boundary with an optional human-readable summary suffix.
- template_
info - Get template info for a document (for plugin rendering).