diff --git a/harness/analysis-text-producer-contract-20260925.md b/harness/analysis-text-producer-contract-20260925.md new file mode 100644 index 00000000..81345685 --- /dev/null +++ b/harness/analysis-text-producer-contract-20260925.md @@ -0,0 +1,95 @@ +# Private syntax text producer prerequisite + +Source baseline: `8d52dab97c92cc31baae9f20d8c324b55818aa5d`. +Selected after independent critique. This prerequisite addresses the named text +timing gap in the carried-phase and emission contracts. It grants no accepted +rewritten-output, public source8, save/history or installation authority. + +## Scope and mode + +Preserve all existing parser entry points, including the explicit carried-phase +route, with their existing limits, charge events and diagnostics. Add a separate +private fixture-constructible text-producing route. Its actual bundle, carried +owner and exact Limits/ProjectLimits come from the existing opaque authority; +arbitrary caller-provided baselines and policy widening remain impossible. +Zero carried storage still selects this mode explicitly. + +The guarantee is limited to the retained syntax String inventory already walked +by `mixed/project/accounting.rs`, plus these named temporary result strings: +raw-scanner JSON validation, quoted decode slack, consumed UUID spellings and +local producer copies awaiting transfer or drop. Moves do not reserve again. +Each simultaneous owned copy reserves its own logical UTF-8 length. Typed +duplicate-name sets, traversal, parser entry/metadata +producer timing and other previously documented scratch remain separate open +domains. Model conversion, architectural validation, decoder internal scratch, +allocator capacity/overhead and native stack are not represented by these logical +String lengths. Internal Exact reconstruction/formatting and BigInt storage +remain under existing numeric policy, with unchanged work charges; this exclusion +does not cover retained AST String/Word/Reference values or copied syntax names. +No universal heap claim is permitted. + +## Admission and lifetime + +Before every in-scope copy, check the prospective total carried text C plus +live producer text and named temporary text against the existing byte ceiling, +using checked arithmetic. Failed reservation changes no totals. These are storage +counts, never source-byte/token/entry/reference/numeric work charges. Entry and +occurrence phase checks retain their existing behavior. + +Before the existing quoted String decoder, reserve P, the UTF-8 payload length +excluding exactly the two quotes. Valid JSON has decoded length D <= P: ordinary +UTF-8 copies equally, simple escapes contract, BMP escapes yield at most three +bytes from six, and surrogate pairs yield four from twelve. On success release +P-D. This conservative rule may refuse escaped text whose decoded bytes fit; +that is intentional only in the new route. No second decoder or exact-number +conversion is introduced. Scanner validation reserves inside the shared scan +body after token extent discovery and before serde validation, then drops the +result before refunding P. Unclosed tokens never invoke that decoder. Refusal +may precede malformed-escape classification in the new route; legacy precedence +must remain unchanged. No resumable refused scanner state is exposed. + +Retained String producers include typed names/references/quoted fields; ordinary +header/include/declaration/AST names, quoted text and words; both retained copies +of declaration field keys; nested keys; and projected keys/reference names. +Static header roles, source slices, literal spans and copied UUID values are not +owned text. All successful consumed spellings must drop before refund: ordinary +optional IDs, typed identities, and ordinary HistoricalUuid values. The ordinary +declaration-kind word must either remain borrowed with unchanged parsing/error +behavior or be accounted while live and released. Nested field key handling +must account the clone overlap and release its discarded local original, or use +a reviewed equivalent move without silently changing duplicate/error semantics. +Project and typed duplicate descriptions already refuse before replacement; +they do not create a successful overwrite exemption. + +Use small scalar state in the existing Budget and narrowly scoped producer hooks. +Do not duplicate full policies or introduce owner-sized inline state. A returned +String may provisionally count as owned T until its consumer transfers or drops +it; temporary decode slack and scanner results stay separately identifiable. +Successful +syntax return has no outstanding named temporary reservation. Independently +reconcile retained T to the existing complete syntax inventory. Resolution seeds +C once, transfers T once and retains the established U/M and bounded counting +work semantics. Its text walk must independently sum/compare rather than charge +T again. Existing routes retain their existing progressive text walk. + +## Acceptance + +- Preserve all prior actual outcomes, public/legacy malformed-token precedence, + complete Project/Usage parity and exact carried-phase caps. +- Check raw/escaped Unicode, simple escapes, surrogate pairs, empty strings, + malformed escapes and unpaired surrogates. Assert reserve-before-decoder and + drop-before-refund ordering through a bounded hook observer where needed. +- Independently derive complete owner and peak counts for real fixtures using one + unchanged profile through parse/resolve. Distinguish arithmetic fault injection + from real provenance. Include scanner temporary release, all three UUID + consumers, ordinary/projected key and reference overlap, nested fields and + multi-file accumulation. A final retained count alone is not a peak oracle. +- Verify exact final T, W=0, once-only C/T transfer, original source and desired + data unchanged, and no accepted-output/extraction route. +- Run new focused cases, the unchanged full library disposition, strict core + all-target Clippy and format comparison. Investigate stack regressions and + measure relevant changed prologues; do not enlarge existing worker stacks. + +Later work still needs entry/metadata producer timing and a finite decision on +remaining scratch, actual-output verification, justified equality work and an +owning accepted-result transition. This prerequisite does not waive them. diff --git a/harness/analysis-text-producer-design-20260925/.gitattributes b/harness/analysis-text-producer-design-20260925/.gitattributes new file mode 100644 index 00000000..631ce65f --- /dev/null +++ b/harness/analysis-text-producer-design-20260925/.gitattributes @@ -0,0 +1 @@ +*.md -text diff --git a/harness/analysis-text-producer-design-20260925/PRODUCER-CRITIQUE.md b/harness/analysis-text-producer-design-20260925/PRODUCER-CRITIQUE.md new file mode 100644 index 00000000..27ff1349 --- /dev/null +++ b/harness/analysis-text-producer-design-20260925/PRODUCER-CRITIQUE.md @@ -0,0 +1,59 @@ +# Independent retained-text producer critique + +Reviewed proposal and current `8d52dab97c92cc31baae9f20d8c324b55818aa5d` producers, prior NEXT-PRODUCER-HOOKS/CRITIQUE, existing syntax text walk and carried-phase contract. Design-only; no source edits, compiler, network or parser execution. + +Disposition: the explicit stronger mode, retained-text scope, named scanner result temporary and raw-payload bound form a useful bounded prerequisite. Do not expand it to U/M producers, duplicate-name sets or traversal. Before coding, make the successful-discard inventory and transfer semantics below concrete. It is not accepted-output verification or completion of broader before-growth requirements. + +## Required lifecycle clarification + +The proposal explicitly identifies ordinary optional_id and typed identity, but there is a third successful UUID spelling consumer: `language.rs::Parser::value_inner`'s `uuid` branch. It calls quoted(), parses an Id, returns Ast::HistoricalUuid and drops the decoded String. Hooking quoted without refunding this path leaks36 into final T and breaks independent reconciliation. Name this producer/consumer pair explicitly, including historical UUIDs nested in arrays/records. No projected text reservation applies to the copied Id. + +For each charged shared producer, distinguish transfer, discard and duplication. Direct names/quoted results moved into retained AST/header/reference structures retain the charge. Optional/typed/historical UUID spellings remain charged until after their actual drop. Nested ordinary fields clone the key into a map while the local key remains alive; reserve the clone before creation, then refund the local original after drop on successful completion. Top-level field keys instead survive in two maps, so both remain charged. Projected keys/references create further live copies. Error-only abort paths need no reusable successful ledger, but scanner validation must release correctly before another token can be processed. + +Avoid a generic rule that refunds every field-local name, counts every clone as retained forever, or replaces later mismatch with a corrective subtraction. Producer T must independently equal the established final inventory. Duplicate-field errors abort before success; they are not justification for ignoring ordinary successful temporary copies. + +The ordinary declaration-kind String and existing typed parameter/call-label/override duplicate-set copies are not part of retained T. The proposal explicitly excludes coordination copies. Keep that limitation precise; shared name/quoted hooks do not automatically account downstream `.clone()` calls. This slice must not claim all parser String allocation has been covered. + +## Reservation and handoff shape + +Scalar state on the shared Budget is a reasonable design because scanner, typed cursor and ordinary State already borrow it. Do not copy C authority or full policy into recursive frames. Initialize the scalar carried text only through the consumed legitimate guard and exact inherited profile; no independent C setter or public arbitrary budget entry. + +Define whether an unclassified returned String counts provisionally as owned T until its consumer drops it, or is W until an explicit transfer. Either can implement correct live totals, but documentation/tests must agree: a method called retained-text observation must not count discarded UUIDs at successful syntax return. W slack must be zero and independently walked retained text must equal the final producer total. Moves are accounting-neutral; copies coexist; release follows actual ownership end. + +Resolver should seed C once and transfer T once, then use the existing bounded syntax walk to independently sum/compare text while retaining its lower-node/occurrence computation and accounted work frontier. That walk must not reserve the same T again. Its legacy and carried-phase-only text actions stay unchanged. An inconsistent producer tally is a failure, never repaired into acceptance. No extra generic AST clone, independent traversal container or second decoder is needed. + +## Scanner and raw-payload policy + +D<=P is sound for valid JSON UTF-8 string payloads and the selected escape/surrogate cases. Reserve P before the current decoder; reconcile successful output D, then release remaining live reservation after dropping validation/identity strings. This is a logical result-length bound, not serde scratch/capacity metering. Conservative rejection of escaped text whose D fits but P does not is a real new-mode policy and should be accepted explicitly. + +Scanner validation happens before grammar consumes any of that file's strings. The scanner hook must run after finding the token extent but before its existing serde call. A closed invalid string can therefore receive a resource error before invalid-escape classification in stronger mode; an unclosed token never reaches that decoder. Preserve the unchanged Iterator/no-op scanner path and ordinary diagnostic precedence for legacy and phase-only modes. Do not accidentally latch stronger-mode failure into an unrelated reusable legacy scanner API. + +Each successful scanner validation temporary ends before grammar decoding, so P must not accumulate across tokens. However retained T from earlier files remains live when scanning later files. Include a multi-file case that discriminates this overlap; releasing scanner W must not release previous-file T or C. + +## Independent finite oracles + +These counts are source-derived, not obtained from the proposed implementation. + +1. **Existing empty E:** exact existing78-byte main.arcadia source; actual owned C=(1,0,102), final T8. Scanner maximum validation P36 gives text138. Grammar retains alias1/name7 before decoding UUID36, producing maximum **146**. Drop UUID and final C+T=110; resolver catalog maximum112. Therefore entries17 and bytes146 complete the whole path; bytes145 must refuse at ordinary project UUID decode, provided the selected hooks cover only the stated domain. Legacy phase-only complete cap112 and its original diagnostics must remain unchanged. The UUID token spans33..71; ordinary parser transport turns a start33 resource error into33..34, not the complete token span. + +2. **Escaped project fixture:** use the E document constructor, replace display name `Project` with twenty literal source escapes `\u0061`, and set body to `description "` + twenty literal `\u0061` escapes + `";`. Each decoded value is20 ASCII `a` bytes, each raw payload120. Exact source bytes326; copied key12+entry12; C.text350, C.entries1. T is alias1+name20+description20=41. Scanner peakP120; grammar name peak1+120=121; UUID peak1+20+36=57; description peak1+20+120=141. Thus combined text peak **491**, cap490 refuses at the description quoted token after earlier phases fit. Syntax has U2 and M14 (13 significant tokens+F1), so owned syntax entries17 and project catalog peak21. With entries21, bytes491 also admits complete resolution: retained text391, catalog peak393, no declarations/lower expressions or warnings. Expected Project has name and description each20 `a` characters. This proves slack refunds and scanner nonaccumulation without letting UUID36 preempt the intended escape bound. Ordinary description quoted token begins200 and ends322; normal ordinary-error transport at start200 is200..201. + +3. **T45 copy oracle caution:** the existing activity `description "é"` final text45 remains correct: project8 + activity alias/name2 + field_spans key11 + AST key11 + literal2 + projected key11. But new-mode C+44 fails **earlier at activity UUID**, whose live subtotal is8+2+36=46. It cannot be reused as a projected-key producer refusal with the old field span. Keep the old phase-only test unchanged; use roomy new-mode T45 reconciliation, or design a later-copy-dominant fixture with independently counted earlier peaks before asserting that refusal site. + +4. Add one historical UUID and one nested record to discriminate consumed spelling refund versus local-key clone refund; one ordinary @reference verifies AST and projected spelling count twice; one typed scoped-name/call-label case verifies retained move versus explicitly excluded coordination clone. Do not multiply permutations once each distinct ownership action is covered. + +5. Direct arithmetic tests cover quoted P/D examples, overflow and invalid refund. Label arbitrary scalar headroom injections as helper tests. Actual pipeline positive/negative caps must include the real complete bundle C and earlier scanner/UUID/retained peaks. Malformed input controls should assert both legacy error stability and explicitly selected stronger-mode precedence. + +## Stack and scope + +Retain the recent binding/prefix/continuation extraction and slim guard. Adding even a few Budget scalars changes inline type sizes and ancestor frames, so inspect actual compiler output and repeat established stack controls after implementation. Do not introduce a heavyweight per-String wrapper or stored callback merely for automatic refunds without reviewing its concrete frame/lifetime cost. A scoped scanner callback borrowing Budget avoids stored callback ownership; exact Rust signatures still require implementation review. + +No new universal stack bound follows. The future verifier still owes actual-output semantic equality, original-E safety against both operands, output owner provenance and the remaining selected entry/scratch timing guarantees. This narrower text prerequisite advances one real gap without recasting every parser allocation as part of it. + +## Parent CONTRACT-DRAFT follow-up + +Read the parent's CONTRACT-DRAFT.md and the implementer's reported lifecycle clarification. The draft now explicitly covers all three UUID consumers, kind-word borrow/accounting choice, nested-key overlap, duplicate-description rejection, separate fixture mode and legacy diagnostics. No further ownership/authority blocker found for this bounded prerequisite. + +One scope sentence should be corrected before acceptance: grouping **numeric reconstruction** with “separate open domains” suggests new unresolved text-accounting work that the selected metric never required. State instead that internal Exact numeric reconstruction/formatting and BigInt storage remain controlled by the existing numeric policy and excluded from this logical syntax-text inventory, with work charges unchanged. That exclusion must not extend to retained AST String/Word/Reference text or copied syntax names merely because they occur near numeric parsing. Traversal/coordination and entry-timing limitations can remain the separately open domains. + +The E146/145 and escaped fixture491/490 counts above assume the declaration-kind word is irrelevant (these are project-only sources), all named UUID Strings drop/refund on success, and the existing complete syntax inventory remains unchanged. They do not depend on the proposed implementation's output. T45 should remain a generous-cap reconciliation example, not an asserted projected-copy threshold. No draft approval should imply final PendingRename verification or a blanket parser-allocation guarantee. diff --git a/harness/analysis-text-producer-design-20260925/PRODUCER-PROPOSAL.md b/harness/analysis-text-producer-design-20260925/PRODUCER-PROPOSAL.md new file mode 100644 index 00000000..3cc04231 --- /dev/null +++ b/harness/analysis-text-producer-design-20260925/PRODUCER-PROPOSAL.md @@ -0,0 +1,89 @@ +# Named syntax-text producer contract — proposal + +2026-09-25. Design only, not accepted requirements or implementation. Source pin `8d52dab97c92cc31baae9f20d8c324b55818aa5d`; paths below are repository-relative under `crates/oa-core/src/`. Builds/runtime/publication remain parent-owned. This refines the named text rows of `NEXT-PRODUCER-HOOKS.md` and the domain audit; it does not implement PendingRename verification or close every parser timing obligation. + +## Smallest useful next slice + +Add an explicit private **text-producing mode** that checks owned syntax text before its producer allocates/copies it, plus the shared scanner's validation-only decoded String. Keep the current legacy and carried-phase-only entry points and checkpoints intact. Enable the stronger mode only through an internally controlled fixture route for now, bound to the actual carried bundle/guard and exact inherited policy. A legitimate zero C still uses the stronger rules; do not enable/disable by its numeric value. The later PendingRename transition can select this mode only under its own accepted ownership contract. + +This is independently useful: a successful stronger-mode syntax witness proves its counted retained text existed only after checks against the still-live carried text. It does **not** yet prove producer timing for all entry slots, traversal scratch or model/validator allocations. It does not expose an accepted output or change public source8 dispatch. + +### Exact domain + +- C is existing carried live Slots, immutable provenance. Its text includes all owned output sources, canonical keys and entry spelling. It is not work Usage. +- T is the same retained syntax String inventory currently counted by `mixed/project/accounting.rs:233–352` and Walk::drain (`:146–230`): ordinary project/header aliases/names/description, include paths, declaration aliases/names, AST field keys/String/Word/Reference text, separate field_spans keys, projected record keys/reference names, and the typed declaration/parameter/reference/type/expression string inventory. Each simultaneously owned retained copy counts its own UTF-8 length. Static header-role names, source slices and numeric literal spans are not copied text. +- W is only named temporary text selected in this slice: scanner validation result, outstanding quoted-decode reservation slack, consumed UUID spelling, and local copies made by these hooks before transfer/refund. On successful syntax return W=0 and charged retained T equals the original independent retained-text inventory. +- Every proposed reservation checks `C.text + T + W.text + delta <= Limits.bytes`, with checked arithmetic. This storage use does not increment bytes/tokens/entries/references/numeric work Usage, shrink the Limits object or reinterpret source-byte work. Existing carried entry/occurrence phase checks remain unchanged. + +This is a logical string-length metric, not capacity/RSS/all heap. Existing raw model construction/serde model conversion, architectural validator heap, exact-number limbs, allocator overhead and native stack remain outside this metric. **The scanner's returned decoded String is included despite being created by serde**; it is not covered by a generic serde exemption. Internal serde decode scratch/capacity is not represented separately by T/W here and must be stated as excluded implementation scratch, not claimed covered by one result-String reservation. Typed duplicate-name coordination sets and traversal/ordinary-open-stack/projection-walk scratch retain their previously documented separate bounds/limitations; they are not silently included or certified by this text slice. Newly introduced containers would require an explicit additional reservation/design decision; the proposed hook state needs only scalar counts. + +## Quoted text policy: select raw payload reservation with refund + +For a complete JSON string token let P be its UTF-8 byte length between the quotes, and D the decoded String byte length. Valid JSON guarantees D<=P: raw UTF-8 bytes copy unchanged; each simple escape consumes two source bytes and yields one; a non-surrogate six-byte `\uXXXX` yields at most three UTF-8 bytes; a twelve-byte surrogate pair yields four. Empty strings have P=D=0. JSON does not normalize Unicode or expand entities. Invalid escapes/surrogates do not produce a successful value. + +Before the **existing** decoder call reserve P. On successful decode, check D<=P and release P-D; move the D charge with the String. If it is validation-only or a consumed identity/historical UUID spelling, drop the value before releasing its remaining reservation. A failed decode drops the decoder result and releases its attempted reservation before reporting failure where the scanner continues classifying tokens. No witness escapes a parser failure; there is no partial successful ledger to repair afterward. + +This conservative policy can refuse a string whose decoded payload alone fits. That is an explicit new-mode admission rule: e.g. available storage 5 cannot admit `"\u0061"` (P6,D1), while available6 can reserve and later retain only1. Existing entry points do not gain that refusal. Do not report rawpayload policy as exact decoded-fit acceptance or hide its new error timing. Use the quoted token span internally for reserve refusals, preserving existing safe original-file transport. Current ordinary_error/located parser transport may report a one-byte public diagnostic at its start; this text slice does not silently change that diagnostic convention. + +| Candidate | Benefit | Cost / reason not selected | +| --- | --- | --- | +| Exact D pre-count by an allocation-free JSON string grammar | Escaped strings admit at exact decoded-fit storage | Duplicates escape/surrogate/invalid-input interpretation or adds a second content pass; must track the actual serde dialect and error precedence. More code and compatibility proof than this bounded slice warrants. | +| Count via serde visitor | Appears to reuse serde grammar | Visitor callbacks can occur after serde has built escaped-string scratch or produced an owned result; counting there is not a pre-growth check. Merely using a custom Visitor does not prove early reservation. | +| Reserve raw P before the existing decoder, reconcile D | Simple proved bound, one existing decode per current consumer, no numeric reparse or multiplier | Conservative refusal must be accepted explicitly; library scratch/capacity is outside the selected logical result-text metric. Recommended. | + +Do not add a second decoder or a third scanner-validation pass. If exact decoded-fit compatibility is required, that is a consequential different contract decision before implementation. + +## Concrete reusable seams + +The natural owner is the already shared Budget, because raw lexing, typed Cursor and ordinary mixed State borrow that one object. A private optional scalar producer-text state can expose reserve, reconcile/refund and final retained-text observation. It must not copy full Limits/ProjectLimits or add an owner-sized enum to each witness: use Budget's existing exact limits and the existing carried authority. State growth and parser stack controls must be measured after implementation, given the prior debug-frame regression. + +Use named methods conceptually equivalent to `reserve_text(bytes, span)`, `release_text(bytes)` and quoted begin/finish transfer; exact signatures are implementation choices. Refund uses checked subtraction, not saturation. Reserve errors do not install new totals. Moves are neutral; copies reserve before creation. Keep retained and selected temporary subtotals distinguishable so W=0 and retained inventory equality are checkable. No arbitrary public setter, caller-supplied unrelated C or fresh policy reset is introduced. + +| Producer / actual source | Required operation and lifecycle | +| --- | --- | +| `raw_tokens.rs:107–130`, allocation at126 | Inside the same scanner, after finding a closing quote but **before** existing serde String validation, reserve P. Let validation finish and drop its String, then refund P. An after-`next()` adapter is too late. Preserve unclosed-token behavior: no decoder and no decoded-result reservation if no close was found. | +| `analysis_source/lex.rs:19–52` | Keep source-byte charge and raw-token charge before scanner advancement, including trivia. Call the hooked scanner only in the stronger mode. Retained significant tokens remain under the existing token bound; this patch must not introduce another tokens.len entry charge. | +| `analysis_source/cursor.rs:67–95` | Reserve exact spelling length before name/reference `.to_owned`; quoted calls reserve P then reconcile to D. Reference-work charge/cursor advance/error order stays unchanged. | +| `analysis_source/declarations.rs:405–434` identity; `language.rs:1211–1237` ordinary optional_id and `:1322–1332` historical uuid | The quoted UUID String is not retained syntax text. Keep it charged through UUID validation/parsing, drop it, then release D on success. No second UUID or Exact parse. Invalid identity aborts as before unless the earlier named storage refusal occurs. | +| `language.rs:1195–1210,1256–1275,1368–1374` | Ordinary quoted, identifier, field key, Ast Word producers reserve before allocation. A hook at mixed State makes the legacy path a no-op. Account retained quoted literals even when stored inside `serde_json::Value::String`: this is AST text, not excluded model conversion. | +| `language.rs:1245` nested fields; `:1518–1525` declaration field/field_spans | Each actual retained key copy is separate. Initial key transfers to one final owner. Reserve exact key.len before clone; refund original local if it drops rather than entering field_spans. Avoid hidden key clones in a convenience helper. A possible move-after-duplicate-check optimization requires separate error/order review, not a new metric exemption. | +| `language.rs:1047–1090` Positions fields/reference clone | Add a narrow fallible copy hook at each existing owned key/reference clone, aggregated with the still-live AST text. Preserve the shared legacy API via its no-op wrapper. Atom projection does not copy quoted payload; HistoricalUuid copies an Id, not a String. No extra decoded-text charge for either. | +| Other ordinary transient spellings and overwritten values | Inventory every successful-return discard of a charged producer result and refund it after drop; retain actual copied objects only once. Unrelated existing coordination copies absent from T are explicitly outside this slice, not silently charged as retained. | + +A minimal scanner seam is an internally shared `next_with_string_hook` body with one scoped callback/event for reserve/refund around **its existing** validation call. `Iterator::next` invokes the same body with an infallible no-op hook, so public/legacy tokens and malformed-token handling remain unchanged. The mixed lexer callback mutably borrows the single Budget for the duration of `next`; no callback is stored, no second scanner traverses the source and no validation String escapes the scanner. One callback with reserve/release events avoids two simultaneous mutable borrows of Budget. Alternate concrete signatures are acceptable if they preserve this timing and shared scan body. + +The rawscanner hook may reserve after lexical cursor advancement to the known closing quote; that is still before the named String producer. A refusal terminates the stronger parse with no token/witness, not a resumable partially advanced scanner API. Reserve errors win over subsequent invalid-escape errors only in stronger mode; this ordering is deliberate and testable. + +## Inspected replacement and discard cases + +These are actual source facts, not an assumption that every successful String copy survives: + +- **Project description** (`language.rs:1560–1579`): header.description.is_some rejects the second field before syntax_entry, quoted decoding or assignment. The first valid assignment replaces only the initially empty String, which has logical length0. There is no successful overwritten nonempty project description to refund. `header.take()` on a rejected duplicate drops its existing header during whole-parse failure; no successful witness remains. +- **Typed description** (`analysis_source/declarations.rs:301–317`): the borrowed-key `seen` set rejects a duplicate field before the field match/quoted decoder/description assignment. The Option starts None. Thus each successful typed description has exactly one retained String; no blanket replacement subtraction is justified. +- **Declaration-kind word** (`language.rs:1587–1589`, still lexically in scope through declaration push at1631): its current to_owned String is not in final T. Prefer replacing only this needless copy with the original source slice `self.current().text(self.source)`, passing that borrowed word to declaration_kind and the unchanged unknown-kind diagnostic. The current Lexeme is a copied span; the borrowed text belongs to the source, not mutable Parser state. Preserve the same kind lookup and error formatting/order. This removes an otherwise new W lifetime without inventing a metric exemption. If inspection/compiler lifetimes prevent this exact borrow, reserve exact word.len before its existing allocation and explicitly drop/refund at the same safe point; do not leave its bytes in final T. +- **Nested map key clone** (`language.rs:1242–1252`): field() produces an original key; fields.insert(key.clone(), value) retains a second allocation; the local original drops at loop end. Mark the original key's existing T charge as W (transfer, no aggregate delta), reserve the clone into T before copying, insert it, then explicitly drop/refund the original W. On a successful iteration one key length survives. In the top-level declaration case (`:1518–1525`), the original instead moves into field_spans while the clone stays in fields: both remain T. Do not apply the nested refund to that two-owner case. +- **Duplicate field insertion**: nested/top-level insertion may replace a previous key/value immediately before returning the existing duplicate-field error. There is no successful replacement continuation. Keep existing diagnostic behavior/order and drop the failed parse; do not add a complex subtree refund traversal solely for a witness that cannot escape. Any newly prior storage refusal belongs only to the explicitly stronger mode. +- **Every successful quoted UUID discard found in this parser**: ordinary optional_id (`language.rs:1211–1237`), ordinary historical `uuid` Ast branch (`:1322–1332`), and typed Cursor::identity (`analysis_source/declarations.rs:405–434`). Each temporarily retains its decoded spelling through validation/Id parsing, then returns only an Id and source spans. Mark its decoded charge temporary, explicitly drop the String, and refund D. HistoricalUuid does not become a counted text reference during projection (`language.rs:1090`) or inventory (`accounting.rs:146–170`). Typed parameter identities use the same Cursor identity path. These are three distinct consuming sites sharing the same quote producer, not three extra decoder passes. +- **Excluded coordination clones remain explicit**: typed parameter_names (`declarations.rs:293`), override target names (`:610`) and Pratt sequence.keys (`syntax.rs:244`) own duplicate-check copies that do not occur in final T. This retained-text prerequisite does not claim to meter those existing scratch sets. Any later inclusion must reserve both entries and copied text before insertion and refund at actual drop; applying a blanket name-producer charge to these clones without release would be wrong. + +The minimal live state can be a few scalar counts owned once in Budget, with narrow transfer/refund methods; it need not wrap every String in a lifetime-carrying type or refactor parser witnesses. Its representation and new helper frames still require measurement against the repaired parser's demonstrated roughly13 KiB numeric-path headroom improvement. No design can spend that margin based solely on source intuition. +## Once-only resolver transfer and reconciliation + +At successful stronger syntax return retain scalar T with Budget/text mode and require no live temporary reservation. Do not charge T as Usage. In resolve, seed the existing ledger with C once, then transfer/reserve known T once along with the established U+M path. Change the existing bounded syntax walk's text action in this mode to checked independent summation/reconciliation, rather than another text reservation. Require the independently walked retained String inventory to equal producer T before a resolved witness escapes. Keep its existing lower-node/occurrence counting and already-accounted work frontier; do not introduce a second complete AST clone or unbounded count traversal. + +Legacy and existing phase-only mode keep their current incremental text walk. Stronger-mode full T remains live during the walk, so work peaks can tighten compared with the old progressive reservation; this is honest simultaneous ownership, not a compatibility promise. Entry-slot producer timing is still not changed by this slice. C must not be rebased away or added twice. M's token-end metadata remains its single established component, not a new charge for every significant token and projection table independently. + +## Finite acceptance cases + +1. **Unchanged APIs:** same raw scanner token stream/spans/classes and legacy parser errors/models/Usage under existing tests, including malformed strings, trivia, Unicode/CRLF and source8 phase timing. Existing carried-phase tests keep their exact prior caps/diagnostics. Stronger mode is explicit, including C0. +2. **Bound cases:** independently hand-count empty payload0/0; `"a"`1/1; raw `"é"`2/2; `"\\"`2/1; `"\n"`2/1; `"\u0061"`6/1; `"\u96ea"`6/3; `"\uD83D\uDE00"`12/4. Test exact P and P-minus-one headroom as hook arithmetic; do not mislabel arbitrary scalar baselines as real owner provenance. +3. **Actual minimal path:** independent critic derived existing empty-project E with C.text102: scanner UUID result peaks at102+36=138; grammar retains alias1+display name7 before its UUID decode, so the selected producer peak is102+1+7+36=146. With sufficient entries17, inherited byte146 should pass and145 should refuse that grammar UUID temporary, leaving final retained T8 (C+T110) on success. This is a proposed real-path oracle, not a run result; preserve current located-span conventions. A real retained bundle fixture with two long escaped names/descriptions (each P greater than UUID36) distinguishes scanner temporary release from cumulative retained T. Derive complete C and all earlier peaks independently before selecting pipeline caps. Exact new-mode pass/refusal must use one inherited profile from entry through resolve, never mutate the live budget. +4. **Named temporaries:** repeated scanner validation does not retain its decoded strings; identity spellings disappear from final T; ordinary and typed UUIDs do not add36 each to final syntax. Raw validation occurs before grammar decoding but their result strings do not overlap. Invalid escape and unpaired-surrogate cases refund attempted scanner text and emit no syntax witness. +5. **Duplicate copies:** the existing ordinary `description "é"` inventory T45 is a discriminating final oracle: header8 + alias/name2 + field_spans key11 + AST key11 + decodedé2 + projected key11. Atom payload is not copied into positions. This is a roomy final reconciliation test, not a C+45/C+44 producer-cap oracle: a preceding declaration UUID causes a temporary text peak46, so C+44 can fail earlier and must not be asserted to reach projected-key allocation. Use a separately hand-counted later-copy-dominant fixture to isolate that hook. Include nested record keys, explicit @reference clone, typed scoped names and included files; reconcile final producer T against the independent existing syntax inventory. +6. **New refusal semantics:** long escaped input with D fitting but P exceeding available storage refuses at the quoted token before decoder growth in stronger mode; ample storage yields the same whole Project/Usage as legacy. Test resource refusal versus malformed escape ordering explicitly. Do not promise exactdecoded acceptance. +7. **Ownership/accounting:** checked overflow and invalid refund fault injection are labeled arithmetic tests; moves do not charge again; copies do; successful W0; resolver transfers C/T once. Actual complete bundle identity and exact Limits/ProjectLimits remain guarded. No hidden owned output extraction or adopted result. +8. **Regressions:** unchanged deep/wide parser and 128 KiB controls, meaningful measured native-frame headroom, all old failure dispositions, and exact numeric work. This slice cannot claim universal allocation containment, solve remaining traversal/entry-producer timing, or substitute byte/length tests for eventual actual-output semantic equality. + +## Decisions requiring acceptance before code + +Select rawpayload conservative admission versus exactdecoded-fit compatibility; explicitly adopt the returned scanner String into W while excluding internal decoder scratch from this logical metric; decide whether the new mode must remain distinct from existing phase-only carried entry; and accept the exact list of still-open entry/traversal/coordination timing obligations. The recommendation is the explicit stronger mode, raw P/refund D, named result-String metric and once-only reconciled transfer above. If the predecessor's broad producer requirement is interpreted as every parser temporary already being in scope, this partial text slice must remain an identified prerequisite—not a silent weakening or final output-verification acceptance.