Files
ARCADIA-Studio/harness/analysis-ordinary-index-20260924/critique.md
T

9.4 KiB
Raw Blame History

Ordinary occurrence successor: independent design critique

2026-09-24. Source-only review of ORDINARY-SUCCESSOR-MAP.md against clean private 93eb6117f95353d25d594d59780018f197c51672 in .local/as3batch. No source edits, Cargo, runtime claims or Gitea work. Parent owns adoption. Source paths below are relative to crates/oa-core/src/.

Recommendation: proceed with the proposed consumed, read-only authored-name owner and physical-token ordinary keys. No fundamental design flaw found. The map correctly separates this dependency from editing and full graphical/textual/API parity. The next contract should resolve the few boundaries below; none requires a generic indexing framework or structural ordinary path arena.

Completeness and provenance

The retained projection is sufficient for the declared authored-name set. Ast::resolve resolves every Reference through global aliases and rejects references in unsupported field roles (language.rs:761–820); ordinary construction recursively resolves every declaration field, with the explicit Trace baseline exception (:1684–1693). semantic_source.rs:13–31 refuses all @alias inside historical semantic payloads, while other baseline fields use ordinary resolution (:87–100). Therefore walking every retained EditKind::Reference covers admitted ordinary authored alias uses, including ordinary→typed targets; do not introduce a second field-name/schema selector or exclude every field named baseline. The existing active-step accounting selector cannot establish this completeness.

The typed family already includes typed→ordinary references. Its qualified parameter names must not enter the ordinary reverse-name table: an ordinary @x binds a global x even when a calculation parameter is also named x or reuses its UUID. Implicit lexical parenthood has no editable name token. Project/ordinary/typed headers together must account for every global exactly once; scoped parameter declarations remain typed occurrences. Model-reference enumeration is an unsuitable substitute because defaults/implicit parents/historical IDs can have no authored alias token.

Keep completeness explicitly grounded in sealed projection emission plus independent complete-set tests. Matching token text does not prove an omitted projection record exists. Rechecking an AST/position parallel walk is an optional stronger invariant, not needed to call the immutable emitted set complete under the already accepted trust model. Do not promise arbitrary coordinated corruption rejection.

Required containment clarification

The phrase field/declaration containment needs a precise exception. EditDeclaration.fields is a synthetic Record whose span is body.start - 1 .. body.end + 1 (language.rs:1129–1135), including braces. It is deliberately not contained in the body interior. A blanket check that every walked EditValue lies inside EditDeclaration.body would reject valid declarations. Validate that synthetic root against the declaration span; apply body/field containment to actual field values and Reference leaves. Start traversal at its Record children if that makes the distinction simpler.

Nested declarations live in the flat ordinary declaration preorder; the parent's fields map does not contain child declaration fields (language.rs:1479–1534). Pair each retained position with its corresponding declaration occurrence and use that owner, rather than choosing the broadest containing declaration or scanning its entire byte range. Parent and child declaration spans overlap legitimately. This matters for both exact ownership and future movement semantics.

Project header and reference token contract

Project SourceHeader.span.start is exactly the project token, after version syntax and any trivia (language.rs:1437–1471). A binary search of retained significant tokens, equality with whole Word project, and the immediately next whole Word alias gives a sufficient narrow projection; require the span inside that same header and compare its target/name to the retained header Project and complete global catalog. Retain canonical entry-file ownership. No new header parser, substring scanner or manufactured numeric source map is justified.

For each ordinary Reference, require the retained full extent to begin at the whole @ punctuation token, then require the next significant token to be a Word with the projected alias and global catalog spelling, and require that Word's end to equal the Reference extent's end. The parser consumes exactly that pair, including arbitrary intervening trivia (language.rs:1333–1336), and the position projection preserves the full consumed extent (:1068–1084). Index only the Word span for replacement. This explicit equality prevents an ambiguous oversized extent from being treated as authenticated just because it contains a matching Word.

The proposed observable tuple includes full Reference extent, but the minimal value sketch lists only owner/role/target. Settle that API detail: retaining the full extent as an inline optional Span is inexpensive and useful for the promised diagnostics/oracle; it adds no logical container slot or owned text. Alternatively keep it construction-only and stop promising it in the returned view. Whole-token validation plus physical duplicate detection is sufficient for overlap safety in rename-only output; do not weaken that requirement to substring spelling checks.

Storage, frame policy and simpler alternatives

The proposed retained delta 1 + D + A entry slots, zero occurrence slots, zero copied text bytes is sound for one physical-keyed map with inline owner/role/target/spans. Existing typed maps, raw arenas, original syntax and warnings remain charged. Account the reverse global-name table, typed physical lookup and all actual iterative work entries concurrently. A header-coverage set or AST↔position verification table, if added, is extra scratch; it is not free because the source was previously admitted.

Do not add Budget::frame(walk_depth) merely to bound the ordinary traversal. The parser's ordinary value policy is already a separate fixed depth64 (language.rs:1291–1298), and semantic declaration nesting uses its own flat/open stack. A new mixed-frame interpretation could reject already accepted ordinary input under a tight typed-frame profile. The proposed iterative reference walk needs only aggregate entry-slot reservations for its live work Vec; it creates no persistent structural path or new recursion. Preserve all usage fields for this successor unless a separately justified depth operation is deliberately specified.

Physical keys are the simpler correct choice here: the owner is immutable and later emission consumes original spans. They are snapshot identities, not semantic IDs across edits. Adding field-name Strings and persistent ordinary paths would raise memory and cleanup costs without improving rename completeness; retained EditValue trees remain available for later scalar/structural work.

A plausible smaller alternative is to stream these same sealed ordinary occurrences directly into a later rename planner instead of retaining an N-entry map. That avoids retaining unchanged occurrences while allocating changed edit records. However it fuses discovery, validation and edit intent and makes the complete read-only boundary less independently inspectable. Given the currently unresolved ordinary ownership coverage, the proposed materialized map is justified as a bounded, testable step. Keep the underlying walker private and simple so a future consumer need not duplicate traversal; do not introduce an additional generalized producer/visitor framework now.

Falsifiers worth carrying into the next contract

  • Nested parent/child ordinary elements, each with explicit references, including one explicit parent and one implicit parent: no synthetic-root containment failure, no double indexing through the parent's overlapping span, no invented token for the implicit edge.
  • @ /* alias-like @noise */ real_alias with the same spelling in prose/enums/includes: only the final whole alias Word is indexed, exact full extent remains available, and no prose token appears in the output set.
  • Ordinary global x plus scoped parameter x sharing or reusing a UUID: the ordinary reference targets only Global(x); typed $x and call labels keep calculation scope.
  • A tiny mixed bundle's complete global header set equals the global name-catalog set exactly, while its repeated references remain separate physical records. Include canonical file order opposite include traversal and identical offsets in two files.
  • Exact baseline + N + live scratch boundary and copied-text delta zero, including late failure/drop; depth64 ordinary values remain under the established policy without borrowing the typed structural-frame metric.

The map's later rename-only scope is a useful subsequent milestone, provided its complete-target diff gate, one inherited authority/profile, complete edit membership, single original-coordinate emission, actual-output admission and whole-Project equality remain mandatory. It must not claim ordinary scalar edits, typed subtree changes, parameter insertion/deletion/reorder, repaired deletion/reidentity, file movement, missing-ID stabilization, public migration, history/checked-save or usable UI/API parity. Those user requirements remain the completion criteria beyond this dependency; no alternative final product is implied by accepting it.