Files
ARCADIA-Studio/harness/analysis-public-read-design-20260925/IMPLEMENTATION-MAP.md
T

263 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Public mixed read: bounded implementation map
Proposal only, source `0c07f53ab517626f536f79dbaa2885a587bf1db7` inspected read-only.
No production changes, compiler invocation or acceptance claim. Parent's ordinary
compatibility gates remain authoritative. Paths below are repository-relative to
that private source commit. This proposal needs independent critique and selection.
## Smallest coherent next outcome
Provide an explicitly separate public **complete-bundle, read-only mixed checker**.
It serves host applications/automation that already own source documents and can
validate typed calculations alongside ordinary architecture without formatting or
building an incomplete edit index. Do not silently replace ordinary `parse`,
`compile_bundle`, or CLI `prepare(Check)` with this path.
Suggested surface in a small `source_project`-adjacent public module:
```rust
pub fn check_mixed_bundle<'s>(
source: &'s SourceBundle,
limits: ProjectLimits,
) -> Result<CheckedMixed<'s>, Vec<SourceDiagnostic>>;
pub struct CheckedMixed<'s> { /* private resolved witness */ }
impl CheckedMixed<'_> {
pub fn project(&self) -> &Project;
pub fn warnings(&self) -> &[SourceDiagnostic];
}
```
The wrapper contains `ResolvedMixedProject<'s>` directly; no cloned Project,
self-reference, second desired lifetime, trait framework, or duplicated policy.
It is not Clone and supplies no mutable model, into_project, index, formatter,
save or update conversion. Borrowed immutable source cannot change/drop while the
result lives. The result owns its parsed/model/diagnostic auxiliaries and drops
them normally; source bundle remains caller-owned. Holding a full resolved witness
costs more retained auxiliary memory than moving only the model; it is the smallest
honest authority with existing cleanup and ledger semantics. Later extraction is
an independent lifecycle design, not required for read-only checking.
A caller can explicitly clone a public Project and misuse an unrelated formatter;
Rust cannot prevent that through an immutable accessor. Documentation must state
that this result grants validation only and does not qualify legacy source save.
## Actual code seams and invariants
- `language.rs:8` currently gates the whole analysis_source module under cfg(test).
Parser's mixed field and hooks are separately gated at1218–1753. Activating only
the root module is insufficient. Inventory and enable the required parser hooks
coherently, retaining None for every existing ordinary caller (483/919).
- `language/analysis_source.rs:3–13` includes index/update/write as well as parsing;
`mixed/project.rs:25` links ordinary_index and carried.rs:5 links PendingRename.
Do not expose or ship all edit machinery merely to silence unused-code warnings.
Audit the minimal production dependency cone; cfg-gate edit-only items or narrow
module wiring, preserving their existing test build. This is actual required
integration work, not an assumption that private tests already compile publicly.
- `mixed.rs:279–308` derives source8 Limits from ProjectLimits then invokes legacy
phase parsing. That route does NOT select both producer checks. Prefer a narrow
internally constructed borrowed C=0 CarriedInput selecting
`carried::parse_entry_producers` (carried.rs:153–168), then project::resolve.
The Borrowed backing already binds bundle/policy (carried.rs:21–26); its existing
constructors are fixture-only. A production constructor must derive policy from
the same bundle/ProjectLimits call, not accept arbitrary Slots/profile authority.
- Exact ProjectLimits survive; source8 internal Limits are derived once using the
existing source8 profile, including caller byte/reference restrictions. No policy
resets between parse and resolve. C=0 excludes externally owned source strings;
U/M and retained text producer checks stay active, plus resolver accounting once.
This explicitly stronger new route may refuse earlier than legacy phase checks;
it must not alter existing ordinary/text-only/phase entry-point acceptance.
- `mixed/project.rs:453` consumes syntax and seeds its ledger from guard slots once;
complete construction/lowering follows;596–665 performs complete validation,
mapped diagnostics and warnings. No typed-only Index, ordinary-index phase,
RenamePlan, PendingRename, equality-to-desired, or AcceptedRename is needed for
fresh read-only source admission. Those are output-edit lifecycle authorities.
- Preserve canonical complete-bundle validation, original byte spans, Unicode
columns, include ownership, full validation/admission, and warnings in order.
Return existing Failure.diagnostics on rejection; never convert errors to warnings
or return a model alongside a failed admission. On success warnings are non-errors.
No migration is implied: mixed entry requires8; ordinary3–7 callers retain their
separate migration path. Explicit UUIDs are required for the project, every
ordinary/typed declaration and every typed parameter: missing IDs are errors,
never generated or stabilized (language.rs:1295; mixed.rs:252). Detached supplied
files are rejected by Traversal::finish (traversal.rs:185–200; mixed.rs:503).
## Why existing CLI check is not a free consumer
`oa-cli/src/lib.rs:213–310` loads DiskProject, lints ordinary raw text, performs
ordinary declaration analysis and compile_bundle, even for Operation::Check.
Prepared (175ff) retains a save-capable compiled result. Reusing that pipeline
would reject typed input before the new checker, or falsely manufacture an index.
`source_files.rs:329` calls discover_missing;495 calls inspect_includes,529 compiles
ordinary reachable source. `source_project.rs:207–245` inspect_includes invokes
ordinary language::parse_unit. Valid mixed files therefore cannot currently use
that loader unchanged. Preserve path containment, include budgets, encoding,
physical aliases, missing files and interrupted-save handling; do not bypass these
by recursively scanning include strings or silently filtering parse failures.
If an actual executable consumer is required in the same milestone, choose a
separate read-only `check-mixed` operation with no Prepared/save authority, plus
an explicitly selected mixed include-inspection/discovery adapter using the shared
parser. This is larger than the core bundle checker and requires its own finite
file-system contract. Do not claim the existing loader already solves discovery.
An explicit manifest of all files could avoid parser discovery, but adds a new
user workflow/format for little value; reject it absent a real caller need.
Full compile_bundle adoption is substantially larger: `source_project.rs:111,287`
returns stable source/index authority used by update/save. It needs typed identity
stabilization, complete SourceIndex/update semantics, complete formatter coverage,
loader integration, and downstream caller review. Read-only validation does not
need these dependencies and should not hold that useful slice hostage to them.
## Finite acceptance and exclusions
1. External, non-cfg(test) consumer checks exact rich OA and SA multi-file literals;
assert independently authored complete Project and every mapped warning. Same
source bytes/maps remain identical, no UUID insertion/migration/formatter path.
2. Include Unicode/CRLF diagnostics, forward references/scoped parameter collisions,
typed wrong-kind/unresolved/error cases, malformed syntax, missing/cyclic includes,
noncanonical paths and detached-file policy exactly as existing mixed contract.
3. Ordinary8-only complete models agree with public ordinary semantics for explicit
IDs; legacy public3–7 migration and ordinary8 six-test roundtrips remain unchanged.
Both long analysis constructors and malformed typed syntax retain intended errors.
4. Exercise inherited source/file/edge/depth/final-model restrictions and selected
strong producer exact caps using C=0 expectations, not pending O-based152/151
numbers. Logical auxiliary entries/text are not an allheap/RSS promise; existing
model/serde/raw validator exclusions and numeric policy remain explicit.
5. Borrow/lifetime compile checks prevent escaping result after source dies; scoped
success/failure destruction controls and existing small-stack suite unchanged.
Audit stack prologues if public wiring changes frames. DEPTH_128_VALIDATED stays
false; user-deferred Linux and unresolved full-pipeline limitations are not waived.
6. If CLI included: actual non-test executable, real three-file mixed fixture,
exact report diagnostics/exit codes, unchanged directory and file bytes, and
explicit refusal of write/rename/stabilize flags. No accepted save artifact.
Decision required: core read-only bundle API first (recommended minimal useful
slice) versus adding disk discovery/CLI consumer immediately. Select explicit new
strong C=0 producer policy and production cfg cone before implementation. No public
editing, repeated-owned adoption, output formatting or universal heap instrumentation
is a prerequisite for the recommended core slice.
## Item-level production wiring refinement
This is a proposed bounded wiring plan, not permission for blanket dead_code
suppression or wider public visibility. Line references remain source0c07.
| Item | Production read requirement / proposed treatment |
| --- | --- |
| language::analysis_source root and Parser mixed hooks | Compile privately in production; preserve ordinary None paths. Mixed selection remains constructor-controlled. |
| analysis_source budget, cursor, declarations, lex, lower, syntax, mixed | Required shared parse/lower dependency cone; keep private. |
| analysis_source index, update, write; model_oracle | Gate entire modules cfg(test) for this milestone. Existing private edit tests still compile their complete chain. |
| analysis_source::parse standalone expression wrapper (analysis_source.rs:107) | Test-only; real mixed parser uses syntax::binding through declarations. Gate wrapper, not shared Binding/Expression types. |
| lower::Unit, lower::lower (lower.rs:273), Tables::ordinary | Legacy typed-only adapter; gate these items cfg(test). Keep Tables, insert, typed, lower_bodies and actual lowering representation in production. |
| mixed::parse / parse_with_profile | Existing phase-only fixtures/tests: cfg(test) wrappers; keep parse_impl shared. Factor the unchanged source8 policy derivation into a small private helper reused by new borrowed constructor and old fixture wrapper. |
| carried SnapshotPolicy, CarriedInput, CarriedGuard | Required; only borrowed source authority is production in this slice. Policies transfer into existing Budget and ParsedMixedSyntax once. |
| carried PendingRename import, SnapshotBacking::Pending, GuardBacking::Pending, from_pending and corresponding match arms | cfg(test): private emitter/acceptance remains a tested internal dependency, not public read's production dependency. |
| carried RetainedSnapshot type, both Retained variants and corresponding match arms | cfg(test): only fixture construction owns this snapshot. Keep existing fixture methods/modules gated. |
| carried Borrowed variant, into_parts, guard slots/check, parse_entry_producers | Production: actual constructor derives policy from ProjectLimits and borrows actual complete bundle; slots returns zero. Do not flatten Some(Borrowed) into None. |
| carried parse_carried / parse_text_producers | Test-only historical phase/text-only entry paths. No extra production entry-point that bypasses selected strong mode. |
| mixed/project ordinary_index module | cfg(test), retaining complete rename/emission/acceptance tests unchanged. |
| IndexedMixedProject, ResolvedMixedProject::index, its impl/accessors; IndexInput and impl; Failure::index | cfg(test). Failure::typed/ordinary and mapped diagnostics remain production. |
| ResolvedMixedProject project/warnings | Required accessors used by public read wrapper. |
| ResolvedMixedProject syntax, expressions, occurrences, storage | Keep all real ownership and ledger retention in production: they back accounted auxiliaries even though read consumers do not inspect them. Do not drop early just to remove warnings or invent reads. |
| ResolvedMixedProject static_limits/static_usage | Immutable admission evidence already computed by resolve; choose retaining it with precise field-level explanation rather than public methods just for lint. Admission itself is always executed. |
Some shared lower representation fields are produced for retained expression/
occurrence evidence and read only by cfg(test) index. Implementation must inspect
actual production lint output item-by-item rather than turn off lint for lower.rs.
Prefer cfg(test) on truly test-only methods; for ownership/evidence fields that
must survive, a **field-level** cfg_attr(not(test), allow(dead_code), with a nearby
reason identifying the retained allocation/evidence) is justified. Do not apply
this to entire structs/modules or change the represented storage inventory. A
private retained-owner substruct with underscore ownership field is an alternative,
but would require touching existing destructures/test access for no runtime value;
prefer narrowly documented existing fields. No fake runtime reads/assertions or
public accessors solely to placate lint. Exact surviving field list is compiler-
verified during implementation, not a promise source inspection caught every lint.
### Opaque wrapper placement and privacy
Place public CheckedMixed in `mixed/project.rs`, beside the only constructor that
can obtain ResolvedMixedProject, with private field `resolved`. Its constructor
accepts source+ProjectLimits, calls the selected strong private parse route and
resolve, and maps Failure.diagnostics. Public project/warnings methods delegate.
`CheckedMixed` is public as a type but its underlying module remains private;
re-export only this type and the checker function through analysis_source then
language (`pub use ...`). Offer the canonical user-facing path
`language::check_mixed_bundle` / `language::CheckedMixed`; this avoids making
analysis_source/mixed/project modules public or widening ResolvedMixedProject.
Reexports through private module ancestors are legal when the final exported type
itself is pub; no public signature mentions a private ledger/syntax/guard type.
Do not simultaneously publish duplicate source_project aliases without caller need.
This chooses concrete placement over the original tentative adjacent-module wording.
Production API is read-only and borrow-bound, with explicit IDs for every project,
ordinary declaration, typed declaration and typed parameter. Finite negative tests
must independently remove each class's UUID, not merely one project UUID. A supplied
unreachable file is an error even when syntactically valid; no ignored detached
payloads. Non-test integration tests exercise the exported path and strong producer
checks; unit cfg(test) tests alone cannot establish public wiring correctness.
## Public policy and finite mode evidence (final bounded question)
Preserve exactly `Limits::source8(ParseLimits { max_source_bytes:
limits.model.max_source_bytes, max_step_references:
limits.model.max_step_references, ..ParseLimits::UNLIMITED })`.
Budget.rs:16–26 therefore derives bytes=min(caller bytes,64MiB),
tokens=min(bytes,1,048,576), entries=262,144 (NOT caller max_records),
references=min(caller references,500,000), frames256 and numeric work50,000,000.
The separate original ProjectLimits.model still enforces actual final graph/record
admission. No new public numeric profile or arbitrary carried baseline knob.
A proportionate evidence set is:
1. **Actual production constructor selection (private observation, real route).**
Construct from the same public-input bundle and ProjectLimits, invoke exactly
the production strong parse helper used by check_mixed_bundle, and observe
`carried=Some(Borrowed)` with slots0, producer_text Some((T,0)),
producer_entries Some(metadata). Inspect every derived limit including entries
=262144 while caller max_records is deliberately small but sufficient for the
fixture. Compare complete model/warnings, Usage and numeric work with the old
zero-carry reference on the same explicit-ID OA/SA fixture. No mutation/reset,
second policy argument, fabricated owner or public instrumentation accessor.
The external integration test calls the actual exported checker; the private
observation is narrowly labeled wiring evidence, not an independently observed
external producer refusal.
2. **Public input-byte boundary.** Minimal explicit-ID E source is78 bytes. Public
caller max_source_bytes78 accepts that input if later full admission fits;
77 refuses input before Traversal, with `invalid_source` and
`Source8 index/output byte limit exceeded.` at main0..1 (corrected by the
independent acceptance review). E's C0 grammar UUID
overlap is only44 (=alias1+name7+UUID36), scanner36 and retained text8. Thus a
hypothetical44/43 producer boundary is unreachable through this public policy:
both reject the78-byte input earlier. Pending output's152/151 includes carried
owned-output bytes and is categorically inapplicable here. Likewise the escaped
fixture's existing C0 producer peak must be compared with its source length;
do not transplant owned-C491/490 as public checker evidence.
3. **Public include policy.** Use the already authored explicit-ID three-file chain
for exact max_files3/2, include edges2/1 and its actual include-depth definition
(count entry root per Traversal, not an invented number). Pin path/span/error
order from existing implementation. Reuse full bundle expected model/warnings;
original complete bytes unchanged. This tests public policy, not entry262144.
4. **Final-record/graph and reference policy.** A small independently authored
valid typed+ordinary model exercises exact final-record and graph counts versus
one less; a real reference-bearing typed fixture exercises declared reference
limit. Counts must distinguish authored source-reference work from final model
ordered-step admission, both constrained through the same caller setting.
Do not assume setting max_records13 sets syntax entry cap13: it does not.
5. **Selected-mode mechanisms are already separately discriminated.** Existing
carried/entry_producer.rs zero-C11/12 and prefix owner/value refusal controls,
text_producer.rs zero-C inventory/phase parity, checked arithmetic and scanner
ordering remain unchanged. Add only the actual production-constructor bridge
above, not duplicate all those profiles through an unsupported public knob.
Keep existing explicit frame/depth controls and add external refusal coverage
at supported policy limits without implying depth128 platform qualification.
The public byte policy masks the independently derived producer boundary for the
minimal E and existing small examples; this is a concrete ordering fact, not a
proof that every possible valid multi-file input has auxiliary text <= source.
Repeated owned key copies can make other inventories larger. Finding a genuinely
producer-dominant *valid* public fixture could later strengthen external evidence,
but is not a reason to fabricate an input profile or block the bounded constructor
selection + existing mechanism + external policy tests. If such a fixture is used,
handderive its peak, verify earlier source/UUID/scanner/catalog phases fit and
assert exact refusal site before claiming independent producer-cap isolation.