Files
rea/docs/specs/agent-environments/prefix-variance/spec.md
T
Edgar ArakelyanandClaude Opus 5.5 ea3534759f feat(analysis-view): share templated positions across manifest tools (#5664)
* docs(specs): plan a template rule that shares templated positions

Record the outcome, requirements, non-goals, plan and tasks for
prefix-variance, an opt-in environment-manifest rule that templates a
literal segment with the parameter another tool already uses at that
position, so a session's writes to one entity share the read's template.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(analysis-view): share templated positions across manifest tools

Add the opt-in prefix-variance template rule. It runs after the other
opt-in rules and templates a literal at a position that another tool,
of any method or segment count, templates by one of those rules after
the same preceding parts, when the literal is one of that parameter's
observed values or carries a digit and is spelled like one. The
parameter takes the shared parameter's name, tools that now match merge,
and a merged position keeps a tool's own rule when one templated it.

A write to the one entity a session edited, such as
PATCH /api/v1/collections/0RZ576QZQA5KG, becomes
patch_collections_by_collection_id on the read's template instead of a
literal single-entity tool.

Tool naming moves to its own module, and the three comparing passes
share the 32-segment split. Manifests that do not list the rule are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(analysis-view): drop the unused ManifestRule alias

Parameters now type their rule as a format rule, a shared opt-in rule
or prefix-variance, so nothing reads the union alias.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(specs): record the prefix-variance checks and corpus results

Record the gates, and the 50 showcase captures with and without the
rule: identical output without it, 25 write and 34 read tools templated
with it, and the write tools the write-plan branch serves on top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(analysis-view): share positions with digit-free generated identifiers

prefix-variance accepted an unobserved literal only when it carried a
digit, so a generated identifier that happened to hold none stayed a
literal tool: an n8n workflow id such as FkMwxmXNGaGVsXFG, whose reads
then never joined the item view. A literal now also qualifies when every
value observed at the position has one length of eight or more characters
and the literal has that length and uses only their character classes.

Across the 50 showcase captures this templates 10 more read tools in
Memos and n8n and no words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(specs): record five environments rebuilt end to end with the rule

Five randomly drawn environments rebuilt on VMs with the rule and the
write-plan branch: smoke, retrieval and write tasks for two models, and
the same calls against the live applications. Record the results, the
misses and their causes, and the corpus numbers after the fixed-length
clause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(analysis-view): share a position with the parameter that observed the literal

A shared position folded every donor's values into the earliest donor's
parameter. With an opaque-token read before sibling-variance reads at
the same position, a PATCH of /api/items/b2 qualified on the sibling's
evidence but became /api/items/{uid} instead of joining the item read's
/api/items/{item_id}. Each position now keeps one donor per naming rule
with its own values, and a literal takes the donor that observed it,
else the earliest one it is spelled like.

Each donor's spelling (length and character classes of its values, and
its fixed-length family) is summarised once per position, so a literal
is checked in time independent of how many values were observed, rather
than copying and rescanning them for every candidate.

A family now forms from one observed value, as the requirement says, so
a digit-free id of the same length shares a position that only one
opaque-token or after-uid-literal tool supplied. The 50 showcase
captures give the same tools as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(specs): record the prefix-variance review round

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(analysis-view): bound the spelling summary of shared positions

spellingSummary classified every observed value with three full-size
replaceAll copies and a set per distinct character, so a donor holding
a multi-megabyte segment cost unaccounted memory and time in finish().
Characters are now classified in one pass, and a value longer than 128
characters takes no part in spelling comparisons: it shares a position
only as an exactly observed value. The 50 showcase captures give the
same tools.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:11:51 +08:00

3.3 KiB

Share templated positions across tools

Issue: https://github.com/morluto/rea/issues/4933

Outcome

A session usually edits one scratch entity: it creates it, then updates and deletes it at a fixed path such as /api/v1/collections/0RZ576QZQA5KG. The manifest templates a segment only when sibling routes of the same method vary there, so those writes stay literal tools (patch_collections_0rz576qzqa5kg) even though the reads of the same collection were templated as /api/v1/collections/{collection_id}. A literal write tool addresses one entity that may not exist in a later state, and nothing can model its effect.

A new opt-in template rule, prefix-variance, templates such a literal with the parameter another tool already uses at that position, so the write becomes patch_collections_by_collection_id on the same template as the read.

Requirements

  • prefix-variance applies only when listed, after every other opt-in rule, so it can share the parameters they produce.
  • A literal at position p is templated when another tool on the same origin, of any method and any segment count, has a parameter at p from one of the other opt-in rules, after the same preceding parts. Parameters in the preceding parts compare by the rule that names them, so a position templated by prefix-variance matches the parameter it shares.
  • The literal qualifies when it is one of the values such a parameter observed at that position, when it carries a digit and has the length and character classes (digits, lower case, upper case, each other character) of one of them, or when every value the parameter observed, one or more, has one length of eight or more characters, as generated identifiers often do, and the literal has that length and uses only their character classes, so an identifier that happens to hold no digit still qualifies. An empty literal, a stop word or a v1-style version never qualifies. Each parameter's spelling is summarised once, so a literal is checked without rescanning its values, and a value longer than 128 characters is compared only exactly, so a huge segment costs no classification.
  • Positions templated by the four format rules are never shared, so /api/teams/{numeric} still absorbs no literal.
  • Values stay with the parameter that observed them: when parameters of different rules share a position, the literal shares the one that observed it, else the earliest one it is spelled like.
  • The parameter takes the name of the parameter it shares (collection_id, uid, a pair's _namespace and _name) and is labelled prefix-variance.
  • Tools whose routes now match, by method and by the rule that names each parameter, merge. A merged parameter keeps the rule of a tool that templated that position itself, when one did.
  • Like the sibling rules, it compares routes of at most 32 segments and says so in a limitation when a longer route exists.

Non-goals

  • No change to the default rules or to any other rule: manifests that do not list prefix-variance are byte-for-byte unchanged.
  • No templating from response bodies, such as an id a create returned; the manifest reads request lines only.
  • No change to which groups are excluded: a write whose response has no body or content type outside /api/ is still excluded as non-json.