# Private mixed syntax proposal: independent review **Disposition: proceed with a private syntax-only implementation on A=`10d7f3340d5cd61a656dc0bcf7c143f8897c5551`, with the bounded corrections below.** Do not first merge the full current root or copy either side's complete language/updater files. The proposed single-buffer cursor, original coordinates, complete-bundle borrow and inherited budget address the real next dependency. A semantic witness, compositor, ID stabilization and public activation remain separate dependent work. Reviewed `.local/analysis-mixed-parser-next-slice-20260923.md`, the published original-span proposal/review at R=`195ddbbba5b352af09bca385a6c3e4dd1c77f8c8`, the private r2 design, and actual A/R source. Source/design review only: no tests, compiler, GUI, source/worktree edits or Gitea operations. Parent's reported A gates are export/typed evidence, not mixed-parser evidence. Line references below are pinned to A or R; `analysis_source/*` means `crates/oa-core/src/language/analysis_source/*`. ## Resolve the implementation base now The proposal's 427/81 whole-file difference is real but does **not** demonstrate materially different ordinary syntax. Direct Git extraction established: - `source_project.rs` is byte-identical from the file start through the entire include/compiler/edit-application section before `format_bundle`. Thus the traversal policy at R/A `:303–605` has no R/A drift. - `parse_unit` and the edit-header/declaration/position section are byte-identical (A `language.rs:905–1109`, R `:1066–1270`). Parser `fields` through `value_inner` is byte-identical (A `:1179–1293`, R `:1336–1450`). The iterative `unit` implementation differs only in A initializing its additional empty `Project.definitions` member. UUID optional-ID behavior is equivalent; R factors the existing shape check into `has_uuid_header_shape`. - Real differences requiring later integration include raw-token versus current bounded tolerant-outline tokenization, A's analysis model/migration/source3 bridge, and R's ordinary defaults plus complete/compact formatter/updater. R `language.rs:1757` and `source_project.rs:853` are semantic/edit behavior, not prerequisites for a syntax-only result. A's generic `declaration_kind` also sees a larger `Kind::ALL`; equal grammar function bodies do not imply equal recognized kind sets. **Concrete base:** keep A's tested private analysis/numeric/export dependency closure and existing module isolation; factor its ordinary syntax/position code in place, using R's pinned ordinary behavior as a compatibility oracle. Implement the mixed unit/bundle owner privately, sharing the factored ordinary grammar and include policy with existing A paths. Do not port R's whole updater, Text outline, Scenario payload or schema constants for this experiment. Keep a narrow compatibility note identifying the equal syntax seams and intentionally deferred semantic/editor differences. Recheck those seams against the parent's eventual integrated pin before proposing production composition. This avoids an unrelated model/GUI integration prerequisite and does not claim A already contains root ordinary default/update behavior. ## Corrections and acceptance conditions 1. **Define ordinary numeric consumption precisely.** A `raw_tokens.rs:158–181` preserves the legacy greedy, *byte-adjacent* numeric alphabet; the mixed significant adapter (`lex.rs:19–51`) discards trivia. A two-token `-` plus Number rule without adjacency would newly admit `- 12.5` and `- //comment\n12.5`. Require contiguous original spans, complete ordinary numeric spelling, finite JSON classification, and the original complete value end. Keep `+1`, `.5`, `1e`, `1_0`, `0x1`, `1-2` invalid as ordinary values; typed `1-2` and exponent `1e-2` retain their different meaning. This belongs in a small ordinary-consumer view over the same cursor, not a second lexer or substring parse. Full field/value spans must include semicolon/delimiters correctly after multi-token negatives. Check nested records/lists and `@ /*not supported*/`-style malformed trivia as well as top-level coordinates. Only `//` comments are supported by the current scanner. 2. **Preserve occurrence ownership before semantic uniqueness.** Explicit IDs are a reasonable first-slice restriction because the ordinary AST and lexical owners currently require `Id`, and edit positions refuse unstabilized declarations (R `language.rs:1232–1240`). Reject missing ordinary/project IDs before `optional_id` generates UUIDs (`:1316–1319`); inspect typed globals and every parameter's existing `IdentitySyntax` (`A declarations.rs:34–42,406–434`). This is staging policy, not proof syntax intrinsically requires explicit IDs. Do not add stabilization here. Conversely, do not key syntax/position storage solely by UUID or alias: ordinary `edit_declarations` explicitly preserves occurrences through temporarily duplicate identities (R `:1151–1154`), and global uniqueness is deferred to resolution. Preserve ordered declaration occurrences and lexical owner occurrence information; either retain duplicate IDs without collapsing nodes, or explicitly label any early uniqueness rejection as additional syntax-slice policy. Reused parameter UUIDs across calculations remain legal. The side table keyed by actual AST start is suitable. 3. **Make the storage table concrete without relabeling model limits.** A `budget.rs:16–24` currently derives syntax entries from caller `max_records` and references from `max_step_references`. Counting every ordinary declaration, field, value and list slot against that same limit can reject a one-project/one-element input under `max_records=2` solely because it has a description field, although the ordinary model has two records. Similarly `parent @x` is not automatically an ordered model step. Keep bounded syntax storage and aggregate ordinary model counts distinct and document which bound each fixture targets. If retaining the existing candidate source8 syntax ceiling is deliberately stricter, state that private policy; do not claim preservation of all caller-limit behavior. Preserve public source3–7 accounting. Tokens/metadata/position copies need an aggregate storage bound, not a fresh per-file check or repeated independent allowance. Do not charge the same AST record again merely because a span references it. A `lowering_entries/index_bytes/lowering_occurrences` are noncharging **phase checks** (`:137–160`) and do not latch failure; all their errors must propagate immediately. `Budget::active` alone is not proof those phase failures were retained. 4. **Keep factoring localized and dispatch contextual.** Share `fields/value/nesting/header` operations; retain the iterative declaration stack. The ordinary parse wrapper can continue selecting its legacy view and the private mixed wrapper its raw-token view, while both call one grammar implementation. No generic parser trait framework or second independently maintained ordinary parser is needed. Inside an ordinary body, reject a *typed declaration header*, not every field whose word happens to be `unit` or `calculation`; ordinary syntax retains generic field names before semantic validation. At document scope, short typed words dispatch first. Explicitly exclude long analysis-derived ordinary kinds on A: `language.rs:236–259` builds names from the expanded `Kind::ALL`, so dispatching short words first alone does not close that alternative syntax. 5. **Provenance is the whole constructor, not token retention alone.** Borrow the actual `SourceBundle`, including entry and all files, validate canonical/case-colliding paths and complete reachability before returning, and mint the path table internally. Maintain one shared cursor index and Budget. Temporary borrowing of the owned token vectors is sufficient; do not create a self-referential stored Cursor. Retaining tokens is justified for the later Index's token witnesses (`A index.rs:185–195`), but there is no need to clone a second token stream or expose a public profile/configuration framework. A test-only tighter-profile constructor or fixed private helper suffices. A result may privately reuse the existing header container with its empty Project shell, but must not expose it as an admitted ordinary model. The distinction between `ParsedMixedSyntax` and a later resolved/admitted witness is sound. Keep construction of the latter internal, with ordinary construction against the full catalog, lower-once, final admission and same-parse Index creation; the current typed-only `Index::parse(ordinary, numeric_files, budget)` is not that authority. ## Bounded first-patch gates The six proposed fixtures are a useful sufficient scope with these additions: signed-value adjacency and nested value/field ends; a contextual typed word used as an ordinary field/alias; long derived analysis-kind refusal on A; duplicate ordinary identities without position collapse; reused scoped parameter UUIDs; ordinary model-record versus syntax-storage boundaries; shared dependency scanned once; and exact Unicode/CRLF source substrings independently specified. Missing-ID failures must leave input unchanged and never call UUID generation. A deliberate phase-bound failure must return no witness, even though that check does not latch the Budget. Require compatibility tests for the public legacy token/parse paths actually touched by factoring, including the existing `raw_tokens::tests::legacy_adapter_retains_authored_numeric_operator_and_trivia_tokens`. Retain ordinary depth 64, typed frame 256/logical depth 128, and the applicable small-stack cleanup controls. These are future acceptance tests, not executed results. Do not require unrelated source updater/GUI integration gates to approve a syntax-only private patch; require those when its code is composed into the corresponding production path. The broader rejection of projection/masking and fabricated `build(Lowered, spans)` provenance is justified. No alternate architecture is needed. The next useful action is this bounded private implementation with the charge table and ordinary numeric adapter specified in its patch, followed by fresh source review and appropriate parser gates.