Defines Component, the parsed representation of a bounded document region delimited by
<!-- agent:name [attrs...] --> (open) and <!-- /agent:name --> (close) HTML comments.
parse(doc) scans the raw document bytes for <!-- / --> comment pairs, builds a
stack-based nesting model, and returns all Component values sorted by open_start.
Markers that appear inside fenced code blocks (backtick or tilde) or inline code spans are
skipped; find_code_ranges(doc) uses the pulldown-cmark AST (CommonMark-compliant) to
locate these regions.
is_agent_marker(comment_text) classifies whether the inner text of a comment is an
agent open/close marker vs. an ordinary HTML comment.
Component names must match [a-zA-Z0-9][a-zA-Z0-9-]*; invalid names, unmatched opens,
unmatched closes, and mismatched open/close pairs all return Err.
boundary:* prefixed markers (<!-- agent:boundary:ID -->) are recognised and skipped
during component parsing; they are not treated as component open tags.
Opening markers may carry space-separated key=value inline attributes
(e.g., patch=append). patch= takes precedence over the legacy mode= alias;
patch_mode() encapsulates this lookup.
The non-agent comment fast path only previews comment text on UTF-8 char boundaries, so
ordinary prose comments near multibyte glyphs never panic the parser.
Marker open_end / close_end byte offsets include a trailing newline when present,
so that content slices are clean.
replace_content(doc, new_content) rebuilds the document preserving both markers,
replacing only the bytes between them.
append_with_caret(doc, content, caret_offset) appends content after existing text, or
inserts before the caret line when the caret falls inside the component.
append_with_boundary(doc, content, boundary_id) locates <!-- agent:boundary:ID -->
inside the component (skipping any occurrence that lives inside a code block), replaces it
with the new content, and re-inserts a fresh boundary marker; falls back to
append_with_caret when no boundary is found.
parse is pure and deterministic: identical input always yields identical output.
All byte offsets (open_start, open_end, close_start, close_end) are valid UTF-8
char boundaries within the document string they were parsed from.
content(doc) returns exactly &doc[open_end..close_start] — no allocation.
replace_content and append_with_* never mutate the original &str; they return a
new String with all offsets consistent for a fresh parse call.
Markers inside any code region (fenced block or inline span) are never parsed as
components and never mutated by any append/replace operation.
append_with_boundary always re-inserts a boundary marker with a fresh UUID, preserving
the invariant that exactly one boundary exists inside the component after each write.
Unknown or malformed key=value tokens in inline attributes are silently discarded;
they never cause a parse error.
Find byte ranges of code regions (fenced code blocks + inline code spans).
Markers inside these ranges are treated as literal text, not component markers.
Check whether a component name refers to tracked work that participates in
do #id closeout (agent:backlog / legacy agent:pending,
agent:review, and agent:icebox).
Detect agent-looking HTML comment markers that were truncated before their
same-line --> terminator. The normal parser only sees complete comments,
so a CRDT/editor split like <!-- /agent:exchange -- can otherwise be
skipped or consume a later unrelated terminator.
Strip deprecated patch=... (and legacy mode=...) attributes from
backlog/pending component opening tags. The backlog component’s patch mode
is always replace by built-in default; the inline attribute is redundant
since the binary owns all backlog mutations via --pending-* flags.