Files
ARCADIA-Studio/harness/experiments/analysis-source-s2b-windows-20260913/archive/evidence/.local/analysis-source8-s2b-handoff-20260913.md
T

19 KiB

Source8 S2b typed lowering checkpoint

2026-09-13, Codex-956atf /root/source8_lowering_plan. Latest commit a2a28f8d23a46ba1696b6a8410d4d3b5c1808f49, branch codex/analysis-s2-956atf-20260913, worktree .local/as2-20260913, initial S2b commit 6de3b53103bf6199bf36aec2c1afb180eb9e7e6d above S2a base b2c970b4673e062e47eadd12906d2316c4b1a7b3. Source is committed, clean and frozen for parent review/gates. This worker did not run Cargo, a compiler, executable tests, native UI or Gitea. Parent owns serialized executable gates and integration.

This is the authorized first private typed resolution/lowering checkpoint, before canonical writing. The parent accepted the boundary in agent coordination: typed units plus a separately supplied ordinary Project skeleton, complete global/category/signature collection, then typed resolution, with one existing semantic admission on the merged Project. This is not complete public source8 parsing or include admission. Public header8 remains rejected and analysis_source remains staged under the existing test-only module registration. No new public test API exists.

Baseline and source scope

Parent-reported prior b2 executable evidence: 129-test listing, 21 typed syntax plus one raw-token test PASS, full 113 PASS / 16 pre-existing unsupported-source8 failures, strict all-target gate PASS at 05:32:11, 524 unchanged admitted inputs. These are prior S2a facts; they do not validate the new S2b code.

Nine changed files, 2196 insertions / 1 deletion:

  • crates/oa-core/src/language/analysis_source.rs: add private lower module and update the staging comment.
  • .../analysis_source/budget.rs: read-only lowering entry and occurrence allocation bounds. Existing syntax/literal counters and limits remain unchanged.
  • New .../analysis_source/lower.rs: model construction, complete category/signature collection, typed resolution, iterative lowering of all 13 Expr variants, original source occurrence and expression-site metadata.
  • New .../analysis_source/lower/tests.rs: 13 authored tests listed below.
  • New .../analysis_source/lower/oracle.rs: independently constructed real Project oracle; no source parsing or formatting.
  • Four new source fixtures under .../analysis_source/lower/fixtures/: ordinary-oa.arcadia, ordinary-sa.arcadia, typed-oa.arcadia, typed-sa.arcadia.

No changes to the S2a scanner/cursor/declaration grammar, language.rs, production DeclKind, source_project, persistence, model, analysis semantics or source3 bridge/module hooks. There was no declaration-parser ambiguity requiring a grammar correction. The original analysis worktree was never edited by this contribution.

Frozen interface

All names below remain private to the staged language module.

lower::lower(ordinary: &Project, units: &[Unit], budget: &Budget) -> Result<Lowered, Failure>:

  • Unit { file: usize, declarations: Vec<declarations::Declaration> } holds already parsed typed roots. file is caller-assigned and unique for this lowering pass. Spans remain original offsets in that file. Caller owns the syntax and can retain every S2a header, field, literal, identity-insertion, parameter and override span after lowering.
  • All units are collected before any body resolves. The global table includes project, elements with actual kind/layer, relations, diagrams, node placements, artifact links, traces, quantity kinds, units and calculations. Global aliases and IDs share one uniqueness domain.
  • The signature table maps calculation ID to parameter name/ParameterId. Collection checks names and IDs only within each owning calculation. The same ParameterId is legal in different calculations and may equal a global UUID. Scoped IDs never enter the global uniqueness map.
  • Missing declaration or parameter IDs return a located stabilization-required error. Syntax remains unchanged with its existing insertion metadata. No UUID is generated and no supplied source/model is mutated. S3/S4 must assign and insert IDs once, then reparse actual stabilized bytes before invoking this lowerer.
  • Lowered { definitions, elements, occurrences, expressions } returns typed additions only. These are real analysis::Definition and Element/ElementBody::shared_in records with original alias, display name, description, layer, required fields, ordered parameters and exact typed bindings. The ordinary skeleton is not cloned into the result.
  • Failure { file: Option<usize>, error: analysis_source::Error } locates typed errors to their unit and original token span. file: None identifies a problem in the separately supplied ordinary skeleton or already-failed inherited Budget, before typed resolution. S3 will map ordinary-skeleton errors through its ordinary declaration/index context; this checkpoint cannot invent an original source span for a caller-created Project.

Typed domains distinguish kind/unit/calculation/property/architectural subject/constraint references and call argument labels. $name resolves only against the owning calculation body. Argument labels resolve against the called calculation; values retain the caller's scope. Wrong-domain and unknown-name failures retain the original alias/name token span.

There is no independent static typechecker. Missing call arguments, type compatibility, pure-calculation rules, layer rules, semantic cycles and complete architectural validity remain in the existing analysis::admit implementation. The complete test caller merges the additions and invokes that admission once. Parsing the separate ordinary source fixture uses its existing legacy path; it does not exercise unresolved mixed ordinary/typed forward fields or the future combined source8 admission path.

S3 occurrence and path contract

Occurrence contains original file, owning declaration owner, typed Field, optional expression-site index, Role, resolved Target and alias/name-only span. Target is explicitly either Global(Id) or Parameter { calculation, parameter }.

Fields distinguish algebra, unit kind, parameter input keyed by ParameterId, result, body, subject, property type/base/display unit, documented constraint, predicate and case override keyed by property ID. Roles distinguish ordinary typed reference, parameter declaration/use, call target, argument label and override target. Header declarations and whole-field/literal spans remain available from the caller-retained S2a syntax.

Every expression node has an ExpressionSite { file, owner, field, parent, span }. parent is an optional (arena_index, Child) edge. Children distinguish list index, unary operand, binary sides, conditional branches, call argument ParameterId, sum operands, power base and as-kind value. This parent-linked arena uses linear metadata storage and avoids allocating a full depth-sized path per node.

Arena indexes are local to a lowering result, not persistent identities. S3 derives a stable owner/field/path by following parent edges. An argument-label occurrence at a call site therefore has the required qualified identity (owning declaration, binding field including override target, call-site path, called calculation, ParameterId). Repeated calls to the same calculation remain distinct; authored argument order is preserved in syntax and reference spans, while the model's argument map is correctly keyed by ParameterId. Reordering authored labels does not change the child identity.

Global Reidentify must continue using Target::Global and existing typed model visitors; it must not rewrite a scoped parameter because UUID bytes coincide. Parameter rename/update must compose all edits from original spans before applying them, including both repeated call sites. This lowerer supplies metadata but does not implement source updates or their conflict/revision rules.

Work and allocation bounds

The lowerer never invokes the scanner, reparses descendants, reconverts Exact literals or charges a reference/literal twice. Tests compare the inherited syntax Usage and numeric work before/after lowering and repeated lowering. Original Exact values are cloned into the real model without numeric normalization work.

Budget::lowering_entries checks phase allocations against the inherited entry ceiling without charging syntax again. Table reservations aggregate ordinary globals, typed globals and scoped signature entries. File-key sets, output expression sites, pending work, parameter/argument/override collections and value stacks are bounded before growth. The number of output records is bounded by the already collected global table. lowering_occurrences bounds source-reference metadata plus parameter declarations (the latter are syntax entries rather than reference uses). Duplicate global/signature attempts are bounded before insertion.

The S2a parse session is still the owner of bytes, tokens, entries, reference occurrences, syntax frames and Exact WorkMeter. S4 must thread that one owner through ordinary and typed parsing and include expansion. The separately parsed ordinary fixtures do not prove combined source8 transport limits or include admission. This checkpoint adds no generic session, additional lexer or public policy switch.

Authored acceptance tests (all unrun)

Prefix language::analysis_source::lower::tests:::

  1. staged_oa_and_sa_lowering_match_complete_independent_17_uuid_oracles: fixed OA r2 17 UUIDs/14 display names and separately constructed SA twin with fresh global IDs; explicit name assertions precede whole-Project equality; actual typed additions admitted once; repeated lowering produces identical occurrence/site metadata and unchanged shared work; public8 remains rejected.
  2. forward_cross_unit_resolution_keeps_original_offsets_and_shared_work: references in an earlier typed unit resolve to later definitions/signatures; reversing already parsed unit order preserves the full model; Unicode and CRLF spans remain original; one shared byte/token/numeric owner, no rescans.
  3. all_thirteen_expression_variants_lower_to_real_typed_values_and_admit: independently authored expected real Expr values for all 13 variants, including reversed authored call-argument order; each is installed into an appropriate complete Project binding and admitted once.
  4. call_sites_and_parameter_scopes_preserve_distinct_original_occurrences: four labels across two commented call sites remain four original spans; call-site paths distinguish left/right; reused parameter UUID/name belongs to two calculations; caller $a and callee label a resolve independently; a global kind UUID equals a scoped parameter UUID without collision.
  5. missing_ids_require_stabilization_without_uuid_or_budget_churn: missing global and parameter IDs retain insertion metadata, reproducible errors and unchanged syntax work across repeated lowering.
  6. duplicate_global_aliases_and_ids_fail_before_body_resolution: conflicts with ordinary records and repeated typed roots, including across distinct unit keys, fail during collection with the failing original file/span.
  7. typed_reference_domains_unknown_names_and_parameter_scope_fail_at_tokens: subject/type/display/literal-unit/property/call/argument/parameter/constraint/override negatives distinguish wrong domain from unknown symbol and assert exact token substrings.
  8. ordinary_non_element_categories_are_collected_and_never_property_fallbacks: actual ordinary project/relation/diagram/node/artifact/trace records enter their categories and fail property use; relation subject lowers to AnalysisSubject::Relation. Synthetic trace structure is not claimed to be a valid OA/SA model.
  9. structural_lowering_defers_type_purity_layer_and_argument_sets_to_admission: bad type, impure calculation, missing call argument, cross-layer property and dependency cycle lower structurally, then fail existing complete admission.
  10. lowering_phase_bounds_count_ordinary_globals_and_scoped_parameters_together: exact 0/16/17 boundaries count 15 global records plus two scoped parameters; guards do not recharge the syntax Budget.
  11. affine_kinds_optional_fields_list_signatures_and_unused_unbound_definitions_survive: forward affine-difference resolution, exact affine offset, ordered list signature, unused/unbound and zero-input calculations, optional none/subject/constraint fields and override identity survive into an admitted real Project.
  12. duplicate_file_keys_and_exhausted_shared_budget_cannot_enter_lowering: duplicate unit key and already-failed shared budget are rejected before typed body resolution.
  13. iterative_lowering_preserves_128_deep_and_1024_wide_accepted_expressions: actual iterative lowering of logical depth128 and list width1024, model traversal assertions and existing semantic admission. This is an authored source/internal model test, not a public JSON depth or native performance claim.

The oracle is hand-constructed from the r2 actual model structure with explicit display names. It does not reuse the old fixture unchanged, parse the expected model, invoke a writer or normalize away names. The authored typed source reverses neutral definition order to exercise forward resolution. Its ordinary OA/SA source is deliberately separate and remains explicitly version7; this staged fixture layout does not claim the full r2 source8 document can yet open.

Worker verification: rustfmt edition2024 with skip_children=true formatted/checks the five Rust files; staged git diff --check passed; source diff and relevant model/parser/admission interfaces were inspected. Source-only verification does not establish Rust type correctness or runtime behavior. All 13 new tests and combined strict gates are UNRUN at this handoff. No lint suppression was added.

Remaining work and gate ownership

Parent must obtain independent source review and compile/list/run the frozen checkpoint, including prior S0/S1/S2a/legacy guards and a combined strict gate. If a correction is needed, unfreeze only the assigned as2 worktree and create a new coherent pin; do not edit an active compiler input tree.

S2 canonical writer remains entirely outstanding: deterministic ordering of roots/definitions, explicit IDs and stable parameter Vec order, all required typed bodies/types and all 13 Expr forms, canonical exact formatting, parse/write equality and canonical text stability, plus a bounded subtree writer for S3. No writer or public save support is claimed here.

S3 still owns source indexes/update/stabilization integration, qualified parameter/call-site update identities, original-span transaction composition, collision handling, alias/parameter rename and source/model parity tests. It should consume the frozen metadata contract and retained syntax rather than derive references by text search.

S4/root still owns whole-document production parser dispatch, complete ordinary/typed collection across includes under one policy/Budget, exactly-once complete admission, source3 migration integration already prepared elsewhere, source version/migration/write guards, public8 exposure only after complete writer/index/update composition, and measured transport/performance/depth gates. Existing frozen legacy JSON envelopes and public depth switches are unchanged.

No further source writes will begin until parent direction after this checkpoint.

Narrow source-review correction

Independent critic /root/source8_s2a_review found that the initial 6de3b53103bf6199bf36aec2c1afb180eb9e7e6d call-site test used unsupported block comments. The accepted scanner grammar supports // line comments. Parent authorized only fixture correction, with no grammar expansion.

Correction 472fe7a4339a23a3339b2b91e8d53d76442f60c4 changes one line in lower/tests.rs: both call-site comments now use // first / // second followed by real source newlines. All four argument-label spans, two call-site paths, reversed authored argument order, scope/collision cases and original-span assertions remain unchanged. Production code is byte-identical to the initial S2b commit. Rustfmt and git diff --check passed; the worktree is clean and frozen. All 13 tests remain UNRUN. Critic follow-up source review of the correction is pending; no compiler, native, or public source8 acceptance is claimed.

Executable AsKind fixture finding and narrow repair

Parent executed frozen 472fe7a4339a23a3339b2b91e8d53d76442f60c4: actual listing 142 tests / 531 unchanged admitted inputs; focused language::analysis_source run closed 33 passed / 1 failed / 0 ignored. All twelve other new lowerer tests passed, including the OA/SA complete oracles, qualified scopes and logical depth128/list width1024. Receipt: .local/analysis-source-gates-20260913/typed-472fe7a.log and adjacent result artifacts. This supersedes the earlier unrun status only for that tested pin, not the correction below.

The sole failure was all_thirteen_expression_variants_lower_to_real_typed_values_and_admit, at its complete-model admit assertion: owner bd5b68e8-65fc-4e35-9071-a73061316a4b, field base, code analysis_type, “AsKind requires an anonymous matching dimension and a linear target”. The source fixture was as_kind(@duration, 1 [@second]); the independent expected Expr likewise wrapped a direct Quantity. That operand is already Named(Duration), so the failure is required semantic behavior, not a parser/lowerer defect.

Read-only diagnosis verified analysis/typecheck.rs delegates AsKind to NumericType::assertion_result; analysis_numeric/quantity.rs explicitly rejects Named input. Its power_result with exponent2 produces an anonymous squared time dimension; multiplicative_result dividing that by a named time quantity produces anonymous time. Multiplication/division by a Number would preserve a nominal operand and is therefore not a sufficient repair. Existing analysis/tests.rs::anonymous_dimension_algebra_and_affine_rules_share_pure_runtime_helpers already asserts named assertion rejection and anonymous matching-dimension acceptance.

Parent-authorized correction a2a28f8d23a46ba1696b6a8410d4d3b5c1808f49, directly above 472fe7a, changes only lower/tests.rs (19 insertions / 5 deletions): the positive source becomes as_kind(@duration, power(1 [@second], 2) / 1 [@second]), and the independently authored actual Expr oracle now explicitly contains the Power and Divide nodes. All 13 variant cases and every complete admission assertion remain. The original invalid AsKind-on-named-quantity form is retained as an additional row in structural_lowering_defers_type_purity_layer_and_argument_sets_to_admission.

No production, lowerer, model, semantic admission, scanner, parser, writer or public API changes. Rustfmt and whitespace checks passed. Source is committed, clean and frozen. The two changed tests and combined corrected pin remain UNRUN; eleven other new lowerer tests are unchanged from the parent's passing evidence. Existing critic /root/source8_s2a_review has received the immutable correction for independent source review. Parent owns reviewed integration and executable rechecks. Writer implementation has not begun.