Files
ARCADIA-Studio/harness/analysis-mixed-index-contract-20260924.md
T

204 lines
14 KiB
Markdown

# Mixed typed occurrence index: successor contract
Accepted bounded implementation contract, 2026-09-24, after parent source
inspection and [independent critique](analysis-mixed-index-review-20260924.md).
This is a design decision, not an implemented or verified index. Implementation facts refer to
`aaec78fcc9b273d1485497126392afdd1fb2e54e`, not the Windows prerelease.
This continues the [complete-Project contract](analysis-mixed-project-contract-20260923.md),
especially section 7, and the [original-span composition review](analysis-original-span-review-20260923.md).
Issue 7 owns scope/status; issue 37's frozen source is unaffected.
The requested end state remains complete graphical/textual/API parity for
quantities, calculations and constraints, with preservation, checked persistence
and usable workflows. A private typed occurrence index is a dependency, not that
end state. Ordinary occurrence indexing, update composition, public source8,
structural editing, migration, UI and transport acceptance remain required.
## Current evidence and problem
- `language/analysis_source/mixed/project.rs:18` owns one admitted complete
Project, original `ParsedMixedSyntax`, warnings, static limits/usage, retained
expression/occurrence arenas and their aggregate storage ledger. Only Project
and warnings are exposed read-only. It does not provide an editing index.
- `language/analysis_source/mixed.rs:39` retains the exact borrowed SourceBundle,
caller ProjectLimits, canonical file table, full-buffer tokens, original typed
declarations and ordinary syntax positions. Numeric file keys belong to this
table; equal offsets in different files are unrelated locations.
- Existing typed-only `analysis_source/index.rs:122-243` owns names and occurrence/
expression maps but borrows a caller numeric source map. Its private builder
combines an ordinary Project with separate Lowered model maps. Feeding the
complete mixed Project into that path unchanged duplicates typed globals.
Its local map-size checks do not account for the retained mixed ledger.
- `analysis_source/update.rs` accepts the typed-only Index in its standalone
Plan and opaque Composition/OriginalEdits adapter. Those APIs do not establish
complete SourceBundle entry/path/profile authority for mixed input.
- Public `source_project.rs:93-117` exposes mutable bundle/model/index fields;
`update_bundle_with_identity_map` recompiles and compares all three before
editing (640 onward). Its ordinary collector applies edits, then runs the
structural updater, then recompiles and compares the complete intended Project
(868 onward). This later-coordinate structural pass cannot be relabeled as
original-coordinate mixed composition. That public contract is unchanged here.
## Accepted choice
Criteria are exact original ownership, complete semantic coverage within the
declared index scope, aggregate resource accounting, compatibility and avoiding
two divergent implementations of structural verification.
| Candidate | Evidence / tradeoff |
| --- | --- |
| Shared private verification/maps with distinct provenance wrappers | Reuses the existing structural-path, token, owner and call-label checks. Requires explicit source/declaration/site views and storage reservations. Preferred if the extraction remains small and typed-only behavior is preserved. |
| Separate copy of the typed index for mixed input | Simpler initial access to mixed fields, but duplicates the nontrivial syntax-edge and call-label verifier and would need every later correction twice. Reject unless extraction exposes a concrete incompatible invariant. |
| Reparse mixed fragments into the old numeric-map Index | Loses complete bundle/profile authority, repeats accounting and can lose original coordinates. Reject. No substring, masked-source or canonicalized bridge. |
Adopt the first candidate with the consumed mixed wrapper below. The critique's
two findings are resolved here: storage domains are fixed by the existing
contract, and reference completeness is distinguished from runtime expression
verification. Revisit only for a demonstrated incompatible verifier invariant
or a concrete requirement for multiple independently retained index owners.
Do not add a public generic indexing framework. Shared helpers may consume
private borrowed inputs only inside the authenticated constructors. There must
be no public or sibling-callable API that treats arbitrary Lowered sites and
caller-replaced token/location maps as an authenticated mixed index.
## Ownership and construction invariant
The proposed mixed constructor consumes `ResolvedMixedProject<'s>` and returns
an opaque `IndexedMixedProject<'s>` owning that witness plus its index maps.
Names are illustrative API identifiers. The output borrows the original bundle
through its retained witness; it contains no self-references. Its read-only
views borrow the output. Construction either succeeds completely or returns
diagnostics with no usable partial index.
Consuming the witness prevents creating multiple independently retained indexes
while charging only one to its ledger. If a borrowed-construction alternative is
chosen, it must prove reservation lifetime/release and simultaneous-index bounds;
extra reservation lease machinery is not justified without a demonstrated need.
The mixed wrapper must not dereference/convert to the old Index or implement an
adapter accepted by old `Plan::renames`, `Plan::apply` or `Composition::renames`.
Read-only access to names/locations does not grant edit authority. A later
compositor must bind the full original entry, file set, canonical paths, bytes,
limits/profile and complete target, not merely compare touched file bytes.
Build from retained full-file tokens/declarations and the existing expression/
occurrence arenas without reparsing, lowering again or duplicating Project
records. Iterate typed declarations with their canonical numeric file keys;
do not clone them into old owned Units. Derive global names exactly once from
the complete Project, including project, definitions, elements, relations,
diagrams, placements, artifacts and traces. Add calculation parameters under
`(calculation_id, parameter_id)`; a parameter UUID reused by another calculation
or a global remains distinct. Parameter spelling is calculation scoped.
Reuse existing expression/occurrence key semantics: file-qualified locations,
owner, binding field, structural child path, token role and qualified target.
Headers and all typed reference roles must be included. Ordinary targets may
appear in the catalog and typed references, but this view does not invent an
ordinary declaration/reference occurrence index. Document that distinction in
the read-only API and tests.
Verify owner containment, UTF-8 source boundaries, exact token spelling and
token classification, uniqueness of physical token ownership and qualified
keys, parent-before-child/path/depth rules, and call-target/parameter-label
agreement. Check structural edges against retained authored syntax, not only
internally consistent arena claims. Keep file ownership when reporting errors;
use an explicit invariant-error location fallback when no one file is justified.
## Live storage and failure policy
Continue the retained ledger and Budget/profile; do not initialize a fresh
permissive budget or recharge original source/token/exact-number parsing.
Reserve checked aggregate additions before allocation, combining the existing
syntax/sites/warnings baseline with new retained maps and all live scratch.
The implementation must inventory names and owned name bytes, occurrence and
expression map entries, unique persistent Path nodes, and temporary owners,
physical locations, path lookup vector, call map, global/parameter spelling
lookups, syntax-site lookup and iterative walk slots. An Arc clone shares a path
node but still occupies its enclosing map/vector slot. No copied path vectors
are needed to construct keys. If `Project::identities()` is used, account for
its temporary Vec (`model.rs:1763`); a streaming traversal avoids that allocation.
Retained lowerer occurrences and newly retained occurrence-map entries coexist.
Preserve the preceding contract's dimensions: lowerer occurrence records retain
their occurrence-slot reservations; new index map/vector/set entries and unique
Path nodes consume entry slots. Separately owned names consume text bytes.
Both representations count once in their respective domains; neither record
is charged twice merely because it is called an occurrence. Do not reset or
release the old arena's reservation while its vectors remain live. Release scratch reservations only
after the corresponding allocations are dropped. Preserve prior logical-slot
scope: this is not an allocator-capacity/RSS or raw model/validator-heap bound.
For the current three-map design let G be complete global-plus-scoped names,
H typed declaration headers, O retained lowerer occurrences, E expression sites,
and P nonroot expression sites. Added retained storage is entry slots
`G + (H + O) + E + P`, occurrence slots zero, and text bytes the sum of copied
names' UTF-8 lengths. The prior baseline still contains E raw expression entries
and O occurrence slots. One Path Step is allocated per nonroot expression; any
additional retained representation requires an explicit additional reservation.
Peak scratch additionally includes owner map H, physical-token set H+O,
arena-position/path/depth vector E, call-site map C, borrowed reverse-name maps
G, syntax-site lookup E and live iterative walk slots W. Count any allocated
file/declaration adapter table too. Drop owners/physical tokens after occurrence
validation, and paths/calls after argument-child validation before syntax-edge
work where possible; otherwise sum their overlapping reservations. A popped
work item releases one logical slot. The scalar visited count consumes no
allocated entry per visited node. Path-node reservations survive dropping the
temporary vector while retained map keys still share those nodes.
Budget errors abort construction. Existing depth checks may update deepest-frame
usage; this is not reparsing or Exact-work recharge. Warning retention and prior static admission
metadata stay unchanged. Neither indexing nor failure recovery repeats complete
model admission or constructs replacement source. Rejection and destruction must
retain the existing bounded-stack policy; no production depth128 enablement is
implied by a narrow private test.
## Required evaluators before implementation acceptance
The [independently enumerated rich-fixture oracle](analysis-mixed-index-20260924/ORACLE.md)
provides concrete names, keys, spans and retained-storage totals. Parent raw-byte
verification passes all 36 original and 36 transformed Unicode/CRLF spans using
the adjacent `check_oracle_bytes.py`, without running the parser, lowerer, index
or compiler. This validates the test data's byte arithmetic, not implementation.
1. Hand-enumerated OA and SA mixed bundles: entire name catalog plus every typed
declaration/reference/expression key, full-file span and spelling. Include
interleaved ordinary declarations, cross-file references in both semantic
directions, Unicode/CRLF and coincident offsets. The expected index must not
be generated by the builder, formatter or lowerer under test.
2. Reuse the complete-Project repeated/reordered-call fixture with shared
parameter UUIDs in distinct calculations; compare all qualified labels and
structural paths, including repeated identical expression text.
3. Internal corruption controls: swapped file ownership, wrong owner/field,
parent cycle/forward edge, structurally wrong but internally consistent child,
duplicate physical token, missing/extra expression, duplicate occurrence,
wrong call label/target, missing required argument label, and wrong token
classification/spelling. Every control must reach its intended existing
structural/token check rather than an unrelated earlier parse refusal.
Complete reference occurrence emission remains an invariant of the sealed
lowerer, tested by the independent exhaustive oracles in items 1 and 2.
The existing syntax-edge checker verifies the expression arena; it does not
prove all parameter-declaration or non-expression type-reference occurrences
are present. Do not claim arbitrary omitted occurrences are runtime-rejected
or introduce an unreviewed duplicate full syntax-reference verifier.
4. Hand-counted live-storage cap and cap-minus-one cases: retained baseline plus
names/paths/maps, peak overlapping scratch, copied-name bytes, and simultaneous
occurrence representations. Check unchanged parse/numeric counters and exact
intended refusal phase; no success by clearing the baseline.
5. Read-only provenance and lifecycle: exact entry/path/file/byte retention,
unchanged whole Project/warnings/admission metadata, no old-updater-compatible
conversion, and no usable failed result. Exercise complete success/drop and
representative late rejection/drop on the existing small-stack harness.
6. Existing typed-only index/update/export tests and full inherited compatibility
dispositions must remain accounted for after shared-helper extraction.
Strict core Clippy and current-source checks remain required. Private full
library source8 failures are not to be suppressed or called passed.
After this dependency, integrate real ordinary and typed original-coordinate
edit producers, combined preflight/emission, output recompile/admission and
whole intended-Project equality. Extend to structural edits, identity changes,
missing-ID stabilization and checked-save/history before claiming the required
editing parity. This proposal does not authorize a smaller final product.