Compare commits
77
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd95bd1f23 | ||
|
|
f810fb40eb | ||
|
|
d4d50f061b | ||
|
|
57f07c83c4 | ||
|
|
bcddaba399 | ||
|
|
e79645a0ec | ||
|
|
763e6d8256 | ||
|
|
69c784f204 | ||
|
|
fb9b0c5caa | ||
|
|
6690ed097e | ||
|
|
b86c8dbc40 | ||
|
|
154bcaf04d | ||
|
|
7a02333c4a | ||
|
|
d99e1a369d | ||
|
|
1783658723 | ||
|
|
d5b37f13fd | ||
|
|
b2ef3f5457 | ||
|
|
6c0d9e807c | ||
|
|
f130a365d5 | ||
|
|
1c2798b9b1 | ||
|
|
a2c7817734 | ||
|
|
81ab373f8e | ||
|
|
dc87babf0f | ||
|
|
852a79b566 | ||
|
|
76acfb1108 | ||
|
|
47f8d0f544 | ||
|
|
4aee179385 | ||
|
|
c599538ce1 | ||
|
|
7ffd08c41e | ||
|
|
2ee740c725 | ||
|
|
b16b9b15aa | ||
|
|
2040b453b8 | ||
|
|
18ae1822d1 | ||
|
|
1a6f2e4f9e | ||
|
|
25b2eeab14 | ||
|
|
b0030ab6f1 | ||
|
|
ae6df4fa1f | ||
|
|
7cfdd13d3a | ||
|
|
29e4f67206 | ||
|
|
a5496cd41d | ||
|
|
296fe71d19 | ||
|
|
c4f10716ac | ||
|
|
960b75a9ea | ||
|
|
2f9ce68a9e | ||
|
|
68b7ad6944 | ||
|
|
450b40a612 | ||
|
|
d4fce3a769 | ||
|
|
0f5f8fb727 | ||
|
|
c79708e550 | ||
|
|
be7470afca | ||
|
|
85cc27fed0 | ||
|
|
983061fa15 | ||
|
|
aecee2aff3 | ||
|
|
b17dfa5f58 | ||
|
|
2737127819 | ||
|
|
2e7c39965c | ||
|
|
f9c5165cb9 | ||
|
|
195ddbbba5 | ||
|
|
5960563b23 | ||
|
|
df4256cb2b | ||
|
|
1d56386708 | ||
|
|
c87a0c2bd9 | ||
|
|
cc3d6a4875 | ||
|
|
6a6cc83bc8 | ||
|
|
9f88938632 | ||
|
|
4ffff0d9d9 | ||
|
|
836f9e14e7 | ||
|
|
031c4dbdbb | ||
|
|
b278866e8c | ||
|
|
3733a657bb | ||
|
|
84434d55a0 | ||
|
|
f95d031048 | ||
|
|
8abc144cf2 | ||
|
|
9e51cd72ba | ||
|
|
3c22fe2629 | ||
|
|
cccd66c5d5 | ||
|
|
355f6d4d24 |
@@ -89,3 +89,5 @@ harness/experiments/analysis-source-s2a-windows-20260913/** -text whitespace=-bl
|
||||
|
||||
# Preserve the pinned Iced dependency bytes and upstream manifest.
|
||||
crates/vendor/iced_widget/** -text whitespace=cr-at-eol
|
||||
harness/experiments/analysis-mixed-syntax-20260923/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
harness/experiments/state-multiselect-delivery-audit-20260923/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
- Follow `PROJECT_GOAL.md` and the user's current instructions. Work autonomously within scope. Resolve discoverable questions yourself; record, test, and revise reversible assumptions. Ask only when a consequential decision needs information or authorization not already available. Continue independent useful work while blocked elsewhere.
|
||||
- Map unfamiliar domains through primary sources, comparable systems, and real user workflows. Identify underlying needs, valuable concepts, and avoidable friction; evaluate improvements rather than merely reproducing features. Synthesize findings into decisions or experiments, and stop research when another action offers greater value.
|
||||
- Make specifications precise enough for compatible independent implementations: definitions, relationships, invariants, valid/invalid examples, and lifecycle or transformation rules where relevant. Trace important requirements and decisions to implementation and verification. Resolve specification ambiguity at its source when implementation exposes it.
|
||||
- Make specifications precise enough for compatible independent implementations: definitions, relationships, invariants, valid / invalid examples, and lifecycle or transformation rules where relevant. Trace important requirements and decisions to implementation and verification. Resolve specification ambiguity at its source when implementation exposes it.
|
||||
- For consequential uncertain choices, compare materially different candidates against explicit user-derived criteria. Ask independent critics to challenge assumptions and attempt to falsify proposals; refine or replace candidates as evidence warrants. Record the choice, evidence, tradeoffs, rejected approaches, and reasons to revisit it. Use proportionate effort for reversible local choices.
|
||||
- Plan milestones that resolve uncertainty or deliver useful capability, with explicit dependencies. Test foundational assumptions before substantial downstream work. At checkpoints, assess progress toward the actual objective and replan when evidence invalidates the strategy or progress stalls.
|
||||
- Define observable success and suitable evaluators before repeated improvement: invariants, examples, round trips, transformations, performance checks, realistic user tasks, or explicit review rubrics. Ensure the evaluator measures the intended outcome. For experiments, record the question, expectations, method, result, and implications; isolate exploratory prototypes from production architecture.
|
||||
- Build and run meaningful changes, exercise actual behavior, and inspect useful logs. Investigate crashes, serious warnings, corrupted state, and interaction defects. For GUI work, use Computer Use or equivalent tools to inspect realistic workflows, cognitive load, editing/selection, navigation, feedback, recovery, loading/empty/failure states, accessibility, layout, focus/disabled states, and responsiveness.
|
||||
- Match independent reviews to the artifact and risks. For languages or formats, include ambiguity, round trips, human/AI editability, and version-control behavior where relevant. Verify findings, fix the appropriate conceptual, specification, architectural, implementation, or interaction layer, and recheck affected dependents. Reuse valid evidence; repeat checks for concrete risks, changes, findings, or required gates. Compilation, screenshots, and worker reports alone do not establish correctness or usability.
|
||||
- Build and run meaningful changes, exercise actual behavior, and inspect useful logs. Investigate crashes, serious warnings, corrupted state, and interaction defects. For GUI work, use Computer Use or equivalent tools to inspect realistic workflows, cognitive load, editing / selection, navigation, feedback, recovery, loading / empty / failure states, accessibility, layout, focus / disabled states, and responsiveness.
|
||||
- Match independent reviews to the artifact and risks. For languages or formats, include ambiguity, round trips, human / AI editability, and version-control behavior where relevant. Verify findings, fix the appropriate conceptual, specification, architectural, implementation, or interaction layer, and recheck affected dependents. Reuse valid evidence; repeat checks for concrete risks, changes, findings, or required gates. Compilation, screenshots, and worker reports alone do not establish correctness or usability.
|
||||
- Favor the simplest maintainable design satisfying known requirements and justified extensibility. Avoid speculative abstraction, unrelated refactoring, and repeating approaches already invalidated by evidence.
|
||||
|
||||
## User input
|
||||
@@ -24,10 +24,10 @@ Keep one authoritative home for each kind of information. Use links and brief sc
|
||||
|
||||
| Information | Authoritative home |
|
||||
| --- | --- |
|
||||
| Live plans, priorities, dependencies, ownership, status, blockers, and handoffs | Gitea issues/milestones; linked PRs hold change review and validation. |
|
||||
| Specifications, architecture, interfaces, and build/run documentation | Established version-controlled project documents. |
|
||||
| Live plans, priorities, dependencies, ownership, status, blockers, and handoffs | Gitea issues / milestones; linked PRs hold change review and validation. |
|
||||
| Specifications, architecture, interfaces, and build / run documentation | Established version-controlled project documents. |
|
||||
| Durable decisions and reusable evidence | `harness/DECISIONS.md` and relevant topic notes, or existing equivalents. |
|
||||
| Navigation and integrated-state checkpoint | `harness/STATE.md`: links, verified code commit/release, capabilities, and material limitations. No live task ledger. |
|
||||
| Navigation and integrated-state checkpoint | `harness/STATE.md`: links, verified code commit / release, capabilities, and material limitations. No live task ledger. |
|
||||
| Shared entrypoint | Gitea Wiki: overview and links, without duplicating versioned documentation. |
|
||||
| Published deliverables | Gitea releases, tied to source commits and verification. |
|
||||
|
||||
@@ -38,9 +38,9 @@ Use Gitea for live coordination and the relevant code version for implementation
|
||||
All independent agents coordinating through Gitea run on completely separate machines, each with its own clone, filesystem, tools, processes, and runtime. Gitea and pushed Git history are the shared communication and delivery channels. Local files (including `harness`), unpushed commits, worktrees, test results, and localhost services are not accessible to peers. Matching branch names or paths do not imply synchronized contents.
|
||||
|
||||
1. On starting or resuming, including after compaction, inspect the working branch, local changes, applicable instructions, relevant shared records, and existing implementation. Recover context from authoritative records. Check for newer shared instructions on the actual remote default branch without overwriting local work. Read what is relevant; avoid repeated full-history scans and constant polling.
|
||||
2. Search before creating tasks. Claim a meaningful outcome in its Gitea issue with a stable session identity, scope, remote repository/branch, and acceptance criteria. Keep small steps within that task. Recheck after claiming; comments are not atomic locks. Respect existing ownership and resolve overlapping claims before overlapping work.
|
||||
3. Independent sessions are peers. Each owns its contribution and delegated work on its own machine. Record one integration/release owner when a milestone needs shared coordination. Use distinct remote work branches, partition files/interfaces, and coordinate changes to shared specifications and documents. Worktrees provide local isolation only; they do not share work between machines.
|
||||
4. At meaningful checkpoints or handoffs, record changed results, commit/PR links, verification commands and environment, blockers, and next actions. Identify the tested code version and label uncommitted or unpublished work as local-only. Before asking peers to consume results, push the required code and versioned documentation, including relevant `harness` updates; publish other required artifacts in Gitea and link them. Use repository-relative paths with commit references, reproducible commands, and necessary environment details; local paths and localhost URLs alone are not handoffs. Do not assume another agent is running or has read a message; silence alone does not establish abandonment. Record evidence and preserve existing work when reassigning a task.
|
||||
2. Search before creating tasks. Claim a meaningful outcome in its Gitea issue with a stable session identity, scope, remote repository / branch, and acceptance criteria. Keep small steps within that task. Recheck after claiming; comments are not atomic locks. Respect existing ownership and resolve overlapping claims before overlapping work.
|
||||
3. Independent sessions are peers. Each owns its contribution and delegated work on its own machine. Record one integration / release owner when a milestone needs shared coordination. Use distinct remote work branches, partition files / interfaces, and coordinate changes to shared specifications and documents. Worktrees provide local isolation only; they do not share work between machines.
|
||||
4. At meaningful checkpoints or handoffs, record changed results, commit / PR links, verification commands and environment, blockers, and next actions. Identify the tested code version and label uncommitted or unpublished work as local-only. Before asking peers to consume results, push the required code and versioned documentation, including relevant `harness` updates; publish other required artifacts in Gitea and link them. Use repository-relative paths with commit references, reproducible commands, and necessary environment details; local paths and localhost URLs alone are not handoffs. Do not assume another agent is running or has read a message; silence alone does not establish abandonment. Record evidence and preserve existing work when reassigning a task.
|
||||
5. Follow project review and merge conventions. Fetch the relevant remote branches and inspect the identified commits before reviewing or integrating another machine's work. Resolve conflicts while preserving others' edits, and verify the combined result locally; report material environment differences. Local instruction-file edits reach peers only after publication and retrieval. Do not overwrite others' work or force-push shared history to resolve coordination problems.
|
||||
6. Close work when its acceptance criteria are met and the result is integrated or delivered as appropriate. Mark duplicates and superseded tasks explicitly with replacement links. Then choose further useful unowned work while the requested objective remains incomplete.
|
||||
|
||||
@@ -64,10 +64,10 @@ Preserve concise records of decisions and rationale, useful experiments, failed
|
||||
|
||||
Consolidate duplicates, repair stale guidance, and remove obsolete temporary files alongside useful project work. Before removing material, check references, active ownership, and ongoing use; preserve unique knowledge and update affected links. Prefer closing, superseding, or archiving history over deletion. User input is excluded from autonomous cleanup.
|
||||
|
||||
If legacy local task ledgers or plans duplicate Gitea, migrate their live content once into existing or appropriately scoped issues, preserve useful decisions/evidence, and mark the old records superseded. Record the migration so later sessions do not repeat it. Do not create empty documents or maintain records for ceremony.
|
||||
If legacy local task ledgers or plans duplicate Gitea, migrate their live content once into existing or appropriately scoped issues, preserve useful decisions / evidence, and mark the old records superseded. Record the migration so later sessions do not repeat it. Do not create empty documents or maintain records for ceremony.
|
||||
|
||||
## Delivery
|
||||
|
||||
Publish versioned Gitea releases at meaningful working milestones; mark unfinished versions as prereleases. Check existing releases/tags and coordinate one owner and version before publishing. Build from an identified integrated commit and verify the packaged result and launch steps.
|
||||
Publish versioned Gitea releases at meaningful working milestones; mark unfinished versions as prereleases. Check existing releases / tags and coordinate one owner and version before publishing. Build from an identified integrated commit and verify the packaged result and launch steps.
|
||||
|
||||
Include runnable builds or appropriate artifacts, concise release notes, build/run/deployment instructions as applicable, known limitations, tested platforms, and verification evidence. Confirm publication and artifact availability. Use existing authorized API access or project tooling when MCP lacks a needed release/upload operation. Do not silently replace published versions with different contents.
|
||||
Include runnable builds or appropriate artifacts, concise release notes, build / run / deployment instructions as applicable, known limitations, tested platforms, and verification evidence. Confirm publication and artifact availability. Use existing authorized API access or project tooling when MCP lacks a needed release / upload operation. Do not silently replace published versions with different contents.
|
||||
|
||||
+2
-2
@@ -17,14 +17,14 @@ Apply these criteria to the scope requested by the user:
|
||||
- Consequential decisions have evidence and rationale. Major assumptions have been validated, explicitly accepted, or isolated without compromising required behavior.
|
||||
- The result builds, runs, and operates on the required platforms. Relevant tests and evaluators pass; integrations, edge cases, and failure states have been exercised against the actual result.
|
||||
- User-facing behavior and usability have been exercised directly, using representative data and workflows.
|
||||
- A fresh independent review covers requirements, domain/semantic consistency, usability, architecture, correctness, regressions, runtime behavior, documentation, and remaining risks. Valid material findings are addressed, blocking and high-impact issues resolved, and affected behavior reverified; no known blocker or high-severity defect remains.
|
||||
- A fresh independent review covers requirements, domain / semantic consistency, usability, architecture, correctness, regressions, runtime behavior, documentation, and remaining risks. Valid material findings are addressed, blocking and high-impact issues resolved, and affected behavior reverified; no known blocker or high-severity defect remains.
|
||||
- Deliverables are maintainable, appropriately extensible, documented, and published as required by `AGENTS.md`. Obsolete scaffolding is removed; documentation and shared state accurately describe the result. Another engineer or agent can reproduce the verification and continue the work.
|
||||
|
||||
If required work or verification is blocked, record the specific gap and continue independent useful work without claiming completion.
|
||||
|
||||
## Final handoff
|
||||
|
||||
Link the delivered result and summarize capabilities, discoveries, architecture and decisions, relevant rejected approaches, verification and independent review, remaining limitations, and exact build/run/deployment/verification instructions. Refer to authoritative records instead of repeating the project history.
|
||||
Link the delivered result and summarize capabilities, discoveries, architecture and decisions, relevant rejected approaches, verification and independent review, remaining limitations, and exact build / run / deployment / verification instructions. Refer to authoritative records instead of repeating the project history.
|
||||
|
||||
## USER-OWNED APPLICATION SPECIFICATION
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ mod hosted;
|
||||
mod reference_authoring;
|
||||
#[cfg(test)]
|
||||
mod review_navigation_tests;
|
||||
#[cfg(test)]
|
||||
mod source_indentation_tests;
|
||||
pub(crate) mod source_rename;
|
||||
mod source_symbols;
|
||||
pub(crate) mod text_workspace;
|
||||
@@ -427,6 +429,7 @@ pub enum Message {
|
||||
Pan(iced::Vector),
|
||||
Fit,
|
||||
SourceEdit(text_editor::Action),
|
||||
SourceIndent(crate::source_navigation::SymbolContext, bool),
|
||||
ApplySource,
|
||||
RevertSource,
|
||||
SourceUndo,
|
||||
@@ -3314,10 +3317,16 @@ impl App {
|
||||
self.pan += delta;
|
||||
}
|
||||
Message::Fit => self.fit(),
|
||||
Message::SourceEdit(action) => {
|
||||
Message::SourceEdit(_) | Message::SourceIndent(..) => {
|
||||
self.source_jump = None;
|
||||
let before = self.source_editor.text();
|
||||
self.source_editor.perform(action);
|
||||
match message {
|
||||
Message::SourceEdit(action) => self.source_editor.perform(action),
|
||||
Message::SourceIndent(_, outdent) => {
|
||||
crate::source_indentation::apply(&mut self.source_editor, outdent);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let after = self.source_editor.text();
|
||||
if after != before {
|
||||
self.source_navigation.refresh(&after);
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
//! Controller acceptance: one indentation gesture is one draft transaction.
|
||||
use super::*;
|
||||
|
||||
fn fixture(source: &str) -> App {
|
||||
let mut app = App::with_project(Project::empty());
|
||||
app.page = Page::Text;
|
||||
app.source_workspace = Workspace::new(
|
||||
&oa_core::source_project::SourceBundle {
|
||||
entry: "project.arcadia".into(),
|
||||
files: std::collections::BTreeMap::from([("project.arcadia".into(), source.into())]),
|
||||
},
|
||||
true,
|
||||
);
|
||||
app.show_source_file(false);
|
||||
app
|
||||
}
|
||||
fn indent(app: &mut App, outdent: bool) {
|
||||
let message = Message::SourceIndent(app.source_symbol_context(), outdent);
|
||||
let _ = app.update(message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indentation_updates_draft_snapshot_version_and_single_undo_redo_without_model_change() {
|
||||
let source = "雨\r\n🚀\r\n";
|
||||
let mut app = fixture(source);
|
||||
app.source_editor.perform(text_editor::Action::SelectAll);
|
||||
let version = app.source_version;
|
||||
let revision = app.source_workspace.revision();
|
||||
let model = app.document.revision();
|
||||
indent(&mut app, false);
|
||||
let after = " 雨\r\n 🚀\r\n";
|
||||
assert_eq!(app.source_editor.text(), after);
|
||||
assert_eq!(app.source_snapshot.as_ref(), after);
|
||||
assert_eq!(app.source_workspace.files["project.arcadia"].text, after);
|
||||
assert!(app.source_workspace.has_edits());
|
||||
assert_eq!(app.source_version, version + 1);
|
||||
assert_eq!(app.source_workspace.revision(), revision + 1);
|
||||
assert_eq!(app.document.revision(), model);
|
||||
let _ = app.update(Message::SourceUndo);
|
||||
assert_eq!(app.source_editor.text(), source);
|
||||
assert!(!app.source_workspace.has_edits());
|
||||
let _ = app.update(Message::SourceRedo);
|
||||
assert_eq!(app.source_editor.text(), after);
|
||||
assert_eq!(app.document.revision(), model);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stale_hidden_and_modal_indentation_is_rejected_before_navigation_invalidation() {
|
||||
for rejected in 0..7 {
|
||||
let mut app = fixture("alpha");
|
||||
let mut context = app.source_symbol_context();
|
||||
match rejected {
|
||||
0 => context.path = "elsewhere.arcadia".into(),
|
||||
1 => context.session = Id::new_v4(),
|
||||
2 => app.page = Page::Home,
|
||||
3 => app.busy = true,
|
||||
4 => app.delete_pending = true,
|
||||
5 => app.hosted.visible = true,
|
||||
_ => app.pending = Some(Pending::New),
|
||||
}
|
||||
let interaction = app.source_symbols.interaction;
|
||||
let version = app.source_version;
|
||||
let _ = app.update(Message::SourceIndent(context, false));
|
||||
assert_eq!(app.source_editor.text(), "alpha");
|
||||
assert_eq!(app.source_version, version);
|
||||
assert_eq!(app.source_symbols.interaction, interaction);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_op_outdent_does_not_add_history_or_increment_source_version() {
|
||||
let mut app = fixture("alpha");
|
||||
let version = app.source_version;
|
||||
indent(&mut app, true);
|
||||
assert_eq!(app.source_version, version);
|
||||
assert!(!app.source_workspace.undo(false));
|
||||
}
|
||||
@@ -33,6 +33,9 @@ fn admission_notice(error: query::AdmissionError) -> String {
|
||||
impl App {
|
||||
pub(super) fn source_input_envelope(&self, message: &Message) -> bool {
|
||||
match message {
|
||||
Message::SourceIndent(context, _) => {
|
||||
context == &self.source_symbol_context() && self.source_navigation_available()
|
||||
}
|
||||
Message::SourceSymbols(context, event) => {
|
||||
context.session == self.source_workspace.session()
|
||||
&& context.path == self.source_workspace.active
|
||||
|
||||
@@ -28,6 +28,7 @@ mod recovery;
|
||||
mod route_edit;
|
||||
mod semantic_review;
|
||||
mod source_annotations;
|
||||
mod source_indentation;
|
||||
mod source_navigation;
|
||||
mod source_rename;
|
||||
mod source_tree;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
//! Source indentation is one workspace edit, with physical line endings intact.
|
||||
use iced::{
|
||||
advanced::{graphics, text},
|
||||
widget::text_editor::{Action, Content, Cursor, Edit, Position},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
const INDENT: &str = " ";
|
||||
|
||||
/// Plain Tab inserts one canonical four-space level at a caret, or prefixes
|
||||
/// every selected line. Shift+Tab removes one leading tab or up to four spaces.
|
||||
/// A selection ending at column zero excludes that final line. All patches are
|
||||
/// local to lines, so CRLF, LF and Unicode bytes outside indentation survive.
|
||||
/// The caller records the resulting buffer once in workspace undo/history.
|
||||
pub fn apply<R>(content: &mut Content<R>, outdent: bool)
|
||||
where
|
||||
R: text::Renderer<Editor = graphics::text::Editor>,
|
||||
{
|
||||
let raw = content.cursor();
|
||||
let selected = content.selection().is_some_and(|s| !s.is_empty());
|
||||
if !selected && !outdent {
|
||||
content.perform(Action::Edit(Edit::Paste(Arc::new(INDENT.into()))));
|
||||
return;
|
||||
}
|
||||
// Determine affected lines before normalizing Word/Line mode. Those modes
|
||||
// expand columns within their endpoint lines; the copied LF count reveals
|
||||
// whether a zero-column endpoint includes the next line or only its edge.
|
||||
let anchor = raw.selection.unwrap_or(raw.position);
|
||||
let first = raw.position.line.min(anchor.line);
|
||||
let mut last = raw.position.line.max(anchor.line);
|
||||
if selected {
|
||||
let selected_text = content.selection().unwrap();
|
||||
let line_breaks = selected_text.bytes().filter(|b| *b == b'\n').count();
|
||||
// Effective selection starts on the minimum raw endpoint line.
|
||||
last = first + line_breaks;
|
||||
if last > first && selected_text.ends_with('\n') {
|
||||
last -= 1;
|
||||
}
|
||||
}
|
||||
let patches: Vec<_> = (first..=last)
|
||||
.filter_map(|line| {
|
||||
let removed = if outdent {
|
||||
let text = content.line(line)?;
|
||||
if text.text.starts_with('\t') {
|
||||
1
|
||||
} else {
|
||||
text.text.bytes().take(4).take_while(|b| *b == b' ').count()
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
(!outdent || removed > 0).then_some((line, removed))
|
||||
})
|
||||
.collect();
|
||||
if patches.is_empty() {
|
||||
return;
|
||||
}
|
||||
let cursor = crate::source_navigation::selection::capture_for_edit(content);
|
||||
let replacement = Arc::new(if outdent {
|
||||
String::new()
|
||||
} else {
|
||||
INDENT.into()
|
||||
});
|
||||
// Descending order leaves Iced's earliest changed line at the first patch.
|
||||
for &(line, removed) in patches.iter().rev() {
|
||||
content.move_to(Cursor {
|
||||
position: Position { line, column: 0 },
|
||||
selection: Some(Position {
|
||||
line,
|
||||
column: removed,
|
||||
}),
|
||||
});
|
||||
content.perform(Action::Edit(Edit::Paste(replacement.clone())));
|
||||
}
|
||||
let transform = |mut position: Position| {
|
||||
if let Some((_, removed)) = patches.iter().find(|(line, _)| *line == position.line) {
|
||||
position.column = if outdent {
|
||||
position.column.saturating_sub(*removed)
|
||||
} else {
|
||||
position.column + INDENT.len()
|
||||
};
|
||||
}
|
||||
position
|
||||
};
|
||||
content.move_to(Cursor {
|
||||
position: transform(cursor.position),
|
||||
selection: cursor.selection.map(transform),
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(all(test, debug_assertions))]
|
||||
mod keyboard_tests;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@@ -0,0 +1,106 @@
|
||||
//! Real mounted Iced keyboard dispatch, using the production binding function.
|
||||
use crate::{app::Message, source_navigation::SymbolContext, views::source_tests::FontLayout};
|
||||
use iced::advanced::widget::operation::Focusable;
|
||||
use iced::{
|
||||
Element, Font, Rectangle, Size,
|
||||
advanced::{Layout, Shell, layout, text, widget as core_widget},
|
||||
keyboard::{
|
||||
self, Key, Modifiers,
|
||||
key::{Code, Named, Physical},
|
||||
},
|
||||
widget::{
|
||||
self,
|
||||
text_editor::{Content, State},
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn mounted_tab_dispatches_only_for_focused_editable_editor_and_plain_shift_variants() {
|
||||
for focused in [false, true] {
|
||||
for editable in [false, true] {
|
||||
for modifiers in [
|
||||
Modifiers::empty(),
|
||||
Modifiers::SHIFT,
|
||||
Modifiers::CTRL,
|
||||
Modifiers::ALT,
|
||||
Modifiers::LOGO,
|
||||
] {
|
||||
let context = SymbolContext {
|
||||
session: oa_core::Id::new_v4(),
|
||||
path: "project.arcadia".into(),
|
||||
};
|
||||
let content = Content::<FontLayout>::with_text("rain");
|
||||
let mut editor = widget::text_editor(&content)
|
||||
.font(Font::MONOSPACE)
|
||||
.size(14)
|
||||
.padding(16)
|
||||
.height(iced::Fill)
|
||||
.key_binding(|press| crate::views::source_binding(press, &context, None));
|
||||
if editable {
|
||||
editor = editor.on_action(Message::SourceEdit);
|
||||
}
|
||||
let mut view: Element<'_, Message, iced::Theme, FontLayout> = editor.into();
|
||||
let mut tree = core_widget::Tree::new(view.as_widget());
|
||||
let size = Size::new(600., 240.);
|
||||
let node = view.as_widget_mut().layout(
|
||||
&mut tree,
|
||||
&FontLayout,
|
||||
&layout::Limits::new(Size::ZERO, size),
|
||||
);
|
||||
if focused {
|
||||
tree.state
|
||||
.downcast_mut::<State<text::highlighter::PlainText>>()
|
||||
.focus();
|
||||
}
|
||||
let event = iced::Event::Keyboard(keyboard::Event::KeyPressed {
|
||||
key: Key::Named(Named::Tab),
|
||||
modified_key: Key::Named(Named::Tab),
|
||||
physical_key: Physical::Code(Code::Tab),
|
||||
location: keyboard::Location::Standard,
|
||||
modifiers,
|
||||
text: None,
|
||||
repeat: false,
|
||||
});
|
||||
let mut messages = Vec::new();
|
||||
let captured;
|
||||
{
|
||||
let mut shell = Shell::new(&mut messages);
|
||||
view.as_widget_mut().update(
|
||||
&mut tree,
|
||||
&event,
|
||||
Layout::new(&node),
|
||||
iced::mouse::Cursor::Unavailable,
|
||||
&FontLayout,
|
||||
&mut iced::advanced::clipboard::Null,
|
||||
&mut shell,
|
||||
&Rectangle::with_size(size),
|
||||
);
|
||||
captured = shell.is_event_captured();
|
||||
}
|
||||
let plain = modifiers.is_empty() || modifiers == Modifiers::SHIFT;
|
||||
let expected = focused && editable && plain;
|
||||
let indentation: Vec<_> = messages
|
||||
.iter()
|
||||
.filter_map(|message| match message {
|
||||
Message::SourceIndent(emitted, outdent) => Some((emitted, outdent)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(
|
||||
indentation.len(),
|
||||
usize::from(expected),
|
||||
"focused={focused}, editable={editable}, modifiers={modifiers:?}"
|
||||
);
|
||||
if expected {
|
||||
assert!(captured, "Tab must not escape to global focus traversal");
|
||||
assert_eq!(indentation[0], (&context, &modifiers.shift()));
|
||||
} else if !focused || !editable {
|
||||
assert!(
|
||||
!captured,
|
||||
"non-editing Tab must remain available to focus traversal"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
use super::*;
|
||||
use iced::widget::text_editor::Motion;
|
||||
|
||||
type Buffer = Content<iced::Renderer>;
|
||||
fn at(line: usize, column: usize) -> Position {
|
||||
Position { line, column }
|
||||
}
|
||||
fn range(start: Position, end: Position, reverse: bool) -> Cursor {
|
||||
Cursor {
|
||||
position: if reverse { start } else { end },
|
||||
selection: Some(if reverse { end } else { start }),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn caret_inserts_four_spaces_and_outdent_removes_only_leading_whitespace() {
|
||||
let mut content = Buffer::with_text(" 雨🚀\r\nnext");
|
||||
content.move_to(Cursor {
|
||||
position: at(0, " 雨".len()),
|
||||
selection: None,
|
||||
});
|
||||
apply(&mut content, false);
|
||||
assert_eq!(content.text(), " 雨 🚀\r\nnext");
|
||||
assert_eq!(content.cursor().position, at(0, " 雨 ".len()));
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.text(), "雨 🚀\r\nnext");
|
||||
assert_eq!(content.cursor().position, at(0, "雨 ".len()));
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.text(), "雨 🚀\r\nnext");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn directional_blocks_preserve_unicode_endings_and_exclude_final_zero_column() {
|
||||
let source = "雨\r\n🚀\nlast\r\n";
|
||||
for reverse in [false, true] {
|
||||
let mut content = Buffer::with_text(source);
|
||||
let original = range(at(0, 0), at(2, 0), reverse);
|
||||
content.move_to(original);
|
||||
apply(&mut content, false);
|
||||
assert_eq!(content.text(), " 雨\r\n 🚀\nlast\r\n");
|
||||
assert_eq!(content.cursor(), range(at(0, 4), at(2, 0), reverse));
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.text(), source);
|
||||
assert_eq!(content.cursor(), original);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outdent_handles_tabs_partial_spaces_and_clamps_endpoint_inside_removed_indent() {
|
||||
for reverse in [false, true] {
|
||||
let mut content = Buffer::with_text("\t雨\r\n 🚀\n fin");
|
||||
content.move_to(range(at(0, 0), at(2, 2), reverse));
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.text(), "雨\r\n🚀\nfin");
|
||||
assert_eq!(content.cursor(), range(at(0, 0), at(2, 0), reverse));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn word_and_line_selections_indent_effective_range_in_both_directions() {
|
||||
for line_mode in [false, true] {
|
||||
for reverse in [false, true] {
|
||||
let mut content = Buffer::with_text("one alpha\r\ntwo beta\nthree gamma");
|
||||
content.move_to(Cursor {
|
||||
position: if reverse { at(2, 8) } else { at(0, 6) },
|
||||
selection: None,
|
||||
});
|
||||
content.perform(if line_mode {
|
||||
Action::SelectLine
|
||||
} else {
|
||||
Action::SelectWord
|
||||
});
|
||||
content.perform(Action::Select(if reverse {
|
||||
Motion::DocumentStart
|
||||
} else {
|
||||
Motion::DocumentEnd
|
||||
}));
|
||||
let selected = content.selection().unwrap();
|
||||
apply(&mut content, false);
|
||||
assert_eq!(
|
||||
content.text(),
|
||||
" one alpha\r\n two beta\n three gamma"
|
||||
);
|
||||
let cursor = content.cursor();
|
||||
assert_eq!(
|
||||
cursor.position.line < cursor.selection.unwrap().line,
|
||||
reverse
|
||||
);
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.text(), "one alpha\r\ntwo beta\nthree gamma");
|
||||
assert_eq!(content.selection(), Some(selected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_op_outdent_preserves_semantic_word_selection_and_last_empty_line_is_excluded() {
|
||||
let mut content = Buffer::with_text("alpha tail\r\n");
|
||||
content.move_to(Cursor {
|
||||
position: at(0, 2),
|
||||
selection: None,
|
||||
});
|
||||
content.perform(Action::SelectWord);
|
||||
let raw = content.cursor();
|
||||
apply(&mut content, true);
|
||||
assert_eq!(content.cursor(), raw);
|
||||
assert_eq!(content.selection().as_deref(), Some("alpha"));
|
||||
content.perform(Action::SelectAll);
|
||||
apply(&mut content, false);
|
||||
assert_eq!(content.text(), " alpha tail\r\n");
|
||||
assert_eq!(content.cursor().position, at(1, 0));
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
//! Effective selected-byte ranges for a committed departure from a source view.
|
||||
//! Effective selected-byte ranges for committed source departures and edits.
|
||||
//!
|
||||
//! Iced's `Cursor` omits cosmic-text's Word/Line selection kind. Saving its raw
|
||||
//! endpoints can therefore save an empty range for a visibly selected word/line.
|
||||
//! Capture only after navigation admission and destination validation succeed,
|
||||
//! immediately before replacing/leaving the live editor. Never use this to inspect
|
||||
//! pending queries, failed/no-op navigation, or restore focus to the same editor.
|
||||
//! Departure capture requires navigation admission and destination validation,
|
||||
//! immediately before replacing/leaving the live editor. Edit capture requires
|
||||
//! an admitted edit with a nonempty patch plan. Neither is a passive query:
|
||||
//! never use these to inspect pending queries, failed/no-op navigation, or restore
|
||||
//! focus to the same editor.
|
||||
use iced::advanced::{graphics, text};
|
||||
use iced::widget::text_editor::{Action, Content, Cursor, Motion, Position};
|
||||
|
||||
@@ -21,6 +23,23 @@ use iced::widget::text_editor::{Action, Content, Cursor, Motion, Position};
|
||||
/// selection joins editor lines with LF regardless of physical CRLF/LF endings.
|
||||
/// Only the selected text is temporarily copied; retained state is one Cursor.
|
||||
pub fn capture<R>(content: &mut Content<R>) -> Cursor
|
||||
where
|
||||
R: text::Renderer<Editor = graphics::text::Editor>,
|
||||
{
|
||||
effective_range(content)
|
||||
}
|
||||
|
||||
/// Capture immediately before a committed indentation edit. Like departure,
|
||||
/// this converts Word/Line selections to their effective directional byte range.
|
||||
/// The caller restores the transformed range after editing the same Content.
|
||||
pub fn capture_for_edit<R>(content: &mut Content<R>) -> Cursor
|
||||
where
|
||||
R: text::Renderer<Editor = graphics::text::Editor>,
|
||||
{
|
||||
effective_range(content)
|
||||
}
|
||||
|
||||
fn effective_range<R>(content: &mut Content<R>) -> Cursor
|
||||
where
|
||||
R: text::Renderer<Editor = graphics::text::Editor>,
|
||||
{
|
||||
|
||||
@@ -1178,6 +1178,15 @@ pub(crate) fn source_binding(
|
||||
use crate::source_navigation::{SymbolEvent, query::Action};
|
||||
use iced::keyboard::{Key, key::Named};
|
||||
use widget::text_editor::{Binding, Status};
|
||||
if matches!(press.status, Status::Focused { .. })
|
||||
&& press.key == Key::Named(Named::Tab)
|
||||
&& (press.modifiers.is_empty() || press.modifiers == iced::keyboard::Modifiers::SHIFT)
|
||||
{
|
||||
return Some(Binding::Custom(Message::SourceIndent(
|
||||
context.clone(),
|
||||
press.modifiers.shift(),
|
||||
)));
|
||||
}
|
||||
if matches!(press.status, Status::Focused { .. })
|
||||
&& press.modifiers.is_empty()
|
||||
&& press.key == Key::Named(Named::F2)
|
||||
|
||||
@@ -1,5 +1,64 @@
|
||||
# Architectural and product decisions
|
||||
|
||||
## Private mixed syntax boundary — 2026-09-23
|
||||
|
||||
Proceed with the [reviewed syntax-only slice](analysis-mixed-parser-review-20260923.md)
|
||||
on tested private source `10d7f334`, retaining current root `195ddbb` as an
|
||||
ordinary-compatibility reference. Direct comparison found the relevant ordinary
|
||||
syntax/include machinery equal or equivalent; whole-file drift chiefly concerns
|
||||
semantic/editor behavior. A full root merge is not a prerequisite for this
|
||||
private experiment, and neither whole language/updater file may replace the
|
||||
other during eventual integration.
|
||||
|
||||
One opaque complete-bundle result borrows the actual original files and owns
|
||||
the shared budget, canonical file table, ordinary occurrence positions and typed
|
||||
unresolved syntax. It supplies no admitted Project, Index or edit authority.
|
||||
Explicit IDs are a staging restriction; missing IDs reject before generation.
|
||||
Retain duplicate syntax occurrences until semantic uniqueness is checked.
|
||||
Ordinary signed numbers require byte adjacency and complete value spans;
|
||||
typed subtraction retains its separate grammar. Bound aggregate syntax storage
|
||||
without silently reinterpreting caller model-record or ordered-step limits.
|
||||
Propagate phase-check failures even where the Budget does not latch them.
|
||||
|
||||
The [proposal](analysis-mixed-parser-proposal-20260923.md) and review define the
|
||||
independent fixtures and rejected shortcuts. Same-pass unresolved syntax is a
|
||||
dependency of later mixed resolution/index/composition, not public source8
|
||||
activation or a substitute for whole-output admission. Source implementation,
|
||||
fresh review and runtime checks remain required.
|
||||
|
||||
## Private source composition decision — 2026-09-23
|
||||
|
||||
Adopt the opaque validated original-span rename batch as the next private
|
||||
analysis adapter step, with the [independent review's clarifications](analysis-original-span-review-20260923.md).
|
||||
The [original proposal](analysis-original-span-proposal-20260922.md) compares
|
||||
this against replacing both ordinary and typed edit representations. The narrow
|
||||
adapter preserves current ordinary compatibility and reduces migration risk;
|
||||
a shared edit AST remains a candidate if structural composition demonstrates a
|
||||
need. Neither sequentially applying producers with stale offsets nor canonical
|
||||
rewriting is acceptable for authored-source preservation.
|
||||
|
||||
The immediate patch exports complete borrowed rename records and splits
|
||||
ownership validation from standalone final-output size preflight. It may defer
|
||||
only hypothetical typed-only output sizing; active inherited budget, plan/name
|
||||
storage, qualified namespace, source equality and complete occurrence checks
|
||||
remain mandatory. Standalone rename/apply semantics remain intact. This is
|
||||
private staging, not a complete parse-session or public source8 boundary.
|
||||
|
||||
Before production composition, one checked parsed-bundle witness must bind the
|
||||
complete source/entry/file map, ordinary model, typed index, profile and complete
|
||||
target intent. Ordinary syntax-kind replacement currently emits same-start
|
||||
insertion/deletion pairs; explicitly normalize such owned operations with exact
|
||||
trivia oracles before admitting them, keeping cross-producer collisions errors.
|
||||
Gate supported changes by a precise complete-model diff. Compile the actual
|
||||
emitted full bundle, use normal admission, and compare the complete intended
|
||||
Project before installation. Exact untouched bytes are an independent gate.
|
||||
Subtree edits, parameter lifecycle, repaired deletion, reidentity, relocation,
|
||||
missing-ID stabilization, migration/history and checked-save remain required
|
||||
delivery work; passing the private rename slice cannot close those requirements.
|
||||
|
||||
The source-pinned proposal/review retain their original local provenance labels.
|
||||
The accepted underlying repair contract is [r2 at analysis source 1b1c3e3](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/1b1c3e3abb6fc3d0934c9dbfbd21fddc8ae4f594/harness/analysis-source8-20260913/analysis-source8-repair-design-r2-20260913.md).
|
||||
|
||||
## Current continuation decisions — 2026-09-06
|
||||
|
||||
- Saving under another source entry basename is destination bookkeeping, not an engineering edit. Adopt an exact current save receipt without adding Undo or clearing Redo; rebase uniform entry names across retained history after collision and compilation checks. Stale receipts cannot redirect newer raw source. Native discovery and eleven focused regression results are in release-save-as-runtime-packaging.md; updated native verification remains required.
|
||||
@@ -456,3 +515,311 @@ Missing global and scoped parameter IDs remain explicit stabilization metadata,
|
||||
not new random identities assigned on each parse. Public source8 integration must
|
||||
thread the same accounting through the outer project and included files; this
|
||||
private checkpoint does not itself admit a complete version8 source bundle.
|
||||
|
||||
## Complete mixed Project before typed editing index — 2026-09-23
|
||||
|
||||
Choose the [private Project-first contract](analysis-mixed-project-contract-20260923.md)
|
||||
as the next semantic dependency, conditional on acceptance of its frozen syntax
|
||||
prerequisite. Reuse ordinary construction and typed lowering once, then check the
|
||||
complete Project and retain original syntax, the global lowering-site arena and
|
||||
its file ownership for later indexing. Including the typed index now would also
|
||||
change source-view/updater compatibility and several simultaneous allocation
|
||||
phases, while still leaving ordinary occurrence editing incomplete. This split
|
||||
preserves a concrete no-rescan/no-relower continuation and isolates model
|
||||
correctness from later edit authority; it does not narrow the required parity goal.
|
||||
|
||||
The [independent critique](reviews/mixed-project-contract-20260923.md) requires a
|
||||
full hand-authored retained-site oracle and a single admission result preserving
|
||||
static usage and every warning. Existing raw architectural diagnostic production
|
||||
is explicitly outside preallocation accounting; new mapped/retained storage must
|
||||
be reserved before copying or retention. Revisit the split if actual ownership
|
||||
work shows sites cannot be retained without duplicated models or repeated parsing.
|
||||
Public source8, mixed editing, checked-save and root reconciliation remain later
|
||||
dependencies, not capabilities delivered by this design decision.
|
||||
|
||||
## 2026-09-24 — preserve mixed bundle authority through index construction
|
||||
|
||||
Adopt the [mixed typed-index contract](analysis-mixed-index-contract-20260924.md):
|
||||
consume the sealed complete-Project witness into a distinct read-only owner and
|
||||
reuse private structural/token verification, with aggregate retained-ledger
|
||||
accounting. A copied verifier would duplicate correction work; reparsing into
|
||||
the old numeric-source Index would discard bundle/profile authority. The
|
||||
[independent review](analysis-mixed-index-review-20260924.md) resolved storage
|
||||
domain and completeness-proof ambiguities before adoption. This is a bounded
|
||||
implementation decision, not runtime acceptance or full editing parity. Revisit
|
||||
if a concrete verifier invariant prevents reuse or multiple retained owners
|
||||
become necessary; no generic public indexing framework is justified now.
|
||||
|
||||
## 2026-09-24 — index ordinary authored names before rename composition
|
||||
|
||||
Adopt the [ordinary occurrence successor](analysis-ordinary-index-contract-20260924.md)
|
||||
after source mapping and independent critique. Retain the accepted typed owner
|
||||
and add a physical-token-keyed ordinary map from sealed original positions.
|
||||
This isolates complete coverage/ownership from later edit intent and avoids a
|
||||
new structural path arena or parser. A fused streaming rename planner could
|
||||
save map storage, but would combine two unverified boundaries; revisit after
|
||||
coverage is established and a real consumer demonstrates the benefit.
|
||||
The contract explicitly handles synthetic brace-containing roots, complete
|
||||
reference extents and the existing ordinary depth policy. It grants read-only
|
||||
name-occurrence authority only. Rename composition and complete editing parity
|
||||
remain separate required capabilities.
|
||||
|
||||
## 2026-09-24 — gate mixed rename intent against the complete desired model
|
||||
|
||||
Adopt the [mixed rename planning contract](analysis-mixed-rename-plan-contract-20260924.md)
|
||||
after source mapping and independent criticism. Consume the complete authored
|
||||
owner, immutably borrow desired Project, and retain only changed-name and physical
|
||||
edit maps. Exhaustive shallow alias exceptions avoid Project clones, generic
|
||||
diff machinery and duplicate legacy batches. Final namespaces are checked
|
||||
simultaneously, so swaps work and collisions with unchanged names reject.
|
||||
|
||||
Existing whole-model PartialEq semantics define non-name equivalence, including
|
||||
signed-zero equivalence across geometry, scalar and historical carriers. Original
|
||||
non-name source bytes remain exact. The allocating iterative Expr comparator
|
||||
requires a conservative E scratch reservation; independent type-graph and
|
||||
frontier analysis bounds E by the retained original expression arena, including
|
||||
all four root families. Revisit if new Expr carriers appear or conservative
|
||||
headroom demonstrably blocks useful cases.
|
||||
|
||||
Deliberate later output parsing must preserve exact inherited per-snapshot policy
|
||||
with separately reported new usage and aggregate live-storage accounting. An
|
||||
independent fresh ledger must not hide retained output or old state. Execution
|
||||
ownership/readmission seams remain separate required implementation; this
|
||||
decision does not label a read-only plan as accepted rewritten source.
|
||||
|
||||
## 2026-09-24 — carry output storage through actual verification
|
||||
|
||||
The [execution source map](analysis-mixed-rename-execution-20260924/RENAME-EXECUTION-SOURCE-MAP.md)
|
||||
identifies the next boundary: output buffers already coexist with parsing, so
|
||||
adding a retained-output baseline only at resolution checks too late. Preserve
|
||||
the exact per-snapshot Limits and ProjectLimits, explicitly drop consumed old
|
||||
auxiliary state, and carry surviving output storage through verification.
|
||||
The final comparison must include aliases and parameter names; the planning
|
||||
gate deliberately omits them and cannot establish accepted rewritten output.
|
||||
|
||||
We considered authenticating exact output bytes, then reserving a conservative
|
||||
parser envelope derived from the unchanged syntax topology. The
|
||||
[independent feasibility investigation](analysis-mixed-rename-execution-20260924/RENAME-EXECUTION-ENVELOPE-FEASIBILITY.md)
|
||||
found useful partial bounds but no complete safe, useful aggregate formula.
|
||||
Finishing it would duplicate parser lifecycle knowledge across expression
|
||||
tasks, name sets, projection buffers, string decoding and include traversal.
|
||||
Select explicit carried storage accounting at actual growth/handoff seams for
|
||||
the next bounded design instead. Revisit an envelope only if a small, stable
|
||||
source-derived proof demonstrates useful caps; do not use unexplained byte or
|
||||
node multipliers. This chooses a direction, not an implemented execution API.
|
||||
|
||||
The [domain audit](analysis-mixed-rename-execution-20260924/CARRIED-STORAGE-DOMAIN-AUDIT.md)
|
||||
keeps the declared metric explicit: logical auxiliary slots/text are distinct
|
||||
from model/serde/raw-validator heap, allocator capacity and process RSS. The
|
||||
exploratory allocation inventory is not a requirement to meter all heap usage.
|
||||
The successor contract must reconcile that domain before selecting growth
|
||||
hooks or claiming an aggregate pre-allocation guarantee.
|
||||
|
||||
## 2026-09-25 — preserve parser compatibility while carrying live storage
|
||||
|
||||
Adopt the [private carried-phase prerequisite](analysis-carried-phase-contract-20260925.md).
|
||||
Keep legacy parser checkpoints unchanged; an explicit carried path checks the
|
||||
combined syntax and retained storage at the declared phase boundaries, including
|
||||
when its carried baseline is zero. An opaque guard binds the actual bundle,
|
||||
exact policy and retained owner through parsing and resolution. Seed the existing
|
||||
resolver ledger once, without charging live storage as new parse work.
|
||||
|
||||
New continuation constructors remain fixture-only until the actual output
|
||||
producer and consumed-owner transition exist. The narrow owning fixture contains
|
||||
only the bundle, so its carried count is F map entries, zero lower occurrences
|
||||
and all source/key/entry UTF-8 bytes. This is a phase-accounting prerequisite,
|
||||
not fulfillment or waiver of stronger parser producer timing requirements for
|
||||
final output acceptance. It grants no editing authority.
|
||||
|
||||
Runtime review of the first carried-phase candidate exposed a stack overflow in
|
||||
an unchanged legacy 128 KiB control during numeric parsing. Remove duplicated
|
||||
policy from the retained guard: the consumed input transfers exact policy into
|
||||
the Budget and syntax limits, while a small guard retains the backing owner.
|
||||
This changes representation without new heap storage or weaker tests. Prefer
|
||||
this to boxing policy or introducing an external policy-owner lifetime. The
|
||||
debugger identifies the active parsing path; it does not prove a sole cause or
|
||||
establish that the representation repair passes before it is actually tested.
|
||||
|
||||
## 2026-09-25 — separate owned emission from accepted rewritten output
|
||||
|
||||
The [emission contract](analysis-mixed-emission-contract-20260925.md) consumes
|
||||
the validated plan. A no-op returns its original owner; changed emission reserves
|
||||
the complete output map and UTF-8 storage while the old plan is live, then copies
|
||||
each file once in original edit coordinates. It drops old auxiliary ownership
|
||||
before constructing the private pending result. Exact policies and the desired
|
||||
whole Project survive, but no parse, adoption, save or public editing authority
|
||||
is granted. Reject any borrowed carried owner on the changed path: dropping a
|
||||
guard cannot free the externally owned allocation. A future owning transition
|
||||
must consume that allocation or account for its continued lifetime explicitly.
|
||||
|
||||
The [source-bound Windows evidence](experiments/analysis-mixed-emission-20260925/README.md)
|
||||
preserves an initial full-run stack abort and the successful repair. Split the
|
||||
existing iterative binding driver's prefix and continuation operations rather
|
||||
than changing arithmetic, increasing stack sizes, boxing state or weakening
|
||||
tests. Independent review establishes mechanical equivalence; actual rebuilt
|
||||
prologues and unchanged runtime controls support the bounded stack reduction.
|
||||
This does not close the older, separately unrerun full-pipeline setup limitation.
|
||||
|
||||
Final acceptance still requires parsing and resolving actual output bytes,
|
||||
complete Project equality under justified scratch bounds, explicit parser
|
||||
producer timing and an owner retaining the accepted bundle. Original expression
|
||||
counts alone do not bound an arbitrary faulty output. Logical auxiliary usage
|
||||
continues to exclude the established model/serde/validator and allocator domains;
|
||||
no process-wide memory guarantee follows from this private milestone.
|
||||
|
||||
## 2026-09-25 — reserve named syntax text at its producer
|
||||
|
||||
The [text producer contract](analysis-text-producer-contract-20260925.md) selects
|
||||
a separate private route bound to actual carried authority. Reserve raw quoted
|
||||
payload P before the existing decoder, then transfer decoded D and release P-D.
|
||||
This avoids a duplicate decoder while deliberately allowing conservative
|
||||
escaped-input refusal on the new route. Preserve legacy/phase-only diagnostics.
|
||||
Count simultaneous key/reference copies and all consumed UUID spellings; drop
|
||||
temporary strings before refund. Borrow the ordinary declaration-kind word.
|
||||
Keep small scalar state, transfer retained text once into the resolver ledger,
|
||||
and independently reconcile it against the existing syntax inventory.
|
||||
|
||||
The [verified Windows packet](experiments/analysis-text-producer-20260925/README.md)
|
||||
records six new passes, unchanged prior outcomes, initial lint repair and the
|
||||
single framework-hint difference in one inherited failure log. Preserve the
|
||||
original checker refusal and narrow named-byte amendment instead of weakening
|
||||
general comparison. Compiler prologue observations and existing stack controls
|
||||
bound evidence only; this adds no universal heap or stack guarantee.
|
||||
Entry/metadata growth timing and the remaining scratch inventory require their
|
||||
own explicit decision before actual emitted-output acceptance can be enabled.
|
||||
|
||||
## 2026-09-25 — strengthen the existing retained-entry metric at named producers
|
||||
|
||||
The [entry producer contract](analysis-entry-producer-contract-20260925.md)
|
||||
preserves U's declared grammar events and the conservative M inventory. A new
|
||||
explicit route checks C+U+M before selected growth; old routes retain their
|
||||
timing. Prefer grammar scalar counts plus a prepaid projector quota to another
|
||||
unmetered AST-counting frontier. Seven-slot declaration envelopes already include
|
||||
synthetic bodies; actual nested fields/values contribute separately. Quota
|
||||
consumption neither recharges nor refunds M, and independent lengths/metadata
|
||||
must reconcile. No saturating correction may create a successful witness.
|
||||
|
||||
[Windows evidence](experiments/analysis-entry-producer-20260925/README.md)
|
||||
preserves both precompile latch fixes, the syntax-cap versus counting-scratch
|
||||
evaluator correction and the initial test-only Debug-bound compile failure.
|
||||
All six new tests pass with unchanged inherited dispositions and strict Clippy.
|
||||
Additional scalar state changes compiler frames, so old stack controls and
|
||||
actual prologues remain evidence requirements; a logical slot is not a native
|
||||
stack byte. Remaining independently bounded parser scratch requires an explicit
|
||||
scope decision, not an inferred universal heap-metering requirement.
|
||||
|
||||
## 2026-09-25 — accept actual emitted bytes into one owning result
|
||||
|
||||
The [acceptance contract](analysis-mixed-acceptance-contract-20260925.md) selects
|
||||
a shared borrow of the complete sealed PendingRename as carried authority,
|
||||
rather than bare counters, duplicated policy or a new heap wrapper. Compile-time
|
||||
covariance permits the short verification borrow. Use both selected parser
|
||||
producer modes, complete resolution/admission and full actual-left Project
|
||||
PartialEq; reserve the actual expression arena count, not original provenance.
|
||||
|
||||
Move the actual model and mapped warnings with the accepted source. This preserves
|
||||
diagnostic/source identity without reparsing or substituting the desired model.
|
||||
Warnings already occupy the resolver ledger: exhaustively count their surviving
|
||||
inventory without charging twice, verify final O+W as a bounded subset while all
|
||||
verification owners remain live, then drop syntax/guards and move the bundle.
|
||||
No mutable extraction, history installation or repeated carried edit is implied.
|
||||
|
||||
Retain independently bounded traversal/delimiter/Pratt/duplicate-name scratch as
|
||||
an explicit separate domain. File/source-byte bounds do not tightly bound copied
|
||||
path bytes. This selected logical accounting is not universal heap accounting.
|
||||
The [finite Windows evidence](experiments/analysis-output-acceptance-20260925/README.md)
|
||||
checks exact inherited limits, real returned models/warnings, lifetime and stack
|
||||
behavior. Preserve the initial two incorrect empty-warning expectations and their
|
||||
independent full-warning correction. A raw build-target path spelling difference
|
||||
requires only a named exact-pair checker amendment, not weakened failure or source
|
||||
comparison. All earlier outcomes remain preserved; public integration is next.
|
||||
|
||||
## 2026-09-25 — restore ordinary schema8 compatibility before mixed adoption
|
||||
|
||||
Current formatters already emit schema8, while the ordinary reader previously
|
||||
rejected it. Admit that version through the existing ordinary grammar and model
|
||||
validation, preserving migration, complete source indexes, identity stabilization,
|
||||
updates and checked saves. Keep typed and long analysis-constructor refusals;
|
||||
ordinary acceptance does not qualify missing typed formatting or mixed editing.
|
||||
The [contract and independent comparison](ordinary-source8-compatibility-contract-20260925.md)
|
||||
reject replacing compile_bundle with an incomplete read-only index.
|
||||
|
||||
[Windows evidence](experiments/ordinary-source8-20260925/README.md) exercises the
|
||||
previously blocked nested/transaction workflows, complete ordinary OA/SA and
|
||||
historical trace round trips, relevant integration tests and actual read-only CLI
|
||||
commands. Preserve the initial example-trace assumption failure, four obsolete
|
||||
private header-rejection assertions and the historical JSON oracle's missing
|
||||
empty definitions catalog. Correct their expectations explicitly while retaining
|
||||
whole-model and typed-refusal checks; two test renames have exact inventory maps.
|
||||
|
||||
Reuse the source-identical core, other integration and CLI evidence after the last
|
||||
three-line migration-test correction. Verify the entire successor diff and every
|
||||
other declared input, rerun the affected target plus all-target Clippy/format, and
|
||||
identify each tested code version. No Linux, GUI or release qualification follows
|
||||
from these core/CLI results. Publication remains blocked by server disk exhaustion.
|
||||
|
||||
## 2026-09-25 — expose complete mixed validation through a borrowed read-only result
|
||||
|
||||
Select `language::check_mixed_bundle` with an opaque non-Clone result borrowing
|
||||
the caller's complete explicit-ID SourceBundle. Retain the real resolved owner
|
||||
and return immutable Project/warning views; do not substitute a bare model or an
|
||||
incomplete editable index. The [contract](analysis-public-read-contract-20260925.md)
|
||||
records alternatives, policy and bounds. Fresh input selects both existing
|
||||
producer modes with zero carried ownership, followed by complete resolution and
|
||||
admission under the exact caller policy. Internal entry ceilings remain separate
|
||||
from final-model record limits.
|
||||
|
||||
Promote only the required parser/resolver dependency cone to production; private
|
||||
index/edit machinery stays test-only. Normal-library tests are required because
|
||||
the production Parser layout changes even when ordinary callers select no mixed
|
||||
mode. That build exposed a missed semantic-row initializer, fixed at its source;
|
||||
two actual compiler warnings received narrow cfg/import corrections.
|
||||
|
||||
[Windows evidence](experiments/analysis-public-read-20260925/README.md) at bab6f96
|
||||
checks complete independently authored OA/SA models, exact warnings and refusals,
|
||||
source conservation, constructor policy, source lifetimes, prior workflows and
|
||||
actual ordinary CLI behavior. All 299 core and 75 selected integration cases pass.
|
||||
Rustdoc's two compile-fail runtime names append a suffix absent from its listing:
|
||||
preserve the recorder refusal and reconcile exactly those two names against the
|
||||
successful three-case raw run. No generic name normalization or rerun is needed.
|
||||
|
||||
This developer-facing API does not enable mixed file discovery in the CLI or
|
||||
graphical editing. Add those through explicit subsequent contracts, retaining
|
||||
filesystem safety and complete model/index ownership. Do not route a nominal
|
||||
mixed check through the ordinary loader, which currently rejects typed syntax
|
||||
and constructs editable compilation. Source/evidence were subsequently published
|
||||
after server storage recovery (issue7 comment1333); no release or Linux
|
||||
qualification follows.
|
||||
|
||||
## 2026-09-25 — separate mixed CLI discovery from editable ordinary loading
|
||||
|
||||
Expose `arcadia check-mixed ROOT [--json]` through a closed read-only dispatch and
|
||||
opaque mixed source snapshot. Reuse the real parser and existing disk checks,
|
||||
but do not construct or expose an ordinary editable index for typed input.
|
||||
The [contract](analysis-mixed-cli-contract-20260925.md) specifies explicit
|
||||
identities, source8, report fields, original locations and exit behavior.
|
||||
|
||||
Share one discovery Budget/ModelCounts across included files and reserve the
|
||||
file metadata before parsing. Retain producer counters conservatively after
|
||||
each temporary syntax unit drops. This is cumulative discovery reservation,
|
||||
not a claim about live allocations. Drop that phase before complete semantic
|
||||
validation under a fresh budget with the original caller policy. Clamp the
|
||||
source-byte ceiling before disk reads. Stop on the first located mixed parsing
|
||||
failure so a span-only budget latch cannot be attributed to a later sibling;
|
||||
retain final filesystem and pending-journal checks.
|
||||
|
||||
[Evidence](experiments/analysis-mixed-cli-20260925/README.md) at f10490b1 checks
|
||||
whole independent OA/SA models, exact reports and bytes, cumulative limits,
|
||||
ordinary migrations/saves and finite stack controls. New public disk and CLI
|
||||
tests passed initially; two old CLI assertions still expected schema7. Correct
|
||||
only their exact migration/header expectations, retaining the immutable fixture,
|
||||
all40 identities and full-text/model/fixed-point checks. Alias the test process
|
||||
Command import to remove the observed warning. Preserve those original outcomes.
|
||||
|
||||
Independent review also found the actual alarm include_str fixture missing
|
||||
from the inherited recorder's input recipe. Add that precise path before final
|
||||
gates (567 inputs); keep the six initial 566-input receipts and their omission
|
||||
caveat. Final source-bound checks pass 302 core,98 integrations,3 docs, strict
|
||||
core/CLI Clippy and5 direct CLI runs. Formatting remains the same inherited
|
||||
failure. Publication recovered without changing the existing release; mixed
|
||||
editing, application adoption and Linux qualification remain separate work.
|
||||
|
||||
+378
-19
@@ -1,20 +1,233 @@
|
||||
# Verified branch checkpoint — 2026-09-13 UTC
|
||||
# Published Windows preview and branch checkpoint — 2026-09-24 UTC
|
||||
|
||||
This describes Codex-956atf's contribution, not a combined release.
|
||||
The published preview below identifies the combined delivery. Earlier
|
||||
contribution checkpoints retain their original source and acceptance scope.
|
||||
[PROJECT_GOAL.md](../PROJECT_GOAL.md) remains authoritative. The complete OA/SA
|
||||
application is unfinished; published previews and finite prototypes are intermediate.
|
||||
|
||||
**Linux/WSL builds and checks remain deferred until the user explicitly reports
|
||||
networking resolved.** No guest setup, diagnosis, restart or cache transfer is
|
||||
active. The VPN remains untouched.
|
||||
**The current prerelease is Windows-only. Linux/WSL builds and checks remain
|
||||
excluded by the user's explicit request, including after networking recovers.**
|
||||
|
||||
## Current integrated candidate and evidence
|
||||
Published [integrated Windows preview](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/tag/v0.2.0-preview.integrated.20260924):
|
||||
**v0.2.0-preview.integrated.20260924**, release7, prerelease=true, draft=false.
|
||||
The tag, exact release body and all seven attachment identities were read back
|
||||
after publication. The 34,168,661-byte Studio ZIP has SHA256
|
||||
`5554e32533e3cb2c33fb4143a5a0902733d5a8d47577303cb2842d268e7bc76d`;
|
||||
the release includes its checksum, two companion kits/checksums and VALIDATION.md.
|
||||
[Release notes](prerelease-integrated-20260924-release-notes.md) and
|
||||
[final validation](prerelease-integrated-20260924-validation.md) identify exact
|
||||
commands, evidence, launch steps, known limits and the two machines' bounded
|
||||
packaged trials. Full application and broad human-checklist acceptance remain
|
||||
unfinished; this development-profile preview is ready for human verification.
|
||||
|
||||
The published Windows source is
|
||||
**715036e132677dd2bc2fb37ed316d93dc9987aec** on
|
||||
`codex/prerelease-integrated-956atf-20260924`. Its
|
||||
[source handoff](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/715036e132677dd2bc2fb37ed316d93dc9987aec/harness/prerelease-integrated-source-20260924.md)
|
||||
identifies the integrated contributions, reviewed event correction and exact
|
||||
test paths. Combined runtime/package acceptance is separate from the
|
||||
contribution-specific evidence below. [Issue37](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/37)
|
||||
owns current build and release coordination.
|
||||
The Route helper qualification and Allocation Text Apply test import corrections
|
||||
are included; both earlier compile failures occurred before tests ran. The candidate's 66 package
|
||||
documents/examples pass [closure and source-identity verification](reviews/prerelease37-windows-documents-20260924.md).
|
||||
The separate e68a839 Route contribution's raw test/lint evidence passed an
|
||||
[independent evidence review](reviews/prerelease37-route-evidence-20260924.md);
|
||||
its results do not establish combined-candidate execution.
|
||||
The full Windows test run at `8ddfadf4` failed a State picker fixture whose
|
||||
canvas-relative coordinates hit the added selection toolbar. The current
|
||||
source includes peer `a9cd364e`'s measured picker slot and capture assertion;
|
||||
the [independent source review](reviews/prerelease37-state-picker-20260924.md)
|
||||
retains its bounded assumptions. [Reviewed targeted evidence](reviews/prerelease37-state-picker-evidence-20260924.md)
|
||||
at `a9cd364e` passes formatting and all26 State tests, including the original
|
||||
failure. The corrected combined [test-evidence review](reviews/prerelease37-final04-tests-20260924.md)
|
||||
at `715036e` verifies 2,200 passed, eight ignored and zero failed across all
|
||||
2,208 names in 61 native harnesses, including all 29 required cases. The
|
||||
[complete gate review](reviews/prerelease37-final04-complete-20260924.md) verifies
|
||||
all 3,709 inputs against immutable Git bytes, strict workspace Clippy and the
|
||||
individual Studio/server builds. The supplemental combined build also passes;
|
||||
its differing artifacts are not the selected package inputs. Packaged acceptance
|
||||
remains separate. The [downloaded package](reviews/prerelease37-downloaded-package-20260924.md)
|
||||
passes exact archive/product/document checks. [Server evidence](reviews/prerelease37-package-server-20260924.md)
|
||||
verifies 16 requests and exact model/source/revision/ETag persistence across an
|
||||
owned forced restart; the initial legacy-schema fixture expectation failure is
|
||||
preserved. [Packaged GUI evidence](reviews/prerelease37-native-gui-20260924.md),
|
||||
[separate-machine QA](reviews/prerelease37-independent-qa-20260924.md) and the
|
||||
[parent visual cross-check](reviews/prerelease37-parent-visual-20260924.md) pass
|
||||
their bounded reviewed scopes. State label congestion, explicit transition-form
|
||||
Cancel and the preserved launcher refusals remain described in final validation.
|
||||
|
||||
## Published read-only mixed source CLI — 2026-09-25
|
||||
|
||||
Source **f10490b13bb3332ff60c2372d554e276f6f44959** is pushed and ref-verified
|
||||
on `codex/analysis-mixed-cli-956atf-20260925`. `arcadia check-mixed ROOT [--json]`
|
||||
discovers explicit-ID schema8 files with the existing filesystem safeguards,
|
||||
then validates the complete ordinary and typed model. Reports preserve original
|
||||
source locations; the command does not change files. Ordinary CLI commands retain
|
||||
their separate migration and editing behavior.
|
||||
|
||||
The [contract](analysis-mixed-cli-contract-20260925.md) and
|
||||
[Windows evidence](experiments/analysis-mixed-cli-20260925/README.md) identify
|
||||
302 core passes, 98 integration passes across eleven suites, three doctests,
|
||||
strict core/CLI Clippy and five direct CLI trials. Exact source bytes, report
|
||||
contents, unchanged file inventories and eleven prior small-stack controls were
|
||||
independently reconciled. The original two stale schema7 test expectations and
|
||||
import warning remain in the evidence, alongside their test-only repairs.
|
||||
The final 567-input recipe includes the alarm fixture omitted by the initial
|
||||
566-input recipe; the initial omission is explicitly retained as a limitation.
|
||||
Formatting still reports the identical pre-existing differences.
|
||||
|
||||
Discovery and final validation have separate bounded budgets; cumulative
|
||||
discovery reservations are conservative and do not establish an all-heap bound.
|
||||
This checkpoint supplies no mixed editing/save/history, graphical adoption,
|
||||
atomic filesystem snapshot or universal depth128 guarantee. The existing
|
||||
Windows prerelease is unchanged, and Linux remains deferred. Live continuation
|
||||
and the user's requested pause belong in issue7, not this checkpoint.
|
||||
|
||||
## Published public mixed source8 read API — 2026-09-25
|
||||
|
||||
Source **bab6f96a5b05b37f2b5d67a430aed0f67d783e73** on
|
||||
`codex/analysis-public-read-956atf-20260925` exposes
|
||||
`language::check_mixed_bundle(&SourceBundle, ProjectLimits)`. The result borrows
|
||||
the complete explicit-ID input and exposes only its admitted Project and located
|
||||
warnings. It retains the existing syntax, storage and admission evidence; no
|
||||
editable index, save permission or CLI discovery is implied.
|
||||
|
||||
The [contract](analysis-public-read-contract-20260925.md) and
|
||||
[Windows evidence](experiments/analysis-public-read-20260925/README.md) record
|
||||
299 core passes, ten new normal-library integration passes, 65 existing ordinary
|
||||
integration passes, three documentation cases, strict core Clippy and actual
|
||||
ordinary CLI check/rename-preview success at this exact source. All 298 prior
|
||||
core outcomes and the named small-stack controls pass. Format retains identical
|
||||
pre-existing differences. The first missing production initializer, subsequent
|
||||
warning cleanup and exact rustdoc recorder-name reconciliation are preserved.
|
||||
|
||||
Source and evidence were published after server storage recovery; all five
|
||||
backlog source refs and evidence ref `f810fb40` were read back successfully.
|
||||
[Issue7 handoff](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/7#issuecomment-1333)
|
||||
confirms publication and identifies the separately pending mixed CLI acceptance.
|
||||
The released preview is unchanged. Mixed CLI discovery is supplied above; graphical/editor adoption,
|
||||
typed saving/history and the broader application remain unfinished. Existing
|
||||
depth qualification and full-pipeline small-stack limitations remain; Linux/WSL
|
||||
checks remain user-deferred.
|
||||
|
||||
## Published ordinary source8 compatibility — 2026-09-25
|
||||
|
||||
Source **7b06b8ea1b7ef902ee0b3d0ec2971a9a7a1f1acd** on
|
||||
`codex/ordinary-source8-956atf-20260925` restores public ordinary parsing of the
|
||||
schema8 files already emitted by current formatters. Versions3–7 still migrate;
|
||||
typed analysis declarations remain explicitly unsupported by ordinary APIs.
|
||||
The [contract](ordinary-source8-compatibility-contract-20260925.md) and
|
||||
[Windows evidence](experiments/ordinary-source8-20260925/README.md) distinguish
|
||||
this compatibility repair from full mixed-source editing.
|
||||
|
||||
The unchanged implementation at **0c07f53ab517626f536f79dbaa2885a587bf1db7**
|
||||
passes all298 core tests, including the16 formerly header-blocked workflows,
|
||||
and60 selected integration tests. Actual CLI check and cross-file rename preview
|
||||
pass with exact reported changes and unchanged input files. The successor only
|
||||
repairs a historical JSON expectation and its note; its five migration tests and
|
||||
strict core all-target Clippy pass. Format retains identical pre-existing
|
||||
differences. Evidence preserves all three failed evaluator stages, two explicit
|
||||
test-name mappings and exact component-version reuse. Source and evidence are
|
||||
published after server recovery; the published preview is unchanged.
|
||||
|
||||
## Earlier private parser and output acceptance checkpoints — 2026-09-25
|
||||
|
||||
Source **edf096cd33350865ecfc3c65ec266a6c0d3c4000** on
|
||||
`codex/analysis-mixed-acceptance-956atf-20260925` connects real emitted output to
|
||||
combined parser producers, full model admission/equality and an owning result
|
||||
containing the actual bundle, model and mapped warnings.
|
||||
[Windows evidence](experiments/analysis-output-acceptance-20260925/README.md)
|
||||
records eleven new passes, strict core Clippy and all 281 prior outcomes preserved:
|
||||
the full 292-name run gives 276 passes/16 inherited failures. All 16 failure bodies remain
|
||||
identical after numeric thread-identifier normalization; format is unchanged.
|
||||
Ten inherited stack controls and new scoped 128 KiB verification/drop pass. Initial
|
||||
nine-pass/two-failure warning-oracle corrections and the exact build-target path
|
||||
spelling exception are preserved. Source and evidence are published. Public
|
||||
typed read validation is supplied above; installation/history and repeated
|
||||
carried editing remain incomplete.
|
||||
Ordinary source8 compatibility is supplied by the later checkpoint above.
|
||||
|
||||
The earlier **29417130c71f70c4eaefe8ed4c879efba78eb72c** on
|
||||
`codex/analysis-entry-producers-956atf-20260925` adds the reviewed
|
||||
[retained-entry producer route](analysis-entry-producer-contract-20260925.md).
|
||||
Its [Windows evidence](experiments/analysis-entry-producer-20260925/README.md)
|
||||
passes six new cases and strict core Clippy. Full library remains failed at
|
||||
265 passed/16 inherited failed, preserving all275 prior outcomes, all16 failure
|
||||
bodies (numeric thread identifiers only normalized) and all ten stack controls. Formatting is
|
||||
unchanged. Initial test-only compilation failure is preserved. This source and
|
||||
packet are published after server storage recovery.
|
||||
Actual output verification/accepted ownership is supplied by the later checkpoint
|
||||
above; public editing remains open.
|
||||
|
||||
Source **97a8703adc75467a7f8e75f5c6cb00ca542b707c** on
|
||||
`codex/analysis-text-producers-956atf-20260925` adds the separate private
|
||||
[syntax text producer route](analysis-text-producer-contract-20260925.md).
|
||||
Its [source-bound Windows evidence](experiments/analysis-text-producer-20260925/README.md)
|
||||
passes six new cases and strict core Clippy. Full library remains failed at
|
||||
259 passed /16 inherited failed; all269 prior outcomes and all ten stack controls
|
||||
are preserved. Format remains the same inherited failure. Failure output is
|
||||
15 exact blocks plus one precisely documented missing framework hint.
|
||||
|
||||
This source and evidence are published after server storage recovery, with
|
||||
remote evidence commit `f810fb40` verified alongside the source branch;
|
||||
emission source `8d52dab9` is published separately. This checkpoint does not
|
||||
change the integrated preview. The later acceptance contract explicitly selects
|
||||
the remaining scratch domain and implements actual output verification/ownership;
|
||||
its exclusions and public-integration limits remain material.
|
||||
|
||||
## Earlier local contribution checkpoint and evidence
|
||||
|
||||
Branch `codex/behavior-authoring-20260910`, published as `codex/release1-956atf`.
|
||||
Current source **c28abcf13a834585a9954f7e54175d47c0a0460b** adds Find focus and
|
||||
departure-selection corrections. Combined execution and native acceptance are
|
||||
not yet established; [integration issue27](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/27)
|
||||
holds current verification and release coordination.
|
||||
Integrated code checkpoint **4ffff0d9d94bd1875e6b316b84ac11e5c5c9657c** combines
|
||||
the reviewed ordinary/Text contribution **3f9e6a18af96b5cd10940da4093be8da28b9c835**
|
||||
with source-editor Tab/Shift+Tab indentation. Windows desktop verification passes
|
||||
1,188 tests with six existing ignores; all 1,194 names and nine targeted
|
||||
indentation cases are accounted for. Strict desktop Clippy and matching GUI
|
||||
build pass on 711 unchanged inputs. The closed native trials cover caret and
|
||||
forward/reverse block indentation, text undo/redo, empty drafts, continued caret
|
||||
typing and Apply/Save/reopen. The saved 577 bytes exactly preserve the baseline's
|
||||
mixed line endings and Unicode while indenting its 13 physical lines. The first
|
||||
trial restored the baseline and is not a save oracle. Find's Tab does not advance
|
||||
focus; this inherited limitation is distinct from the verified editor boundary.
|
||||
This is Windows contribution acceptance, not complete editor accessibility,
|
||||
public source8, a combined peer union, or a packaged release.
|
||||
[Exact gates, original native captures and independent review](experiments/text-indentation-4ffff0d-20260923/README.md)
|
||||
retain both the failed initial compilation and the interrupted first trial.
|
||||
|
||||
Earlier code checkpoint **8abc144cf233c64e43c6bee5033c22ee818e2d14** preserves
|
||||
the production inputs of **feab2020d8e5b6bfdb59c86ab4aee161617b8b6f**. Its Windows
|
||||
desktop suite passes 1,096 tests with three existing manual ignores; all 1,099
|
||||
names are admitted. Targeted navigation/rename checks, strict desktop Clippy and
|
||||
the matching development GUI build pass. The closed native trial verifies
|
||||
Details-to-Preview scroll restoration, explicit reset boundaries, and exact
|
||||
six-file preservation after Cancel and Save. The
|
||||
[portable evidence](experiments/rename-scroll-feab202-20260913/README.md), published
|
||||
at **f95d0310482565e91220a97e13fc756f27f9d590**, retains the initial failing test,
|
||||
20 original frames and independent review. Its committed bytes and verifier were
|
||||
rechecked on September 22. This narrow trial does not establish Text integration,
|
||||
complete rename acceptance or release readiness.
|
||||
|
||||
Earlier production source follows; each result retains its original code scope.
|
||||
Verified production source **44095f78c28b79d6d085863dc928adba8e24d955** includes
|
||||
Find focus, departure-selection and scoped Escape corrections. Its Windows
|
||||
desktop suite passes1095 with3 existing manual ignores; core passes471 with1
|
||||
manual ignore; server passes56. All three strict Clippy scopes and the matching
|
||||
development GUI/server build pass. [Exact source, commands and raw evidence](release-navigation-440-windows-20260913.md).
|
||||
The integrated documentation checkpoint **3c22fe2629fc242714d32805790262fa2c4e33b9**
|
||||
preserves those production inputs and includes the updated AGENTS instructions.
|
||||
|
||||
The actual440 native trial closed normally with79 notes,78 images and14 complete
|
||||
saved-model/source comparisons. Rename/Undo/Redo/reopen, scoped selection,
|
||||
placement/state targeting and sampled OA/SA lifecycle/topology navigation are
|
||||
verified within the [closed trial's explicit scope](experiments/navigation-native-440-20260913/REPORT.md).
|
||||
It found a same-page Details-to-Preview scroll-loss defect; initial keyboard
|
||||
Delete after chooser navigation also required an explicit canvas click. Neither
|
||||
is hidden by passing saved-byte checks. The scroll defect is corrected and
|
||||
verified by the separate feab trial above; the initial chooser-to-canvas keyboard
|
||||
focus friction remains a limitation of the 440 trial. This remains a development
|
||||
checkpoint, not a combined release. [Integration issue27](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/27)
|
||||
owns current verification, correction and release coordination.
|
||||
Earlier source **e1240295bd114d23d3f67a69e6b38bdb2e25bb0d** combines the canvas
|
||||
contribution with source/diagram navigation and reviewed alias rename. Its1082-test
|
||||
listing,17 cross-feature tests,4 mounted preview-scroll tests and strict all-target
|
||||
@@ -70,16 +283,162 @@ failures and corrections. Earlier authoring and allocation checkpoints remain in
|
||||
|
||||
## Isolated contributions and material limitations
|
||||
|
||||
Analysis/core source checkpoint **b2c970b4673e062e47eadd12906d2316c4b1a7b3**,
|
||||
Combined peer candidate **e34ba27e26ede3ab55f276acc250d92b2e0c3204**, published on
|
||||
`codex/peer-union-956atf-20260923`, composes current Text/Tab with saved Scenario,
|
||||
final inspector actions, attachments, State bends and the transition footer.
|
||||
The literal Windows workspace suite passes 2,005 tests with zero failures and
|
||||
eight named ignores; all 2,013 listed names across 60 executables and three
|
||||
doctest sections are accounted for. Strict workspace/all-target Clippy and the
|
||||
matching native/external-oracle builds pass on 760 unchanged inputs. The
|
||||
[portable gate evidence](experiments/peer-union-e34-windows-20260923/README.md)
|
||||
binds three rebuilt executables through fresh listings and preserves the failed
|
||||
historical f82 desktop run (1,337 passed, three failed, seven ignored), the
|
||||
missing-DLL listing attempt, and capture limitations. Its verifier passes the
|
||||
positive case and rejects all 12 semantic mutations. The preceding
|
||||
[partial gate archive](experiments/peer-union-windows-20260923/README.md) retains
|
||||
earlier Scenario and lint failures. The separate
|
||||
[native checkpoint](experiments/peer-union-e34-native-20260924/README.md) records
|
||||
33 successful whole-model/source checkpoints, the retained failed G2 pointer
|
||||
attempt and its recovery, and five transition checks through fresh reopen and
|
||||
unchanged reapply. The first trace identity and all resulting source-bundle bytes
|
||||
remain exact. Independent review checks 245 frame pins and inspects 38 keyframes;
|
||||
17 transition-oracle controls meet their expected outcomes. The original
|
||||
interrupted process and later normal-close observations remain distinct. Dirty
|
||||
middle-button pan, held-drag Escape and short-window Scenario Apply are unobserved.
|
||||
Public format and release acceptance remain incomplete; accepted root production
|
||||
remains4ffff0d. The newer prerelease candidate and live coordination are in
|
||||
[issue37](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/37).
|
||||
|
||||
Analysis/core source checkpoint **a2a28f8d23a46ba1696b6a8410d4d3b5c1808f49**,
|
||||
publication branch `codex/analysis-core-956atf-20260911`, is not integrated into
|
||||
production. It adds source-save decode/equality containment and a private staged
|
||||
expression/declaration parser, then repairs the frozen source3 lowering envelope.
|
||||
Its129-test library run has113 passes and16 failures, all at the unsupported
|
||||
source8 header. All22 expression/declaration/token cases and8 bridge/save guards
|
||||
pass; strict all-target Clippy passes on524 unchanged inputs. The separate language
|
||||
integration target has7 passes and9 failures:8 unsupported headers and an old V2
|
||||
oracle that omits the new empty definitions catalog. [Exact S2a evidence](release-analysis-source-s2a-20260913.md)
|
||||
preserves every failure and the independent structural comparison.
|
||||
production. Its private staged typed parser/lowerer has142 listed tests,
|
||||
34 passing typed cases,1 passing raw-token case and strict all-target core Clippy
|
||||
on531 unchanged inputs. The complete library run remains126 passed/16 failed,
|
||||
with all16 failures at the unsupported public source8 header. The original
|
||||
fixture error and its test-only correction remain in [exact S2b evidence](release-analysis-source-s2b-20260913.md).
|
||||
Published private writer **f1d79df4979121335ed7b4ce4da84b2fca8a9ef4** has
|
||||
[portable S2c evidence](experiments/analysis-source-s2c-windows-20260913/README.md):
|
||||
152 listed, 44 typed and one token test passed, strict Clippy passed; the full
|
||||
library result remains 136 passed / 16 failed at unsupported public source8.
|
||||
Published source **1b1c3e3abb6fc3d0934c9dbfbd21fddc8ae4f594** adds a private
|
||||
qualified source index/rename plan and the independently reviewed cleanup for
|
||||
the demonstrated depth129 rejected-tree stack overflow. Its
|
||||
[S3 evidence](experiments/analysis-source-s3-windows-20260922/README.md), published
|
||||
at **345a42e4658f6e0e8e01ef64a2df8f4e28a8945a**, records 167 listed tests,
|
||||
59 typed passes (nine index/five update), one token pass, three clean stack
|
||||
controls and strict Clippy on 538 unchanged inputs. The original overflow and
|
||||
dirty diagnostic/probe results are retained. No current full-core pass is
|
||||
claimed. Public source8 parser, writer, source-update and persistence composition
|
||||
remain incomplete; these branches are not integrated production analysis.
|
||||
|
||||
Published private source **10d7f3340d5cd61a656dc0bcf7c143f8897c5551** adds
|
||||
complete borrowed original-span export for later edit composition. Its
|
||||
[Windows evidence](experiments/analysis-original-span-20260923/README.md) records
|
||||
173 listed tests (all prior 167 retained), 65 typed passes including all 11
|
||||
updater cases, and strict core all-target Clippy on the same 538 committed
|
||||
inputs. Review caught and corrected an intermediate standalone budget
|
||||
regression. This is an isolated export adapter; the later syntax checkpoint
|
||||
below supplies mixed-bundle ownership, while output compilation and public
|
||||
source8 remain incomplete.
|
||||
|
||||
Published private mixed-syntax source
|
||||
**a578ac98a06772a60bec00ae287e65650680d119** retains the complete source bundle,
|
||||
original positions and exact caller policy, using shared ordinary/typed token
|
||||
consumption with explicit identities and aggregate file/byte admission. Its
|
||||
[Windows evidence](experiments/analysis-mixed-syntax-20260923/README.md) records
|
||||
194 listed tests, all prior 173 retained, 20 focused mixed passes and 85 typed
|
||||
passes within the actual full result: **178 passed / 16 failed**. All 152
|
||||
historical statuses are unchanged and all 42 later tests pass. Strict core
|
||||
all-target Clippy passes on 541 unchanged committed inputs. Formatting remains
|
||||
failed in six inherited, unchanged files. Original failed gates and the host
|
||||
clock discontinuity are retained; a fresh actual direct listing binds the final
|
||||
focused/full executable after Cargo rebuilt it. This syntax witness does not
|
||||
resolve or admit a complete mixed Project, activate public source8 or implement
|
||||
editing composition. The accepted
|
||||
[complete-Project contract](analysis-mixed-project-contract-20260923.md) defines
|
||||
the semantic boundary implemented by the separate private checkpoint below.
|
||||
|
||||
Published private complete-Project source
|
||||
**aaec78fcc9b273d1485497126392afdd1fb2e54e** retains the original syntax, bundle,
|
||||
budgets and limits while resolving/admitting the complete ordinary/typed model.
|
||||
The next [mixed typed-index contract](analysis-mixed-index-contract-20260924.md)
|
||||
is accepted after source review and resolved accounting/completeness findings.
|
||||
Private typed-index source **93eb6117f95353d25d594d59780018f197c51672** implements
|
||||
the consumed witness and shared verifier. Its
|
||||
[Windows evidence and independent oracle review](experiments/analysis-mixed-index-20260924/README.md)
|
||||
verify strict core Clippy, all seven new cases and the complete 216-name inventory
|
||||
on 545 unchanged inputs. Full library remains **200 passed / 16 failed**,
|
||||
preserving all 209 baseline statuses; formatting still has the identical eight
|
||||
inherited blocks. Original lint and depth-expectation test failures are preserved.
|
||||
The [source review](analysis-mixed-index-20260924/source-review.md) records three
|
||||
repaired diagnostic findings; its reviewed production hashes are unchanged.
|
||||
The new owner keeps legacy updater authority separate. Complete mixed editing
|
||||
and public source8 remain required.
|
||||
The [ordinary occurrence successor contract](analysis-ordinary-index-contract-20260924.md)
|
||||
uses retained parser positions and physical token keys, with a separate consumed
|
||||
read-only owner. Private source **ee500908e3d77182ddd54e12524f9b6c6eb43b60** now
|
||||
implements that dependency. Its [Windows evidence and independent review](experiments/analysis-ordinary-index-20260924/README.md)
|
||||
verify all13 new cases, strict core Clippy and the229-name inventory on549
|
||||
unchanged inputs. Full library remains **213 passed /16 failed**, with all216
|
||||
prior outcomes and failure bodies unchanged; formatting retains the identical
|
||||
eight inherited blocks. Initial9-pass/4-fail fixture evidence and exact test-only
|
||||
repairs are preserved. Both occurrence families now retain complete original
|
||||
authority, but no rename composition or public edit capability follows yet.
|
||||
The [whole-target rename planning contract](analysis-mixed-rename-plan-contract-20260924.md)
|
||||
is implemented privately at **18073a6f2eabce83fc83997f094e331eec835a16**.
|
||||
Its [Windows evidence and independent review](experiments/analysis-mixed-rename-plan-20260924/README.md)
|
||||
verify all 17 new tests and strict core Clippy on 551 unchanged inputs. The full
|
||||
246-name run remains **230 passed / 16 failed**, preserving all prior outcomes;
|
||||
formatting retains identical inherited failures. Complete non-name comparison,
|
||||
simultaneous namespaces, exact merged edits, inherited caps and combined sizing
|
||||
are verified. The scoped planner comparison/drop test passes on 128 KiB;
|
||||
separate full-pipeline parsing/setup overflows remain explicitly unresolved.
|
||||
The [carried-phase prerequisite](analysis-carried-phase-contract-20260925.md)
|
||||
is implemented privately at **fa7a980418ef99d772e67c66c28dfa7b5181f875**.
|
||||
Its [Windows evidence](experiments/analysis-carried-phase-20260925/README.md)
|
||||
records 12 new passes, strict core Clippy, 553 unchanged inputs and a completed
|
||||
258-name full run with **242 passed / 16 failed**. Exact policy, retained bundle
|
||||
ownership and aggregate phase accounting survive parsing and resolution;
|
||||
legacy checkpoints remain unchanged. An initial full-run stack regression was
|
||||
corrected by retaining a smaller guard, with the existing 128 KiB controls
|
||||
unchanged and passing. The earlier separate setup overflow remains unresolved.
|
||||
At that checkpoint, continuation constructors are fixture-only. The subsequent
|
||||
[private output-emission contract](analysis-mixed-emission-contract-20260925.md)
|
||||
is implemented at **8d52dab97c92cc31baae9f20d8c324b55818aa5d** on
|
||||
`codex/analysis-mixed-emission-956atf-20260925`.
|
||||
Its [Windows evidence](experiments/analysis-mixed-emission-20260925/README.md)
|
||||
records eleven new passes and a completed 269-name full run with **253 passed /
|
||||
16 unchanged failed**, strict core all-target Clippy and identical inherited
|
||||
formatting failures on 555 unchanged inputs. The consuming no-op preserves the
|
||||
original owner; changed output reserves all owned source storage before copying
|
||||
and remains private and unverified. Borrowed carried owners cannot use the changed
|
||||
path. An initial stack abort is preserved; a mechanical parser split reduces
|
||||
the observed numeric-prefix prologue reservations by 13,032 bytes, and the
|
||||
unchanged overflowing control passes the final suite and three fresh processes.
|
||||
Accepted editing and stronger parser allocation-timing obligations remain open.
|
||||
[DECISIONS.md](DECISIONS.md) records the scope and rejected
|
||||
alternatives; live ownership and acceptance remain in issue7.
|
||||
The preceding Project [Windows evidence](experiments/analysis-mixed-project-20260924/README.md)
|
||||
distinguishes runtime source **71cadfa0cd0e112caa29588d2494753301f3cb6c** from
|
||||
the formatting-only aaec successor. Strict core all-target Clippy, actual listing
|
||||
209, Project 13/13, shared validation 2/2 and four exact public compatibility
|
||||
cases pass on 544 unchanged inputs. Full lib remains **193 passed / 16 failed**,
|
||||
preserving all prior statuses and exact unsupported-public-source8 diagnostics.
|
||||
Successor formatting remains failed on eight inherited blocks in five unchanged
|
||||
files; no aaec runtime rerun is claimed. The parent-reviewed portable verifier
|
||||
and all 15 finite controls pass, with independent raw-output/pin readback.
|
||||
This private source is not integrated into the application prerelease. Public
|
||||
source8, mixed edit execution, checked output and UI parity remain
|
||||
unfinished.
|
||||
|
||||
The [reviewed S1/S7 assessment](issue28-s1-s7-assessment-956atf-20260923.md)
|
||||
distinguishes static analysis/case overlays from contextual inheritance,
|
||||
fixed/default bindings and executable trade studies with durable result
|
||||
provenance. Strengthened fixture and parity criteria remain proposals, not
|
||||
implemented evaluation or a replacement metamodel decision.
|
||||
Earlier [S2a evidence](release-analysis-source-s2a-20260913.md) retains its
|
||||
129-test113/16 library result and separate7/9 language integration result,
|
||||
including the old V2 oracle that omitted the empty definitions catalog.
|
||||
[Earlier bridge evidence](release-analysis-source3-bridge-20260913.md) remains scoped
|
||||
to6216cff.
|
||||
The earlier2c515cf full library run had98 passes and16 failures:14 rejected the
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# Private carried-baseline phase-check contract
|
||||
|
||||
2026-09-25. **Selected private prerequisite; implementation and runtime acceptance remain pending.** Source inspected: `18073a6f2eabce83fc83997f094e331eec835a16`. This contract builds on [the domain audit](analysis-mixed-rename-execution-20260924/CARRIED-STORAGE-DOMAIN-AUDIT.md) and the accepted mixed-parser, mixed-Project, typed-index, ordinary-index and mixed-rename-plan contracts. It neither implements a parser nor grants rewritten-output acceptance.
|
||||
|
||||
## 1. Deliverable and nonclaims
|
||||
|
||||
Introduce one private way to parse a deliberate complete snapshot under the **exact inherited Limits and ProjectLimits**, while carrying a constructor-controlled live auxiliary baseline through existing parser phase checks and subsequent resolution. The resulting parsed/resolved witnesses keep that baseline; no separately passing fresh ledger may hide it.
|
||||
|
||||
The metric remains the existing logical triple `(entry_slots, lower_occurrence_slots, owned_in_scope_text_bytes)`. This dependency preserves current parser timing limits: it is **not before-every-allocation admission**, a complete parser-transient inventory, a raw model/serde/validator heap meter, an allocator-capacity/RSS bound, or a stack guarantee. Existing grammar entry checks, raw token/byte/Exact accounting and model/static policies remain intact.
|
||||
|
||||
This is independently useful because any later owned-output verifier needs exact policy and nonzero live-storage participation before it can safely compose existing parser/resolver phases. It is insufficient on its own to accept rewritten output. Emission reservations, actual-byte verification, whole-intent equality, returned ownership and installation/history remain separate successor requirements.
|
||||
|
||||
## 2. Ownership and construction authority
|
||||
|
||||
The production continuation is private and constructible only from an owning or borrow-bound retained-state witness with a verified ledger and exact policy. A scalar Slots argument alone is not authority. It contains the inherited policy and the scalar carried live Slots. It must not be Clone/Copy or expose a production constructor accepting arbitrary Limits, replacement Budget or arbitrary Slots. A scalar Slots type can remain Copy internally; the authority wrapping it cannot be independently duplicated through its API.
|
||||
|
||||
Selected scope: no production constructor or old-owner/emitter transition is delivered in this prerequisite. Both borrowed and retained construction remain in fixture-only helpers; the production-shaped parser/guard machinery is exercised without granting fabricated output authority. Test-only construction binds a real retained output-shaped fixture owner and its actual bundle; it demonstrates arithmetic and propagation, not an implemented emitter transition. A bare Slots argument plus an unrelated later bundle is forbidden even for the proposed production shape. The minimal concrete ownership seam is specified in §5.
|
||||
For actual later use, the transition must distinguish:
|
||||
|
||||
- **Old auxiliary state dropped:** consume and finish dropping old syntax/index/maps/warnings/plan-owned auxiliary data before constructing the verification continuation. Surviving output buffers/map/path keys/entry and any additional named auxiliaries supply C.
|
||||
- **Old auxiliary state retained:** C includes the still-live old baseline plus all surviving new output/auxiliary ownership. A mere change of phase cannot release old reservations.
|
||||
|
||||
The desired Project remains an external immutable borrow with the established model-allocation exclusion. An emitted SourceBundle must have a stable external owner throughout any syntax/result borrowing it. Do not return an owning bundle alongside a witness that borrows that same field. A future callback/scoped verifier or drop-syntax-then-own-output result requires its own accepted design.
|
||||
|
||||
The parser consumes the continuation and borrows the actual complete SourceBundle. Entry, canonical paths, exact file set/bytes and normal include/reachability authority still come from that bundle and the normal traversal. No replacement numeric file table, caller-supplied tokens/model, loose index or partial file subset is accepted. Failure returns diagnostics, no reusable continuation or partial witness; its external output owner remains responsible for dropping its own buffers.
|
||||
|
||||
## 3. Policy and disjoint counters
|
||||
|
||||
Let:
|
||||
|
||||
- C = live carried Slots inherited from the owning transition; fixed for this parse/resolution attempt unless a documented owned allocation is actually released.
|
||||
- U = current snapshot `Budget.usage.entries`.
|
||||
- M = current existing `ParsedMixedSyntax.metadata` subtotal.
|
||||
- T = current snapshot retained syntax text counted by the existing bounded syntax-accounting walk at resolution.
|
||||
- A = subsequent existing resolver/catalog/lower/diagnostic reservations and named accounting scratch.
|
||||
|
||||
Create one **new-snapshot** Budget from the exact captured Limits. Preserve all Limits fields, including tightened bytes/tokens/entries/references/frames/numeric_units, and the complete captured ProjectLimits. Do not reconstruct defaults from only caller bytes/references, silently widen, or replace the old live witness's Budget. Work Usage and numeric usage start at zero for this deliberate snapshot and accumulate normally across all included files.
|
||||
|
||||
C is live storage, not parse work: do not add it to bytes/tokens/entries/references Usage, Exact work, model records or deepest_frame. New source bytes are charged once during scanning even if those same bytes are also carried owned output text: these are distinct work and storage dimensions. Original input/output parse work reports remain distinct, never reset/subtracted to pretend the reparse did no work.
|
||||
|
||||
All arithmetic composing C with phase totals must use checked addition and refuse overflow. The entry ceiling is Limits.entries; occurrence ceiling remains the existing entries-plus-references ceiling; text ceiling remains Limits.bytes. Aggregate output byte size remains a separate source-size check. A failure from nonlatching lowering/index phase checks must propagate immediately; later `Budget::active()` is not a substitute.
|
||||
|
||||
## 4. Exact phase checks and temporal limits
|
||||
|
||||
Use the current syntax charge table without adding speculative containers. In particular M begins with file references and later adds the current `tokens.len()`-based metadata component, value-end subtotal, ordinary position slots and lexical-owner count (`mixed.rs:277–280,321–330`). The module header describes the token-count component as token-end metadata and tokens themselves as token-bounded; preserve the existing one component, **do not introduce a second tokens.len() charge** by relabeling it. Dropped value-end subtotal may remain the inherited conservative overestimate.
|
||||
|
||||
Required ordering/checkpoints for the explicit carried route (legacy wrappers retain their existing checks):
|
||||
|
||||
1. **Continuation admission:** after policy validation/Budget construction and before broad traversal allocation, check all three C dimensions against the exact inherited ceilings. Report overflow/cap failure safely at entry/default span.
|
||||
2. **Complete input size precheck:** retain current checked sum of all source file lengths and `index_bytes(total_source_bytes)` (`mixed.rs:269–276`). Do not sum borrowed input bytes into C.text again merely because they are being parsed. In the output-owned case their ownership is already in C.
|
||||
3. **Initial file metadata:** preserve the current file-slot precheck before `Traversal::new` (`:277–284`), replacing its independent entry check with `C.entries + M` (U is zero here).
|
||||
4. **Existing scan/grammar checks:** preserve current raw token, byte, syntax-entry, reference, depth and Exact event checks exactly. Do not add a new check on every allocation or change legacy parser semantics. C does not change these work counters.
|
||||
5. **Per-file preprojection metadata checkpoint:** after the parsed unit and existing `ordinary_position_slots` count, construct prospective M with checked arithmetic, then check **C.entries + U + M** before position projection (`:319–340`). This is the new combined aggregate phase check. It includes all completed prior files and current grammar work. It is not a proof that current-unit ASTs, tokens or counting scratch were never temporarily allocated before refusal.
|
||||
6. **Successful complete-syntax boundary:** after traversal succeeds and before returning the witness, recheck C plus final U+M, and C's other dimensions. Preserve exact carried C and scalar M in the sealed syntax result. No second reservation is created by a noncharging check.
|
||||
7. **Resolver transition, exactly once:** start its Ledger with C, then run the existing syntax-accounting admission once: reserve U+M and walk retained structures to reserve T and accounting-work slots. Continue all existing catalog, lowering, mapped-diagnostic and index reservations from that same ledger. Final resolver baseline is C+the normal resolved baseline, with the same existing releases. Do not add parser checks as reservations and charge U/M again; do not seed zero; do not run two syntax walks merely to recreate authority.
|
||||
|
||||
Parser-owned syntax Strings and selected parser temporaries retain their **existing timing**: retained text is admitted by the bounded walk after parsing, before resolver-dependent allocations. Traversal internals, position delimiter/end scratch and parser counting Vecs do not suddenly become individually Ledger-metered. They retain existing independent file/token/depth controls; no universal auxiliary-preallocation claim may be made. Accounting::syntax's own counting work remains explicitly reserved before its growth.
|
||||
|
||||
The resolver already declares model/serde and raw architecture-validator allocations outside this metric (`accounting.rs:1,72–79`; Project contract §3). Keep these exclusions. Produced raw Issues are admitted into charged retained diagnostics before destination retention; output/source-key Strings newly introduced by a later emitter are in scope and cannot use the exclusions to disappear.
|
||||
|
||||
## 5. Smallest concrete Rust ownership seam
|
||||
|
||||
Selected private types (names may follow repository conventions):
|
||||
|
||||
```rust
|
||||
struct SnapshotPolicy { limits: Limits, project_limits: ProjectLimits }
|
||||
|
||||
// Owns the actual bundle represented by its verified retained slots. Fields
|
||||
// private; no production nonzero constructor until the emitter transition.
|
||||
struct RetainedSnapshot {
|
||||
bundle: SourceBundle,
|
||||
policy: SnapshotPolicy,
|
||||
retained: Slots,
|
||||
}
|
||||
|
||||
enum SnapshotBacking<'s> {
|
||||
// External caller-owned input, exactly like the existing parser domain;
|
||||
// its source bytes are borrowed, so C is zero. Not an emitted-owned result.
|
||||
Borrowed { bundle: &'s SourceBundle, policy: SnapshotPolicy },
|
||||
Retained(&'s RetainedSnapshot),
|
||||
}
|
||||
|
||||
// Not Clone/Copy. Methods derive bundle, exact policy and C from the backing;
|
||||
// no independently supplied bundle or arbitrary C at parse invocation.
|
||||
struct CarriedInput<'s> { backing: SnapshotBacking<'s> }
|
||||
|
||||
fn parse_carried(input: CarriedInput<'_>) -> Result<ParsedMixedSyntax<'_>, Diagnostics>;
|
||||
```
|
||||
|
||||
`RetainedSnapshot` keeps the output map, source Strings, path keys and entry alive; retained counts correspond to that exact owner. It must not have a public or generally available `new(bundle, slots, policy)`. For this prerequisite, `cfg(test)` builds a real retained fixture bundle and counts its F entries and actual source/key/entry UTF-8 bytes internally. Its policy comes from the tested existing immutable witness/profile, not a widened replacement. Production support for emission must later reserve these allocations before copying and install verified counts through its sole transition constructor. No arbitrary other live old-owner allocations may be claimed by this minimal retained shape; if the future design keeps old auxiliaries, add an explicit guard for them then.
|
||||
|
||||
The borrowed variant supplies a fixture-only carried C=0 route without pretending an owned output is free. It captures exact policy through a narrow internal read-only policy snapshot of an existing sealed witness. There is no independent replacement profile at `parse_carried` invocation. Its bundle is fixed in the input. Test-only tighter-profile construction remains explicitly test-only. The two backing variants describe ownership, not a numeric-zero branch controlling checks.
|
||||
|
||||
Consume `CarriedInput<'s>` at parser entry, transferring its exact policy into the new Budget and existing syntax ProjectLimits field. Retain only a small `SnapshotGuard<'s>` distinguishing borrowed zero carry from a reference to the allocation-owning RetainedSnapshot. Do not duplicate the full policy inside every later syntax/resolved/index/plan value. The current bundle reference is derived from the same consumed input. This uses the existing bundle lifetime, so no self-reference or extra generic lifetime is needed. In retained mode both references borrow the external stable snapshot; the syntax cannot outlive it. Keep the small guard inside syntax when resolve consumes syntax and places it in `ResolvedMixedProject`. Read-only methods expose no way to remove or replace the guard. Baseline extraction for resolution is an internal scalar read, not a second independently transferable authority.
|
||||
|
||||
Use one shared parse body with an explicit legacy-versus-carried option. Existing parse wrappers select legacy and retain their old checkpoint timing. The carried entry always runs combined checks, including its borrowed C=0 variant. Do not select behavior with `C == 0`. A narrow resolver initialization obtains C from the guard (zero for legacy), seeds Ledger once, and invokes existing `accounting::syntax` once; existing resolved ownership already retains syntax and therefore the guard. No separate wrapper around every later index phase is necessary.
|
||||
|
||||
The current Budget keeps Limits private. Add only an internal read-only exact-policy snapshot seam if needed, not mutation or resetting of a live Budget. New snapshot Usage remains independent. Do not implement carry by subtracting C from Limits globally; that would conflate storage with source/token/reference/depth/numeric work. Do not duplicate grammar, include budgets, scans, model state or generic allocation infrastructure.
|
||||
|
||||
This representation deliberately postpones an owning accepted-output result and emitter. An actual emitted bundle must live in `RetainedSnapshot` (or an equally explicit future sealed owner) before verification borrows it. Parsing/resolution failures drop the temporary guard/witness; the surrounding owner then drops output normally. No accepted output or installation authority escapes merely because a carried parse/resolve succeeded.
|
||||
## 6. Observable acceptance through real paths
|
||||
|
||||
Except explicitly labeled arithmetic/fault-injection controls below, cases must use real `parse_with_profile`-equivalent parsing and `resolve`, not synthetic parser outputs or a separately fabricated accepted Project. Expected arithmetic and affected phase/location are independently authored. Do not mutate a live admitted owner to tighten its Budget.
|
||||
|
||||
1. **Zero-C compatibility:** accepted existing OA/SA, multiple canonical files, Unicode/CRLF, ordinary positions, warnings, Project, original bundle borrowing and parse/numeric Usage remain identical through full resolution/index. Compare opt-in carried C=0 successful outcomes with the original entry, while separately verifying the original path preserves its old refusal timing. Current ordinary callers preserve exact policy and prior phase behavior. Run existing syntax/project/index/rename tests and retain inherited failure dispositions. The earlier-refusal qualification below must be explicit.
|
||||
2. **Carried retention:** a small admitted bundle with independently hand-counted baseline C yields the same complete Project, warnings, syntax work/numeric usage and canonical file keys as zero C. Resolved live Slots differ by exactly C in each domain; lower temporary releases never release C. This output-shaped owner has C.occurrences = 0; occurrence overflow/cap checks may be fault-injection or direct arithmetic tests, not claims of a real retained occurrence owner.
|
||||
3. **Initial checkpoint:** C entries plus all-file references exactly fit/fail at cap/cap-minus-one before traversal; C text/occurrences each independently fit/fail without relabeling source bytes or references. Use realistic retained fixture storage for positive cases. Dedicated arithmetic-overflow tests may use test-only max values.
|
||||
4. **Combined C+U+M checkpoint:** author a real minimal/multi-file fixture where each independent C, U and M fits but the sum fails. Cap-minus-one refuses at the intended preprojection or final syntax boundary, with original current-file diagnostics if that checkpoint has a justified file. Exact cap returns syntax; resolve may need more headroom and must not be claimed passed under that smaller cap. For a combined parser+resolver positive, choose the cap from the measured/hand-counted maximum of **all** phases.
|
||||
5. **Resolver carry:** choose a fixture/cap pair where parsing passes and the carried syntax/catalog/lower/warning aggregate crosses the cap in resolve, while the zero-C version fits. Assert the actual resource refusal and original file/span policy. Separately show a successful full path retains C once, not twice.
|
||||
6. **Text timing/exclusion honesty:** parse a quoted-string/ordinary-position-copy fixture, then require resolve's C.text+T to fail/succeed at its existing text-accounting boundary. Do not report that fixture as rejecting before decoding/copying the syntax Strings. Verify raw Issue exclusion and retained warning admission remain as before.
|
||||
7. **Overflow:** exercise checked C+file metadata, C+U+M, text and resolver initial composition overflow through private test construction and the real call entry. Overflow must return a small safe diagnostic, never wrap/saturate into success or return a partial witness. Distinguish overflow from ordinary cap failure if an earlier C dimension already exceeds the hard ceiling; direct checked-add helper tests may be needed for unreachable-under-valid-policy arithmetic, and must be labeled as such rather than claiming an impossible accepted C.
|
||||
8. **Policy fidelity:** tightened independent bytes/tokens/entries/references/frames/numeric_units and caller model/file/include/depth policies are carried unchanged; a second-snapshot normal-looking input must still obey every tightened limit. Usage is new-snapshot work, not previous Usage+C. No default profile fallback.
|
||||
9. **Failure/ownership lifecycle:** consumed continuation cannot be reused; borrowed bundle/intent remain unchanged; failure exposes only diagnostics. Tests holding a real external baseline allocation prove it remains alive through parse/resolve and drops normally afterward. Future emitter ownership is not simulated as accepted production provenance.
|
||||
|
||||
Existing admission/index small-stack cases remain separate regression tests. This slice promises no new universal stack bound, and preserves the documented environment-sensitive upstream parsing observation.
|
||||
|
||||
## 7. Required explicit clarifications / possible revisions
|
||||
|
||||
**Temporal wording:** parser proposal “bound ordinary temporary containers/references before allocation” and Project contract “before allocating or copying an in-scope representation” must not be cited as proof that this phase-only seam admits every parser allocation before growth. Existing code admits retained syntax text later and has independent parser transient controls. Adoption should explicitly state: this prerequisite carries the surviving baseline through current logical **phase checks**; it neither closes nor waives any stronger before-growth obligations for the final execution contract. If parent interprets the earlier broad wording as an unconditional requirement on every counted parser producer now, that interpretation and this intentionally phase-only deliverable conflict. Parent must explicitly amend/scope the predecessor requirement or defer acceptance of this limited prerequisite; implementation may not silently weaken it.
|
||||
|
||||
**Zero baseline and earlier refusal — selected compatibility rule:** keep the original path and phase checks unchanged, and enforce combined checks only through the explicit carried path, including a legitimate zero C. That carried C=0 path can reject a syntax-only witness earlier where original syntax succeeded but original resolve rejected U+M. Document and test this intended difference. Successful complete outcomes and Usage must agree. A numeric-zero bypass would violate the opt-in carried contract, while globally imposing U+M on legacy syntax would violate the chosen compatibility scope. No claim of identical parser-only acceptance across these two deliberately distinct private paths is made.
|
||||
**Final execution acceptance:** the rename contract requires a surviving aggregate baseline during actual-output parse/resolve and whole-Project equality, but that requirement alone does not approve an emitter or resolve all parser temporal policy. This prerequisite can be accepted independently while the output producer, before-growth decision, E equality reservation, old-owner drop boundary and owning accepted-result design remain unfinished. No release claim of accepted mixed editing follows.
|
||||
|
||||
## 8. Exit criterion
|
||||
|
||||
A reviewed private continuation plus real zero/nonzero-baseline parser/resolver tests establish exact policy retention, disjoint work/live dimensions, aggregate checks at the listed boundaries, once-only resolver transfer and safe failure ownership. Evidence must name the source pin, counted domain, actual refusal phases and remaining timing/exclusion limits. Broader rewritten-output acceptance stays blocked on its own explicit contract and tests, not silently considered satisfied by this prerequisite.
|
||||
|
||||
## Parent scope decision
|
||||
|
||||
Accept this as a limited phase-accounting prerequisite. The existing entry path retains its checkpoints unchanged; only the explicit carried path performs combined checks, even at zero C. This neither satisfies nor waives stronger predecessor before-growth requirements for final output acceptance. The final execution contract must still resolve those requirements before editing authority is enabled. No production entry can yet create a carried continuation: fixture-only construction tests exact-policy capture and propagation, not an implemented consuming old-owner transition. The retained positive fixture counts exactly F map entries, zero lower occurrences, and all actual source/key/entry UTF-8 bytes. Nonzero occurrence or impossible arithmetic cases are explicitly fault injection, never successful owner provenance.
|
||||
@@ -0,0 +1,102 @@
|
||||
# Private retained-entry producer prerequisite
|
||||
|
||||
Baseline `97a8703adc75467a7f8e75f5c6cb00ca542b707c`. This selected contract
|
||||
strengthens the timing of the existing logical entry metric. It does not grant
|
||||
accepted-output, public source8 or save/history authority. Source/evidence remain
|
||||
local until the Gitea storage publication blocker is resolved.
|
||||
|
||||
## Metric and authority
|
||||
|
||||
Add one explicit fixture route enabling both text and entry producers, using the
|
||||
existing opaque CarriedInput and exact inherited policy. Preserve legacy,
|
||||
carried-phase and text-only routes and their diagnostic timing. C comes from the
|
||||
actual carried guard, including an explicitly selected zero guard.
|
||||
|
||||
U remains exactly Budget.usage.entries, the existing cumulative syntax events.
|
||||
M remains F supplied file records + one significant-token-end subtotal + unique
|
||||
ordinary value-end keys + ordinary lexical-owner occurrences + projected slots.
|
||||
Projected slots remain seven per ordinary declaration (including its synthetic
|
||||
body and conservative header envelope), one per field, one per actual Ast value.
|
||||
Node headers also retain the seven envelope. Dropped token/value-end structures
|
||||
keep their conservative subtotal through syntax return. Usage never includes C,
|
||||
M or quota consumption, and significant tokens do not gain a second M charge.
|
||||
|
||||
Before selected growth check checked `C.entries + U + M + delta` against the
|
||||
exact entry ceiling. A failed check changes no U/M total. Use only small scalar
|
||||
optional Budget state; do not duplicate policy or create another owning wrapper.
|
||||
Preserve current byte/guard checks, then atomically validate/install C and M=F
|
||||
before Traversal construction. F is transferred, not charged again, when file
|
||||
records move between containers.
|
||||
|
||||
## Producer and reconciliation rules
|
||||
|
||||
- Budget::entry preserves its existing syntax-work check first; in the new mode
|
||||
check the prospective aggregate before incrementing U or returning to callers.
|
||||
Existing typed/ordinary event sites remain unchanged.
|
||||
- Encapsulate value-end key-presence check, reservation and insertion in one State
|
||||
helper. Charge only a new key. Encapsulate lexical-owner reservation and push
|
||||
likewise; charge occurrences, not distinct UUIDs. Hide unchecked mutable
|
||||
metadata access from the ordinary parser.
|
||||
- Count pending projection with checked scalar grammar hooks: seven per ordinary
|
||||
declaration, one per successfully parsed field and one per successful value.
|
||||
Nested values/fields naturally contribute. Project/include/description do not
|
||||
call these hooks; duplicate fields fail the entire parse. The synthetic body
|
||||
is already in seven, and adds no value event.
|
||||
- At projection boundary atomically reserve token count plus pending projection
|
||||
into M before ends/header/field/value construction. The stronger route must
|
||||
not call the old unmetered borrowed-work Vec counting pass. Other routes keep
|
||||
that existing path.
|
||||
- A scalar prepaid quota is consumed before projector growth: seven before a
|
||||
declaration/header envelope, one before each field, one before each actual
|
||||
value (before recursive children). It neither recharges nor refunds M. Require
|
||||
zero after projection. Under/over quota is an internal invariant failure,
|
||||
never a successful witness with corrected/subtracted counts.
|
||||
- After each file compare reserved map/owner counts with actual lengths and
|
||||
M delta with checked token/owner/map/projected inventory. At syntax completion
|
||||
compare total M with the independently accumulated metadata field. Keep the
|
||||
existing once-only C then U+M resolver ledger transfer; text reconciliation
|
||||
remains unchanged. Never seed a combined total and add syntax a second time.
|
||||
|
||||
## Rejection behavior
|
||||
|
||||
New aggregate ceiling refusal uses `Source8 lowering entry limit exceeded.`
|
||||
Overflow uses `Source8 producer entry size overflow.` Both latch in the new
|
||||
entry mode, leave totals unchanged and propagate immediately. Legacy phase
|
||||
checks keep their existing nonlatching semantics. U-only failure retains its
|
||||
existing precedence and message. Invariant mismatches return an explicit error;
|
||||
they cannot silently repair a count or produce an accepted result.
|
||||
|
||||
Attribute U to its existing event span; owner to the original declaration start;
|
||||
value-end to the completed Ast's start/end; file and complete projection
|
||||
reservation to Span::default in the current file. Grammar counter overflow uses
|
||||
its corresponding declaration/field/value span. Ordinary diagnostic transport
|
||||
continues to use the existing one-byte start representation. Tests distinguish
|
||||
these actual seam diagnostics from later phase or resolver refusal.
|
||||
|
||||
## Acceptance and exclusions
|
||||
|
||||
Real E: C1/U1/M11 gives syntax13/12; full resolver17/16 is a separate boundary.
|
||||
Real three-file chain: C3/U3/M19 gives syntax25/24, separate resolver29/28.
|
||||
Use sufficiently large unchanged text policies (at least E146 and chain358),
|
||||
so earlier text limits cannot preempt the entry assertion. First ordinary owner
|
||||
refuses at prefix cap4; first description value-end refuses at prefix cap7.
|
||||
Neither next integer is claimed to admit the complete document. Review the
|
||||
reserve-plus-mutate helpers and test unchanged collections on refusal directly.
|
||||
|
||||
Independently author a nested record/array/reference/historical UUID fixture and
|
||||
node/element envelopes, with literal counts and spans fixed before runtime.
|
||||
Cover repeated map keys, quota underflow/leftover, overflow and latched refusal
|
||||
as labeled internal controls. Verify actual-owner and explicit C0 routes,
|
||||
whole OA/SA and multi-file Project/Usage/numeric parity against text-only, source
|
||||
conservation, once-only transfer and unchanged old caps/errors. Run new focused
|
||||
cases, full existing disposition, strict core Clippy and format comparison;
|
||||
inspect changed Budget/State/projector prologues and all old small-stack controls.
|
||||
Do not enlarge stacks, loosen tests or add a heap wrapper to hide regressions.
|
||||
|
||||
This retained metric does not bound allocator capacity/node overhead, file-table
|
||||
physical transfer overlap, significant-token storage beyond its existing token
|
||||
bound, traversal/open-declaration/delimiter/Pratt work stacks, duplicate-name
|
||||
scratch, numeric/decoder internals, model/validator heap or native stack. Those
|
||||
named scratch domains need a later explicit finite decision. Actual emitted-byte
|
||||
verification, justified whole-Project equality work and accepted bundle ownership
|
||||
also remain open. No claim of before-every-allocation or all-heap accounting.
|
||||
@@ -0,0 +1,54 @@
|
||||
# Independent critique of retained entry producer prerequisite
|
||||
|
||||
Reviewed ENTRY-PROPOSAL.md against local immutable HEAD `97a8703adc75467a7f8e75f5c6cb00ca542b707c`. No code, compiler, runtime, network or publication action. References below are repository-relative at that source. This is a design review, not implementation acceptance.
|
||||
|
||||
## Disposition
|
||||
|
||||
The proposed scalar grammar count plus prepaid projection quota is a reasonable bounded next prerequisite. It preserves the established logical U/M domain without pretending to bound every allocation. I found no inherent accounting contradiction or need for a parser rewrite. Before implementation, settle the new rejection contract and explicitly distinguish prepaid quota consumption from live accounting. Broader output verification and owner transition remain open.
|
||||
|
||||
## Required precision before implementation
|
||||
|
||||
1. Specify the new aggregate error message, attribution and poison behavior. Existing `Budget::entry` first checks `active`, checks the syntax-only bound, latches a failure, then increments U (`budget.rs:170–206`). Existing metadata phase checks are nonlatching (`mixed.rs:1–17`, `budget.rs:238`). The new mode must run the existing syntax-work check first, then checked aggregate arithmetic, and commit U only after both succeed. Define whether aggregate failure latches, and require immediate propagation consistently; do not inadvertently change legacy error precedence. An overflow must not mutate U/M or masquerade as a limit comparison.
|
||||
|
||||
2. Initialize and validate `C.entries + F` before installing the entry state or constructing Traversal. C comes from the actual guard, including an explicitly present zero guard. The existing source also checks source bytes before the file reservation (`mixed.rs:300–329`): retain that ordering unless the new route's contract intentionally says otherwise. Policy caps in entry tests need generous text/byte/token limits so this earlier validation cannot preempt the claimed entry seam.
|
||||
|
||||
3. Define projection quota as consumption of an already reserved logical subtotal, not another live charge. At the boundary reserve `tokens.len + pending_projection` atomically once; every producer consumes quota before its representation growth, and completion requires zero. Consumption must never reduce Budget M or charge M again. Seven per declaration covers the synthetic body and conservative header envelope, even though node headers have only four actual roles (`language.rs:1121–1168`). No release of M follows temporary ends/value-map destruction: the established metric conservatively retains those subtotals through the witness (`mixed.rs:42–47`, `368–429`).
|
||||
|
||||
4. Make the attribution of new owner/value-map/pending overflow checks explicit. The owner seam occurs after consuming the opening brace (`language.rs:1693–1702`), so a generic current-token error would point into the body, not the declaration start. Pass the selected declaration span deliberately. The value-end seam has the completed Ast offset and end (`1357–1375`); choose and test that source span, including the ordinary one-byte diagnostic transport. The proposal currently promises the original declaration span but does not fully define all new diagnostics.
|
||||
|
||||
## Coverage and lifecycle review
|
||||
|
||||
U is cumulative syntax work, not a count of simultaneously live allocated objects. Keep exactly the old calls: ordinary project/declaration/include/description/field/value events; typed declaration/field/type/dimension/override and expression/operator/call-argument events. Existing `syntax.rs:60–63` excludes grouping from a new entry, and `169–176` charges binary operators before their deferred construction. The new check belongs in the common Budget seam, not additional Vec pushes. Existing Pratt/open-declaration work stacks stay outside this selected metric.
|
||||
|
||||
Successful grammar-derived projection counts match the old walk's shape: seven per ordinary declaration, one per successful field and one per successful value. `language.rs:1294–1343` recursively routes nested object fields through field(), and `1357–1375` routes every child Ast through value(); `mixed.rs:440–465` counts precisely those same retained fields/values. Duplicate fields cause whole-parse failure after insertion (`language.rs:1307`, `1589`) and cannot create a successful replacement that needs a projection refund. Project description and includes bypass field/value and correctly do not contribute projected slots. Incrementing only after successful grammar completion avoids presenting a partial failed parse as a reconciled witness.
|
||||
|
||||
The value-end helper should check key presence, reserve only a new key, then perform insertion in the same private operation. Real successful source generally supplies distinct Ast offsets; a repeated key is a useful labeled internal replacement control, not a claim about ordinary grammar provenance. The owner helper counts declaration occurrences, including repeated IDs, before the Vec push. Final comparisons against actual lengths are needed because merely carrying counters alongside unchecked public fields would not establish producer coverage.
|
||||
|
||||
F is initialized once for every supplied file. The later BTreeMap-to-Vec transfer (`mixed.rs:410–436`) moves those same logical records. It is not another F, and this policy does not claim to bound transient physical container overlap. Similarly, the resolver reconstructs a distinct ledger from C and existing U+M; it must not seed the combined subtotal and add syntax again. Keep existing file/path/model validation and resolver equality checks, rather than inventing a second accepted witness authority.
|
||||
|
||||
## Finite oracle assessment
|
||||
|
||||
The existing independently authored E and three-file fixtures support the proposed totals:
|
||||
|
||||
| Fixture | C | U | M | Syntax total | Separate resolver peak |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| E | 1 | 1 | 11 = F1 + token ends10 | 13 | 17 |
|
||||
| Three-file chain | 3 | 3 | 19 = F3 + token ends16 | 25 | 29 |
|
||||
|
||||
Use syntax-only 13/12 and25/24 boundaries, then separate full-resolution17/16 and29/28 boundaries. The text-producer route must have a sufficient actual inherited byte cap; E146 remains the known complete text control. Scanner raw token work31 in the chain must not become M16. Exact chain refusal file/span requires the literal traversal fixture, not aggregate arithmetic alone.
|
||||
|
||||
The owner cap4 control is sound as a prefix: C1 + F1 + project U1 + declaration U1 =4 immediately before the first owner M reservation. The first ordinary description-value cap7 is also a prefix: C1 + F1 + U4 + owner1 =7 before its value-end insertion. Neither cap5 nor cap8 proves a complete successful syntax; the following token/projection subtotal is larger. Timing must be shown by a finite observer or directly reviewed reserve-plus-mutate operation, with a roomy positive instance of the same real fixture. A final error alone cannot prove that no map/Vec insertion happened first.
|
||||
|
||||
For the additional nested fixture, author the literal source and expected U, distinct value offsets, owner count, significant tokens and projection subtotal before writing test expectations. Include both a nested Ast Record and the synthetic declaration body so they cannot be conflated; retain node's seven-envelope distinction. Quota underflow/leftover and arithmetic overflow controls are internal fault injections, not complete-source acceptance evidence. Whole OA/SA/project and Usage parity at ample limits provides the positive semantic control; no generic output-derived counting oracle is needed.
|
||||
|
||||
## Simpler alternatives and boundaries
|
||||
|
||||
Keeping the old borrowed-work Vec count and adding a live scratch allowance would touch fewer grammar sites, but introduces a new peak metric and policy, precisely the expansion this slice avoids. A recursion-based counting pass adds another depth-sensitive walk and is worse after the existing stack investigation. The proposed scalar counter is the simplest option that both eliminates that extra counting frontier on the new path and keeps U/M unchanged.
|
||||
|
||||
Quota could technically be omitted after trusting the grammar count, but then a future projector branch could silently escape the prepaid inventory. A single narrow scalar consumption callback is worthwhile as an internal coverage invariant; do not turn it into a generic visitor or a second retained ledger. Ensure value quota is consumed before recursive children and header envelope before header collection; field quota can precede its recursive value construction. Text and quota callbacks may require a carefully scoped common borrower, not a second Budget copy.
|
||||
|
||||
The existing delimiter Vec at `language.rs:1033–1040`, Pratt stacks, traversal structures and declaration open stack remain named excluded scratch. Significant tokens remain covered by their existing token bound; token-end M is reserved before ends construction, not falsely billed as two N-sized containers. Those exclusions are compatible with a retained-inventory prerequisite but forbid all-heap, physical peak or complete before-allocation claims. Measure actual Budget/State/projector frames and retain all existing small-stack controls without changes; a few scalar fields are not evidence of harmless stack cost.
|
||||
|
||||
Recommended next step: implement only the explicit fixture route, common prospective U check, private metadata helpers and grammar counter/prepaid quota with these finite cases. Retain legacy, carried-phase and text-only behavior verbatim. This produces earlier enforcement of the existing entry metric, not accepted output or closure of broader scratch obligations.
|
||||
|
||||
Parent's subsequent selected clarification resolves the diagnostic ambiguity if adopted explicitly: aggregate refusals reuse the lowering-entry-limit message at the actual producer span and latch only in the new mode; checked overflow has a distinct source-producer-entry-size-overflow error. Nested ordinary declarations do not undermine the successful-count argument: `language.rs:1540–1600,1693–1723` keeps declarations as separate flat occurrences with their own fields and seven-slot envelopes. The open stack supplies lexical ownership, not a second declaration or projected synthetic body.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Existing retained U/M producer timing — proposal
|
||||
|
||||
Source `97a8703adc75467a7f8e75f5c6cb00ca542b707c`; 2026-09-25. Original read-only proposal, selected by the sibling entry-producer contract. Source references are repository-relative at the pinned commit; original local worktree links are transcribed as plain paths for relocation. No build or runtime result is inferred. This is a next prerequisite for the existing private output-verification path, not an accepted-output API or all-heap accounting.
|
||||
|
||||
## Selected-domain invariant
|
||||
|
||||
U remains exactly Budget.usage.entries, the existing cumulative syntax-event charge; do not relabel every allocated object or Vec push as a new U event. M remains exactly the existing conservative subtotal: F complete-file slots + significant-token-end count + unique ordinary value_ends entries + lexical-owner entries + ordinary projection slots. Its dropped value-end/token-end portions remain represented through the syntax witness as before.
|
||||
C is the actual retained guard's immutable Slots, never Usage. In a new explicit entry-producing mode, every selected U/M growth must first check checked `C.entries + U + M + delta <= exact Limits.entries`. A refused reservation installs no new U/M total. Existing occurrence and numeric work semantics do not change; text-producing checks continue independently against the same policy.
|
||||
The final U/M inventory must equal the existing inventory for successful input. This strengthens timing, not the metric. Token storage still uses the token bound: M has ONE token-end component, not separate charges for significant tokens and ends. Capacity, container node overhead and native stack do not become entries.
|
||||
|
||||
## Compatibility and concrete owner
|
||||
|
||||
Keep legacy, carried-phase and text-only routes unchanged, including their phase timing/diagnostics. Add a fixture-only route enabling text plus entry producers from the existing opaque CarriedInput; no arbitrary baseline/profile constructor and no numeric-zero bypass. Existing text-only E146/145 and phase-only tests retain their meanings.
|
||||
A small optional Budget entry state can hold only carried-entry baseline and current M; U is read from existing Usage, never duplicated. Derive C directly from the guard at initialization. Initialize M=F before Traversal::new using the existing file check. No full policy copy, owner enum, new heap container or String wrapper is needed. Measure generated frames after implementation rather than spending the repaired stack margin by assumption.
|
||||
Use Budget::entry as the common prospective-U seam: preserve the old syntax-work check/error behavior, then perform the new aggregate check before incrementing Usage or letting the caller create its associated representation. These checks must not reset work, reinterpret references as occurrences, or add U again at final handoff.
|
||||
A per-file scalar pending_projection count belongs in mixed State, where ordinary grammar callbacks already meet the shared Budget. It counts future projection slots without reserving them prematurely. Keeping this scalar distinct from live M avoids charging output that has not been produced yet.
|
||||
|
||||
## Concrete seams and ownership
|
||||
|
||||
| Existing component | Producer seam | Required action / reconciliation |
|
||||
| --- | --- | --- |
|
||||
| U ordinary events | `crates/oa-core/src/language.rs`:1192 syntax_entry; field1321, value1357, project1513, include1613, description1637, declaration1657 | All route through State::entry/Budget::entry before their current grammar event. Preserve exact event counts and caller order. No charge for every open-stack push or every Rust enum. |
|
||||
| U typed events | `crates/oa-core/src/language/analysis_source/declarations.rs`:261,290,476,542,611; `crates/oa-core/src/language/analysis_source/syntax.rs`:61,169,242 | Existing pre-event calls cover declaration/field/type/dimension/override and Pratt expression/operator/argument events. Grouping mutates an existing expression and does not invent an entry. Deferred node construction uses its already reserved event. Keep the repaired iterative driver unchanged. |
|
||||
| F file records | `crates/oa-core/src/language/analysis_source/mixed.rs`:314–329 | Initial complete-file reservation stays before traversal. Map-to-canonical-Vec consumption transfers the same logical file records; do not add another F merely for the new container. |
|
||||
| Ordinary value-end map | language.rs:1373, after successful Ast construction but before map insertion | A State::remember_value_end helper checks whether the offset is new, reserves one M only for a new key, then inserts. Ast already has its U event. Replacement updates do not add a slot. Per-file reserved count must equal actual map.len before its conservative subtotal is retained/dropped. |
|
||||
| Lexical owners | language.rs:1700, before push and ordinary declaration insertion | A State::push_lexical_owner helper reserves one M before its current Vec push. Count occurrences, not unique IDs. Per-file delta must equal Vec.len. Typed roots/project header do not gain fabricated ordinary-owner entries. |
|
||||
| Token-end metadata | language.rs:1032 ends collection; mixed.rs:368+ preprojection boundary | Reserve exactly tokens.len once before ends creation, alongside projection below. No need to charge M during lex::tokens significant-token push: that producer belongs to the existing token-bound-only domain, and ends does not yet exist. |
|
||||
| Ordinary projected slots | language.rs:1042–1168 Positions and per-declaration construction | Pre-reserve pending_projection once before any projected declaration/header/field/value allocation. Preserve seven logical slots per ordinary declaration/body/header envelope, one per field key, one per Ast-projected value; keep the node-header envelope conservative rather than revising it. |
|
||||
|
||||
Direct map/Vec growth should remain inside the same narrow State helper as its reserve; expose no independent unchecked mutable metadata operation for the new path. The shared ordinary Parser invokes these helpers only through its existing optional mixed State. Public grammar need not acquire a new state owner.
|
||||
|
||||
## Avoid the current counting-work Vec on the new path
|
||||
|
||||
The current `crates/oa-core/src/language/analysis_source/mixed.rs`:440+ is a postparse saturating tally with an unmetered borrowed-work Vec. Calling it before a projection reservation does not establish before-growth accounting for that Vec. Do not silently charge its scratch under the retained projection subtotal or call saturation checked arithmetic.
|
||||
Recommended replacement ONLY for the new route: increment checked pending_projection by7 when an ordinary declaration is created, by1 for every successful ordinary field(), and by1 for every successful ordinary value(). Nested objects/arrays are visited naturally by those existing calls; each child value and nested key contributes exactly once. Project/include/description grammar does not call field/value in that path and must not enter this projection counter. Failed whole parses need no successful-witness reconciliation.
|
||||
At the projection boundary, reserve pending_projection + tokens.len into M once. Maintain a scalar projection quota consumed by the actual projected producer:7 per declaration,1 per field,1 per EditValue. Check quota subtraction before the corresponding production and require zero at completion. This compares the independent grammar-derived inventory with actual projection consumption without a second AST walk or an extra collection. Static header roles are included in the existing7 envelope; do not also subtract their individual count.
|
||||
Legacy/carried-phase/text-only retain ordinary_position_slots and their prior behavior. The stronger path's quota hook can be an additional narrow optional callback/scalar in the existing shared projector; do not add a generic visitor framework or clone ASTs. The source review must compare grammar counting order and projection consumption coverage, including synthetic body Record handling.
|
||||
The synthetic per-declaration body Record is already part of7 and is NOT a second value() contribution. Ast::Object below a field is an actual value and consumes1 plus its field entries; Ast::Array consumes1 plus items. Atom/Reference/HistoricalUuid each consume1. This distinction needs explicit tests.
|
||||
|
||||
## Transfer and final checks
|
||||
|
||||
After each file, compare its reserved value-end/owner counts with actual lengths and its consumed projection quota with zero. Compute the expected M increment from those lengths, tokens.len and the reconciled projection count; compare against the producer M delta instead of adding it again. Initial F is checked separately once.
|
||||
At final syntax return assert Budget's M equals ParsedMixedSyntax.metadata and the file inventory's checked total. Keep Usage.entries as the original U. The existing resolver still seeds C once and reserves U+M once in its distinct ledger; this is transfer/reconstruction, not an additional simultaneously retained allocation. Do not seed C+U+M and then call the unchanged additive syntax path again. Text T transfer/reconciliation remains as implemented.
|
||||
No new occurrence storage is allocated in this slice; C.occurrences continues its inherited checks. If a future producer introduces an auxiliary container, it is not covered by these retained counters unless explicitly inventoried.
|
||||
|
||||
## Finite acceptance oracles and limits
|
||||
|
||||
1. Empty E: C.entries1, U1, M11 (F1 + ten token ends), final syntax13; cap13 parses,12 refuses before token-end/projection creation, full resolver peak17 remains distinct. Real inherited text policy must be sufficiently large (producer E146) so text cannot preempt the entry control.
|
||||
2. Existing three-file chain: C.entries3, U3, M19 (F3 + sixteen token ends), final25; syntax25/24 and resolver29/28 remain separate cases. Verify actual file/checkpoint attribution and no double-add at transfer. Scanner raw-token work is31, not M's sixteen significant tokens.
|
||||
3. Minimal ordinary empty activity: before its first lexical-owner push C1+F1+U2=4; entry cap4 can distinguish the new owner reservation refusal. It is a negative timing control, NOT a claim cap5 admits the complete syntax. Use actual guard ownership, generous text/token limits and original declaration span.
|
||||
4. First ordinary `description ""` value: C1+F1+U4+one lexical owner=7 immediately before its new value-end entry; cap7 refuses before map insertion. Again cap8 only fits that prefix, not the later complete metadata. A bounded test observer or separately reviewed reserve-plus-insert helper must establish ordering; a final retained count alone cannot.
|
||||
5. Independently hand-count flat fields, nested record/array/reference/HistoricalUuid and node versus element headers: exact grammar projection counter equals old retained inventory, and actual projection quota ends at0. Invalid under/over quota and repeated map-key controls are labeled internal fault injection, not real source provenance. No AST cloning or output-derived expected model.
|
||||
6. Whole real OA/SA/multi-file outcomes and Usage/numeric parity against text-only at ample limits; explicit C0 new mode; old route cap/error behavior unchanged. Work Usage counts must not absorb C, M or projected quota events.
|
||||
7. Preserve all old 128 KiB/deep/wide controls and measure changed Budget/State/projector frames. No stack/test-size relaxation or RUST_MIN_STACK. Repeated failure must not leak a partial witness or new source authority.
|
||||
|
||||
## Finite domain decision still required
|
||||
|
||||
The projector also uses a delimiter Vec at language.rs:1033–1040; traversal and ordinary open-declaration coordination likewise remain existing scratch, not retained M. The proposed contract can honestly cover U/M while leaving those named scratch producers open. It cannot claim the single N token-end reservation accounts two simultaneous N-sized containers. If the parent requires these scratch entries now, choose an explicit additional live W, reserve before each push/release on pop, and derive new peak oracles; that is a separate finite metric addition.
|
||||
Comparison: keep the old count walk and add bounded W for its work frontier (smaller initial grammar edits, but expands scratch policy and peak caps), versus grammar scalar + producer quota (more named seams, no new frontier/domain). Recommend the latter for this narrowly retained-inventory prerequisite. Broader scratch, final actual-output equality and accepted-owner transition remain out of scope. No additional task is proposed or started here.
|
||||
@@ -0,0 +1,151 @@
|
||||
# Private actual-output rename acceptance
|
||||
|
||||
Baseline `29417130c71f70c4eaefe8ed4c879efba78eb72c`. Select the complete pending
|
||||
owner borrow, actual-output equality bound and moved model/warning outcome after
|
||||
independent design, domain and ownership critiques. This connects the verified
|
||||
emitter and named parser producers; it is no longer another fixture-only
|
||||
continuation. The surrounding mixed implementation remains private experimental
|
||||
source. Public source8, installation/history and release integration are separate.
|
||||
|
||||
## Authority and result
|
||||
|
||||
Add a consuming verification operation on opaque PendingRename. Its only normal
|
||||
constructor remains validated consumed emission. No production constructor may
|
||||
accept an arbitrary bundle/model/Slots/profile tuple. Add CarriedInput::from_pending
|
||||
accepting a shared reference to that complete pending owner; derive bundle,
|
||||
exact Limits/ProjectLimits and retained O from the same owner. Both backing and
|
||||
guard retain a complete pending reference, not just numeric counters. Keep enum
|
||||
variants private and expose only narrow immutable pending views to carried code.
|
||||
|
||||
Prefer `&'s PendingRename<'s>` inside the existing single-lifetime backing, using
|
||||
the immutable desired reference's covariance to shorten a longer desired borrow
|
||||
to the verification borrow. Actual Rust compilation must establish that relation.
|
||||
Do not thread a second lifetime through every parser owner, duplicate full policy
|
||||
inside guards, introduce a heap wrapper or permit mutation while the guard lives.
|
||||
The existing fixture constructors and old parser entry points keep their behavior.
|
||||
The new continuation is the sole emitter-connected entry into the combined text
|
||||
and retained-entry producer route, including actual zero metadata if applicable.
|
||||
|
||||
On success return a non-self-referential owning AcceptedRename with the actual
|
||||
SourceBundle, actual resolved Project, mapped warnings, exact inherited policies
|
||||
and final retained Slots. Preserve scalar verification Usage and numeric work
|
||||
separately from original-snapshot work; no cumulative reinterpretation. The
|
||||
accepted type has private fields and read-only accessors, with no unchecked or
|
||||
mutable constructor, borrowed syntax or borrowed desired model. Source, desired
|
||||
and pending may be dropped before the accepted result is inspected.
|
||||
|
||||
This result does not itself save files, edit history, install a model or enable
|
||||
repeated carried-source emission. Later adoption must jointly preserve its
|
||||
graph/source/diagnostic relationship; no separate mutable extraction is added.
|
||||
No-op remains the existing explicit unchanged-owner branch.
|
||||
|
||||
## Actual verification and equality
|
||||
|
||||
Parse the actual complete pending bundle under its exact policy using both named
|
||||
producer modes. Propagate its located parse diagnostics. Consume the resulting
|
||||
syntax through the existing resolver and complete model admission, preserving O
|
||||
through all parser/resolver stages. Never default policy, substitute intended
|
||||
tokens/model, drop untouched files, re-emit bytes for comparison or reset carry.
|
||||
|
||||
After actual model admission reserve `E_actual = resolved.expressions.len()`
|
||||
entry slots against that resolved owner's full live ledger, which includes O,
|
||||
syntax and mapped warnings. Compare the entire actual Project with desired using
|
||||
its established PartialEq, including aliases, parameter names, all maps and
|
||||
historical payloads. Do not use rename::same_project, which exempts names. Release
|
||||
the equality frontier after comparison. A mismatch returns a small static
|
||||
invalid_source diagnostic at entry/default span0..0, not a formatted model.
|
||||
|
||||
The independently reviewed bound follows every reachable actual Expr root:
|
||||
calculation body, property base, case overrides and check predicate. Each actual
|
||||
node has a source expression-site entry. Iterative Expr equality's live pairs
|
||||
correspond to distinct nodes of its actual left operand; list/call shape checks
|
||||
precede child queueing, and no nested equality frontier remains live. Whole-model
|
||||
comparisons visit roots sequentially. E_actual0 cannot invoke an allocating Expr
|
||||
comparison from a nonexistent actual root. Existing signed-zero PartialEq remains
|
||||
semantic equality, not bitwise equality. Revisit the proof when payload types or
|
||||
lowering/equality implementations change. Original pending E is provenance only;
|
||||
the new implementation must use the current resolved arena for its reservation.
|
||||
|
||||
## Mapped warnings and ownership transfer
|
||||
|
||||
Retain the mapped warnings by moving them, together with the actual resolved
|
||||
Project, after successful equality. The model remains in its existing excluded
|
||||
model-allocation domain and has already passed admission. Mapped warnings remain
|
||||
in the selected auxiliary domain. Do not clone a model, warning, path or vector.
|
||||
|
||||
Compute warning inventory W with a checked borrowed loop over the actual records:
|
||||
one entry per warning, zero occurrences, and UTF-8 lengths of path, code, optional
|
||||
field and message. Require current mapper invariants: every related vector empty
|
||||
and no Error severity. Unexpected shapes fail before producing accepted authority;
|
||||
do not silently ignore newly introduced fields/related locations. The diagnostic
|
||||
field accounting should be exhaustive enough that schema changes demand review.
|
||||
|
||||
W already participates in the full resolver ledger. Do not charge it twice during
|
||||
equality or transfer. Compute final O+W with checked arithmetic, verify it is a
|
||||
componentwise subset of the still-live ledger, and check its exact inherited
|
||||
ceilings while Budget exists. This is a destination-inventory check, not an early
|
||||
release: keep full coexistence accounting until all temporary owners actually
|
||||
drop. Move Project/warnings to locals, drop all verification syntax/guard,
|
||||
expression/occurrence/catalog owners, then move the pending bundle/policy into
|
||||
AcceptedRename. Rust must enforce that no pending borrow survives that move.
|
||||
Final retained counts exclude released syntax and equality scratch but include
|
||||
all surviving mapped warnings. Failure returns only diagnostics and destroys
|
||||
the consumed pending output and partial verification state.
|
||||
|
||||
## Explicit remaining scratch decision
|
||||
|
||||
Choose the existing logical retained domain plus the named decode/equality
|
||||
temporaries; do not expand it into universal parser/all-heap accounting. Existing
|
||||
traversal, delimiter, ordinary-open, Pratt and duplicate-name scratch retain their
|
||||
independent file/edge/token/grammar controls and are excluded from carried W.
|
||||
Significant-token storage retains its independent token ceiling; M counts the
|
||||
separate token-end representation once. No new output-verification collection
|
||||
may be hidden under an old exclusion.
|
||||
|
||||
File count/source-text limits do not tightly bound copied traversal path bytes.
|
||||
Path folding/canonicalization and include target/location copies can occur before
|
||||
edge refusal; retain that known limitation explicitly. Open-declaration depth is
|
||||
bounded by declaration events, not typed-value depth. Pratt frames are not native
|
||||
stack bytes. Decoder/numeric internals, raw model/validator allocation, allocator
|
||||
capacity/overhead and native stack remain their established separate domains.
|
||||
Do not claim aggregate admission before every allocation or process-memory bounds.
|
||||
This resolves the earlier scratch-domain choice without waiving selected retained
|
||||
producer timing, actual output admission, equality or returned ownership.
|
||||
|
||||
## Finite acceptance
|
||||
|
||||
Use unchanged inherited profiles from original parse/index/plan through emission
|
||||
and verification. Never tighten an admitted owner to manufacture a late failure.
|
||||
Minimal project p→next emits81 bytes, O=(1,0,105), T11. Entries17 and bytes152
|
||||
admit the full pipeline; bytes151 reaches output UUID decode at37..38, line2
|
||||
column27, after scanner peak141 and emission peak114. Entry16 fails emission
|
||||
first and is not a later verifier cap. Assert the entire independent expected
|
||||
Project/bundle, empty warnings, final O, exact policy and separate snapshot Usage.
|
||||
|
||||
Retain a real warning-bearing rename with an independently authored full
|
||||
diagnostic and exact final O+W. Distinguish final retention counts from greater
|
||||
earlier peaks; do not invent a final-only cap-minus-one boundary. Reuse emitter
|
||||
OA/SA/cross-file/Unicode/CRLF/swap byte oracles and whole expected models where
|
||||
valid, checking returned warning paths/spans against the actual returned bytes.
|
||||
The [empty-name warning oracle](analysis-mixed-acceptance-design-20260925/WARNING-ORACLE.md)
|
||||
uses unchanged entries18 and bytes161/160: old emission peaks159 bytes, actual
|
||||
output warning mapping161, and accepted O+W=(2 entries,0 occurrences,157 text).
|
||||
Its negative warning-map diagnostic retains the full project-header11..69 span,
|
||||
unlike the parser's one-byte token-start transport. These are expectations to
|
||||
verify, not results inferred from source arithmetic.
|
||||
|
||||
Equal-byte test-only corruption can cover wrong-but-admissible alias/name,
|
||||
malformed source and model-invalid output while preserving O. A length-changing
|
||||
corruption must first be rejected by an explicitly selected inventory check or
|
||||
use independently verified actual-O fixture provenance, never stale counts.
|
||||
Include greater actual expression count than old E, wide/deep comparison,
|
||||
target-only mismatch and signed-zero cases. Label internal inventory/shape faults
|
||||
as such; do not relabel them as authentic emitted histories. Check true owning
|
||||
lifetime by returning success out of a scope that drops original input/desired.
|
||||
|
||||
Preserve all previous tests, failure bodies and format disposition; run focused
|
||||
new cases, full core library, strict all-target Clippy and format comparison.
|
||||
Exercise meaningful scoped128KiB verify/drop cases with prerequisites prepared
|
||||
outside the worker, preserve all old stack controls and inspect changed
|
||||
prologues. Do not enlarge stacks, loosen policies or rerun failures until lucky.
|
||||
Older separately unrerun full-pipeline setup limitations remain distinct.
|
||||
@@ -0,0 +1,136 @@
|
||||
# Independent actual-output acceptance oracle — proposal only
|
||||
|
||||
Source inspected: `a629ae01d49bb3cb482a047eb41832ad4246a5c6`. Derived from literal
|
||||
bytes and existing source, not parser/emitter execution. Only string lengths and
|
||||
literal substring offsets were evaluated. Future verification API/domain/equality
|
||||
contract is not yet selected; all runtime acceptance remains pending.
|
||||
|
||||
## Minimal real rename, one unchanged inherited policy
|
||||
|
||||
Entry/key `main.arcadia` has 12 ASCII bytes. Original exact source (final LF):
|
||||
|
||||
```text
|
||||
arcadia 8;
|
||||
project p "Project" id "00000000-0000-0000-0000-000000000001" {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Desired differs only in project alias `p` -> `next`. Expected complete emitted
|
||||
bundle is exactly one file under the same entry/key, containing (final LF):
|
||||
|
||||
```text
|
||||
arcadia 8;
|
||||
project next "Project" id "00000000-0000-0000-0000-000000000001" {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Original source is 78 bytes; output is 81. The sole edit is original [19,20),
|
||||
replacement `next` (four bytes); output alias is [19,23), display text [25,32),
|
||||
UUID quoted token [37,75). Output retained O=(1 entry, 0 occurrences, 105 text),
|
||||
where 105=81 source+12 map key+12 entry bytes. No output key/path is omitted.
|
||||
|
||||
Complete expected Project: schema_version=8; id=00000000-0000-0000-0000-000000000001;
|
||||
alias="next"; name="Project"; description=""; definitions, elements, relations,
|
||||
diagrams, artifact_links and traces are all empty maps. Expected warnings empty.
|
||||
This asserts every model field, not just the changed alias. E_original=E_actual=0.
|
||||
|
||||
Select original Limits entries=17, bytes=152 (or 151 negative), all other fields
|
||||
unchanged from an admissible roomy source8 profile; keep the same ProjectLimits
|
||||
through original parse/index/plan/emission/verification. Never tighten live policy.
|
||||
|
||||
| Stage | Logical entries | Logical text | Derivation |
|
||||
| --- | ---: | ---: | --- |
|
||||
| Original syntax retained |12|8|U1 + M11; alias1+name7 |
|
||||
| Original resolver peak |16|10|Project catalog +4 entries, two alias copies |
|
||||
| Original typed index retained |13|9|One global name; no typed headers/expressions |
|
||||
| Original ordinary index retained |14|9|One authored project header |
|
||||
| Rename plan peak/retained |16|9|R1 name target + namespace Q1 (then dropped), M1 edit |
|
||||
| Emission overlap |17|114|Plan16/9 + output O1/105 |
|
||||
| Output strong syntax retained |13|116|C1 + U1 + M11; C105 + T11 |
|
||||
| Output resolver peak |17|124|Syntax13 + project catalog4; two four-byte alias copies |
|
||||
| Output resolved retained/equality |13|116|Catalog dropped; E_actual0 equality scratch |
|
||||
| Owning accepted bundle after verification owners drop |1|105|Only actual output O remains |
|
||||
|
||||
Original indexing/transient peaks do not exceed the original resolver/plan/emission
|
||||
entry ceiling17 for this empty model; prior emitted-overlap source tests explicitly
|
||||
use entries17 and bytes114 through the real predecessor path. The new proposed
|
||||
152/151 byte profiles are looser than that already authored predecessor boundary.
|
||||
No new verification allocation occurs while the old authored owner remains live.
|
||||
|
||||
## Exact new byte boundary and timing
|
||||
|
||||
Scanner validation of the output UUID reserves raw payload36 before decoding.
|
||||
No grammar text exists during that file scan: C105+W36=141 (display payload7 is
|
||||
smaller). Grammar first retains alias4 and display name7, hence T11. Its UUID
|
||||
consumer reserves P36 while T11 remains live: 105+11+36=152, before the existing
|
||||
serde decode. Valid decode D36 transfers then UUID parsing drops/refunds it;
|
||||
final T11 and W0. Project has no projected ordinary values or textual keys.
|
||||
|
||||
Therefore 152 is the full-pipeline positive byte cap and 151 isolates the new
|
||||
actual-output grammar producer refusal, after predecessors/emission and scanner
|
||||
have fit. Expected source path main.arcadia, code invalid_source, message
|
||||
`Source8 index/output byte limit exceeded.`, ordinary transported span [37,38),
|
||||
line2 column27, no related locations. Raw quoted extent is [37,75), but the
|
||||
ordinary error transport intentionally retains its one-byte start representation.
|
||||
Do not expect this refusal at the former unverified-emission114 boundary.
|
||||
|
||||
Entry cap17 permits the whole pipeline, but cap16 refuses **emission first**:
|
||||
plan16 plus O1 cannot fit. Thus it cannot demonstrate a later verification/resolver
|
||||
entry refusal. Equality reserves zero here; no equality-specific minus-one case
|
||||
exists. A different justified fixture is needed for any proposed late entry gate.
|
||||
|
||||
## Equal-byte corruption controls (not genuine emitted results)
|
||||
|
||||
Start each control from a fresh legitimately emitted pending owner under roomy
|
||||
unchanged inherited limits. Mutate only in the private fixture harness. Equal UTF-8
|
||||
length preserves O numerically; production must not expose mutation/constructors.
|
||||
|
||||
- Output alias [19,23): `next` -> `nope`. Valid alias and otherwise empty model;
|
||||
parse/admission should pass, complete Project equality must reject.
|
||||
- Output name [25,32): `Project` -> `Changed`. Valid decoded display name, same
|
||||
seven bytes; parse/admission should pass, non-name equality must reject.
|
||||
- Version byte [8,9): `8` -> `?`. Equal bytes, malformed source; scanner/parser
|
||||
must reject before model equality. Do not claim a successful wrong-model case.
|
||||
|
||||
Each failure must drop pending verification state, return no accepted owner, and
|
||||
leave original source and desired unchanged. Do not recursively format models.
|
||||
The new verifier's semantic-mismatch message is deliberately unspecified here.
|
||||
|
||||
## Actual expression count larger than original, unchanged O
|
||||
|
||||
Use the same project wrapper with this exact single body line:
|
||||
|
||||
```text
|
||||
calculation c "C" id "00000000-0000-0000-0000-000000000002" { result Number; body 10000; }
|
||||
```
|
||||
|
||||
Original source168 bytes; a genuine project p->next rename emits171 bytes, O=(1,0,195).
|
||||
Desired includes the unchanged Number calculation c, same ID/name, no parameters,
|
||||
and literal10000 expression. Original arena E=1. On a fresh pending corruption
|
||||
fixture replace output expression [160,165) `10000` with `1 + 2` (five bytes).
|
||||
The bytes still describe a Number calculation, now binary Add with two numeric
|
||||
children: actual raw-expression arena E_actual=3. Bundle lengths/keys/entry/O
|
||||
remain unchanged; complete equality must reject its different body. Use roomy
|
||||
entries/bytes4096 from the original parse, not a policy replacement after emission.
|
||||
|
||||
The equality reservation must derive 3 from the freshly resolved actual output,
|
||||
not trust pending's old scalar1. This fixture proves provenance/count selection;
|
||||
its unequal root variants may short-circuit comparison and do not prove a frontier
|
||||
actually exceeding1. Lowering already reserves five entries per actual node,
|
||||
while equality requests only E_actual. No isolated equality-cap-minus-one refusal
|
||||
is claimed; the earlier lowering peak may dominate. A meaningful additional
|
||||
wide/deep positive and target-shape mismatch must be justified independently.
|
||||
|
||||
## Source basis and limits
|
||||
|
||||
At the pinned source, `rename/emission.rs:6` defines the sealed pending fields;
|
||||
its output_slots counts all source/key/entry bytes, and emit_changed_unverified
|
||||
reserves old plan+O before copies and drops old source before constructing pending.
|
||||
`rename/emission/tests.rs` already pins literal NEXT and predecessor17/114.
|
||||
`mixed/project.rs:245`/`:315` reserve the project alias/owner/table catalog; catalog
|
||||
storage releases before returning resolved state. `mixed/project/accounting.rs`
|
||||
seeds syntax and lower scratch independently; LowerStorage::all uses5N+2A.
|
||||
`budget.rs::quoted_text` and raw_tokens StringEvent implement the P/D timing above.
|
||||
These are logical storage derivations, not allocator/RSS or runtime test claims.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Actual emitted-output acceptance — working proposal
|
||||
|
||||
2026-09-25, parent read-only design based on source97a8703 and the entry-producer
|
||||
contract; entry implementation has not yet passed gates. This is neither selected
|
||||
contract nor permission to activate public source8. No next implementation claim.
|
||||
|
||||
The useful next outcome is a single owning accepted output after parsing the
|
||||
actual complete emitted bytes with inherited policy and carried output storage,
|
||||
resolving/admitting them and comparing the entire Project to desired intent.
|
||||
Do not insert another unneeded fixture-only milestone after the retained producer
|
||||
requirements pass. Remaining scratch-domain precision still needs explicit
|
||||
decision and independent critique; see DOMAIN-DECISION-CRITIQUE.md when ready.
|
||||
|
||||
## Narrow authority/lifetime candidate
|
||||
|
||||
Current private emission::PendingRename contains actual SourceBundle, exact
|
||||
Limits/ProjectLimits, reserved output Slots, original E and immutable desired
|
||||
Project borrow. Its only non-test constructor is consumed emission. Existing
|
||||
carried::CarriedInput currently accepts borrowed or fixture RetainedSnapshot.
|
||||
|
||||
Candidate A: add a named CarriedInput::from_pending(&PendingRename), with access
|
||||
only through read-only sealed pending views. It must derive all bundle, exact
|
||||
policy and retained slots from that same pending owner, accepting no loose
|
||||
bundle/profile/Slots. Backing can store the existing bundle/policy plus a shared
|
||||
reference to the pending retained Slots; guard needs only that reference after
|
||||
policy transfers to Budget. The function's borrow lifetime keeps the entire
|
||||
pending owner unavailable for mutation or consumption during verification. This
|
||||
avoids introducing desired's second lifetime into every parser owner. Prove this
|
||||
with actual Rust type checks; do not assume a reference to counters alone is
|
||||
sufficient authority if construction can be separated from the owner.
|
||||
|
||||
Candidate B: move owned snapshot storage into a shared RetainedSnapshot wrapper
|
||||
used by PendingRename, then reference it directly. This may simplify backing but
|
||||
must avoid an unrestricted new(bundle,slots,policy) constructor or unnecessarily
|
||||
coupling parser construction to emitter internals. Compare actual code size and
|
||||
representation before choosing. No generic trait/callback allocator framework.
|
||||
|
||||
A consuming PendingRename::verify method borrows itself for the strong combined
|
||||
text/entry parse; every result remains local until success. Consume syntax through
|
||||
project::resolve under the same carried guard, so complete model admission is
|
||||
the existing one. After equality and bounded validation, drop resolved syntax,
|
||||
model/catalogs and guards explicitly, then move SourceBundle into a narrow
|
||||
owning accepted result. Failure returns located diagnostics and drops pending
|
||||
output; no usable partial bundle or accepted token escapes. An owned accepted
|
||||
bundle is not a self-referential parsed witness. Repeated retained-source editing
|
||||
and actual filesystem/history installation remain distinct work.
|
||||
|
||||
## Whole equality and scratch
|
||||
|
||||
Reuse complete Project PartialEq, including established signed-zero semantics;
|
||||
do not reuse rename::same_project, which intentionally exempts names. The
|
||||
comparator's left operand must be the freshly resolved actual output model.
|
||||
Use that resolver's actual raw-expression-site count E_actual as the conservative
|
||||
equality frontier bound, reserving it against its live ledger before comparison
|
||||
and releasing after equality returns. Original E remains provenance only and
|
||||
cannot bound faulty emitted output. Existing planner proof covers Expr's iterative
|
||||
frontier only when every actual left-model Expr root is represented in the source
|
||||
expression arena; re-audit this reachability for full Project equality (including
|
||||
opaque historical carriers) before selecting E_actual. Original scalar count is
|
||||
not proof of actual output topology. No additional counting traversal or cloning
|
||||
desired model should be introduced without its own bound.
|
||||
|
||||
Reject malformed bytes, model-invalid bytes, admissible-but-wrong aliases and
|
||||
admissible-but-wrong non-name semantics. Error reporting must not recursively
|
||||
format arbitrary models. Exact input/output policies survive; new parser Usage
|
||||
is separate snapshot work. Output C remains live through syntax, resolver and
|
||||
equality and must never be reset to zero or added twice.
|
||||
|
||||
## Required finite acceptance before implementation
|
||||
|
||||
Reuse published emitter exact OA/SA/all-file/Unicode/CRLF maps as independent
|
||||
byte expectations. Construct at least one actual emitted owner whose inherited
|
||||
profile admits original parse/index/plan/emission and then passes verification,
|
||||
plus cap-minus-one refusal at the intended later stage; do not tighten a live
|
||||
owner after admission. Fake/mutated pending bytes are labeled corruption controls.
|
||||
Original empty/project rename may have a new combined producer peak greater
|
||||
than the emitter's former114-byte oracle: recompute the whole pipeline honestly.
|
||||
|
||||
Test wrong-but-admissible output, malformed output, exact policies, complete
|
||||
source/target immutability and scope/lifetime of returned ownership. Wide/deep
|
||||
actual output versus target-only shape mismatch must establish equality's chosen
|
||||
frontier bound. New tests do not replace existing public/legacy/fmt dispositions,
|
||||
stack controls or the separately unrerun older full-pipeline setup limitation.
|
||||
Full parsed-output acceptance remains private until a separate public integration
|
||||
contract reconciles all16 schema8 failures and complete graphical/source behavior.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Independent actual-output acceptance critique
|
||||
|
||||
2026-09-25. Design-only readback of ACCEPTANCE-PROPOSAL.md SHA256 `b59ca190e3cde85611158542ccf86e67c210b853b09a1fd0354daf57d4304509`, the ownership source map and domain critique, against local source `29417130c71f70c4eaefe8ed4c879efba78eb72c`. Entry runtime acceptance remains separate. No source edits, compiler, parser or network execution.
|
||||
|
||||
The proposed actual-byte parse/resolve/full-equality boundary is the useful next outcome. No further fixture-only intermediary is intrinsically required once the selected prerequisites pass. Prefer Candidate A as refined by OWNERSHIP-SOURCE-MAP: retain a complete immutable PendingRename reference, with lifetime shortening through its covariant desired Project borrow. This is simpler and stronger to inspect than projecting authority down to a bare Slots reference, and avoids Candidate B's unnecessary rearrangement of existing owning fields. Actual type checks must establish the proposed coercion and borrow scope; this review does not claim compilation.
|
||||
|
||||
## Ownership and accounting decisions to retain
|
||||
|
||||
Pending's only production constructor is consumed emission (`mixed/project/ordinary_index/rename/emission.rs:6` and its concluding construction). Its bundle, policy and retained Slots are private; emission reserves complete O before copies and drops the old indexed owner before Pending escapes. A from_pending constructor must accept the complete pending reference only and derive all views from that object. Keep guard variants private, add no arbitrary production tuple constructor, and do not copy the full policy into the guard. Existing output keys, entry and all files remain C through the new parse and resolver.
|
||||
|
||||
Put verification in a consuming Pending method. A local scope can borrow pending, use the strong text+entry route, consume syntax through existing project::resolve, reserve equality scratch on that resolved owner's live ledger, compare, then drop the resolved owner and all borrowing guards. Only afterward move the actual SourceBundle into a non-self-referential accepted owner. Returning borrowed syntax alongside it, resetting C to zero, defaulting policies or exposing a mutable Pending bundle would defeat this seam. None is needed. No-op remains the separately consuming original-owner branch.
|
||||
|
||||
Choose the accepted result's retained contents explicitly. If only bundle/policy/accepted authority survives, drop resolver warnings with verification storage. If warnings are retained or returned alongside it, their mapped strings/path copies and destination slots survive too and need an explicit transfer; final live storage is no longer O alone. `mixed/project.rs` currently reserves every mapped warning before pushing it (around lines 588–643). Do not silently clone warnings or equate excluded raw validator Issues with those counted mapped diagnostics. A small entry/default-span mismatch diagnostic is sufficient; recursive formatting of whole models is unnecessary.
|
||||
|
||||
## Actual-expression equality bound
|
||||
|
||||
Use `resolved_actual.project().eq(desired)` under reserved `E_actual = resolved_actual.expressions.len()`, not the old pending scalar or rename::same_project. All current Project-to-Expr roots remain CalculationDefinition.body (`analysis/types.rs:85–94`), EngineeringProperty.base, AnalysisCase.overrides and AnalysisCheck.predicate (`model.rs:667–682`). Historical Trace/SemanticBaseline/FacetReview payloads are closed and contain ordinary strings/IDs/LifelineBinding rather than analysis Expr (`semantic/types.rs:84–174`, `model.rs:526,1632–1650`). The model/type/equality/lowering files are unchanged from the previously reviewed `18073a6` proof.
|
||||
|
||||
`lower.rs:687–699,755–846` routes each real binding through expression lowering, emits one ExpressionSite per visited node, and schedules all child variants; mixed resolution retains this arena while merging model definitions/elements. `analysis/expression_lifecycle.rs:170–270` keeps one iterative pair frontier, checks list/call shape before child insertion and never invokes another Expr equality with its frontier live. Pair members correspond to distinct nodes of the actual left tree, so every simultaneously live frontier is bounded by its actual tree size, hence E_actual. Sequential whole-Project field/container comparisons do not require summing all separate equality Vecs. E_actual may conservatively reject a comparison that would short-circuit; do not promise unconditional success with no phase headroom.
|
||||
|
||||
Make E_actual=0 explicit: derived Binding/parent variant checks reject target-only Expression before entering Expr::eq; no allocating equality call has a zero-node actual Expr. Keep whole-model PartialEq, including +0/-0 equivalence across geometry, ordinary and historical real carriers. Equality establishes semantic PartialEq, not bitwise target identity. Renew this reachability proof if Project payload types or expression production change.
|
||||
|
||||
## Corruption controls and finite gates
|
||||
|
||||
Corrupted Pending tests must preserve their claimed live-storage provenance. Equal-byte replacements can change valid semantics, syntax or expression topology while retaining the authenticated O. Length-changing test mutations must either be rejected by an explicitly selected inventory invariant or construct an independently verified actual-O fixture under the inherited policy; keeping stale O after growing the bundle is not evidence of correct carried accounting. Especially test faulty actual output with more expression nodes than original E to demonstrate why E_actual is used.
|
||||
|
||||
Use one unchanged inherited profile for original parse/index/plan/emission and verification. Recompute the combined original and new-snapshot peaks; a syntax-only cap need not admit the independent counting walk, resolver catalogs or final equality. Require a real full-pipeline positive and a cap-minus-one that genuinely reaches the intended late stage, plus wrong-but-admissible names and non-name data, malformed/model-invalid output, E=0 target-only damage, actual wide/deep equality and signed zero. Drop original inputs and desired after success and inspect the independently owning returned bytes. Failed verification must yield only diagnostics and drop Pending, without exposing a usable partial bundle.
|
||||
|
||||
The domain critique's explicit independent bounds for named remaining scratch are compatible with this outcome; they must be selected and documented, not described as aggregate carried reservations. Existing bounds/exclusions do not exempt new output ownership, equality frontier or retained mapped diagnostics. Native verifier/drop frames require concrete measurements and existing stack controls; earlier separately unrerun setup failures are not converted to success by this design. Public source8, repeated retained editing and filesystem/history adoption remain separate contracts.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Accepted owner contents: independent critique
|
||||
|
||||
Read-only inspection of the current resolver/warning mapper and owned diagnostic schemas, with unchanged relevant behavior from97a8703 through2941713. No source modification, build or runtime claim. This recommends a contract choice; parent owns selection.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Prefer an opaque owning result containing the verified SourceBundle, the **actual freshly resolved Project**, mapped warnings, exact inherited policy and its final retained Slots. This avoids throwing away already admitted graph data and actionable diagnostics immediately before a later coherent source/graph adoption step. It remains a narrow non-self-referential value: Project and SourceDiagnostic own their contents and do not borrow syntax. No history/install operation, public source8 activation or repeated-edit constructor follows automatically.
|
||||
|
||||
Bundle/policy only is a valid smaller proof artifact, but requires a later parse/admit step to recover the graph and warnings for adoption. It is preferable only if the deliberate next consumer needs exclusively bytes and no diagnostics/model. That does not appear to match the currently described editing goal. Moving existing values after verification is smaller than introducing another cache, clone or deferred parse protocol.
|
||||
|
||||
The accepted model must be the resolver's actual output model, not a clone/move of desired intent merely because equality passed. Whole equality is the gate, not a replacement constructor. Existing model/serde/raw-validator heap exclusions permit retaining that already admitted Project without adding its internal maps/strings to logical auxiliary W; call this an explicit inherited domain, not a claim that the Project occupies no memory.
|
||||
|
||||
## Exact retained-warning inventory
|
||||
|
||||
`mixed/project.rs:594–649` reserves each mapped diagnostic before its path copy/destination push. The reservation is one entry, zero occurrences, and byte lengths of path + code + optional field + message. Severity/object UUID/span/line/column are scalar; no copied text is hidden there. `source_project.rs:80–84` defines `SourceDiagnostic { path, diagnostic, related }`; mapper always creates empty related. The return at project.rs:651 rejects any Error-severity issue before returning a resolved success.
|
||||
|
||||
For the current successful producer, compute without allocations:
|
||||
|
||||
```
|
||||
W.entries = warnings.len()
|
||||
W.occurrences = 0
|
||||
W.text = checked sum over warnings of
|
||||
path.len + diagnostic.code.len + optional field.len + message.len
|
||||
```
|
||||
|
||||
Use the same Slots checked arithmetic as the mapper, not saturating sums or a numeric total copied from a previous phase. Require every related vector empty and every severity non-Error under this sealed extraction route. An unexpected shape is an invariant refusal before returning the accepted owner, never silently ignored. If later mapper changes introduce related locations, update the named inventory (entries and path bytes) and tests together; this choice does not authorize flattening/dropping them.
|
||||
|
||||
A checked borrowed loop over current warnings allocates no extra frontier or String. Do not construct a secondary warnings Vec, clone diagnostics, format the Project, or rerun validation to count them. Current storage ledger already contains these warning reservations while syntax and equality are live; **do not reserve W a second time there**. Reconstruction for final transfer is distinct from additive growth.
|
||||
|
||||
## Safe transition and accounting
|
||||
|
||||
Recommended logical sequence:
|
||||
|
||||
1. Resolve the actual complete output with carried O under exact inherited policy; keep resolver and warnings live.
|
||||
2. Reserve the selected actual-model equality scratch against the full live ledger, compare the entire actual Project with desired, and release E. Retaining warnings means they must already participate in that equality-time aggregate, as they currently do in resolver storage.
|
||||
3. Compute W from the current warning records and checked final `O + W`. Validate that final total under the resolver's original Budget while it still exists. It should be a subset of the successfully held full storage; a componentwise subset check is a useful internal invariant, not a substitute for correct ownership inventory. If checking fails, return diagnostics with the existing failure escape and drop output, never a usable partial owner.
|
||||
4. Destructure/move actual Project and warnings into local owners, explicitly drop all remaining syntax/index/expression/occurrence/catalog/guard state, then move pending SourceBundle/policy into the accepted owner. Rust must establish that the guard borrowing pending is gone before its bundle moves. No copied warning path/model is necessary and no self-reference remains.
|
||||
|
||||
Final retained entries are O.entries + warning count; text is O.text + W.text; occurrences are O.occurrences (normally zero for the emitted bundle) plus zero. Do not carry released syntax U/M/T, equality E or resolver catalogs as live accepted storage. Conversely, do not return O alone when warnings remain owned. Model and original desired borrow do not become new logical slots merely by this ownership transition.
|
||||
|
||||
An independently computed final subset check can happen before physically dropping other objects because it is checking the eventual destination inventory, not claiming those drops already happened. The full resolver ledger must continue to cover coexistence until actual drops. An implementation that resets that live ledger to O+W early and subsequently allocates against its artificial headroom would be incorrect.
|
||||
|
||||
All accepted-result fields should remain private with read-only accessors. No public unchecked bundle+Project+warnings+Slots constructor, mutable bundle/model access, or from-desired shortcut. Any later consuming adoption method needs its own invariant about jointly installing graph/source/warnings. Read-only accepted ownership itself does not authorize saving/history mutation.
|
||||
|
||||
## Finite evaluators and caveats
|
||||
|
||||
Use a real emitted output that resolves with at least one stable mapped warning. Independently derive warning entry/text bytes from its literal expected path/code/field/message; assert warning content/location unchanged, actual Project equality and exact final O+W. A warning-free fixture alone cannot detect the dropped-W bug. Include multiple warnings or an optional field only if needed to distinguish summation from one-record handling; do not expand into a full validator redesign.
|
||||
|
||||
Keep the equality-time warning reservation and final retention tests separate from output verification caps: final O+W is usually below the already admitted resolver/equality peak, so a purported final-only cap-minus-one failure may be impossible through a real earlier-admitted owner. Use a checked-inventory fault control for impossible overflow/related-shape defects and label it accordingly; retain a real profile unchanged through actual pipeline positives/refusals. Do not lower the policy after admission to fabricate provenance.
|
||||
|
||||
Warnings should stay actionable after syntax drops: source path, span, Unicode line/column and optional field must still refer to the verified returned bytes. Moving them preserves the mapper's positions; rewriting output after extraction would invalidate that relation. An independently matching desired Project alone cannot establish diagnostic-to-byte identity.
|
||||
|
||||
Optionally retain already available scalar new-snapshot Usage/static admission metadata if a concrete caller needs it, but it is not necessary to retain expression arenas or whole syntax just to avoid losing those scalars. Original work and verification work must remain separately identified. No new arbitrary constructor is justified by exposing counters.
|
||||
|
||||
I see no correctness blocker in moving actual Project plus warnings with explicit O+W transfer. The material obligations are exact warning inventory, no duplicate charge, full-ledger coexistence through equality/drop, and sealed immutable construction. This recommendation leaves actual equality-frontier proof and output-admission behavior to their separate accepted contract/review.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Remaining parser scratch: bounded independent critique
|
||||
|
||||
Read-only source basis97a8703adc75467a7f8e75f5c6cb00ca542b707c. Entry-producer work is pending and is not assumed accepted or executed here. This is a recommendation for the parent to decide, not an accepted domain change or runtime finding.
|
||||
|
||||
## Conclusion and obligation
|
||||
|
||||
Yes: an output-acceptance contract can explicitly preserve existing independent file/token/grammar/numeric bounds for named remaining parser scratch instead of adding all that scratch to the carried aggregate. This is consistent with the bounded logical domain, provided the contract accurately names its timing and exclusions. It must not claim one global physical memory ceiling, aggregate before-every-allocation, or that an independent bound is a reservation against the surviving output owner.
|
||||
|
||||
The user need is reliable graphical/text/API editing and persistence. A physical heap meter is not a user-owned requirement identified in the domain audit. The accepted rename-plan contract's mandatory successor *does* require complete actual emitted output, exact inherited policy, surviving-output accounting, actual parse/resolve/admission, whole desired-Project equality with E scratch, documented old-owner transition, and no usable failed result. These are not waived by choosing a smaller scratch domain. That contract does not name every parser coordination stack as a new carried-ledger allocation.
|
||||
|
||||
The earlier `CARRIED-STORAGE-DOMAIN-AUDIT.md` calls itself a design audit, not an accepted contract. Its recommended expansion seams and question about traversal/delimiter scratch must not silently become user requirements. In particular, its suggested significant-token push charge is not the currently accepted metric: the entry contract explicitly retains token storage under the token bound, with one token-end M subtotal reserved before ends construction. The newer text contract explicitly names its retained String producers and temporary decode/result strings. Neither permits hiding a newly introduced in-scope owned output/path/equality structure as old scratch.
|
||||
|
||||
## What existing source actually bounds
|
||||
|
||||
All source references below are repository-relative at97a8703.
|
||||
|
||||
| Scratch | Existing guard or structural bound | Remaining limitation |
|
||||
| --- | --- | --- |
|
||||
| Folded path table and traversal paths | `source_project/traversal.rs:22–87` checks file count and source-text sum before its folded table; validates every supplied path. Active/visited unique paths are related to file count; pending includes to include-edge count. | File-count bounds are not total path-byte bounds. Folded Unicode path copies and canonicalization allocate outside aggregate T. `include` at149–178 resolves/copies target and location before its edge-limit refusal; it is false to describe every such temporary as guarded before growth. |
|
||||
| Traversal queue/children/active stack | Same file/edge/depth policy; `next` checks depth before visited insertion; `finish_file` transfers pending children into stack (`89–186`). | Repeated include targets still consume edges and path copies. Entry count and path text can coexist with output C without debiting its aggregate ceiling. A deep/wide graph is not bounded solely by visited-file count. |
|
||||
| Delimiter stack | `language.rs:1032–1040`: at most one push per opening delimiter in the already scanned significant-token sequence. Ends array is the selected M subtotal. | Delimiter stack is another collection, not prepaid by the same N ends reservation. Token guard is a separate finite bound; no aggregate C+M charge for delimiter slots exists. |
|
||||
| Ordinary open declarations | `language.rs:1539–1723`: stack carries indices into the flat declaration vector. Existing declaration events/model count checks precede each declaration and its open push. | Maximum live depth is structurally at most declarations. Do not claim this vector is controlled by typed-value depth64 or by the typed Pratt frame budget; those are different controls. |
|
||||
| Pratt coordination | `analysis_source/syntax.rs:18–45,60–63,154–264`: tasks/values/sequence coordination are iterative; expression/operator/argument events, raw tokens and relevant grammar-frame checks constrain growth. | Not every Vec push has its own reserve, and grammar frame count is not native stack bytes. Completed subtree values remain owned while siblings parse. Existing small-stack successes are finite evidence, not a universal stack guarantee. |
|
||||
| Typed duplicate-name/ID sets | `declarations.rs:284–307,604–624` and `syntax.rs:238–249`: entries track already charged declarations/arguments/overrides. Named string clones derive from parsed reference/name text. | These clones are explicitly excluded scratch, not retained T or scanner/grammar decode W. Work count bounds their number, not independently their total copied bytes; original text/source bounds provide an additional constraint. No existing aggregate reservation covers their overlap. |
|
||||
|
||||
These are finite structural relationships, not exact peak formulas. With unlimited/wide configured policies, they may be practically large. UTF-8 case folding, path normalization, repeated path copies, large sequence coordination and native enum sizes are reasons not to present the logical ceiling as a process-memory bound.
|
||||
|
||||
## Choices
|
||||
|
||||
1. **Retain named independent bounds, explicitly excluded from carried W.** Smallest next step. Complete selected retained T/U/M hooks and reconciliation; retain exact existing traversal/token/grammar checks and refusal semantics; finish owning actual-output admission/equality. Document the table above in the acceptance contract. This is my recommendation for the currently stated editing objective.
|
||||
|
||||
2. **Add selected scratch W, starting with a demonstrated problem.** Useful if a specific unbounded or disproportionate copy threatens the intended deployment, or if the parent selects a stronger aggregate resource promise. For example, traversal path storage would require canonicalization/folded-path temporary and queue ownership decisions, with path-byte rather than just file-slot accounting. A delimiter-only W is simpler but proves nothing about the other excluded structures. Each addition needs before-growth placement, release/transfer rules and a literal peak oracle; it is not a harmless extension to current caps.
|
||||
|
||||
3. **Universal parser/all-heap containment.** Much larger and unsupported as the automatic next prerequisite. Allocator capacity, model/serde/validator and numeric internals are already excluded by accepted contracts. Instrumenting only parser stacks would still not establish this promise.
|
||||
|
||||
Do not choose option1 while retaining prose from option2 that says all parser auxiliary storage is charged against C. Conversely, do not block actual-output correctness on proving an unrequested universal bound.
|
||||
|
||||
## Concrete evidence needs without scope expansion
|
||||
|
||||
Before relying on the existing bounds, source review must establish each structural relationship and no new output-verification helper bypasses its existing checks. Reuse existing limit controls where they already cover duplicate include edges, depth, token exhaustion, declaration nesting and wide/deep expressions. A missing relevant control is a reason for one finite diagnostic test, not a generic scratch allocator framework.
|
||||
|
||||
The clearest risk deserving a specific design note is traversal path text: source-byte sum excludes map keys, and include canonicalization occurs before edge refusal. The accepted owned-output C already counts all emitted path keys and entry text, but that does not account folded/path queue copies. Either explicitly retain this limitation, or select a separate path-specific strengthening. Do not claim file/source limits alone provide a tight path-byte peak. No measured failure in this review requires instrumentation immediately.
|
||||
|
||||
New accepted-output lifetime/equality scratch is different: it is explicitly mandated and cannot be excluded as parser coordination. Preserve old B during emission, carry actual O after the documented old-owner drop, include new verification syntax/storage against O, reserve E against the correct verification live total, and drop temporary verification before returning a non-self-referential owning accepted result. An excluded raw desired/model borrow does not justify losing in-scope path/output copies. Retained mapped diagnostics continue to require their existing reservations even though transient refusal diagnostics have an escape.
|
||||
|
||||
Native stack risk remains empirical. Preserve existing128KiB/deep/wide controls and inspect changed prologues if new state/hooks alter frames. A stack failure is not repaired by putting vector slots in W; neither a phase check nor a token bound proves Rust stack headroom. Do not relax tests to support a stronger claim.
|
||||
|
||||
Suggested precise acceptance wording: “The verifier checks the declared retained syntax and auxiliary domain, plus the named temporary decode and equality domains, against the exact inherited aggregate policy including surviving output. Existing traversal, delimiter, ordinary-open, Pratt and duplicate-name scratch retain their independent file/edge/token/grammar bounds and are excluded from that aggregate metric. This is not a physical-memory or before-every-allocation guarantee.” Actual source/evidence must support the selected hooks before that wording is claimed implemented.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Pending output ownership source map — proposal only
|
||||
|
||||
Source inspected: `a629ae01d49bb3cb482a047eb41832ad4246a5c6`; no compilation,
|
||||
source modification or acceptance claim. This refines only the lifetime seam in
|
||||
[ACCEPTANCE-PROPOSAL.md](ACCEPTANCE-PROPOSAL.md), not equality/scratch policy.
|
||||
Paths below are relative to `.local/as3batch` at that commit.
|
||||
|
||||
## Existing authority
|
||||
|
||||
`crates/oa-core/src/language/analysis_source/mixed/project/ordinary_index/rename/emission.rs:6`
|
||||
owns PendingRename's bundle, exact Limits/ProjectLimits, retained Slots, original
|
||||
expression count and immutable desired Project reference. Its constructor at the
|
||||
end of `emit_changed_unverified` follows output reservation and explicit old-owner
|
||||
drop; no public bundle/slots constructor exists. Those private fields currently
|
||||
prevent sibling carried code from reading authority.
|
||||
|
||||
`.../mixed/carried.rs:40` consumes CarriedInput into a bundle reference, one policy
|
||||
value and a slim guard. `:63` derives C from that guard; `:116` selects both producer
|
||||
modes. `.../mixed.rs:39` stores the guard alongside the borrowed bundle and Budget;
|
||||
`:308` is the shared parser. Consumed resolution at `.../mixed/project.rs:453`
|
||||
retains that syntax. None of these owners currently needs desired's lifetime.
|
||||
|
||||
## Recommend Candidate A with a complete pending reference
|
||||
|
||||
The smallest variant avoids projecting authority down to a bare `&Slots` at all:
|
||||
|
||||
```rust
|
||||
// Private variants in the existing enums; no new allocating wrapper.
|
||||
SnapshotBacking::Pending(&'s PendingRename<'s>)
|
||||
GuardBacking::Pending(&'s PendingRename<'s>)
|
||||
|
||||
impl<'s> CarriedInput<'s> {
|
||||
pub(super) fn from_pending<'t: 's>(p: &'s PendingRename<'t>) -> Self {
|
||||
Self { backing: SnapshotBacking::Pending(p) }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a proposed Rust shape, not a compiler-tested patch. PendingRename is
|
||||
covariant in its sole lifetime: the only use is `desired: &'t Project`, and all
|
||||
other fields own data without that lifetime. Consequently the longer desired
|
||||
borrow can be shortened to the pending borrow `'s` when storing `p`. The original
|
||||
pending value retains its original type/lifetime; no data moves or self-reference
|
||||
is created. Parser, resolved and indexed owner types keep their single existing
|
||||
`'s`. Immutable `&PendingRename` itself prevents mutation, consumption or dropping
|
||||
its bundle while syntax/guard remain usable. No trait object or PhantomData proof
|
||||
is needed, and future invariant lifetime-bearing fields would require revisiting
|
||||
this coercion rather than silently bypassing it.
|
||||
|
||||
Add narrowly visible immutable Pending methods `bundle() -> &SourceBundle`,
|
||||
`policy() -> (Limits, ProjectLimits)` and `retained() -> Slots`, restricted to
|
||||
`pub(in crate::language::analysis_source::mixed)`. CarriedInput accepts only the
|
||||
complete pending reference, never those components as independent arguments.
|
||||
`into_parts` derives bundle/policy from its stored pending and transfers the same
|
||||
reference into GuardBacking::Pending; `slots()` calls that pending's retained
|
||||
method. Policy is copied once into the existing preparse transfer value and then
|
||||
Budget/syntax limits; the guard contains only one pointer, not another policy.
|
||||
Pending necessarily retains its original immutable policy as owner provenance.
|
||||
No recomputation of C, tuple authentication or runtime identity comparison helps.
|
||||
|
||||
## Candidate B and visibility
|
||||
|
||||
Embedding an owned RetainedSnapshot in Pending would remove the cross-reference
|
||||
between carried and emission modules and also avoid desired lifetime covariance.
|
||||
It adds no necessary heap allocation, but replaces existing pending fields,
|
||||
changes emission construction and existing direct inspection tests, and requires
|
||||
a controlled production snapshot constructor or wider sibling field authority.
|
||||
That larger migration has no present ownership benefit over the complete pointer.
|
||||
Prefer B only if later genuinely shared owning snapshot behavior justifies it.
|
||||
|
||||
The module paths are already visible: `ordinary_index.rs:433` exposes rename to
|
||||
analysis_source, and `rename.rs:2` exposes emission likewise. Pending type itself
|
||||
has that visibility. Keep carried private to mixed; descendants can name its
|
||||
module. The needed changes are just its from_pending entry point and a named
|
||||
strong parse entry with visibility up to mixed, plus the three immutable pending
|
||||
views. Keep SnapshotBacking/GuardBacking variants and fields private to carried;
|
||||
do not export SnapshotPolicy or add arbitrary production RetainedSnapshot inputs.
|
||||
|
||||
## Consuming verification and finite type checks
|
||||
|
||||
Implement verify in emission, where it can consume self and eventually move its
|
||||
private bundle. A local block calls the strong parser with from_pending(&self),
|
||||
consumes syntax into resolve, performs separately specified bounded equality,
|
||||
then drops resolved owner/guard before leaving that block. Only afterward move
|
||||
self.bundle into an owning accepted result. No parsed witness or desired borrow
|
||||
escapes, so accepted output has no lifetime parameter or self-reference. Failure
|
||||
returns diagnostics and drops self; successful no-op remains the separate old
|
||||
owner branch. This note does not select accepted-result extraction/installation.
|
||||
|
||||
Compiler acceptance must demonstrate: long-lived desired + local pending can
|
||||
produce a short scoped syntax; resolved owner cannot outlive pending; moving or
|
||||
mutating pending while the guard is subsequently used is rejected; dropping all
|
||||
verification borrows permits moving the bundle into the accepted owner. Positive
|
||||
runtime tests should drop original input and desired after acceptance and still
|
||||
inspect returned output. Preserve exact inherited policies and C once throughout;
|
||||
no new carrying-mode bypass or policy mutation. Any compile-fail examples should
|
||||
be narrow external snippets/appropriate harness, not runtime unsafe tricks.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Independent unnamed-project warning oracle
|
||||
|
||||
Authored from existing mapper/catalog/index/emission logic at2941713 (relevant behavior unchanged from97a8703), not parser or runtime output. This is a prospective acceptance evaluator, not a passing execution claim. Literal-only Python checked lengths, hashes and offsets; no compiler/parser/binary ran.
|
||||
|
||||
## Exact original and output
|
||||
|
||||
Single file/entry `main.arcadia` (12 UTF-8 bytes each). Original71-byte source, including final LF:
|
||||
|
||||
```text
|
||||
arcadia 8;
|
||||
project p "" id "00000000-0000-0000-0000-000000000001" {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Original SHA256 `68b9215285d622c77b46df105839f65c40fb76f2ba7c55a6a9cbbc1fc4576146`. Rename only project aliasp→next; physical original alias span19..20. Output74-byte literal:
|
||||
|
||||
```text
|
||||
arcadia 8;
|
||||
project next "" id "00000000-0000-0000-0000-000000000001" {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Output SHA256 `dbde19f06d6bde26c16b4672dcc43036dec693fb04ebc23de76e4faa369dd81f`. O=(entries1, occurrences0, text98), since74+12+12=98. Exact inherited entries18 and bytes161 are the proposed unchanged positive policy; bytes160 is the proposed late-refusal sibling, with all other limits roomy and unchanged throughout each pipeline. Original parsing must be the supported legacy uncarried route because changed emission rejects carried syntax.
|
||||
|
||||
## Complete expected Project and warning
|
||||
|
||||
Actual accepted Project must have schema_version8, UUID00000000-0000-0000-0000-000000000001, alias`next`, name`""`, description`""`, and all six maps empty: definitions, elements, relations, diagrams, artifact_links, traces. Original Project differs only in alias`p`. No expressions or lowered occurrences exist, so E_actual=0 for equality.
|
||||
|
||||
Exactly one mapped diagnostic is expected:
|
||||
|
||||
- path`main.arcadia`; related empty;
|
||||
- severityWarning; code`unnamed`; object_idSome(ID1); fieldSome(`name`);
|
||||
- message`Give the project a descriptive name.` (36 bytes);
|
||||
- output span11..69, line2, column1.
|
||||
|
||||
`validation.rs:325–333` emits that warning for empty trimmed project name. `project.rs:666+` falls back to the project header for the name field; empty name does not manufacture a field span. Header start11 is unchanged, opening brace69 ends the output header. Original warning instead spans11..66. The returned warning must be the output warning, not one moved from original admission.
|
||||
|
||||
Current mapper `project.rs:594–649` makes W=(entries1, occurrences0, text59): path12 + code7 + field4 + message36. Scalar span/UUID/severity/line/column add no string bytes. Final accepted O+W=(2,0,157). Model payload remains the established excluded domain; this is not its physical memory size.
|
||||
|
||||
## Verification peak, with catalog lifetime
|
||||
|
||||
Output U1/M11/T4: one project syntax event, F1+ten significant tokens, aliasnext4 and empty name/description. Work bytes74, raw tokens19, references0, numeric units0. Combined retained syntax is entries13/text102=O98+T4. Scanner temporary36 fits134; grammar project UUID temporary36 overlaps alias4, requiring138. No ordinary positions, value maps or typed syntax exist.
|
||||
|
||||
Catalog creation reserves alias/owner2 entries with alias4 text, then table2 entries with another alias4 (`project.rs:240–325`). Its peak is entries17/text110. `project.rs:521–524` drops aliases before lowering; `557–560` drops tables before warning mapping. Thus neither extra alias copy remains at the warning reservation. The owner table remains one entry, no text, through mapping, and drops afterward (`655`).
|
||||
|
||||
Immediately before warning mapping: entries14=syntax13+owner1, text102. The mapped warning reserve adds1/59, reaching entries15/text161. At bytes160 the exact refusal is `Source8 index/output byte limit exceeded.`, codeinvalid_source, pathmain.arcadia, span11..69, line2column1, no related diagnostics. This typed mapper failure preserves the full header span; it is not the ordinary parser's one-byte transport. Bytes161 admits this reservation. Owner table then drops, leaving resolver entries14/text161 =O + U/M/T + W. EqualityE0 adds nothing. After syntax drops, retained accepted inventory is entries2/text157.
|
||||
|
||||
The final O+W check is not itself the161-byte peak and must not be called the site of160 refusal. It rechecks the smaller eventual retained subset. The intended negative occurs before warning destination allocation while original output-owned C is still live.
|
||||
|
||||
## Original predecessor clearance under the same policy
|
||||
|
||||
Original uncarried syntax has U1/M11/T1. Its name is empty; original mapped warning has the same59-byte string inventory. Catalog peaks at syntax12+4=16 entries and text3; at warning mapping it retains syntax12+owner1+warning1=14 entries/text60. Owner release leaves13 entries/text60. Typed index adds one retained global-name entry/text1, giving14/text61. Ordinary authored index adds one header occurrence entry; its one-global reverse map is temporary, so final authored state15/text61. No expression/occurrence/field work adds another slot.
|
||||
|
||||
Plan stores one changed-name entry and one physical edit entry; replacements borrow desired and add no owned text. Its final state is17 entries/text61. Collision-check one-element namespace occurs before the edit exists, so it does not exceed17. E0 adds no equality scratch. Old emitted-output overlap is17+O1=18 entries and61+98=159 text. Both bytes160 and161 therefore clear old parser/resolver/index/plan/emission; source/output byte lengths71/74 also fit. Emission drops old owner/warning before verification, so the old59 warning bytes do not coexist with the new warning map.
|
||||
|
||||
This derivation agrees with the existing named empty emission envelope after removing seven old name bytes and adding one59-byte/one-entry original warning. It is nevertheless an independently traceable source calculation, not a runtime result. Do not introduce a default policy, a newly tightened pending owner, or a borrowed numeric baseline to make the negative pass earlier stages.
|
||||
|
||||
Expected real end-to-end distinction: identical entries18 and other policies, bytes161 succeeds with exact output/Project/warning/O+W; bytes160 reaches actual-output warning mapping and refuses there. If runtime rejects earlier, investigate actual source/lifetime/count differences rather than changing the oracle from observed output. Additional copy/reservation introduced by the future acceptance implementation must be disclosed and independently justified before claiming this cap.
|
||||
@@ -0,0 +1,121 @@
|
||||
# Mixed source8 command-line checking
|
||||
|
||||
Selected next outcome in the already-owned textual-language scope: an engineer
|
||||
can run `arcadia check-mixed ROOT [--json]` on an explicit entry file and receive
|
||||
located results for its complete included mixed model, without changing files.
|
||||
Baseline source is public-read checkpoint bab6f96a. This contract is local-only
|
||||
while Gitea writes/publication remain unavailable. The published preview is frozen.
|
||||
|
||||
## User-visible behavior
|
||||
|
||||
Keep existing check/lint/stabilize/rename behavior and the ordinary library
|
||||
`prepare` contract. Add one explicit check-mixed spelling, rejecting --write,
|
||||
unknown/repeated options and invalid argument counts. Route it separately from
|
||||
editable preparation; do not construct a fake Prepared or SourceIndex. Use a
|
||||
closed command-dispatch enum rather than an ambiguous combination of mode flags.
|
||||
|
||||
The existing Report envelope remains version1. Operation is check-mixed; success
|
||||
is checked/exit0, with advisory warnings permitted. Changes is empty, written is
|
||||
false, migration is null, identities_to_stabilize is zero. All locations refer to
|
||||
captured original input. Missing explicit UUIDs, unsupported versions, malformed
|
||||
syntax and semantic invalidity are errors, not implicit stabilization or migration.
|
||||
Retain actual warning order and authored object identities from the admitted model.
|
||||
|
||||
Use the existing exit conventions: source/semantic rejection1, arguments2,
|
||||
disk/path/journal/output failure3. Match existing treatment of loader diagnostics
|
||||
and disk error variants, including its source-limit distinctions; document/test
|
||||
the actual relevant precedence instead of assuming every limit uses one phase.
|
||||
Human output/help must explain the explicit-ID schema8 read-only contract and
|
||||
make the check result clear without implying proposed edits.
|
||||
|
||||
## Source discovery and ownership
|
||||
|
||||
Add `source_files::load_mixed_source(entry, limits)` returning an opaque
|
||||
MixedSourceSnapshot with immutable bundle() and diagnostics() views. It captures
|
||||
original bytes only. It confers no save authority, editable compilation, recovery
|
||||
or promise of an atomic snapshot against another process. A caller must handle
|
||||
discovery diagnostics before treating the bundle as complete. CLI owns this
|
||||
snapshot, invokes check_mixed_bundle on its borrowed bundle only after discovery
|
||||
succeeds, and copies diagnostics into the owned report before dropping the result.
|
||||
|
||||
Reuse the existing private disk discovery loop and path/read/physical-alias/journal
|
||||
checks through a closed ordinary/mixed selector. The ordinary route remains
|
||||
unchanged, including overlays, detached buffers, expectations and final compilation.
|
||||
The new fresh mixed route has no overlays and skips ordinary compile_bundle.
|
||||
Consume its private DiskProject storage into bundle/diagnostics and discard unused
|
||||
expectations/root/reachability after the checks; avoid cloning reachable_bundle or
|
||||
exporting DiskProject as mixed save authority.
|
||||
|
||||
Before disk reads, clamp the mixed source-byte allowance to min(caller,64MiB),
|
||||
matching the parser's hard ceiling; preserve all other caller restrictions.
|
||||
Keep canonical root-relative paths, UTF-8, regular-file/link rules, case and
|
||||
physical-alias detection, aggregate files/bytes/edges/depth and pending journals.
|
||||
Pending transactions remain an error and are never recovered implicitly.
|
||||
Resolve includes with the existing resolver. Parse each successfully loaded path
|
||||
once in existing deterministic traversal order; count repeated authored edges.
|
||||
Complete semantic checking still detects cycles and cross-file errors.
|
||||
|
||||
Inspect includes by the real shared mixed Parser::unit grammar, including typed
|
||||
declarations, explicit IDs and long-form refusals. Centralize the minimal parser
|
||||
setup/operation needed by discovery and complete parsing; preserve the latter's
|
||||
grammar, producer hooks, policy, retained witnesses and stack behavior. No regex
|
||||
scanner, second grammar or complete-checker call on partial bundles is permitted.
|
||||
Return no partial include list after a unit syntax failure.
|
||||
|
||||
## Bounded discovery phase
|
||||
|
||||
Choose one shared discovery Budget and ModelCounts for the entire discovery pass,
|
||||
derived by the existing mixed source profile. Enable existing text and entry
|
||||
producer checks once with zero initial reservation. Byte/token/reference/numeric
|
||||
work and syntax/model counts accumulate across files; do not restart allowances
|
||||
per file. Charge each inspected file before lexing/parsing and keep the existing
|
||||
prospective syntax/value/owner producer checks. Tokens keep their existing
|
||||
pre-scan bound; disk/path/traversal tables retain their separate filesystem limits.
|
||||
Do not allocate edit positions or a resolved/indexed model merely for discovery.
|
||||
|
||||
Completed unit syntax is dropped after moving its include information. Its
|
||||
remaining producer charges deliberately remain reserved until this phase ends:
|
||||
these counters are a conservative cumulative admission bound, not a claim of
|
||||
exact live storage or a verifier-owned carry. Ordinary in-parser temporary and
|
||||
UUID/key releases remain unchanged. No unit-drop refund mechanism or new generic
|
||||
allocation framework is needed. Shared grammar and once-per-path order consume
|
||||
the same syntax/work events as full parsing, with fewer later projections; tests
|
||||
must discriminate cumulative accounting from accidental per-file resets.
|
||||
|
||||
A syntax/budget failure is terminal for mixed parsing: record its original located
|
||||
diagnostic, do not reuse a poisoned span-only Budget for another file, and do not
|
||||
invoke final model checking on incomplete discovery. Still perform required final
|
||||
filesystem and journal checks. Ordinary aggregation remains unchanged.
|
||||
|
||||
After successful discovery, drop the discovery budget/scratch and run the existing
|
||||
complete checker with a fresh profile and the original caller policy. These are
|
||||
two explicitly bounded passes, not a claim of one shared whole-command numeric
|
||||
allowance or all-heap accounting. Discovery grants no semantic admission witness.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Real executable and library cases load mixed OA/SA multi-file fixtures with
|
||||
cross-file/scoped typed references and nested ordinary records. Independently
|
||||
construct complete expected models for those same bytes; check actual complete
|
||||
JSON/human diagnostics and status rather than inventing a model field in Report.
|
||||
- Prove exact source/directory preservation on success, warning and refusal,
|
||||
including Unicode/CRLF and comment/string text resembling includes or aliases.
|
||||
Exercise missing UUID classes and wrong-kind/unresolved typed references.
|
||||
- Test missing/cyclic includes, root/path escape, case and physical aliases,
|
||||
invalid UTF-8/nonregular files, pending journal, and selected exact file/byte/
|
||||
depth/edge boundaries. Platform-specific checks are claimed only when run.
|
||||
- Observe the actual shared discovery constructor/counters: multi-file cumulative
|
||||
work, retained conservative reservations after dropping a unit, zero temporary
|
||||
balance after successful units, exact caller/profile capture and first-error
|
||||
location with an unparsed later sibling. Use real small boundary controls with
|
||||
positive cases; test-only tightening must not become public policy.
|
||||
- All old core and relevant filesystem/source/stack tests remain passing. Run
|
||||
existing ordinary CLI tests plus new mixed CLI tests, actual CLI commands,
|
||||
strict core/CLI Clippy, doctests and formatting disposition. Bind gates to a
|
||||
reviewed clean source commit and preserve initial failures without weakening
|
||||
model, bytes, locations or resource expectations.
|
||||
|
||||
Independent source/runtime review follows implementation. Parent owns integration,
|
||||
compiler execution and acceptance. Core discovery/parser and CLI/report/tests/docs
|
||||
may be delegated with disjoint files and the interfaces above. Linux remains
|
||||
user-deferred; no GUI/editor/save/history or release integration is implied.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Read-only mixed CLI: independent critique
|
||||
|
||||
Research only against `bab6f96a5b05b37f2b5d67a430aed0f67d783e73`; no builds, application execution, production edits or remote actions. Reviewed implementation map SHA256 `cb611919a1d6b6463f5e7054922d40457734305656e0dfff9dd4a1388a2c4ed7`. References below are relative to that source. This selects a bounded next outcome, not acceptance of an implementation.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Implement explicit `arcadia check-mixed ROOT [--json]`: discover actual included files safely, then invoke the existing complete borrowed checker on captured original bytes. Require schema8 and explicit UUIDs, including ordinary declarations in this command. Return diagnostics through the existing report envelope, with no changes, migration, stabilization or write. This delivers useful command-line validation for the textual-model/linting goal in `PROJECT_GOAL.md:64–69,96`, while leaving editable model adoption separate.
|
||||
|
||||
`check --mixed` is also coherent, but offers no semantic advantage and requires more option-combination rules. Choose one spelling. Automatic replacement of `check` is unsafe: existing ordinary drafts intentionally accept omitted IDs and older versions. Schema8 alone cannot select between those policies. A manifest of every file is a simpler parser-free discovery interface, but transfers routine include enumeration to users and is not an equivalent root-file workflow. Full compile/index adoption is substantially larger and unnecessary here.
|
||||
|
||||
## Simpler correct discovery policy
|
||||
|
||||
Prefer **one shared discovery Budget and ModelCounts, with conservative completed-unit reservations retained until discovery ends**. This is simpler than the map's proposed exact release/reconciliation seam. Do not describe its counters as exact live storage, an admitted syntax witness, or carry into the final verifier. Ordinary and public in-memory checker accounting must remain unchanged.
|
||||
|
||||
The source supports this narrower policy:
|
||||
|
||||
- `analysis_source/mixed.rs:390–422` performs lexing and the shared `Parser::unit` using one Budget/ModelCounts. `lex.rs:15–68` charges bytes, scanner events including trivia, and scanner temporary string work. State shares model counts and typed numeric parsing rather than creating a fresh per-file allowance.
|
||||
- Full parsing retains each completed unit, tokens and lexical owners, and additionally constructs positions (`mixed.rs:425–511`). Dropping the discovery unit does not itself decrement Budget. Leaving its final charges reserved therefore remains an upper bound on live producer-domain storage; it does not create dangling ownership or an authority witness. Keep normal existing temporary/UUID/provisional-key releases within the parser unchanged.
|
||||
- For the same successfully parsed files and depth-first order, discovery uses the same unit grammar, U/token/reference/numeric events and transient string decoding as full parsing. Omitting position construction removes nonnegative metadata/text charges. Initial or incremental discovery file-slot reservations must be no greater than the full parser's F file slots, and must not charge already-visited paths again. Under these conditions, retaining completed-unit charges causes **no additional producer-cap refusal relative to the corresponding successful full syntax parse**, which retains those units anyway. This conditional argument does not promise identical failure precedence for invalid input or disk discovery.
|
||||
- Both existing walkers push includes in reverse for source-order DFS (`source_files.rs:511–517`, `source_project/traversal.rs:179–183`). Preserve that order and once-per-path inspection. Repeated authored edges still count; repeated targets do not get another syntax budget.
|
||||
|
||||
Name the phases explicitly: one bounded discovery syntax pass, followed by one independently bounded complete verification pass. Derive both profiles from the same original caller policy; do not expose arbitrary production profiles. In particular, numeric work is capped per named pass, not falsely advertised as one 50,000,000-unit command-wide allowance. Discovery Budget, parser state and all ordinary/typed/token owners must be dropped before full verification starts. Only loader-owned sources, bounded include/path bookkeeping and diagnostics survive. Do not retain an unnecessary parsed model or clone a complete syntax witness.
|
||||
|
||||
This reasoning covers the existing logical producer domains, not all Rust allocations, path bookkeeping, model heap, allocator capacity or RSS. Resolved include targets/locations belong to the existing bounded loader domain; do not call their transfer a producer-ledger reconciliation. Discovery never invokes the resolver or its exact syntax-inventory check. No new refund mechanism is needed merely to make already-freed units disappear from a conservative reservation.
|
||||
|
||||
An alternative fresh unit budget with explicit remaining aggregate work caps could also be correct, but requires transferring numeric/event usage and separating remaining work from per-unit storage limits. That is more machinery than retaining reservations. Fresh unrestricted per-file budgets are rejected: they silently multiply numeric and other work ceilings by file count.
|
||||
|
||||
**Concrete failure obligation:** existing discovery continues after `inspect_includes` failures (`source_files.rs:519–521`), whereas `Budget::active` (`budget.rs:228`) returns a latched Error containing a Span but no filename. Reusing that failed budget for a sibling would risk reporting the old span against the sibling. Select terminal mixed syntax/work failure: keep its first located diagnostic and perform no further unit parses using that budget. Still perform the selected final filesystem/journal checks. Preserve ordinary-path aggregation unchanged. Specify first-failure behavior rather than attempting to claim diagnostic identity with complete in-memory validation.
|
||||
|
||||
## Disk ownership and safety
|
||||
|
||||
Reuse the existing logical-path, root-containment, regular-file, bounded-read, case/physical-alias and journal checks (`source_files.rs:111–325,536–549`). Before any read, enforce aggregate effective source bytes `min(caller.model.max_source_bytes, 64 MiB)`; checking only the caller's possibly unlimited ceiling and rejecting later in the parser is insufficient. Pass the original ProjectLimits to final verification, without silently widening or replacing them.
|
||||
|
||||
For a fresh load, consume the discovered DiskProject into an opaque read-only `{ bundle, diagnostics }` after final checks, dropping expectations/root/reachability. Every stored source was discovered from the entry; no overlay/detached-input preservation is needed. Avoid `reachable_bundle()` (`source_files.rs:59–72`), which clones all source strings. The existing temporary raw expectation bytes and UTF-8 strings are two bounded copies, not one accounted allocation; document reuse honestly. A smaller fresh-only storage owner may be a later optimization, not a prerequisite for this milestone.
|
||||
|
||||
Keep reserved journal names, pending-save refusal and no implicit recovery. Existing path checks do not establish an atomic multi-file snapshot or defeat every concurrent replacement race (`source_files.rs:177`); promise validation of captured bytes and no writes by this command. Do not broaden platform claims beyond actual tests. Fail discovery before invoking the complete checker on missing/invalid buffers.
|
||||
|
||||
Route this command before ordinary CLI `prepare` (`oa-cli/src/lib.rs:213–310`), which calls ordinary lint/ID analysis/compilation even for Check. An Arguments command branch is sufficient; do not add a fake SourceIndex, editable Prepared value, save conversion or mixed write option.
|
||||
|
||||
## Falsifiable acceptance
|
||||
|
||||
1. Real executable OA/SA multi-file fixtures: typed/scoped cross-file references, ordinary nesting, escaped includes, comments containing `include`, Unicode and mixed CRLF. Compare complete diagnostics/report bytes and independently authored complete models for the same captured literals. Hash files and directory entries before/after; reject `--write` and unknown options.
|
||||
2. Discovery-budget tests: two files each individually below a tightened private numeric/event cap but jointly over it; repeated target inspected once; repeated edges counted; one shared ModelCounts limit across files; exact cap/cap-minus-one boundaries. Test-only profile tightening must not become caller-controlled public authority. Compare discovery producer reservations with the full parser at equivalent successful prefixes/fixtures, including quoted provisional releases and omitted projection charges.
|
||||
3. Failure attribution: first file triggers a latched budget refusal while a sibling remains queued; assert the original file/span once, no sibling reinterpretation and no final checker invocation. Include missing IDs in project, ordinary declaration, typed definition and parameter, plus unresolved/wrong-kind references reaching final verification.
|
||||
4. Existing filesystem invariants: bounded aggregate reads even with unlimited caller bytes; include depth/edges/files, invalid UTF-8, nonregular files, escapes/reserved names, case/physical aliases, cycles and pending journals. Preserve ordinary loader/CLI results. Pin mixed diagnostic precedence where discovery differs; platform-specific link/FIFO cases remain conditional.
|
||||
5. Verify actual normal-library/CLI boundaries and relevant finite stack controls after helper extraction. No universal headroom or full authoring claim follows from these checks.
|
||||
|
||||
No design blocker remains if the contract adopts the conservative reservation meaning, terminal failure rule, effective pre-read byte cap, and separate fresh final verifier above. The implementation must demonstrate those conditions; this report does not waive existing parser limits or substitute discovery success for complete semantic admission.
|
||||
@@ -0,0 +1,164 @@
|
||||
# Mixed CLI read-only check: implementation map
|
||||
|
||||
Design only against public-read branch bab6f96a (parent reports accepted gates).
|
||||
No source edits, compiler or remote actions. Paths/lines refer to this source.
|
||||
|
||||
## Recommended user outcome
|
||||
|
||||
Add explicit `arcadia check-mixed ROOT [--json]`, requiring the public checker's
|
||||
schema8 and explicit UUIDs. Preserve check/lint/stabilize/rename-alias behavior.
|
||||
Use the existing report envelope with operation check-mixed, status checked or
|
||||
invalid, no changes, written=false, migration=null and identities_to_stabilize=0.
|
||||
The operation validates captured original bytes; it does not stabilize, export,
|
||||
format, index or save. Help must state this distinction and reject --write.
|
||||
|
||||
The command choice and discovery architecture are separate decisions. Merely
|
||||
adding a command enum variant does not make the existing loader support typed
|
||||
syntax. A real parser-consistent discovery seam is the prerequisite below.
|
||||
|
||||
## Current blockers and reusable code
|
||||
|
||||
- oa-cli/src/lib.rs:213 prepare loads source_files::load_project, then ordinary
|
||||
lint/analyze/compile (234–310). Operation::Check still returns Prepared holding
|
||||
CompiledSourceProject and a disk snapshot; it is not a read-only mixed route.
|
||||
- main.rs:76 dispatches all accepted arguments through prepare and optional write.
|
||||
Add a separate report-returning mixed-check branch before that branch. Do not
|
||||
forge Prepared or an empty SourceIndex. An explicit Arguments command enum can
|
||||
separate read-check from existing editable Operation, or use a distinct
|
||||
check_mixed flag/variant handled before prepare; avoid illegal write combinations.
|
||||
- source_files.rs:329 load_project creates a DiskProject then discover_missing.
|
||||
Discovery's DFS reads bounded bytes and tracks originals/expectations (389–494),
|
||||
but495 calls ordinary inspect_includes and529 runs ordinary compile_bundle.
|
||||
- source_project.rs:207–268 inspect_includes validates paths and calls ordinary
|
||||
language::parse_unit, so it rejects valid short typed declarations. Filtering
|
||||
that diagnostic cannot reveal the missing include graph safely.
|
||||
- mixed.rs:390–422 already lexes and invokes the shared Parser::unit with actual
|
||||
mixed State and explicit IDs, producing ordinary.includes plus typed syntax.
|
||||
This exact unit grammar can inspect includes without resolving global references.
|
||||
Extract/reuse this narrow unit operation instead of a regex, guessed brace
|
||||
scanner, second quote decoder or calling the complete checker on partial bundles.
|
||||
- source_files.rs:104–216 root_entry/check_logical/disk_path/read_bounded already
|
||||
enforce root containment, canonical logical names, reserved journal namespace,
|
||||
link/regular-file restrictions and bounded reads.240 check_snapshot and293
|
||||
check_physical_aliases preserve aggregate and physical-alias checks. Reuse these
|
||||
functions in one core discovery engine; do not replicate their security logic in CLI.
|
||||
|
||||
## Minimal safe ownership shape
|
||||
|
||||
Introduce a named read-only discovery entry in source_files, with a small private
|
||||
closed selector OrdinaryEditable / MixedRead for shared discovery dispatch.
|
||||
Existing public discover_missing/load_project select OrdinaryEditable and retain
|
||||
all current completion/lint behavior. MixedRead selects mixed include inspection
|
||||
and skips ordinary compile/stabilization; it still performs all disk/path/journal
|
||||
checks. No generic caller-provided parser/loader callbacks or new public framework.
|
||||
|
||||
Prefer an opaque owning `MixedSourceSnapshot` exposing only bundle() and
|
||||
load_diagnostics(), or a narrowly scoped `load_mixed_source` result owning those
|
||||
values. Do not advertise it as a save snapshot or provide conversion into editable
|
||||
CompiledSourceProject. Internally reusing DiskProject's captured bytes is possible,
|
||||
but returning DiskProject publicly would unnecessarily expose save/discovery
|
||||
operations and expectations. Keep original raw-byte expectations private if reused.
|
||||
This design adds a small wrapper, not a clone of every buffer for an extra model.
|
||||
|
||||
CLI owns the snapshot, borrows its complete reachable SourceBundle while calling
|
||||
language::check_mixed_bundle, maps warnings/errors into the existing Report, then
|
||||
drops CheckedMixed before dropping source. Report owns mapped diagnostic strings;
|
||||
no borrowed checker escapes and no self-referential source/result struct is needed.
|
||||
Report has no Project field: complete model evidence comes from independent core
|
||||
and CLI-library tests of those same literals, not an invented JSON assertion.
|
||||
|
||||
## Discovery parser work and limits: resolve before implementing
|
||||
|
||||
Discovery is an extra syntax pass; final borrowed checker remains the sole complete
|
||||
semantic admission. Its existing budgets must be fresh for that full pass; do not
|
||||
subtract discovery work from final counts or represent a successful partial scan
|
||||
as an admitted model. Re-reading/reparsing captured strings is explicit bounded work,
|
||||
not a claim that the checker itself reparses or that disk is reread between phases.
|
||||
|
||||
The mixed unit helper needs a genuine Budget and ModelCounts. A naïve new budget
|
||||
per file silently multiplies allowed discovery numeric/token/reference work by the
|
||||
file count; a single shared budget with all retained-text totals left charged after
|
||||
units are dropped misrepresents live storage. Therefore contract must choose a
|
||||
small explicit **discovery-phase work policy** and lifetime:
|
||||
|
||||
- Recommended: one shared discovery work budget across all captured file parses,
|
||||
cumulative bytes/tokens/references/numeric/syntax-event work, with per-unit syntax
|
||||
owners dropped after copying only include locations. Reuse Parser::unit and its
|
||||
resource checks. Name and check temporary per-unit metadata/text ownership before
|
||||
growth if selecting producer mode; reconcile/release it on unit destruction.
|
||||
This is a real small producer-lifetime seam to specify, not existing free behavior.
|
||||
- Simpler alternative: per-unit bounded inspection with a documented aggregate
|
||||
upper bound of max_files times its cap. It is finite but can be far larger than
|
||||
the selected checker work profile; do not choose it silently or describe it as
|
||||
inheriting one whole-project numeric budget. Parent may reject that cost policy.
|
||||
- Do not retain all parsed witnesses then clone/reparse the complete bundle merely
|
||||
to avoid accounting a dropped unit. That grows live state and complicates source
|
||||
lifetimes for no consumer benefit. Do not stream-load into a borrowed BTreeMap
|
||||
while previously parsed units retain references into it; ordinary Rust borrowing
|
||||
disallows this without additional ownership infrastructure, which is unnecessary.
|
||||
|
||||
The implementation contract should pin the selected discovery bound/diagnostic
|
||||
order and helper's drop/refund rules before source edits. This is the main remaining
|
||||
bounded design question, not an argument for full editable-source adoption.
|
||||
|
||||
## Filesystem and diagnostic contract
|
||||
|
||||
Preserve existing root/file checks, UTF-8 rejection, aggregate byte/file/edge/depth
|
||||
limits, case/physical alias refusals and pending-journal detection. Root depth0;
|
||||
include paths resolved by existing resolve_include; count repeated authored edges.
|
||||
Final complete check still rejects cycles/semantic failures using its exact original
|
||||
coordinates. Discovery diagnostics prevent invoking checker with missing/invalid
|
||||
buffers. Return exit3 for disk/path/pending-journal failures under existing CLI
|
||||
mapping; exit1 for source/semantic rejection,0 for valid with advisory warnings,
|
||||
2 for invalid arguments. Pin mixed loader's diagnostic precedence in tests rather
|
||||
than assuming it equals in-memory checker's earlier/later limit branch.
|
||||
|
||||
Do not suppress pending_save simply because operation is read-only: existing CLI
|
||||
refuses it, and the captured files may represent interrupted save state. No journal
|
||||
recovery is implicit. Neither old nor new read path promises atomic multi-file
|
||||
snapshot/CAS against concurrent external replacement (source_files.rs:177 comment).
|
||||
Promise unchanged bytes by this command and validation of captured bytes, not
|
||||
that the disk still equals that snapshot after a concurrent editor writes.
|
||||
|
||||
## Compared/rejected options
|
||||
|
||||
- Automatically replace ordinary check with mixed: breaks existing omitted-ID and
|
||||
migration behavior. Schema8 alone does not distinguish ordinary drafts from the
|
||||
stricter explicit-ID mixed contract. Avoid heuristic detection/fallback on errors.
|
||||
- `check --mixed`: coherent alternative explicit spelling, but adds an option whose
|
||||
invalid combinations must be excluded for mutations. Dedicated check-mixed makes
|
||||
the limited outcome easier to explain; select one spelling, not both initially.
|
||||
- Explicit all-files CLI manifest/bundle: can reuse checker immediately, but forces
|
||||
users to enumerate includes and introduces another input/argument format. It is
|
||||
useful only if a real pipeline already supplies bundles; not the recommended
|
||||
ordinary filesystem workflow and not a substitute for safe include loading.
|
||||
- Full compile_bundle adoption: requires typed stabilization/index/update/formatter
|
||||
and application consumers; none is necessary for this read-only outcome.
|
||||
|
||||
## Finite acceptance and scoped files
|
||||
|
||||
Core changes: source_files shared discovery selector + read-only snapshot;
|
||||
language mixed unit inspection helper and narrow reexport for core-only use;
|
||||
source_project include-location conversion reuse where appropriate. CLI lib
|
||||
arguments/report path + main dispatch, docs/source-cli.md/help, focused tests.
|
||||
No changes to updater/save/formatter or public CheckedMixed authority.
|
||||
|
||||
Test actual executable on independently authored OA/SA three-file fixtures with
|
||||
cross-file typed/scoped references and ordinary nesting. Exact complete JSON
|
||||
warning/error reports, raw original byte hashes/directory listing unchanged after
|
||||
each command, including CRLF/Unicode and comments mentioning include/aliases.
|
||||
Core tests compare independently authored full models for those same bytes.
|
||||
|
||||
Exercise missing/cyclic include, invalid path/root escape, case/physical aliases,
|
||||
nonregular/invalid-UTF8 file, pending journal and exact aggregate/depth/edge limits.
|
||||
Only claim platform-specific link/FIFO tests where cfg permits; Linux remains
|
||||
user-deferred. Exercise missing IDs in all four classes and typed unresolved/wrong
|
||||
kind errors. Verify --write rejection and all existing ordinary CLI commands remain
|
||||
unchanged. No fake success for an empty include graph or wrong command dispatch.
|
||||
Add unit-hook counter/lifetime evidence for the chosen discovery work policy and
|
||||
repeat relevant existing filesystem/stack regressions after shared-loop factoring.
|
||||
|
||||
Parent decisions needed: command spelling; explicit discovery work/storage policy
|
||||
above; whether reuse of private DiskProject storage under opaque wrapper is worth
|
||||
its duplicated captured bytes versus a smaller read-only buffer owner. No source
|
||||
or compiler work is authorized by this proposal.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Private mixed rename emission prerequisite
|
||||
|
||||
2026-09-25. Selected private prerequisite following bounded design and independent
|
||||
ownership/oracle review; implementation and runtime acceptance pending. Source baseline:
|
||||
`fa7a980418ef99d772e67c66c28dfa7b5181f875`. This implements the output construction
|
||||
and old-owner lifetime portion of the [rename successor](analysis-mixed-rename-plan-contract-20260924.md#mandatory-successor-accepted-rewritten-output).
|
||||
It does not implement accepted output, public source8, persistence or history.
|
||||
The [carried parser prerequisite](analysis-carried-phase-contract-20260925.md)
|
||||
and its remaining before-growth limitations retain their stated scope.
|
||||
The [producer inventory](analysis-mixed-emission-design-20260925/NEXT-PRODUCER-HOOKS.md),
|
||||
[independent critique](analysis-mixed-emission-design-20260925/NEXT-PRODUCER-CRITIQUE.md),
|
||||
[transition proposal](analysis-mixed-emission-design-20260925/EMISSION-TRANSITION-PROPOSAL.md)
|
||||
and [contract review with ownership correction](analysis-mixed-emission-design-20260925/EMISSION-CONTRACT-REVIEW.md)
|
||||
record candidates and rationale. This selected contract supersedes conflicting
|
||||
earlier proposal choices, including the owning enum and runtime byte guard.
|
||||
|
||||
## Ownership and API
|
||||
|
||||
Consume the opaque `RenamePlan` and borrow a complete current `SourceBundle`.
|
||||
Revalidate current entry, complete file set, paths and all bytes against the
|
||||
original snapshot before any copying, including for no-op. Reuse the planner's
|
||||
complete physical edit validation; no external edit list, Project or policy may
|
||||
replace its authority.
|
||||
|
||||
If no names changed, return the original `AuthoredMixedProject` unchanged, with
|
||||
its actual bundle, policy, work usage, warnings and storage. Allocate no output.
|
||||
The changed result owns a complete pending bundle, the exact inherited `Limits`
|
||||
and `ProjectLimits`, its verified output storage total O, the desired Project
|
||||
borrow and scalar original expression-site count E. It retains no old syntax,
|
||||
catalog, warning, index or plan map. Original caller-owned source and desired
|
||||
Project remain untouched. This does not claim those external borrows are freed.
|
||||
|
||||
Keep pending fields private. Expose no bundle extraction, mutation, installation,
|
||||
history, save or accepted-result conversion. Tests may inspect fields. No general
|
||||
constructor accepting arbitrary bundle/Slots/policy is authorized. The only
|
||||
construction path consumes the actual plan after checked emission. Reuse or add
|
||||
a sealed carried-snapshot connection only if it accepts this actual pending
|
||||
owner, never loose parts; invoking parser verification remains outside this slice.
|
||||
|
||||
For changed emission in this prerequisite require original legacy syntax
|
||||
(`carried == None`). Reject an explicit carried source before output reservation,
|
||||
even its borrowed-zero mode. Dropping a source witness only drops its guard; an
|
||||
external RetainedSnapshot would remain alive, so claiming only O survived would
|
||||
hide C. Future repeated owned editing needs an explicitly consuming owner
|
||||
transition or surviving C guard. No-op may preserve any source and its guard
|
||||
unchanged, because no old reservation is discarded. This narrow provenance
|
||||
restriction is intentional, not a numeric-zero shortcut or a final editing API.
|
||||
|
||||
Select two explicit consuming methods:
|
||||
`into_unchanged(self, current) -> Result<AuthoredMixedProject<'s>, Failure>` and
|
||||
`emit_changed_unverified(self, current) -> Result<PendingRename<'t>, Failure>`.
|
||||
Both validate current snapshot and complete edits and enforce their branch;
|
||||
calling the wrong branch refuses. Callers can select using the existing immutable
|
||||
`changed_names().is_empty()` observation. A branch cannot change after that read.
|
||||
This separates source and desired lifetimes without boxing, a large common
|
||||
owning result enum, generic callback machinery or lint exemptions. Do not
|
||||
duplicate full policy inside old syntax owners. Keep all existing stack controls.
|
||||
|
||||
## Storage and construction
|
||||
|
||||
Let B be the existing plan owner's live ledger, which already includes both the
|
||||
R changed-name entries and M physical-edit entries. Do not add R+M twice.
|
||||
Compute the complete final file byte sum S using the existing checked original
|
||||
coordinate sizing walk, including untouched files. Then compute
|
||||
|
||||
```text
|
||||
O.entries = original complete file count F
|
||||
O.occurrences = 0
|
||||
O.text = S + sum(canonical key UTF-8 byte lengths) + entry UTF-8 byte length
|
||||
peak during emission = B + O
|
||||
```
|
||||
|
||||
Every addition/subtraction must be checked. Reserve all O against the original
|
||||
ledger and exact inherited policy before constructing any output String, copied
|
||||
key, entry or map element. Reserving the complete monotone output up front covers
|
||||
its partial construction; capacity/allocator overhead remain outside the logical
|
||||
metric. Original sources and desired replacement aliases are borrowed during
|
||||
copying. No lengths map, copied edit list, temporary complete file or second
|
||||
output buffer is needed. Any additional owned container requires explicit scope
|
||||
and reservation before growth. Source-size shrinkage does not release old B.
|
||||
|
||||
Walk canonical files and the sorted edit stream. For each file, append original
|
||||
untouched ranges and the exact qualified target's desired alias in original byte
|
||||
coordinates, then the tail. Produce one String per file, including untouched
|
||||
files; preserve complete paths and entry. Avoid reparsing, decoding, UUID creation,
|
||||
normalization and global textual replacement. Validate original UTF-8 boundaries
|
||||
and nonoverlap through the existing complete edit validator before construction.
|
||||
Check the constructed length against independently computed size before ownership
|
||||
transition. Check final complete file count and byte total without a second copy.
|
||||
|
||||
Capture policy and E as scalars; destroy old plan maps and the complete old source
|
||||
owner explicitly before returning the pending owner. O is then the only retained
|
||||
in-scope owner from this operation. Failure yields existing located diagnostics
|
||||
and drops partial output; no partial owner escapes. Preserve failure ordering:
|
||||
stale snapshot, invalid edit map/size, output storage reservation, construction
|
||||
consistency; changed carried-source refusal precedes output reservation.
|
||||
Arithmetic fault injection must be labeled as such, not successful
|
||||
real-world owner provenance.
|
||||
|
||||
## Verification and remaining boundary
|
||||
|
||||
Use independent literal original-coordinate maps and expected full bytes for OA
|
||||
and SA, simultaneous global/scoped swaps, repeated/reordered labels, cross-file
|
||||
references, ordinary categories, Unicode/CRLF and comments. Verify copied untouched
|
||||
files and exact entry/keys. No-op must preserve original owner data/pointers, not
|
||||
an equivalent reconstructed owner. Corrupt current touched/untouched data, paths,
|
||||
entry and file set, and corrupt plan edit locations/targets through test-only
|
||||
access; require no result. Reuse valid planner tests where they cover the same
|
||||
validator rather than duplicate all cases.
|
||||
|
||||
Independently hand-count a small real fixture's B and O. Choose exact entry/text
|
||||
caps that admit all predecessor phases and refuse cap-minus-one at emission.
|
||||
Do not mutate an admitted live ledger or widen policy to manufacture this test.
|
||||
Assert final O, original exact policies, desired borrow and E. Include combined
|
||||
grow/shrink and unchanged-file sizing. Small-stack emission/drop checks prepare
|
||||
parser prerequisites on the normal thread, then move the complete consumed plan
|
||||
into the worker; preserve all prior full-pipeline controls and limitations.
|
||||
|
||||
Independent byte fixtures test the emitter; the pending type does not assert
|
||||
runtime semantic authentication. A duplicate streaming emitter/comparator is not
|
||||
required just to return this unverified internal state. Final acceptance still
|
||||
requires actual-output parse/resolve/admission under the exact policy and carried
|
||||
O, strict whole-Project equality with E scratch reserved, a resolved temporal
|
||||
parser accounting contract, and an owning accepted result after temporary syntax
|
||||
drops. Those requirements cannot be substituted by length checks or byte tests.
|
||||
Original E is provenance metadata, not a demonstrated bound on arbitrary faulty
|
||||
emitted syntax. The later verifier must justify its equality bound against both
|
||||
actual operands and cannot rely on an unperformed runtime topology check.
|
||||
@@ -0,0 +1 @@
|
||||
*.md -text
|
||||
@@ -0,0 +1,43 @@
|
||||
# Independent emission contract review
|
||||
|
||||
Reviewed `harness/analysis-mixed-emission-contract-20260925.md` against the current `fa7a980418ef99d772e67c66c28dfa7b5181f875` planner/guard shapes, accepted rename successor and carried-phase scope. Read-only; no contract/source edits, builds or network activity.
|
||||
|
||||
Disposition: **no blocking design finding; suitable for the bounded private implementation described.** This review accepts its unverified prerequisite boundary, not final edited-output acceptance.
|
||||
|
||||
## Runtime byte guard decision
|
||||
|
||||
The selected omission is reasonable. My earlier NEXT-PRODUCER-CRITIQUE recommended a streaming guard partly to establish authenticated topology for a potential later parser envelope. This draft does not grant that authority. An opaque unverified pending owner does not need a second runtime comparator merely to prove the same emission operation again. Independently authored complete byte fixtures discriminate emitter defects without installing another production algorithm.
|
||||
|
||||
A runtime guard becomes worthwhile if a later phase relies on unchanged token/AST/include topology **before** parsing actual bytes, or promises runtime preservation of all non-name bytes independently of emitter correctness. In that case it should consume actual output by matching borrowed original/replacement chunks and prefixes, rather than reconstructing output through the same append loop/helper; comparison must separately cover entry, file set, keys and untouched files. Whole-Project equality alone does not establish lexical preservation of comments/formatting. None of those stronger claims is made by this pending type, so the guard can remain deferred.
|
||||
|
||||
## Ownership and sizing
|
||||
|
||||
The contract correctly requires stale complete-snapshot and complete-edit validation before any output copies, including no-op. No-op returns the original authored owner and allocates no output. Changed output derives solely from the consumed sealed plan, borrows aliases while copying, retains exact policy and desired borrow, and offers no extraction/mutation/save/adoption escape.
|
||||
|
||||
O is correctly F entries plus every final source byte, copied canonical key and the distinct entry-path bytes, with zero lower occurrences. B already contains R+M. Reserving B+O before construction covers monotone partial output without double-charging plan maps or prematurely crediting shrinkage. Repeating a scalar sizing walk is preferable to an extra lengths map. Per-file length, complete count and total consistency checks detect size-construction disagreement without implying byte authentication.
|
||||
|
||||
The named old-owner drop is essential: capturing output/policy/desired/E does not itself release old syntax/index/warnings/maps. Implementer must make that destruction precede return and preserve the original external source/desired borrows. Failure diagnostics retain the existing bounded rejection exception; no partial pending owner escapes.
|
||||
|
||||
The proposed callback or nested-result shape is appropriately left for actual type review. It should not evade accounting with an otherwise unnecessary Box, duplicate the full policy inside old syntax or change expectations merely to satisfy enum-size lint. Compiler/Clippy and the inherited stack controls remain necessary evidence.
|
||||
|
||||
## Useful acceptance boundaries
|
||||
|
||||
The independent full-byte fixtures, combined growth/shrink, copied untouched files and no-op ownership assertions test the actual new behavior. Reusing the existing complete edit validator and its corruption evidence avoids duplicating the entire planner test matrix. New B+O exact-cap tests must admit predecessor phases under the same profile; final O assertions must follow actual old-owner destruction rather than scalar subtraction alone.
|
||||
|
||||
Normal-thread setup followed by scoped small-stack emission/drop isolates the new operation without falsely promising that upstream parsing fits every worker stack. Existing full-pipeline controls and prior abort limitations remain separate.
|
||||
|
||||
## One explicit future-use caution
|
||||
|
||||
Original E is valid provenance metadata, but without runtime byte authentication it is **not automatically a bound on arbitrary actual output topology**. A faulty emitter may produce admissible-but-wrong bytes with a different structure. A future topology-based parser envelope or whole-Project comparison must prove its scratch bound for that case, derive a safe bound from admitted actual output/intent, or reject structural mismatch before exceeding the reserved bound. Merely retaining E from the original owner is not that proof.
|
||||
|
||||
This is not a blocker to pending emission: the draft defers parser verification, temporal accounting and strict whole-intent equality. Preserve that deferral in code/API/docs; do not wire a future accepted-result constructor while relying only on this review, output lengths or test fixtures. No broader parser scratch expansion is required to implement the selected private milestone.
|
||||
|
||||
## Qualification after carried-lifetime finding
|
||||
|
||||
The original no-blocker disposition missed a material ownership edge identified by the other oracle reviewer. A source parsed through a retained carried guard borrows an external RetainedSnapshot. Destroying its syntax/index/plan drops only the guard, not that external owner or C. Returning a changed pending result with only O would therefore discard live-storage accounting authority without ending the corresponding ownership. My original disposition is insufficient without the following amendment.
|
||||
|
||||
Reread the amended contract: **changed emission requires `syntax.carried == None`; any Some variant, including borrowed-zero mode, is refused before O reservation.** This is an explicit provenance boundary, not `slots == 0`. No-op remains permitted for any source only because it returns the same authored owner and guard without releasing the original baseline. Complete-current-snapshot and edit validation still precede copying/no-op as specified.
|
||||
|
||||
With this restriction, the pending operation can honestly retain only O after the consumed legacy syntax/index/plan owner dies. Future repeated edits of owned output require consuming the actual external output owner or retaining its guard and counting surviving C; merely borrowing and later dropping a source witness is inadequate. Runtime tests should distinguish changed legacy success, changed borrowed-zero refusal, changed retained refusal and guarded no-op preservation, with adequate caps so unrelated resource failures do not hide this rule.
|
||||
|
||||
The amendment resolves the identified edge for this prerequisite; the qualified disposition is suitable for bounded implementation. I also verified the contract now explicitly states that original E does not bound arbitrary faulty emitted syntax and requires a justified bound against both future equality operands.
|
||||
@@ -0,0 +1,133 @@
|
||||
# Proposed independent emission-transition oracle
|
||||
|
||||
2026-09-25. **Design proposal and source-derived expectations, not runtime results or accepted output.** Source: `fa7a980418ef99d772e67c66c28dfa7b5181f875`. Reviewed initial `EMISSION-TRANSITION-PROPOSAL.md` SHA256 `c0734464991ab841ae59d6c3c26a5095b3c0908ce35656158db92476d76682de`; parent subsequently selected changed-source legacy-only guard admission. No application parser, emitter, Cargo or executable was run. UTF-8 lengths below are literal byte arithmetic, not values obtained from implementation output.
|
||||
|
||||
Use A for the admitted authored source ledger, L for the plan's ledger **already including R+M**, and O for newly owned output. Emission must reserve L+O, not L+(R+M)+O. All examples below start through the legacy source path, so no external carried baseline is concealed in A.
|
||||
|
||||
## Minimal exact predecessor and emission caps
|
||||
|
||||
E is the existing `project::tests::single("")` literal, entry/key `main.arcadia` (12 UTF-8 bytes each):
|
||||
|
||||
```text
|
||||
arcadia 8;\nproject p "Project" id "00000000-0000-0000-0000-000000000001" {\n\n}\n
|
||||
```
|
||||
|
||||
This notation represents actual LF bytes. Original source length78, syntax U1/M11, retained syntax text8; no expressions, references, lower occurrences or warnings. These grammar/accounting terms also appear in the independent carried-phase oracle. Desired changes only the project alias from `p` to `next`. Exactly one physical token changes: canonical file0, range19..20. Independently authored complete expected source is:
|
||||
|
||||
```text
|
||||
arcadia 8;\nproject next "Project" id "00000000-0000-0000-0000-000000000001" {\n\n}\n
|
||||
```
|
||||
|
||||
Expected source length81. The extra entry-path string is separate from the equal-spelled file key. Thus O=(1,0,81+12+12)=(1,0,105).
|
||||
|
||||
| E phase | Retained entries/text after phase | Maximum entries/text within phase |
|
||||
| --- | --- | --- |
|
||||
| Resolve | 12 / 8 | 16 / 10 |
|
||||
| Typed index (one global project name, no typed sites) | 13 / 9 | 14 / 9 |
|
||||
| Ordinary index (one project header) | A=14 / 9 | 15 / 9 |
|
||||
| Rename E0, Q1, R1, M1 | L=16 / 9 | 16 / 9 |
|
||||
| Output reservation | L+O=17 / 114 | 17 / 114 |
|
||||
| Pending after old source/maps drop | O=1 / 105 | — |
|
||||
|
||||
All occurrence counts are zero. Phase maxima are coordinatewise logical maxima, not allocator/RSS measurements. The complete real path must fit at **entries17 / bytes114**. Entries16 with bytes114, or bytes113 with entries17, clears all predecessors and independently refuses the upfront emission reservation. Source-byte work78, planned output81 and changed-name-byte check4 all fit either byte cap. No live Budget mutation is needed to manufacture these pairs.
|
||||
|
||||
Source derivation: `mixed/project/accounting.rs:233–352` charges U+M and syntax text; `mixed/project.rs:273–314` project catalog adds four temporary entries and two alias bytes, later released. `index.rs:288–298` retains one name entry/byte and `:684–709` temporarily reserves the one global lookup. `ordinary_index.rs:98–108,123–153,251–263` retains the single ordinary header while releasing one reverse-global scratch entry. `rename.rs:14–28,30–91,106–120` gives E0 and max(R+Q,R+M)=2; no new copied text is retained by the plan.
|
||||
|
||||
H is the exact three-file Unicode/CRLF chain from `CARRIED-PHASE-ORACLE.md`: main101B includes part25B, which includes last6B (`//é\r\n`); entry `main.arcadia`; all three keys total36B, entry12B. Only change project p→next, again main range19..20; canonical file order last/main/part makes that file1. Main becomes104B; part and last remain byte-exact. Original U3/M19 and syntax text32 give:
|
||||
|
||||
| H quantity | Entries | Occurrences | Text |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Resolved retained | 22 | 0 | 32 |
|
||||
| Authored A (one name plus project header) | 24 | 0 | 33 |
|
||||
| Planned L, R1/M1 | 26 | 0 | 33 |
|
||||
| Output O, S135 + keys36 + entry12 | 3 | 0 | 183 |
|
||||
| Emission overlap L+O | 29 | 0 | 216 |
|
||||
|
||||
Resolver maximum26entries/34text; typed-index maximum24entries/33text; ordinary-index maximum25entries/33text; planning maximum26entries/33text. Thus **29 / 216** fits the entire path and **28 / 216**, **29 / 215** independently fail only at emission overlap. This distinguishes accounting for all untouched files and copied path/entry strings from source-size-only checks.
|
||||
|
||||
## Unchanged branch and guard boundary
|
||||
|
||||
E no-op fits the original pipeline at entries16/bytes78; H at entries26/bytes132. An unnecessary output copy would exceed those byte ceilings (E A.text+102=111; H A.text+180=213). A successful unchanged branch at these actual inherited caps therefore discriminates against reserving/copying identical output. It must return the original authored owner with unchanged ledger, Usage/numeric work, warnings, Project, maps and exact original bundle borrow. Signed-zero-equivalent target intent is also unchanged bytes; no new semantic rewrite is authorized.
|
||||
|
||||
Freshness is checked even on unchanged intent: mutate an untouched comment byte, entry, key or file set in an independent current snapshot and require refusal before branch return. An independently allocated but equal complete current bundle is acceptable; emission authority still belongs to the retained original, not that comparison input.
|
||||
|
||||
**Required selected edge test:** produce an authored source via carried parsing, both borrowed-zero Some guard and actual retained nonzero guard, then plan a changed alias. Changed emission must refuse before O reservation for either Some guard. No-op must preserve and return that original guarded owner. Dropping a borrowing guard does not drop its external RetainedSnapshot; carrying only O after such a changed source would hide still-live counted ownership. The narrow legacy-None restriction avoids that false transition without inventing an emitter/verification ownership architecture. A zero numeric C is not sufficient to bypass the selected guard restriction.
|
||||
|
||||
## Independent four-file mixed swap bytes
|
||||
|
||||
This proposed fixture combines a typed/ordinary global swap with cross-family references, a leading multibyte character, CRLF, comments containing alias spellings and an untouched included file. Every line below ends CRLF, including the last line of each file. UUID strings are literal. Entry is `main.arcadia`; canonical order is a/b/main/untouched.
|
||||
|
||||
Original `a.arcadia`:
|
||||
|
||||
```text
|
||||
calculation f "F" id "00000000-0000-0000-0000-000000000010" { result Number; body 1; }
|
||||
```
|
||||
|
||||
Original `b.arcadia`:
|
||||
|
||||
```text
|
||||
// f and w are comments
|
||||
oa_activity w "Work" id "00000000-0000-0000-0000-000000000002" {}
|
||||
```
|
||||
|
||||
Original `main.arcadia`:
|
||||
|
||||
```text
|
||||
// 雨
|
||||
arcadia 8;
|
||||
project p "Project" id "00000000-0000-0000-0000-000000000001" {
|
||||
include "a.arcadia"; include "b.arcadia"; include "untouched.arcadia";
|
||||
oa_property v "Value" id "00000000-0000-0000-0000-000000000003" { subject @w; type Number; base @f(); }
|
||||
}
|
||||
```
|
||||
|
||||
Original and expected `untouched.arcadia`:
|
||||
|
||||
```text
|
||||
// 雪 untouched f w
|
||||
```
|
||||
|
||||
Desired changes exactly calculation10 alias f→w and activity2 alias w→f; every other Project field remains original. Independently authored expected `a.arcadia`:
|
||||
|
||||
```text
|
||||
calculation w "F" id "00000000-0000-0000-0000-000000000010" { result Number; body 1; }
|
||||
```
|
||||
|
||||
Expected `b.arcadia`:
|
||||
|
||||
```text
|
||||
// f and w are comments
|
||||
oa_activity f "Work" id "00000000-0000-0000-0000-000000000002" {}
|
||||
```
|
||||
|
||||
Expected `main.arcadia`:
|
||||
|
||||
```text
|
||||
// 雨
|
||||
arcadia 8;
|
||||
project p "Project" id "00000000-0000-0000-0000-000000000001" {
|
||||
include "a.arcadia"; include "b.arcadia"; include "untouched.arcadia";
|
||||
oa_property v "Value" id "00000000-0000-0000-0000-000000000003" { subject @f; type Number; base @w(); }
|
||||
}
|
||||
```
|
||||
|
||||
Exact original-coordinate edit oracle:
|
||||
|
||||
| Canonical file | Range | Old | New | Target |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 0, a.arcadia | 12..13 | f | w | calculation10 |
|
||||
| 1, b.arcadia | 37..38 | w | f | activity2 |
|
||||
| 2, main.arcadia | 232..233 | w | f | activity2 |
|
||||
| 2, main.arcadia | 254..255 | f | w | calculation10 |
|
||||
|
||||
File byte lengths are88,92,265,22, unchanged by the swap; S467, key bytes47, entry12. Therefore **O=(4,0,526)**, R2/M4. The original raw-expression count E is2 (calculation literal and property call). Preserve this scalar in pending, but do not call it an already-proven bound for future equality over arbitrary reparsed output; that successor must establish the compared side/shape bound explicitly. The cap proof for this richer fixture is intentionally not invented: use generous inherited limits and the independent E/H cap pairs above. Fixture syntax/admission still requires a real gate; these bytes do not report an unrun parser success.
|
||||
|
||||
This exact output catches sequential spelling substitution (f→w followed by w→f), alias replacement in comments/display names, loss of markers, accidental newline conversion and omission of untouched content. Add the existing independently authored rich OA/SA full maps for scoped parameter swaps/reordered labels and the category fixture for comment-separated references/historical UUID preservation. Do not generate expected output by running the implementation's sizing/emission helper or copying its returned map.
|
||||
|
||||
## Outcome shape and remaining evaluator requirements
|
||||
|
||||
The proposed owning enum is understandable but contains the large unchanged authored owner; smaller pending payload does not make that union small. Box/Rc/Arc would introduce allocation and accounting concerns rather than demonstrate a free repair. Source-only analysis cannot guarantee debug-frame behavior, particularly after the prior inline-policy regression.
|
||||
|
||||
Parent selected **two consuming, branch-checked methods**: `into_unchanged(self,current) -> Result<AuthoredMixedProject<'s>,Failure>` and `emit_changed_unverified(self,current) -> Result<PendingRename<'t>,Failure>`. Existing `changed_names().is_empty()` supports caller selection; both methods independently validate freshness and enforce the selected branch. Wrong-branch use refuses with no partial output. This avoids a new large owning enum, generic callbacks, extra owner allocation and lint suppression; pending has no original-source lifetime and unchanged has no desired lifetime. Tradeoff: two explicit private entry points. Scoped callbacks were considered as an alternative if one dispatch method were essential, but add generic callback layering. The selected split still requires stack verification and does not warrant weakening the old 128 KiB tests.
|
||||
|
||||
Before implementation acceptance require: complete expected maps, exact source/key/entry count and O retention; E/H predecessor-clearing caps; stale/no-op and Some-guard controls; immutable desired/old bundles; policy equality across all captured fields; no parse/Exact work during emission; no pending partial result on checked failure; and an observable source/map drop before pending escapes. A helper returning Pending from a scope holding the original bundle should prove pending does not borrow old source after the changed transition. After extracting unchanged, desired need not remain borrowed. Keep all legacy stack controls unchanged and add success/no-op/refusal/drop coverage for the chosen new outcome shape. No production pending extraction/adoption, parser entry, final whole-model equality or accepted-output claim is part of this oracle.
|
||||
@@ -0,0 +1,105 @@
|
||||
# Private emitted-unverified rename transition — proposal
|
||||
|
||||
2026-09-25. **Design only; not an accepted contract, implementation or edited-output acceptance.** Source pin `fa7a980418ef99d772e67c66c28dfa7b5181f875`. Paths below are relative to `crates/oa-core/src/`. No source changes, builds or Gitea operations.
|
||||
|
||||
## Minimal outcome and privacy
|
||||
|
||||
Parent selection supersedes the earlier enum/callback candidates: use two named consuming methods, with callers selecting from immutable changed_names().is_empty() before consumption. Both methods call validate_current and the existing validate internally, then reject the wrong branch. No common result enum, callback adapter, heap indirection or lint suppression is needed. This is accepted design direction, pending implementation/runtime gates.
|
||||
|
||||
Use a narrow `rename::emission` child owning the transition and an opaque pending owner:
|
||||
|
||||
```rust
|
||||
// Fields private to rename::emission. Not Clone/Copy/Serialize/AsRef/Deref.
|
||||
struct PendingRename<'t> {
|
||||
bundle: SourceBundle,
|
||||
limits: Limits,
|
||||
project_limits: ProjectLimits,
|
||||
retained: Slots,
|
||||
expression_nodes: usize, // E, verified original count for later equality
|
||||
desired: &'t Project,
|
||||
}
|
||||
|
||||
impl<'s, 't> RenamePlan<'s, 't> {
|
||||
fn into_unchanged(
|
||||
self, current: &SourceBundle,
|
||||
) -> Result<AuthoredMixedProject<'s>, Failure>;
|
||||
|
||||
fn emit_changed_unverified(
|
||||
self, current: &SourceBundle,
|
||||
) -> Result<PendingRename<'t>, Failure>;
|
||||
}
|
||||
```
|
||||
|
||||
Use the repository's existing restricted visibility (`pub(in crate::language::analysis_source)`) only where the private caller must name types/methods. Implementation in a child of `rename` can read its parent's private plan fields; no mutable plan/model/token authority is exposed. `current` is only a freshness comparison input; emission reads the retained original bundle. It cannot substitute the source to emit.
|
||||
|
||||
For **this bounded step**, PendingRename owns the bundle/policy/Slots/E directly. Do not widen `carried::RetainedSnapshot` with a sibling-callable `new(bundle, slots, policy)`. The future sole consuming transition can take an actual sealed PendingRename and transfer its verified fields into RetainedSnapshot after its execution contract is accepted. Until then the pending type exposes no production bundle getter/extractor, no borrowed carried input, no verification/adoption method and no conversion to SourceBundle/Project/session state. `cfg(test)` read-only inspection suffices to verify emitted bytes/counts/intent/policy. Existing RetainedSnapshot fixture constructors and carried parse APIs remain unchanged.
|
||||
|
||||
This is an explicit staging choice: the current result is an **emitted-unverified owner**, not yet a RetainedSnapshot usable by production carried parsing. Its retained formula is exactly the future snapshot formula; eventual transfer can move fields without copying. If parent instead requires constructing RetainedSnapshot in this slice, the alternative is a carried-owned factory accepting the **sealed RenamePlan itself** and performing the emission transition internally, with minimal read-only/consuming plan access. An arbitrary-parts constructor is not justified. The pending-only option changes fewer existing privacy boundaries and creates no premature verification entry.
|
||||
|
||||
An owning pending result with inspection only in fixtures is sufficient for an independently testable producer: consumers can hold/drop it but cannot save, install or treat its raw bytes as accepted model state through its API. The private name and absence of extraction are intentional authority restrictions, not runtime cryptographic authentication. A future trusted private implementation can add its sole verifier; no hash/token duplication is needed now.
|
||||
|
||||
## No-op and unchanged authority
|
||||
|
||||
First run existing `validate_current(current)` (`rename.rs:161–169`) so even no-op execution refuses a stale complete snapshot. If the sealed plan's names/edits are empty, consume its empty maps and return the original AuthoredMixedProject unchanged. No output String/key/entry copies, new snapshot parsing or new storage reservation occur. The source's original exact bundle borrow, maps, warnings, Project and policy survive.
|
||||
|
||||
The unchanged owner remains an already-admitted original owner, not a newly emitted result. The whole-target gate already established alias-only equality; signed-zero-equivalent desired representation does not authorize rewriting scalar bytes. The no-op branch can end the desired borrow because it does not need later output equality.
|
||||
|
||||
Do not implement a no-op by allocating an identical owned SourceBundle and calling that free. Do not run a second whole-model comparator merely to reconfirm the sealed plan.
|
||||
|
||||
## Validation and emission sequence
|
||||
|
||||
1. Consume the opaque plan. Complete-current-bundle validation compares entry, all keys, exact file set and every byte, including untouched files.
|
||||
2. Rely on plan construction's `validate()` proof for whole token membership, original spelling, UTF-8 ranges and nonoverlap (`rename.rs:178–239`). No API mutates the maps afterward. Reuse its sizing logic and source authority; do **not** re-lex/lower/admit or build another seen/token/map inventory. Calling the same private validator once at emission can support internal fault-injection tests, but is redundant for sealed production authority and is not required as a new authentication layer. Parent should choose deliberately; prefer the sealed proof and cheap checked emission invariants below.
|
||||
3. If changed, reject every explicit carried source (syntax.carried.is_some()), including borrowed-zero mode, before output reservation. Its external retained owner would survive dropping the source guard; O alone would then omit live C. No-op preserves any carried guard without rebasing. For this prerequisite changed emission therefore starts only from legacy syntax. Then compute checked complete output length S using the existing subtract-removed-before-add-replacements formula (`rename.rs:261–308`). Include every original file. Sum copied canonical key byte lengths K and entry byte length J using checked arithmetic; let F be the existing file count. Capture exact Budget::limits, syntax ProjectLimits, desired borrow and E as scalar metadata, without cloning the model or names.
|
||||
4. Reserve the entire output increment `O=(F,0,S+K+J)` against the **still-live plan ledger** before allocating/copying any output String, map key or entry. The current ledger already includes old B plus R+M; do not add those again. Failure maps through existing source diagnostics while the old witness is alive and returns no pending owner.
|
||||
5. Emit each file exactly once into one final String from original coordinates, traversing canonical files and the sorted physical edit map. Repeated sizing iteration is allowed; a new lengths map is unnecessary. For each file compute its final length with a scalar pass over that file's edits, allocate that String capacity, then append unchanged original slices and replacement names in order, followed by the untouched suffix. Clone that canonical path once into the final map. Files with no edits still get one exact full copy. Clone entry once. Markers/comments/includes/prose/UUIDs remain in unchanged slices.
|
||||
6. Every cursor/range calculation is checked; exact token boundaries are inherited from the plan. At each file require produced logical length equal its computed length, final cursor within source and all file edits consumed. Require complete file count and total S after assembly. These are inexpensive producer invariants, not a new independent syntax authenticator or guarantee of intended semantic validity.
|
||||
7. No partial map escapes on any failure. After complete assembly, snapshot the surviving O/policy/E/desired scalars, destructure and explicitly drop the old names/edit maps and AuthoredMixedProject **before constructing and returning PendingRename**. The output bundle moves once into pending. Drop the old ledger with its owner; pending retained state is O, not B+R+M+O.
|
||||
|
||||
Rust's return/drop order should be visible in code: use a narrow local owning output, capture scalar/reference metadata, `drop(names); drop(edits); drop(source);` then construct pending. Borrowed original SourceBundle remains caller-owned after the source auxiliary owner drops, exactly as before; this transition does not claim to free or charge that external borrowed input. The external desired Project also remains borrowed and unchanged.
|
||||
|
||||
## Counts and lifetimes
|
||||
|
||||
Let B be the admitted authored owner's existing live auxiliary Slots, R changed targets and M changed physical edits. The plan already retains `L=B+(R+M,0,0)`. During emission the output reservation establishes peak **L+O** in each existing dimension:
|
||||
|
||||
```
|
||||
O.entries = F
|
||||
O.occurrences = 0
|
||||
O.text = S + sum(canonical_path_utf8_bytes) + entry_utf8_bytes
|
||||
```
|
||||
|
||||
The entry is a separately owned String even when it equals a map key. Unchanged files still contribute their complete output bytes to S. Old source Strings are externally borrowed, not copied into B; all newly owned output bytes are counted once. Existing copied old syntax/name/warning text remains live in L throughout production and cannot be released early merely because a replacement shrinks a file.
|
||||
|
||||
A whole-output upfront reservation avoids per-file partial reservation bookkeeping and an extra lengths map. Final file capacity uses its exact precomputed length, but accounting is logical bytes, not allocator capacity/BTree node overhead/RSS. Temporary String then map insertion transfers the same reservation, not two copies. Checked reserve before creation does not promise recovery from operating-system allocator failure; existing logical resource-failure behavior remains the scope.
|
||||
|
||||
Once the old owner/maps drop, pending stores O and the exact inherited policy, with E retained only as original expression-count provenance for a future whole-Project equality reservation; it is not a proven bound on arbitrary faulty emitted syntax. Future carried verification must still account O plus parser/resolver allocations and decide required producer timing; the successful emission reservation proves none of those later checks. It also does not prove output is syntactically admissible or semantically equal to desired.
|
||||
|
||||
## Avoiding another stack-layout regression
|
||||
|
||||
Do not add Box/Rc/Arc or clone the old owner/model to simplify the outcome. Such allocation would require its own design/accounting and is unnecessary. Enum size is the maximum variant payload plus tag/alignment, not the sum of both payloads; nevertheless debug return temporaries can amplify a large unchanged owner. Keep helper layering shallow and do not retain duplicate inline policy in witnesses that already own it. Pending needs its one policy because the old owner actually drops.
|
||||
|
||||
The selected split consuming API avoids a common large enum and requires no callback framework. Each method enforces its branch; the two explicit wrong-branch errors are acceptable bounded API checks. Ordinary Result layouts and generated stack usage still require parent gates; this source-level choice is not a measured stack guarantee.
|
||||
|
||||
## Independent acceptance cases
|
||||
|
||||
- **No-op:** pointer identity of original bundle and retained owner state, identical Slots/Usage/numeric/warnings, no output allocation/copy; stale unchanged-file or entry mismatch still refuses. No desired mutation.
|
||||
- **Whole bytes:** rich OA/SA global+scoped swaps, nested/reordered/repeated labels, canonical multi-file coincident spans, Unicode/CRLF and category fixture with line-comment-separated references. Independently authored entire expected file strings/maps, not reconstruction through an emitter-like expected helper. Every non-token byte must match original at its corresponding unchanged segments; historical UUIDs/prose untouched.
|
||||
- **Combined sizing:** the existing31-byte node shrink plus typed f growth example emits924 bytes from930, despite a hypothetical typed-only954; the933-byte negative refuses the inherited930-byte output-size cap before copying. Owned-text overlap may legitimately refuse under that same cap even when final S fits: use sufficient inherited text allowance for a successful emission test and distinguish planning-size versus live-owned-text caps.
|
||||
- **Exact overlap:** independently hand-count F/S/K/J and old plan L. A cap fitting L and O separately but below L+O refuses before the first output copy. Exact combined cap succeeds if all actual predecessors fit; test entries and text independently. Assert final pending retained exactly O, not L+O or O twice. Do not tighten a live owner's Budget after admission to manufacture a boundary.
|
||||
- **Complete stale input:** touched and untouched source bytes, file removal/addition, path rename and entry changes reject before allocation. Equal independent current bundle content succeeds; emitted authority still comes from the retained original.
|
||||
- **Failure lifecycle:** malformed internal fixtures must enter existing plan-validation tests before a sealed plan exists; do not fabricate externally installable edited maps. Where emission has its own checked-arithmetic/range invariants, targeted private fault injection can assert no partial pending owner escapes. Overflow beyond valid profile ceilings is explicitly labeled helper/fault-injection evidence.
|
||||
- **Provenance limitation:** changed sources from both real retained C and explicit borrowed-zero carried mode refuse before output allocation; no-op preserves each original guard. No numerical zero bypass. A future consuming carried-owner transition is required before repeated owned edits.
|
||||
- **Ownership/API:** desired remains externally borrowed, old owner is dropped before Pending creation, output is independently owned and immutable through available API; only cfg(test) inspections reveal bytes/policy/O/E. No production extraction, parse/admission, session adoption or persistence path is added.
|
||||
- **Regressions:** preserve all existing planner/carried outcomes and unchanged small-stack controls, inherited failure dispositions and formatting exclusions. Emitted-unverified success is reported separately from future output acceptance.
|
||||
|
||||
## Minimal files and next decisions
|
||||
|
||||
- `mixed/project/ordinary_index/rename/emission.rs`: emission outcome, pending owner, sole consumed-plan producer and its tests as a child module. Access existing private plan/source fields through lexical ancestry, not public mutable accessors.
|
||||
- `rename.rs`: module wiring and, if needed, narrowly factor existing per-file checked-length iteration for use by sizing/emission without allocating a lengths table. Preserve the sealed constructor validation and existing inspection APIs.
|
||||
- Scoped implementation note/tests. `mixed/carried.rs` need not change for pending-only delivery; no arbitrary RetainedSnapshot constructor is opened.
|
||||
|
||||
Read against the parent draft harness/analysis-mixed-emission-contract-20260925.md: parent selected pending-only staging, split consuming methods, changed legacy-only provenance, one upfront O reservation and no production extraction. The draft requests reuse of complete edit validation and malformed-plan fixture coverage; invoking the existing validate once before construction is compatible and avoids inventing a second authenticator. No duplicate streaming byte comparator is proposed. Parent retains API selection and contract acceptance authority. A later accepted contract must specify the sole Pending-to-RetainedSnapshot/verifier transition and cannot mistake this owner for accepted rewritten output.
|
||||
|
||||
Minimal independent oracle supplied by reviewer: empty project p renamed next has authored A=(14,0,9), plan L=(16,0,9), output O=(1,0,105), peak L+O=(17,0,114). Exact entries 17/text 114 and predecessor-compatible minus-one caps are the preferred first actual-path acceptance cases. These are independent hand counts, not new runtime results.
|
||||
|
||||
Superseding parent decision: both split methods rerun the existing complete validator after stale-current validation, enforce the correct no-op/changed branch, and refuse changed carried input before O allocation. Earlier proposal preferences for relying only on construction proof or callback delivery are not the implementation selection. Await parent claim/contract publication before source edits.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Independent critique of the next producer proposal
|
||||
|
||||
Read-only review against source `fa7a980418ef99d772e67c66c28dfa7b5181f875`, `NEXT-PRODUCER-HOOKS.md`, the accepted carried-phase contract, the rename-plan successor requirements, Project resource contract and execution domain audit. No source changes, Cargo, network or runtime execution.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Do not make the proposed complete U/M/T producer ledger plus selected parser scratch the next single implementation milestone. The inventory is useful and identifies real timing gaps, but spans the shared scanner, ordinary parser/projection, typed cursor/declarations/expressions, traversal and resolver handoff. Calling that a small set of hooks understates its policy, lifetime and regression surface.
|
||||
|
||||
The smallest useful next rename implementation is **private emission and authenticated output ownership**, stopping before accepted-output authority. Reserve exact output ownership while the old plan is live, emit from original coordinates, independently authenticate actual bytes against the authorized edit stream, and establish a constructor-controlled output owner with exact policy and a documented old-owner drop. Preserve an explicit unchanged outcome for no-op intent. This is necessary work under every plausible future parser accounting decision; it makes actual rename progress without silently settling that decision.
|
||||
|
||||
Do not expose installation/save/history adoption or label this result accepted edited source. The proposed milestone should be explicitly approved as a private prerequisite, just as carried-phase accounting was. A complete accepted-output API still requires actual-byte parse/resolve/admission, strict whole-Project equality with reserved E scratch and a resolved temporal accounting contract.
|
||||
|
||||
## What the contracts actually require
|
||||
|
||||
Three categories should remain separate:
|
||||
|
||||
1. **Necessary new output ownership.** The rename-plan successor explicitly names F output-map entries, complete strings, canonical copied keys and entry; output overlaps the old B during emission. Old syntax/index/plan allocations must actually drop before their reservations disappear, or both owners remain charged. These requirements are unambiguous and cannot be deferred behind a generic parser exclusion.
|
||||
2. **Existing retained inventory.** Project §3 requires before-allocation aggregate checks for in-scope representations. Existing retained syntax aliases, field keys, AST text and projected copies are counted today, but some only at resolution. The domain audit and carried contract explicitly preserve this timing limitation, without waiving the stronger obligation for final execution. Producer hooks for those exact existing families are a defensible way to close it; a proven conservative reservation is another. The successful phase prerequisite does not itself discharge it.
|
||||
3. **Explicit temporaries versus inferred universal scratch.** New emitter containers and already named accounting/equality work must be admitted. The original successor does not separately list every inherited traversal/path/scanner/duplicate-set allocation. Project §3's broad wording and parser proposal's temporary wording deserve an explicit finite scope interpretation; they do not by themselves establish that all of those structures already belong to one exact slot inventory. Automatically adding all of them is a metric expansion, not merely repairing the timing of existing T. Automatically exempting all of them would also be unjustified.
|
||||
|
||||
Accordingly, broad parser scratch expansion is **not established as a prerequisite to implementing private emission**, and should not be imposed implicitly. It may become necessary for the final selected guarantee if parent explicitly includes those structures. That decision should identify each family and its logical unit, rather than using either “everything is already bounded” or “all parser allocation must now be metered.” Allocator capacity, model/serde-conversion heaps, raw validator Issues, BigInt limbs and native stack remain distinct exclusions/limits as documented.
|
||||
|
||||
## Concrete bounded next implementation
|
||||
|
||||
Use the existing opaque RenamePlan and its complete snapshot/edit validation. Add one private emission module beside planning; do not change shared parser producers in this milestone.
|
||||
|
||||
1. Revalidate complete original bundle authority and all physical edits before copying. Preserve canonical paths/file set/entry and both occurrence families. No caller-supplied partial file list or replacement model authority.
|
||||
2. Repeat the existing checked per-file sizing walk, without a lengths map. Compute exact O: F entries and `sum(final source lengths) + sum(copied canonical key byte lengths) + entry byte length`, zero lower occurrences. The existing resolved ledger already includes retained R+M plan maps: reserve O against that live total before constructing any output buffer/key/map. Reserving all O up front is simple and sufficient for a once-built complete bundle whose logical live output grows monotonically toward O. Do not debit old storage for shrinkage.
|
||||
3. Construct each final file once by appending original untouched slices and borrowed desired aliases in increasing original coordinates. Copy untouched files too when delivering the specified complete owned output. Charge every implementation-added temporary if one is introduced; the preferred walk requires only iterator/scalar state and the currently growing output String. Container capacity is not a new logical-byte charge.
|
||||
4. While the original owner still lives, use a separate streaming comparison of the **actual** output against the original-slice/replacement sequence. Check entry, exact canonical file set and every byte, including untouched files. No second output buffer, lexer or output hash as a substitute. This catches admissible-but-wrong non-name damage and creates useful authenticated topology evidence for any later envelope option.
|
||||
5. Capture exact immutable policy and E scalar while the old witness still authorizes them. Consume/drop old syntax, indexes, warnings and plan maps at a named transition; retain only the complete output owner, desired borrow, policy and documented scalar metadata. Install O through the sole private output transition, never a general `new(bundle, arbitrary_slots)` constructor. The stable owner may later lend bytes through the carried guard. Do not return a self-borrowing bundle-plus-syntax pair.
|
||||
6. For no-op intent, return the original owner in an explicit unchanged branch without constructing/copying a complete output. No history/install behavior follows from this private result.
|
||||
|
||||
The output handle should be opaque and have no public extraction/adoption route. Test-only inspection can examine bytes and provenance. A later internal scoped verifier can borrow it and drop temporary syntax before returning owning acceptance. Failure drops partial output and consumes no install authority; the immutable original caller-owned source bytes and desired model remain unchanged.
|
||||
|
||||
This is a proposal requiring a small successor contract, not authorization to add a production constructor under the already-finished phase-only contract.
|
||||
|
||||
## Acceptance for that bounded milestone
|
||||
|
||||
Reuse the independent complete rich OA/SA, swaps, scoped repeated/reordered call labels, cross-file Unicode/CRLF and ordinary-category maps. Author exact expected bytes from the original fixture and literal replacement coordinates, without invoking the emitter as its own oracle. Include untouched files and the previously agreed combined grow/shrink sizing case. Verify original bytes/intent unchanged and no-op preserves ownership.
|
||||
|
||||
Hand-count emission cap/cap-minus-one at **old live B including R+M plus O**, ensuring the same profile first admits parsing, indexing and planning. Assert exact O after old ownership ends. Corrupt emitted touched/untouched bytes, a non-name byte, entry/key/file set and a replacement belonging to the wrong qualified target; streaming authentication must reject each. These are emitter/ownership tests, not substitute proof of actual output semantic admission. Parent should retain the later whole-Project equality requirement explicitly.
|
||||
|
||||
## Quoted-text bound and future hooks
|
||||
|
||||
The proposal's `decoded UTF-8 bytes D <= raw payload UTF-8 bytes P` is sound for valid JSON strings, including escapes and surrogate pairs. P must exclude exactly the two ASCII quotes. Reserving P before decode and releasing P-D is a straightforward conservative logical-text bound. It can reject escape-heavy source whose decoded retained text would fit; that rejection is a real selected policy change for the opt-in path, not exact minimal acceptance. An escaped/unescaped pair with identical decoded text should document this tradeoff. No second decoder or Unicode normalization claim is warranted.
|
||||
|
||||
The scanner already decodes once for validation, before the grammar decoder. Therefore grammar-only hooks cannot claim preadmission of that earlier temporary. If it enters the selected domain, its reservation must occur inside the scanner after token extent discovery and before validation, then release before the later grammar decode. A post-next callback is too late. Adding this hook changes a shared API/error-transport seam; it should have independent invalid-string and legacy precedence controls, not be hidden in a retained-text patch.
|
||||
|
||||
If parent instead chooses a parser producer milestone next, narrow it first to **retained syntax text T and its once-only transfer**. List every counted String producer and temporary UUID/declaration-key disposition, keep U/M phase checks explicitly unchanged, and do not claim complete before-growth execution acceptance. The most consequential tests are copied ordinary reference/key overlap, escaped strings at P versus D caps, temporary UUID release and no double charge in resolver. This is still a meaningful prerequisite, but should not silently grow into traversal and all scratch in the same change.
|
||||
|
||||
## Compatibility, maintainability and stack
|
||||
|
||||
The accepted carried route is opt-in even when C=0; legacy constructors must keep their original admission and diagnostic timing. Any new hooks need an explicit mode boundary, not numeric-zero detection. Avoid cloning Budget, resetting live Usage or rebuilding policy from defaults. Resolver reconciliation must verify/transfer admitted retained counts, not reserve them twice.
|
||||
|
||||
A ledger moving from parser to resolver introduces subtleties: U is monotone grammar work, value-end/token-end metadata contains deliberate conservative retention, and scratch is genuinely released. Treating all three as interchangeable live Vec sizes risks weaker caps or double counting. Keep a short authoritative ownership table and tests for those distinct rules; a universal allocation abstraction is unnecessary.
|
||||
|
||||
The recent stack regression demonstrates that even an inline policy field can enlarge many ancestor frames. It does not prove producer hooks are unsafe, nor that more hooks solve stack usage. Keep policy in existing Budget/syntax, retain the slim owner guard, use scoped borrowed accounting state, and avoid large inline callback/guard enums on recursive paths. Preserve the nine existing stack cases and the earlier abort evidence. Neither emission nor producer accounting earns a universal stack guarantee.
|
||||
|
||||
Unresolved before accepted execution: the exact selected pre-growth retained/scratch domain; actual-output parser/resolver temporal coverage; E-reserved strict whole-intent equality; owning accepted-result construction and install/history lifecycle. The bounded emission step deliberately leaves these visible rather than letting a larger parser refactor substitute for actual rename output.
|
||||
@@ -0,0 +1,70 @@
|
||||
# Next parser producer hooks — bounded proposal
|
||||
|
||||
2026-09-25. **Proposal, not accepted requirements or implemented behavior.** Read-only source pin `fa7a980418ef99d772e67c66c28dfa7b5181f875`. Paths below start at `crates/oa-core/src/`. No source edits, builds, runtime execution or Gitea activity. Scope follows the accepted carried-phase contract and domain audit: logical auxiliary entries/occurrences/text, not universal heap/RSS/stack accounting.
|
||||
|
||||
## Recommendation
|
||||
|
||||
The already-counted retained syntax representations can be admitted before their growth with a small set of named producer hooks and one carried ledger. Preserve current work Usage separately, transfer existing reservations rather than count them again at resolve, and use exact lengths for copies. Quoted-string payload length is a safe conservative reservation before the existing decoder, with exact release afterward.
|
||||
|
||||
This closes **named retained-representation timing gaps**, not every current parser allocation. Traversal, scanner-validation Strings and certain parser scratch tables require explicit scope decisions below. The accepted broad before-growth obligation cannot be called completely discharged while those questions are unresolved. No universal allocator interception, second numeric parse, new decoder, or large whole-source multiplier is necessary.
|
||||
|
||||
## Existing domain and minimum producer inventory
|
||||
|
||||
C is the surviving owned-bundle baseline; U remains cumulative grammar-entry work; M is existing logical metadata. New live text reservations T and named scratch W must participate in aggregate checks with C. Do not globally reduce Limits to account for C: source-byte/token/reference/Exact work is a separate domain.
|
||||
|
||||
| Counted representation | Current producer / minimum pre-growth hook | Transfer, release and reconciliation |
|
||||
|---|---|---|
|
||||
| Syntax entry slots U: project/declaration/include/description, field/value/list items, typed declaration/parameter/expression events | Existing `Parser::syntax_entry` (`language.rs:1168`), `State::entry` (`mixed.rs:98`), typed `Budget::entry` calls in declarations/syntax. Preserve exact charge events; additionally check carried live entries plus prospective U/M/named scratch before the event permits its representation to grow. | Do not increment U twice or reinterpret every Vec element as another grammar event. U's established monotone/conservative syntax baseline transfers once into resolver storage. |
|
||||
| Borrowed file records and per-file bookkeeping | `mixed.rs:296–306` initial file count; parsed-file insertion and final collection `:384–410`. Existing F is reserved before traversal. | Preserve F once; moving the map's file values into canonical Vec does not create another retained F. If implementation temporarily retains two actual coordination containers, name/reserve that overlap rather than hiding it. |
|
||||
| Ordinary value-end entries | `Parser::value`, `language.rs:1298–1307`, immediately before `value_ends.insert`. | Check one new logical entry before insertion (existing-key replacement must not invent a new slot). Existing final metadata may conservatively retain dropped value-end subtotal; do not both carry that subtotal and re-add table length. |
|
||||
| Lexical-owner entries | `language.rs:1627–1630`, before push. | Transfer scalar count to M once. Keep correspondence with declaration occurrences, not unique IDs. |
|
||||
| Token-end metadata (one token-count component) | `edit_positions_from_tokens`, `language.rs:1022`, before collecting `ends` of length significant-token count; currently `mixed.rs:339–355` admits this component at the phase boundary. | Preserve the current **single** tokens.len() metadata component. It is conservative after projection scratch drops. Do not add another tokens.len() merely to label retained Token storage; see distinction below. |
|
||||
| Ordinary EditDeclaration/header/field/value/list slots | Existing `ordinary_position_slots` (`mixed.rs:415+`) and `edit_positions_from_tokens` (`language.rs:1014–1140`). Reserve the existing exact/conservative projected slot total before construction; keep the current seven-per-declaration/header envelope and field/value table semantics unless independently revised. | Positions transfer to retained syntax. Header role keys are borrowed static strings (`language.rs:1114–1127`), **not copied text**. Reserve counting-walk work before its own push, or derive the projection count incrementally from successful grammar events without another traversal. |
|
||||
| Typed retained names, references, display names/descriptions/symbols | `Cursor::name` exact borrowed spelling before `to_owned` (`cursor.rs:67–79`); `Cursor::quoted` before existing decode (`:81–95`). | Name/reference strings move into typed declarations once. Reserve decoded-string upper bound, reconcile to exact length, and transfer surviving text. UUID spelling temporaries consumed by identity parsing must release when dropped; they do not appear in the retained syntax text oracle. |
|
||||
| Ordinary retained aliases/names/includes/descriptions/reference/word strings | `Parser::identifier/quoted` (`language.rs:1194–1210`), Ast word copy (`:1370+`), project/declaration/include consumers. | Exact spelling length before copy; quoted rule below. Distinguish retained use from consumed UUID spelling and temporary declaration-kind word. The latter must not become retained T accidentally. On an aborted parse the entire phase unwinds; no reusable ledger/partial result escapes. |
|
||||
| Ordinary field keys and their distinct copies | `Parser::field` (`language.rs:1250+`); declaration fields/key-span map insertion (`:1515–1529`); nested `fields` (`:1230–1246`). | Initial key ownership transfers to one retained map; reserve additional key.len() before each clone. Top-level declaration field_spans owns a second key. Nested-field `key.clone()` coexists with the original local key until scope end: either account/release that temporary or move the key after a duplicate check, preserving error order. |
|
||||
| Projected copied field keys/reference spellings | `Positions::fields/value`, `language.rs:1047–1090`. | Reserve exact existing key/name lengths before cloning, aggregate with still-live AST copies. They remain in T; Atom projection does **not** copy decoded literal text. Existing T45 ordinary-description test is a useful discriminating oracle. |
|
||||
| Resolve syntax inventory / counting work | `mixed/project/accounting.rs:233–352`. | Consume parser's checked U/M/T reservations once; don't seed C then add already-carried syntax totals again. Keep the existing bounded walk for independent reconciliation/LowerStorage calculation if useful, but change its text action from re-reservation to verification. Any walk work still reserves/release entries before growth. Require equality with the established final inventory (including conservative metadata), not silent subtraction after over-allocation. |
|
||||
|
||||
### Tokens versus metadata
|
||||
|
||||
`lex::tokens` charges source bytes once and every **raw** scanner token, including trivia, before scanner advance (`lex.rs:19–45`). It stores only significant tokens (`:47–52`). Current mixed module documentation says tokens themselves use the token bound, while its one tokens.len() entry component represents token-end metadata. That is the declared existing metric even though both token Vec and projection ends can coexist physically.
|
||||
|
||||
Do not silently add retained significant tokens as a second auxiliary entry family, nor claim the old single metadata component separately counts both physical Vecs. The minimal proposal preserves raw-token prechecks and token-bound-only retained storage, and reserves the one established token-end component before its producer. Any change to count significant-token Vec entries separately is an explicit metric revision with new oracles, not a timing repair.
|
||||
|
||||
## Quoted text: raw payload bound is valid
|
||||
|
||||
For a syntactically valid JSON string token, let P be the **UTF-8 byte length between its surrounding ASCII quotes** (checked token.len()-2), and D the decoded Rust String.len(). Then **D <= P**:
|
||||
|
||||
- Unescaped valid UTF-8 scalar text copies its bytes unchanged.
|
||||
- Each simple escape (`\"`, `\\`, `\/`, `\b`, `\f`, `\n`, `\r`, `\t`) occupies two ASCII source bytes and decodes to one byte.
|
||||
- One nonsurrogate `\uXXXX` occupies six ASCII bytes and decodes to at most three UTF-8 bytes.
|
||||
- A valid surrogate pair occupies twelve ASCII bytes and decodes to one scalar of four UTF-8 bytes.
|
||||
- Empty payload has P=D=0. JSON decoding does not Unicode-normalize text or expand entities; invalid escapes/unpaired surrogates are rejected, not larger valid strings.
|
||||
|
||||
Therefore reserve P owned-text bytes against the live ledger **before the existing `serde_json::from_str` call**, then on success assert/check D<=P and release P-D. Move the D reservation with the returned String, or release D when a temporary UUID spelling is consumed and dropped. Use byte lengths, not character counts. Overflow/subtraction failures refuse safely; do not use saturating arithmetic to accept malformed bounds. The envelope may transiently reject an escaped string whose final decoded bytes would fit; that is an explicit conservative pre-growth tradeoff, not a claim of exact minimal admission. No second decoder, escaped-length pass or Exact conversion is required.
|
||||
|
||||
This bound covers logical String bytes only. It does not count String capacity, serde scratch allocation or allocator overhead. A decode failure may have transient partial internal allocation bounded by the raw string extent, but that is not an exact internal-heap claim; the attempt fails and returns no witness.
|
||||
|
||||
### Important earlier existing decode
|
||||
|
||||
`raw_tokens::Scanner::next` scans a quoted token and already calls `serde_json::from_str::<String>` to validate it (`raw_tokens.rs:107–130`, allocation at126). The grammar later decodes it again. Merely hooking Cursor::quoted/Parser::quoted therefore cannot claim **every** decoded String was pre-reserved: scanner validation has already created and dropped one.
|
||||
|
||||
Label that validation-only decoded String as a distinct parser temporary; it is not retained T. It is not automatically covered by the accepted ordinary model/serde-conversion exclusion merely because serde_json produces it. Those exclusions concern model conversion/raw validation domains, not a generic exemption for every parser String. If parent requires this named parser temporary within the before-growth envelope, add an optional private reservation/release hook **inside the scanner immediately before its existing validation call**, after its span is known. Reserve P, drop validation value, release P; later grammar decode receives its separate nonoverlapping reservation. A callback after `scanner.next()` is too late. Do not add a third validation/decoding pass. Public scanning behavior and raw-token work semantics must remain unchanged.
|
||||
|
||||
## Named scratch and traversal decisions — not an invitation to all-heap accounting
|
||||
|
||||
The current inventory does not separately Ledger-meter every structure below. They cannot be declared fully covered merely because another bound exists. Choose their status explicitly before final verification acceptance:
|
||||
|
||||
- Projection counting Vec (`mixed.rs:418+`) and delimiter stack (`language.rs:1023–1030`): they are narrow borrowed work frontiers. A reserve-before-push/release-after-pop hook fits the existing auxiliary-work model, but adds explicitly named scratch peaks; it must not double count token-end metadata. Prefer borrowing/taking existing parsed value ends where possible without a second parse, only if semantic coverage remains identical.
|
||||
- Typed duplicate-name sets clone parameter/override names (`declarations.rs:293,610`). These are temporary syntax coordination copies absent from retained T. Reserve their live map entries and copied name bytes before insertion, release when the set drops, or use borrowed names where lifetimes permit. Do not count them as new retained names. Whether these already-existing temporary sets join this patch's declared domain needs parent approval.
|
||||
- Ordinary open-declaration stack and local String clones: distinguish the existing grammar U reservation from additional simultaneously live coordination. Avoid adding hidden copied strings; any newly introduced work structures require explicit reservations.
|
||||
- Shared traversal owns folded-path table, visited/active/children/stack and normalized/copied path/location strings (`source_project/traversal.rs:9–16,59–87,128,144–180`). Current file/include/depth prechecks bound workload, not every overlapping map slot/owned path byte. If these are included now, use a localized optional private accounting hook at actual insert/push/copy/drop points, retaining public behavior through a no-op path. `path.to_lowercase()` can expand UTF-8 spelling; original path.len() is **not** automatically its bound. Prefer a checked chars-based length sum followed by the existing conversion, or avoid its owned copy with a proved equivalent borrowed comparator; no general huge multiplier. Do not assume all visitation structures share one F slot.
|
||||
|
||||
Raw model construction/serde conversion and architectural validation heaps retain the accepted exclusions; retained mapped warnings are already charged separately. BigInt limbs remain under numeric policy, not this text ledger. Native stack size and allocator/RSS are outside the logical metric. None of these exclusions permits newly owned output strings/map/path keys or actual retained syntax copies to disappear.
|
||||
|
||||
## Bounded next decision
|
||||
|
||||
Yes: pre-growth admission for the **named existing retained auxiliary inventory** is achievable with producer hooks, decoded-text reconciliation and once-only transfer. No: that statement alone does not prove every declared parser-temporary obligation has been met. Parent must pin the scratch/scanner/traversal rows it intends to include or leave explicitly unresolved; doing so is a finite representation-table decision, not universal allocation metering.
|
||||
|
||||
Recommended next design is a producer ledger for U/M/T with per-copy hooks and raw-payload quoted reservations, plus explicitly selected borrowed-work scratch. Keep policy exact and legacy behavior isolated. Prove constructor/ownership transfer and independent cap oracles before integrating actual output verification. Stop here: no requirement is amended, no stronger guarantee accepted, and no code is proposed as already tested.
|
||||
@@ -0,0 +1,116 @@
|
||||
# Exhaustive authored mixed typed-index oracle
|
||||
|
||||
2026-09-24. Independent source/data derivation for private source `aaec78fcc9b273d1485497126392afdd1fb2e54e`. Reuse fixture and independent model construction in `crates/oa-core/src/language/analysis_source/mixed/project/tests.rs:254–330`, `expected` at line 52, and the explicit site oracle at lines 331–538. No Index, lowerer, formatter, parser or compiler executed to produce expectations. Numeric spans below were checked using direct unique substring locations in independently reconstructed literal source; all original fixture bytes are ASCII/LF. This is suggested test data, not a passing-test report.
|
||||
|
||||
## Fixture identity and file binding
|
||||
|
||||
Use the existing `id(n)` helper (line 9): it formats n as twelve decimal digits inside a UUID then parses that UUID. **Do not substitute `Id::from_u128(n)`**: for n=10 the fixture suffix is `000000000010`, not `00000000000a`.
|
||||
|
||||
Retain entry `main.arcadia`; canonical numeric files are 0=`a.arcadia` (213 bytes), 1=`b.arcadia` (213 bytes), 2=`main.arcadia` (474 bytes), aggregate 900 original bytes. Include spelling/order in main is b then a; numeric file order is canonical a then b. File 0 has calculation f/id(10), file 1 g/id(11); both declare parameter x/id(1), y/id(12). Parameter x UUID also equals the Project's global id(1).
|
||||
|
||||
Main's ordinary node n points forward to typed property v; property v's subject points forward to ordinary activity w. Its base is exactly `@f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6)`. Typed declarations begin after the Project header, includes and ordinary node. Reuse the existing independently built full Project, including the diagram/node defaults and both calculation bodies; do not replace full equality with an index-only projection.
|
||||
|
||||
Notation: `G(n)` = `Target::Global(id(n))`; `Q(c,p)` = `Target::Parameter { calculation: id(c), parameter: ParameterId(id(p)) }`. Paths are complete **root-to-leaf** `Child` sequences: L=Left, R=Right, A1=Argument(ParameterId(id(1))), A12=Argument(ParameterId(id(12))). `[]` is a real empty expression-root path. `—` means `None`, not `Some(empty)`. All spans are half-open full-original-file byte spans.
|
||||
|
||||
## Entire expected names catalog (G=11)
|
||||
|
||||
| Qualified target | Name | Original declaration anchor |
|
||||
|---|---|---|
|
||||
| G(1) | p | main: `project p` |
|
||||
| G(2) | w | main: `oa_activity w` |
|
||||
| G(3) | v | main: `oa_property v` |
|
||||
| G(4) | n | main: `node n` |
|
||||
| G(5) | d | main: `diagram d` |
|
||||
| G(10) | f | a: `calculation f` |
|
||||
| G(11) | g | b: `calculation g` |
|
||||
| Q(10,1) | x | a: `input x` |
|
||||
| Q(10,12) | y | a: `input y` |
|
||||
| Q(11,1) | x | b: `input x` |
|
||||
| Q(11,12) | y | b: `input y` |
|
||||
|
||||
Global p/w/n/d names are required even though this typed index must contain **no ordinary declaration/reference occurrences** for them. There are 7 global names plus 4 scoped names; every name is one UTF-8 byte.
|
||||
|
||||
## Entire expected expression map (E=15)
|
||||
|
||||
Each row is `(ExpressionKey { owner, field, path }, Location { file, span })`. E labels are explanatory, not persisted arena positions or part of key identity. The order below matches the authored lower-site oracle only for ease of comparison; compare a complete map/set of keys rather than relying on BTree ordering of Path.
|
||||
|
||||
| Row | File | Owner | Field | Path | Span | Exact source slice / unique anchor |
|
||||
|---|---:|---:|---|---|---|---|
|
||||
| E0 | 0 | 10 | Body | [] | 202..209 | `$x + $y` |
|
||||
| E1 | 0 | 10 | Body | [L] | 202..204 | `$x` |
|
||||
| E2 | 0 | 10 | Body | [R] | 207..209 | `$y` |
|
||||
| E3 | 1 | 11 | Body | [] | 202..209 | `$x - $y` |
|
||||
| E4 | 1 | 11 | Body | [L] | 202..204 | `$x` |
|
||||
| E5 | 1 | 11 | Body | [R] | 207..209 | `$y` |
|
||||
| E6 | 2 | 3 | Base | [] | 290..334 | `@f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6)` |
|
||||
| E7 | 2 | 3 | Base | [L] | 290..317 | `@f(y: 2, x: @g(x: 3, y: 4))` |
|
||||
| E8 | 2 | 3 | Base | [L,A12] | 296..297 | `y: 2`, offset 3, length 1 |
|
||||
| E9 | 2 | 3 | Base | [L,A1] | 302..316 | `@g(x: 3, y: 4)` |
|
||||
| E10 | 2 | 3 | Base | [L,A1,A1] | 308..309 | `x: 3`, offset 3, length 1 |
|
||||
| E11 | 2 | 3 | Base | [L,A1,A12] | 314..315 | `y: 4`, offset 3, length 1 |
|
||||
| E12 | 2 | 3 | Base | [R] | 320..334 | `@f(x: 5, y: 6)` |
|
||||
| E13 | 2 | 3 | Base | [R,A1] | 326..327 | `x: 5`, offset 3, length 1 |
|
||||
| E14 | 2 | 3 | Base | [R,A12] | 332..333 | `y: 6`, offset 3, length 1 |
|
||||
|
||||
There are 3 roots and 12 nonroot sites, hence **P=12 distinct allocated shared Path Steps** under one-Step-per-child construction. Maximum expression depth including root is 4. Same spans 202..209 and parameter token positions in a/b are deliberately different owners/files.
|
||||
|
||||
## Entire expected occurrence map (H+O=21)
|
||||
|
||||
Each row spells every `OccurrenceKey` field: owner, optional field, optional path, token role and qualified target, plus physical file/span. `Decl` means `TokenRole::Declaration`; every other role below means `TokenRole::Use(lower::Role::<name>)`. Input1/Input12 mean `Field::Input(ParameterId(id(1/12)))`. Every token length is 1, with @/$ excluded.
|
||||
|
||||
| Row | File | Owner | Field | Path | Role | Target | Span | Exact spelling / independent source anchor |
|
||||
|---|---:|---:|---|---|---|---|---|---|
|
||||
| H0 | 0 | 10 | — | — | Decl | G(10) | 12..13 | f; `calculation f`, +12 |
|
||||
| H1 | 1 | 11 | — | — | Decl | G(11) | 12..13 | g; `calculation g`, +12 |
|
||||
| H2 | 2 | 3 | — | — | Decl | G(3) | 206..207 | v; `oa_property v`, +12 |
|
||||
| O0 | 0 | 10 | Input1 | — | ParameterDeclaration | Q(10,1) | 68..69 | x; `input x`, +6 |
|
||||
| O1 | 0 | 10 | Input12 | — | ParameterDeclaration | Q(10,12) | 128..129 | y; `input y`, +6 |
|
||||
| O2 | 0 | 10 | Body | [L] | ParameterUse | Q(10,1) | 203..204 | x; `$x`, +1 |
|
||||
| O3 | 0 | 10 | Body | [R] | ParameterUse | Q(10,12) | 208..209 | y; `$y`, +1 |
|
||||
| O4 | 1 | 11 | Input1 | — | ParameterDeclaration | Q(11,1) | 68..69 | x; `input x`, +6 |
|
||||
| O5 | 1 | 11 | Input12 | — | ParameterDeclaration | Q(11,12) | 128..129 | y; `input y`, +6 |
|
||||
| O6 | 1 | 11 | Body | [L] | ParameterUse | Q(11,1) | 203..204 | x; `$x`, +1 |
|
||||
| O7 | 1 | 11 | Body | [R] | ParameterUse | Q(11,12) | 208..209 | y; `$y`, +1 |
|
||||
| O8 | 2 | 3 | Subject | — | Reference | G(2) | 269..270 | w; `subject @w`, +9 |
|
||||
| O9 | 2 | 3 | Base | [L] | CallTarget | G(10) | 291..292 | f; `@f(y:`, +1 |
|
||||
| O10 | 2 | 3 | Base | [L] | ArgumentLabel | Q(10,12) | 293..294 | y; `y: 2`, +0 |
|
||||
| O11 | 2 | 3 | Base | [L] | ArgumentLabel | Q(10,1) | 299..300 | x; `x: @g`, +0 |
|
||||
| O12 | 2 | 3 | Base | [L,A1] | CallTarget | G(11) | 303..304 | g; `@g(x:`, +1 |
|
||||
| O13 | 2 | 3 | Base | [L,A1] | ArgumentLabel | Q(11,1) | 305..306 | x; `x: 3`, +0 |
|
||||
| O14 | 2 | 3 | Base | [L,A1] | ArgumentLabel | Q(11,12) | 311..312 | y; `y: 4`, +0 |
|
||||
| O15 | 2 | 3 | Base | [R] | CallTarget | G(10) | 321..322 | f; `@f(x: 5`, +1 |
|
||||
| O16 | 2 | 3 | Base | [R] | ArgumentLabel | Q(10,1) | 323..324 | x; `x: 5`, +0 |
|
||||
| O17 | 2 | 3 | Base | [R] | ArgumentLabel | Q(10,12) | 329..330 | y; `y: 6`, +0 |
|
||||
|
||||
Totals: H=3 typed global headers. O=18 lower occurrences: 4 parameter declarations, 4 parameter uses, 1 subject reference, 3 call targets, 6 labels. Header occurrences are produced by indexing and are absent from the retained lower O vector. Repeated f labels have different full paths; nested g labels differ by both path and calculation scope. Ordinary node's `element @v` remains absent from this typed occurrence map.
|
||||
|
||||
For executable expected records, reuse the existing unique-anchor `span(source, context, offset, len)` helper at line 156; assert the numeric values above for the unmodified fixture. Build expected paths from these literal Child arrays, not by following `resolved.expressions.parent` or enumerating actual Index keys. Construct expected keys/targets explicitly from this table. Exhaustive equality must compare all 11 names, all 15 expressions, all 21 occurrences, and the entire independent Project.
|
||||
|
||||
## Exact added retained storage and scratch anchors
|
||||
|
||||
Under accepted contract dimensions and current three-map/shared-Step design:
|
||||
|
||||
| New retained representation | Entry slots | Occurrence slots | Owned text bytes |
|
||||
|---|---:|---:|---:|
|
||||
| Qualified names | 11 | 0 | 11 |
|
||||
| Occurrence map | 21 | 0 | 0 |
|
||||
| Expression map | 15 | 0 | 0 |
|
||||
| Unique Path Steps | 12 | 0 | 0 |
|
||||
| **Added retained total** | **59** | **0** | **11** |
|
||||
|
||||
Thus final Ledger is exactly the incoming accepted-witness Ledger plus `(entries:59, occurrences:0, text:11)` if no additional retained representation is introduced. The baseline retains the raw 15 expression-site entry slots and 18 occurrence slots; neither is released merely because indexed versions now exist. Original source bytes 900 are borrowed and are not added again to text storage.
|
||||
|
||||
Known scratch sizes are owner map 3, physical-token set 21, path lookup Vec 15, call map 3, reverse-name maps 11, syntax-site lookup 15. The original all-roots-first LIFO syntax traversal's peak work Vec has 5 elements (root main pops, right call contributes x/y while a/b roots and left call remain). This 5 is specific to the present traversal order, not a requirement to preserve that order. A final retained delta is fixed; a whole-construction cap must separately account for the chosen scratch lifetime/ordering and for any earlier resolution peak. Do not claim `baseline.entries+59` is a sufficient construction cap while scratch is alive. With all original scratch still alive at syntax-walk peak, scratch is 3+21+15+3+11+15+5=73; explicit earlier releases can reduce this overlap. Any implementation reserving conservative bounds should state the difference instead of weakening exact semantic oracles.
|
||||
|
||||
## Corruption that must reach the call-site check
|
||||
|
||||
Before Index construction, mutate only O11 (main 299..300, owner3, Base, expression site7 / path[L]) from target `Q(10,1)` to `Q(11,1)`. Keep source, tokens, owner, field, expression and span unchanged.
|
||||
|
||||
This is deliberately not an unknown-target or spelling error: both calculations have x/id(1); both qualified target names are `x`. The token is the same full Word inside its expression/owner. The changed key does not collide with nested g's label because that label has path[L,A1], and physical ownership remains unique. ArgumentLabel role accepts a scoped target with a path. The call at path[L] still targets G(10), so `index.rs:438–448` must reject with `Argument label crosses its called calculation.` at span299..300. Assert this diagnostic, not merely any error. Repeating with O10's y Q(10,12)->Q(11,12) is equivalent but unnecessary duplication.
|
||||
|
||||
A distinct runtime omission negative removes O11 while leaving its argument child E9: the qualified-label check (`index.rs:455–469`) must reject `Argument child has no qualified label.` at E9 span302..316. By contrast removing O0 or O8 is an exhaustive-output-oracle failure, not a promised current runtime rejection.
|
||||
|
||||
## Optional direct extensions without changing oracle provenance
|
||||
|
||||
- **SA:** apply the same rich additions to `bundle(Layer::Sa)` and construct model from `expected(Layer::Sa)`. Its system s/id(6) adds one global name. H/O/E/P and all expression/token spans through main's base remain the same because `sa_property` and `oa_property` have equal length and the system/diagram-layer differences occur later. G=12, new retained entries=60, name bytes=12. Assert the system in the complete Project and catalog; it contributes no typed occurrence.
|
||||
- **Unicode/CRLF:** independently prefix each file with `// 雨\r\n` (8 UTF-8 bytes) and replace each original LF with CRLF. For any original endpoint b in these ASCII files, the transformed byte endpoint is `8 + b + count(original[..b] == LF)`. This raw-byte transformation is independent of parsing/indexing and applies separately to start/end. Or use the same unique literal anchors against transformed sources; Rust string find returns byte offsets. Keep exact original bundle comparison. Do not carry the ASCII numeric offsets unchanged into this variant.
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Parent raw-byte check of independently authored fixture/index expectations."""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import re
|
||||
|
||||
def ident(n):
|
||||
return f'00000000-0000-0000-0000-{n:012}'
|
||||
|
||||
body = (f'node n id "{ident(4)}" {{ diagram @d; element @v; }}\n'
|
||||
f'oa_property v "Value" id "{ident(3)}" {{ subject @w; type Number; base 1; }}\n'
|
||||
f'oa_activity w "Work" id "{ident(2)}" {{}}\n'
|
||||
f'diagram d "Diagram" id "{ident(5)}" {{ }}\n')
|
||||
main = f'arcadia 8;\nproject p "Project" id "{ident(1)}" {{\n{body}\n}}\n'
|
||||
main = main.replace('base 1;', 'base @f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6);')
|
||||
main = main.replace('node n', 'include "b.arcadia"; include "a.arcadia";\nnode n')
|
||||
files = []
|
||||
for alias, name, n, op in [('f', 'F', 10, '+'), ('g', 'G', 11, '-')]:
|
||||
files.append((f'calculation {alias} "{name}" id "{ident(n)}" {{\n'
|
||||
f'input x id "{ident(1)}" : Number;\n'
|
||||
f'input y id "{ident(12)}" : Number;\n'
|
||||
f'result Number; body $x {op} $y;\n}}\n').encode())
|
||||
files.append(main.encode())
|
||||
assert list(map(len, files)) == [213, 213, 474]
|
||||
oracle = Path(__file__).with_name('ORACLE.md').read_text(encoding='utf-8')
|
||||
rows = [line.split('|')[1:-1] for line in oracle.splitlines() if re.match(r'\| (E|H|O)\d+ \|', line)]
|
||||
expressions = [r for r in rows if r[0].strip().startswith('E')]
|
||||
occurrences = [r for r in rows if not r[0].strip().startswith('E')]
|
||||
expected_expressions = ['$x + $y', '$x', '$y', '$x - $y', '$x', '$y',
|
||||
'@f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6)',
|
||||
'@f(y: 2, x: @g(x: 3, y: 4))', '2', '@g(x: 3, y: 4)', '3', '4',
|
||||
'@f(x: 5, y: 6)', '5', '6']
|
||||
expected_occurrences = ['f', 'g', 'v', 'x', 'y', 'x', 'y', 'x', 'y', 'x', 'y',
|
||||
'w', 'f', 'y', 'x', 'g', 'x', 'y', 'f', 'x', 'y']
|
||||
assert len(expressions) == 15 and len(occurrences) == 21
|
||||
checks = []
|
||||
for group, expected, span_column in [(expressions, expected_expressions, 5),
|
||||
(occurrences, expected_occurrences, 7)]:
|
||||
for row, value in zip(group, expected, strict=True):
|
||||
name, file = row[0].strip(), int(row[1])
|
||||
start, end = map(int, row[span_column].strip().split('..'))
|
||||
assert files[file][start:end] == value.encode(), (name, files[file][start:end], value)
|
||||
transformed = b'// \xe9\x9b\xa8\r\n' + files[file].replace(b'\n', b'\r\n')
|
||||
shifted_start = 8 + start + files[file][:start].count(b'\n')
|
||||
shifted_end = 8 + end + files[file][:end].count(b'\n')
|
||||
assert transformed[shifted_start:shifted_end] == value.encode()
|
||||
checks.append(name)
|
||||
assert 11 + 21 + 15 + 12 == 59
|
||||
print(json.dumps({'result': 'PASS', 'file_bytes': list(map(len, files)),
|
||||
'original_span_checks': len(checks), 'unicode_crlf_span_checks': len(checks),
|
||||
'retained_entries': 59, 'retained_name_bytes': 11,
|
||||
'scope': 'Independent raw fixture/byte arithmetic, no parser, lowerer, index or compiler execution.'}))
|
||||
@@ -0,0 +1,74 @@
|
||||
# Private mixed typed-index source review
|
||||
|
||||
Parent publication note: production was frozen at
|
||||
`a18b7966e5ac6f5526deecdc4dd6ae8ca0e5ac51` with all three final reviewed production
|
||||
hashes below verified unchanged. Final test bytes at that commit are
|
||||
`f7561e05fb6c03f6d4926bb1583f87c91dabccc4370d221d80b1f9251d994caf`;
|
||||
they include the corrected nested-abs lifecycle fixture after the reviewer's
|
||||
supporting test snapshot. Successor `1d02206c57d5c32caa67f08c6e58f345c0fb5970`
|
||||
changes only an equivalent test range pattern and an implementation note after
|
||||
the first strict lint failure. The original review's source-only scope and
|
||||
findings are retained; this note does not claim runtime acceptance.
|
||||
|
||||
2026-09-24. Reviewer: `/root/mixed_index_source_review` (GPT-6 Astra). Parent owns acceptance, publication, and integration. This is local-only preliminary source evidence; no compiler, test execution, Gitea mutation, source edit, or commit was performed by this reviewer. Issue 37 and its frozen Windows prerelease source were not touched.
|
||||
|
||||
## Scope and exact source
|
||||
|
||||
Reviewed the uncommitted production delta in `.local/as3batch`, branch `codex/analysis-mixed-index-956atf-20260924`, HEAD/base `aaec78fcc9b273d1485497126392afdd1fb2e54e`, against root `harness/analysis-mixed-index-contract-20260924.md` and its accepted independent design review. Paths below are relative to `crates/oa-core/src/` in that checkout. Parent-owned AGENTS.md changes are excluded.
|
||||
|
||||
Initial SHA-256 source inventory (after first source read, before reported repairs):
|
||||
|
||||
| File | SHA-256 |
|
||||
| --- | --- |
|
||||
| `language/analysis_source/index.rs` | `BEC770704DE957134AD05DC6FFA1117F114B5AC8787032A312B7D31B28FA05F5` |
|
||||
| `language/analysis_source/mixed/project.rs` | `EDC2D182FFC2F03F4039872A8B392174FF78185DD41F0A1B5611C6A93502878C` |
|
||||
| `language/analysis_source/mixed/project/accounting.rs` | `3EE9FF1ECDDAE29B35062DFF4738322C7941DED773D128C20D37EAE2BAAF30F6` |
|
||||
|
||||
Final production source reinspection after builder reported its freeze (SHA-256):
|
||||
|
||||
| File | SHA-256 |
|
||||
| --- | --- |
|
||||
| `language/analysis_source/index.rs` | `7C02DDA3622957D837B4AC39D477AE7842570BF3F0709ED48CD5495652636781` |
|
||||
| `language/analysis_source/mixed/project.rs` | `7FE6EF88729718C38D2FFFD46331CDD03624E1B52108DE0B7609DA4FBBDBAC2A` |
|
||||
| `language/analysis_source/mixed/project/accounting.rs` | `3EE9FF1ECDDAE29B35062DFF4738322C7941DED773D128C20D37EAE2BAAF30F6` |
|
||||
|
||||
New test-source snapshot at that checkpoint: `language/analysis_source/mixed/project/tests/index_tests.rs` SHA-256 `6AEC4BE3CCA5D2F69A47DF3F88CC56BB012142E828305A8E121B7FE0A780A074`. The reviewer inspected corruption/transport/storage tests as supporting source, but did not perform a complete independent test-oracle audit or execute them. `git diff --check` returned exit 0.
|
||||
|
||||
## Concrete findings and current disposition
|
||||
|
||||
1. **Late call checks lost current file ownership.** `IndexData::build` initially updated `Original.at` while populating calls, but not while checking argument-label/callee agreement or argument-child/label agreement. A failure in either later loop could combine the current span with the last file in the preceding occurrence loop. Sent directly to parent and builder. Builder added `sources.at.set(Some(at.file))` and `sources.at.set(Some(site.file))` at the respective loop heads. Source reinspection confirms the repair. Runtime corruption controls must assert the relevant canonical file as well as the message.
|
||||
|
||||
2. **Invalid numeric files acquired fabricated entry-file offsets.** `ResolvedMixedProject::index` initially filtered out-of-range `failure.file` to `None`, then passed the untouched span to `Failure::typed`, whose existing fallback selects the entry file. Corrupting an expression/occurrence file to `files.len()` therefore assigns an unrelated offset to the entry. Parent independently identified the same concern. Builder now explicitly resets the span to `Span::default()` for missing/out-of-range file authority before transport; source reinspection confirms that fallback repair. Valid canonical file failures continue to retain their span.
|
||||
|
||||
3. **UTF-8 split offsets can panic during diagnostic conversion.** An internal expression/occurrence span whose start splits a multibyte character is rejected by the verifier, but `Failure::typed` passes its start to `language::diagnostic`, which slices `&source[..start]` without checking UTF-8 boundaries (`language.rs:178` onward). Thus the required damaged-span rejection could panic while reporting the intended error. Sent directly to parent and builder. Builder now tests the full error span with `source.get(start..end)` at the mixed consumed-constructor transport seam. Invalid UTF-8/range spans reset to `Span::default()` while retaining a known canonical file; unknown/out-of-range file authority uses the entry default. Source reinspection confirms the repair, and the added source test specifically chooses a byte inside `雨` and asserts the real `a.arcadia` path with default span. It does not alter unrelated public diagnostic code. Runtime execution remains pending. This was a concrete source control-flow issue reachable through required internal corruption, not through arbitrary fabrication of the sealed witness.
|
||||
|
||||
## Ownership and compatibility assessment
|
||||
|
||||
- `ResolvedMixedProject::index(self)` consumes the retained witness and moves it unchanged into an opaque `IndexedMixedProject`. It neither clones the complete Project nor reparses/re-lowers any source. Its views borrow the wrapper, whose retained syntax still borrows the original `SourceBundle`.
|
||||
- `IndexInput`'s private `files` field seals construction within the witness module; no method exports an input value. Shared verifier access to project/sites and borrowed original tokens does not expose an authenticated sibling constructor accepting replaceable source/token maps. No self-reference is stored in the output. The nested input lifetime/covariance still requires compilation to establish Rust acceptance; source design does not require unsafe code.
|
||||
- `IndexedMixedProject` has no `Deref`, `AsRef`, conversion, or updater adapter to legacy `Index`. `update::Plan`/`Composition` still use the nominal legacy type. Arbitrarily constructible internal `IndexData` alone cannot construct either provenance wrapper.
|
||||
- The mixed catalog streams Project, definitions, elements, relations, diagrams, diagram nodes/placements, artifact links, and traces exactly once, plus `(calculation, parameter)` names. This matches all `Project::identities` categories without allocating its temporary Vec. Scoped parameter UUID reuse cannot collide with globals or parameters of another calculation.
|
||||
- Typed-only name construction, borrowed numeric sources, output wrapper, and local budget checks are preserved. Shared `Storage(None)` adds no reservations; the existing local occurrence-cap and scalar-visited checks remain enabled only on that path. Owner/expression/token/call/structural check order remains equivalent, aside from earlier scratch destruction and unobserved diagnostic attribution. No typed-only semantic regression was identified by source comparison; test/compiler compatibility is not claimed here.
|
||||
|
||||
## Structural and token invariants
|
||||
|
||||
The extracted verifier retains owner containment; binding-field validity; parent-before-child rejection of forward/cyclic edges; file/owner/field agreement; proper subtree spans; unique qualified expression paths; role/qualified-target checks; whole original Word-token boundaries and spelling; duplicate physical-token/qualified occurrence rejection; call-label/callee agreement; required label existence for argument-child edges; and authored-syntax traversal comparing actual child edges to arena claims. The syntax-site lookup and visited total reject missing/extra expressions. It still intentionally trusts sealed lowering for complete non-expression reference/parameter occurrence emission; no additional completeness claim follows from the runtime checks.
|
||||
|
||||
## Aggregate live-storage review
|
||||
|
||||
Let G be global-plus-scoped names, H typed headers, O raw occurrences, E raw expression sites, P nonroot sites, C calls, W live syntax work items. The source adds retained entry slots `R = G + H + O + E + P`, zero occurrence slots, and exactly copied-name UTF-8 bytes. Prior raw E entries and O occurrence slots remain charged in the consumed ledger throughout.
|
||||
|
||||
- Every owned name reserves one entry and its bytes before copying/insertion.
|
||||
- Each owner reserves one scratch entry before insertion; each new occurrence reserves two entries before its physical-token-set and retained-map insertions.
|
||||
- Each nonroot path reserves one retained Step before `Arc::new`. Each expression reserves two entries before retained-map insertion and scratch-path-vector push. Arc clones allocate no additional Step; enclosing map/vector slots remain charged.
|
||||
- After occurrence validation, owners and physical tokens are explicitly dropped before releasing H and H+O scratch entries. Paths and call entries are explicitly dropped/released after argument-child validation. P shared path-node reservations remain retained while map keys still own those nodes.
|
||||
- Reverse borrowed-name maps reserve G before insertion, syntax-site lookup reserves E incrementally before insertion, and each root/child walk push reserves one entry. A popped work slot is released immediately according to the accepted logical-live-slot policy; the scalar visited total adds no mixed allocation charge. Reverse maps/sites/work are dropped before the final scratch release.
|
||||
- No allocated declaration/file adapter table or copied path vector was introduced. `Path::edges` remains used only by tests. Error transport remains outside successful retained storage, consistent with the existing witness policy.
|
||||
|
||||
The success-path peak expressions are: occurrence completion `R + H + (H + O) + E`; call validation `R + E + C`; syntax traversal `R + G + E + W`, in addition to the inherited baseline. These are source-derived formulas, not measured peaks. Earlier prefixes cannot exceed the first expression under valid monotonic accumulation; alternative fixture peaks still need exact tests. Checked aggregate `Ledger::reserve` precedes all new allocation growth; normal reserve failures return immediately and consume/drop the whole witness, so no stale lease or partial success can escape.
|
||||
|
||||
## Destruction and remaining gates
|
||||
|
||||
Persistent Path comparison/debug/drop remain iterative; final Arc ownership peels parents without recursive Step destruction. New verifier traversal is iterative and retains the inherited frame check. Syntax/Project destruction remains on existing lifecycle policy; runtime success and late-rejection small-stack checks are required, not established by this source review. No parse-byte/token/entry/reference or Exact-work charging calls were added to the mixed index path, and complete admission is not repeated; frame checking may update deepest-frame usage as permitted.
|
||||
|
||||
All three concrete findings are repaired by source inspection at the final production hashes above. No remaining blocking source finding was identified for this bounded implementation. Compilation, runtime and oracle acceptance remain unverified by this reviewer. Required full numeric authored oracles, qualified repeated/reordered calls, all intended corruption controls, exact aggregate cap/cap-minus-one tests, provenance/metadata checks, small-stack execution, inherited typed-only index/update/export compatibility, strict core Clippy, and inherited full-library disposition remain parent acceptance gates. This read-only private index is a prerequisite for complete original-coordinate mixed editing; it does not implement ordinary occurrence indexing, public source8, or the user's full editing/UI parity objective.
|
||||
@@ -0,0 +1,203 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Mixed typed-index seam: independent source/design critic
|
||||
|
||||
2026-09-24. Source-only review of clean private source `aaec78fcc9b273d1485497126392afdd1fb2e54e`; source paths below are relative to `crates/oa-core/src/`. Read root mixed-Project contract section 7, original-span proposal and accepted review, and parent's draft `harness/analysis-mixed-index-contract-20260924.md`. The reviewer performed no compiler, source/build/Gitea mutation, or runtime check. Parent subsequently verified and resolved the findings and adopted the revised [contract](analysis-mixed-index-contract-20260924.md). Initial findings and final disposition are preserved below. Prerelease #37 is unaffected.
|
||||
|
||||
## Assessment and two precise draft refinements
|
||||
|
||||
The consumed wrapper plus shared private verifier is the smallest sound next slice. It preserves original complete-bundle authority without claiming an ordinary occurrence index or enabling editing. Separate mixed verifier duplication offers no demonstrated benefit over narrow borrowed-input extraction. Parent's draft is implementable after settling these two points explicitly:
|
||||
|
||||
1. **Set accounting dimensions in the contract, not during implementation.** Existing mixed-Project contract section 3 assigns map/vector/work entries and expression sites to entry slots; occurrence slots cover lowerer occurrence records. Consequently every new index-map entry, including an occurrence-map entry, charges `entry_slots`; retained `lower::Occurrence` records keep their existing `occurrence_slots`. Owned copied names charge text bytes separately. Parent draft lines 115–119 currently leave this choice open. Applying the old `Index::insert` local `lowering_occurrences(map.len())` check would not satisfy that inherited aggregate policy (`analysis_source/index.rs:643`).
|
||||
2. **Separate runtime damage checks from completeness by sealed origin.** Parent draft lines 138–144 list missing/extra occurrences among corruption controls. The existing verifier does not independently enumerate all expected syntax references: its own module header states that occurrence completeness trusts the lowerer (`index.rs:1–5`). `check_syntax_edges` only traverses expression structure (`:478–632`). Deleting an isolated parameter-declaration occurrence or a non-expression type reference can leave all runtime checks satisfied. Do not promise arbitrary omission rejection without adding a separate reviewed reference-syntax verifier. For this minimal slice, retain sealed parse/lower completeness, use hand-enumerated full occurrence output as the independent oracle, and restrict mandatory runtime omission rejection to checks actually present (missing expression, missing call label for an existing argument child). This is not a reason to widen scope or expose fabrication APIs.
|
||||
|
||||
## Concrete ownership/API candidate
|
||||
|
||||
A private constructor consumes `ResolvedMixedProject<'s>` and returns `IndexedMixedProject<'s> { resolved, data }`. `resolved` owns the unchanged accepted Project, syntax, warnings, admission metadata, raw sites and Ledger (`mixed/project.rs:16–32`, `:535–543`). `data` owns names and the typed expression/occurrence maps. Read-only methods return views borrowing the wrapper; a view may expose canonical file/path/source lookup and qualified keys, but no mutable fields, raw-site constructor or old `Index` conversion. No extra lifetime is needed for self-references because `data` owns its copied name Strings and keys rather than borrowing fields of `resolved`.
|
||||
|
||||
During construction, narrowly split borrows of retained immutable syntax/project/sites, mutable Budget (for the existing depth check), and mutable Ledger. These borrows exist only inside the builder and end before returning the owner. The retained `SourceBundle` borrow outlives the wrapper and prevents safe mutation while it is live; identical lifetimes alone are not provenance, so neither source nor file table is a separately supplied parameter. Keep the constructor in the witness's module boundary or expose only a constructor-authenticated private view to the shared verifier.
|
||||
|
||||
Do not reconstruct `BTreeMap<usize, String>` from mixed files. `ParsedMixedSyntax.files` already fixes canonical ordering, original source strings and tokens (`mixed.rs:36–58`, `:370–376`). A borrowed file lookup can return `(original_source, token_slice)` for either existing typed-only inputs or the mixed file table. Typed declaration iteration should yield `(file_key, &Declaration)` over retained vectors; site inputs are borrowed expression/occurrence slices. Avoid allocating cloned `Unit` declarations, relexing, rebuilding Lowered model maps, rerunning admission or generating replacement source.
|
||||
|
||||
The old nominal `Index<'s>` remains the only input to `Plan` and `Composition` (`update.rs:15–27`, `:238–245`). A shared private `IndexData`/verification implementation does not justify a generic update trait, `Deref<Index>`, `AsRef<Index>`, or a public adapter. Keep the old `sources: &BTreeMap<usize, String>` authority in its wrapper (`index.rs:122–128`) and preserve typed-only checks/semantics. Mixed-only aggregate reservations must not be accidentally imposed on legacy tests via an unreviewed policy change.
|
||||
|
||||
## Reuse boundary and scope
|
||||
|
||||
Reuse structural key/path semantics (`index.rs:15–120`), owner/physical-token checks (`:246–283`, `:635–675`), expression-parent/path construction (`:288–359`), qualified roles and call-label checks (`:360–472`), and original-syntax expression-edge verification (`:478–632`). Extract these algorithms with small private input/storage adapters, rather than introduce a public generic indexing framework.
|
||||
|
||||
Replace the current name-construction assumption only for mixed input. It currently enumerates ordinary identities and then separate Lowered definitions/elements (`index.rs:209–241`); mixed resolution already moved those models into the complete Project (`mixed/project.rs:439–459`). Iterate every complete Project global once, then scoped parameters once. Global categories include Project, definitions, elements, relations, diagrams and placements, artifacts, and traces (`model.rs:1763–1783`). A streaming borrowed walk avoids `Project::identities()`'s temporary Vec; otherwise reserve that Vec before calling it. Names include ordinary globals for resolution/namespace purposes, but indexed declarations/references remain typed-owned. Ordinary references to typed targets are preserved in syntax/model but not supplied by this view.
|
||||
|
||||
A separate mixed-index implementation would duplicate roughly the whole path/call/syntax-edge verifier and its damage tests; later fixes could diverge. Reconsider only if extraction exposes an actual incompatible invariant, rather than because mixed fields require private access. The distinct wrappers already express the genuine provenance difference.
|
||||
|
||||
## Aggregate storage inventory and release points
|
||||
|
||||
Continue `Ledger::reserve`'s checked totals and inherited Budget (`mixed/project/accounting.rs:43–70`), including retained syntax, warnings, expression sites and occurrences. Never start from zero. One consumed owner prevents repeated retained indexes using one accounting baseline.
|
||||
|
||||
For a successful simple implementation let G be complete global-plus-scoped name count, H typed headers, O retained lower occurrences, E expression sites, P nonroot expression sites, and C calls. The added retained logical storage is **entry slots = G + (H + O) + E + P; occurrence slots = 0; owned text = sum of the copied names' UTF-8 lengths**. The existing baseline already contains E raw-site entry slots and O raw-occurrence slots. P counts each allocated shared Path Step once; Arc clones do not allocate another Step but their map/vector records still count. This formula assumes exactly the current three maps and one Step per nonroot expression; any added representation must be listed separately.
|
||||
|
||||
Scratch must additionally reserve before growth:
|
||||
|
||||
- typed 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; iterative syntax work slots W;
|
||||
- any allocated file/declaration view table, error mapping retained in success, or identity-visitor scratch.
|
||||
|
||||
Borrowed reverse-name strings cost no new text bytes. Work-pop releases its logical slot; this remains a logical live-element policy, not retained Vec capacity/RSS metering. Scalars such as `visited` are not a separately allocated entry per visited expression.
|
||||
|
||||
Explicitly drop/release owners and physical-set storage after occurrence validation, then paths/calls after argument-child validation and before syntax-edge work where possible. Otherwise all remain live and must be summed at that peak. Retained Path Steps remain charged even after dropping the temporary path vector, because expression/occurrence maps share them. Failure drops the entire consumed owner; no partial reusable success or stale reservation lease escapes. Preserve iterative Path destruction (`index.rs:68–79`). `Path::edges` allocates a Vec (`:82–90`) and currently has test-only call sites; do not turn it into a new unmetered production materialization API.
|
||||
|
||||
## Discriminating acceptance cases
|
||||
|
||||
1. Independently enumerate complete names and all typed key/location/spelling tuples in OA and SA mixed files with Unicode/CRLF, ordinary prefixes and coincident offsets across canonical paths. Compare every tuple and original whole bundle, Project, warnings and admission metadata; do not generate expectations by the builder/lowerer. Include a parameter UUID equal to a global and reused in two calculations.
|
||||
2. Reordered repeated calls must retain distinct parent paths, correct callee-scoped labels and original argument order. Corrupt a label to an existing other callee with the same parameter UUID/spelling so token/catalog checks cannot mask the intended call-site rejection (`index.rs:426–469`).
|
||||
3. Runtime negatives: missing/extra expression; forward/cyclic parent; cross-file/owner/field location; internally consistent but syntax-wrong child edge; duplicate physical token or qualified occurrence; non-Word/partial/UTF-8-split token; missing call label with an argument child. Record which exact check rejects. For arbitrary reference omission, the full authored oracle must fail; do not label this builder rejection unless new syntax completeness logic exists.
|
||||
4. Hand-count a retained baseline plus the formula above and peak scratch: exact cap succeeds, cap minus one fails at the intended reservation before growth. Separate copied-name-byte pressure and overlapping temporary maps. A case where old baseline and new maps each fit alone but their sum does not catches ledger reset; retain both raw and indexed representations throughout. No parse byte/token/entry/reference or Exact-work recharge is permitted; inspect control flow as well as counters. The existing `Budget::frame` may update deepest-frame usage while checking depth (`budget.rs:118–121`); this is not another parse.
|
||||
5. Type/API inspection must establish no old-updater-compatible conversion and no replaceable bundle/table/profile inputs; wrong-session composition is a later compositor negative, not an invented runtime API in this read-only slice. Test original provenance through views and success/late-failure cleanup on the existing small-stack harness. Re-run legacy Index/update/export oracles after extraction.
|
||||
|
||||
## Dependencies deliberately still open
|
||||
|
||||
This slice neither authenticates a complete ordinary occurrence set nor authorizes rename emission. Subsequent work must derive both edit producers and complete rename intent from the same witness/target; define the precise supported ordinary diff/compound-edit normalization; aggregate and validate original-coordinate edits; emit once; recompile/admit the actual complete result; compare the whole independently intended Project; and preserve atomic history/save behavior. Full parity still requires typed subtree and parameter edits, repaired deletion/reidentity, file movement/ownership, missing-ID stabilization/reindexing, migration/public dispatch, and editor/root reconciliation. These remain delivery requirements, not reasons to expand this next read-only dependency.
|
||||
|
||||
## Revised parent draft disposition
|
||||
|
||||
Re-read the updated contract's live-storage and evaluator clauses after parent revision. Both requested refinements are now explicit: new map/vector/set/Path storage uses entry slots while retained lower occurrences keep occurrence slots, and runtime expression/token/call checks are separated from complete occurrence emission guaranteed by sealed lowering and independently enumerated output tests. Those changes resolve the two design ambiguities identified above. No remaining blocking source/design finding for this bounded implementation proposal. The concrete retained-storage formula and failure cases in this report are implementation guidance, not measured results or a final accepted decision. Parent retains adoption and gate authority.
|
||||
@@ -0,0 +1,91 @@
|
||||
# Next private mixed-parser slice
|
||||
|
||||
**Original proposal, subsequently narrowed by the [independent review](analysis-mixed-parser-review-20260923.md).** The parent accepted the private syntax-only direction with that review's corrections; implementation and runtime acceptance remain open. In particular, the review resolves the base to A and corrects this proposal's inference of ordinary grammar drift from whole-file statistics. The following inspection is retained as its original reasoning, not a public source8 claim.
|
||||
|
||||
Read-only inspection, 2026-09-23. Private source pin A=`10d7f3340d5cd61a656dc0bcf7c143f8897c5551`; current ordinary/public pin R=`195ddbbba5b352af09bca385a6c3e4dd1c77f8c8`. Both pins checked before and after inspection. No compiler, source edits, GUI or Gitea operations. Parent reports A passed Windows 173 listing/65 typed/strict; those gates do not exercise mixed parsing.
|
||||
|
||||
Read the published `harness/analysis-original-span-proposal-20260922.md` and `harness/analysis-original-span-review-20260923.md` at R, plus A's `harness/analysis-source8-20260913/analysis-source8-repair-design-r2-20260913.md`, especially “Source pipeline and exact editing” and the resource/older-version contracts. This note narrows their next parser dependency; it does not replace them.
|
||||
|
||||
## Recommendation and exact deliverable
|
||||
|
||||
Implement **one private complete-bundle syntax parse**, producing an opaque `ParsedMixedSyntax` witness. It retains ordinary unresolved syntax and ordinary edit positions alongside typed unresolved declarations, from one significant-token stream per original file and one inherited budget for the complete pass. Start with explicit stable IDs only, source8 entry, existing ordinary grammar, all existing typed declaration grammar, and normal include/path rules. It returns no Project, Index, rename authority, output text or installed document. A complete semantic/session witness is a dependent slice, not an alternative name for this syntax result.
|
||||
|
||||
This resolves actual mixed-file dispatch, full-file coordinates, lexical ownership, aggregate scanning and same-parse ordinary edit provenance before undertaking cross-domain lowering or production composition. Root public dispatch remains closed; a private constructor selects source8 policy before scanning and verifies that the actual entry says 8. No schema constant, public parser acceptance, save route or model change belongs in this patch.
|
||||
|
||||
## Existing source seams
|
||||
|
||||
Paths below are repository-relative; line numbers belong to their indicated pin.
|
||||
|
||||
| Existing site | Consequence for the slice |
|
||||
| --- | --- |
|
||||
| R `language.rs:1066` `parse_unit`; `:1272` Parser; `:1489` unit | `strict_tokens` owns a separate token Vec; unit mixes entry/header/includes, iterative ordinary declaration nesting and fields. Add a private mixed entry through factored grammar operations, retaining the iterative declaration-owner stack. Public versions currently stop at 7. A has the corresponding unit at `:1332`. |
|
||||
| R `language.rs:1155–1270` `edit_declarations`/`edit_positions` | `edit_declarations` reparses and `edit_positions` rescans, derives delimiter ends and assumes token shapes. A mixed caller cannot invoke these helpers on the original mixed file. Factor a positions projection over the already parsed ordinary AST and retained token/span metadata. Keep the legacy wrappers' observable behavior. |
|
||||
| R `language.rs:1392` ordinary `value_inner` | Ordinary numbers remain finite JSON values; they are not Exact. Raw `-` + number must be consumed as one ordinary signed value with its complete span; typed `1-2` is subtraction. Preserve ordinary rejects such as `+1`, `1e`, `1_0`, `0x1` and nonfinite JSON numbers. |
|
||||
| A `language/raw_tokens.rs` Scanner and legacy adapter; `analysis_source/lex.rs:23` tokens | Scanner already preserves raw full-buffer spans and separates typed operators. Legacy adaptation greedily groups adjacent numeric parts and performs JSON classification. Do not use that whole-file legacy adapter for mixed source; typed lex currently charges bytes/raw tokens, including trivia, before retaining significant tokens. |
|
||||
| A `analysis_source/cursor.rs:5` Cursor; `declarations.rs:243` parse | Typed parse already consumes a borrowed significant cursor, checks inherited version=8, rejects lexical owners, and returns unresolved full-buffer declaration/field/reference/literal spans. This is the useful dispatch seam; `analysis_source::parse` is an expression-only whole-input wrapper. |
|
||||
| R `source_project.rs:303–605` compile_once | Existing iterative include visitor owns path normalization, cycle/depth/edge/visited checks, aggregate ordinary counts, unreachable-file rejection and located errors. Reuse/factor its traversal policy for private syntax collection; do not call compile_once and discard its model. Its `:429` parse_unit call is the later production substitution point. |
|
||||
| A `analysis_source/index.rs:147–195` parse/build | Current parse scans typed-only numeric-keyed files and accepts a separately supplied ordinary Project. Calling it on mixed buffers fails; calling it on extracted typed text invents provenance. Keep build private. This slice does not manufacture an Index. |
|
||||
| A `analysis_source/lower.rs:269` lower | Accepts ordinary skeleton plus all typed units; collects all typed globals/signatures before bodies; deliberately does not admit the skeleton. Needed in the next semantic slice after the shared syntax witness exists. |
|
||||
| R `source_project.rs:895`, `:918`, `:984`, `:1050–1071` update path | Actual-file ordinary edit ASTs, formatted comparison ASTs and local project-header spans have different roles. Later production editing uses retained actual-file positions; retain CompleteForEdit/Compact formatting and their comparison semantics. Scalar application, structural second pass and full candidate equality remain outside this parser patch. |
|
||||
|
||||
R and A's ordinary files are materially different (427 insertions/81 deletions across language.rs/source_project.rs in the inspected comparison). R also contains current CompleteForEdit/Compact work. Do not copy A's whole language/source_project files over R or overwrite the parent's Scenario integration. Pin the combined implementation base and agree ownership of the shared grammar hooks before coding.
|
||||
|
||||
## Minimal private interfaces and ownership
|
||||
|
||||
Names are illustrative, not a request for a public framework:
|
||||
|
||||
```rust
|
||||
parse_mixed_syntax(bundle: &SourceBundle, limits: ProjectLimits,
|
||||
test_profile: /* optional tighter private profile */)
|
||||
-> Result<ParsedMixedSyntax<'_>, Vec<SourceDiagnostic>>;
|
||||
```
|
||||
|
||||
The result privately borrows the **actual complete SourceBundle**, owns the one finished Budget, canonical file table, parsed units and retained significant tokens/ordinary position metadata. It retains entry, every canonical path and original bytes through that borrow. File keys are minted once from canonical bundle keys before traversal; the include visitor visits each reachable file once. A FileKey is meaningful only through its owning result, never an independently accepted `(usize, path)` mapping. Store paths/source references into the borrowed bundle rather than a self-referential owned Index-plus-source-map structure. Constructors are private; expose read-only inspection only. This establishes syntax provenance, not semantic validity or mutable-current freshness.
|
||||
|
||||
Each file result contains its source reference, entry/fragment role, include spans, ordinary declarations with lexical owners, typed declarations, and ordinary edit positions. Positions remain half-open **full original file UTF-8 byte offsets**, even after Unicode comments, the project header, includes or preceding declarations. No header/include offset is added to typed spans. Nested ordinary declaration spans legitimately contain descendant declarations; declaration ranges are descriptive ownership, not automatically disjoint replacement authority.
|
||||
|
||||
Use one shared significant-token cursor state. Ordinary grammar methods may have a domain-specific borrowed view; they must advance the same token position used by typed `declarations::parse`, without copying/rescanning a declaration or replaying a speculative parse. Preserve legacy grammar through factoring, not by cloning a second independently maintained ordinary parser. Keep token access/classification adapters small and local; no general parser trait framework is required.
|
||||
|
||||
At document scope, dispatch exact typed declaration words before generic ordinary `declaration_kind`. Inside an ordinary element's open body, recognize a typed header only to deliver the existing “must be roots” error; do not reinterpret it as an ordinary field. Contextual words such as `unit`/`calculation` must remain legal aliases where already allowed. Entry descriptions/includes keep current placement rules. Generic derived long analysis kind names must not become an alternative accepted syntax.
|
||||
|
||||
For ordinary edit positions, a raw numeric value may cover several significant tokens (`-12.5`). The current token-end heuristic would cover only `-`. Record ordinary value end spans as grammar consumes values (a small per-file side table keyed by the existing AST start offset is sufficient), then project EditValue from that AST plus spans. Keep the shared legacy/migration Ast representation unless a demonstrated need justifies changing it. Record ordinary header token roles from actual parsing as well; do not obtain them with another `edit_header` scan. Typed declaration spans/expressions never enter ordinary EditKind::Record recursion.
|
||||
|
||||
**Stable-ID scope:** reject omitted project, ordinary global, typed global or parameter IDs in this first private entry before returning a witness. The ordinary `optional_id` path currently creates UUIDs, so the private mode must reject before that generation; typed IdentitySyntax already retains missing identity/insertion information. This intentionally postpones stabilization instead of assigning hidden IDs or granting edits against pre-insertion offsets. Later accept missing IDs only through bounded insertion into the returned full documents and a new complete parse of those actual bytes.
|
||||
|
||||
## Budget and parser invariants
|
||||
|
||||
Create one Budget at the private complete-parse boundary from source8 hard ceilings intersected with caller restrictions and any tighter test profile. Own it in the returned witness; lower/index/compose later obtain it from that witness, with no ambient replacement/reset API. Creating a Budget for each include or switching token policy after seeing local fragment syntax is invalid. Selecting explicit private source8 mode before lexing avoids a public version-probe implementation in this slice; eventual public dispatch needs a bounded header read with unambiguous accounting.
|
||||
|
||||
Precheck aggregate file/UTF-8 byte size before broad token/String allocations. Charge each file's original bytes once in scanning; a prior noncharging aggregate limit check is not another charge. Charge every raw token including trivia once, before storing; significant filtering and ordinary legacy-compatible numeric consumption do not recharge tokens. EOF carries no token charge. Do not scan or convert typed exact atoms again to derive positions. JSON ordinary values keep their finite numeric domain, and exact numeric WorkMeter use belongs only to typed numeric consumption.
|
||||
|
||||
The mixed parser must also bound ordinary temporary containers/references before allocation; existing per-unit graph counts and final `check_model` alone are insufficient. Specify the charge table in the patch: ordinary declaration/field/value/list-entry allocations join the private syntax-storage ceiling; retain caller graph/record accounting separately; ordinary reference storage is bounded before copying, while caller ordered-step/reference semantics remain explicit rather than silently relabeling every scalar reference a model step. Typed existing entry/reference charges stay intact. Count aggregate phase metadata (file table, positions, catalogs later) before reserving; the existing typed budget phase checks are reusable but do not magically bound ordinary additions. Preserve ordinary value-depth64 and separate typed frame256/logical-depth128 semantics and safe failure cleanup. Tests must discriminate which bound fails.
|
||||
|
||||
## What this does not yet solve
|
||||
|
||||
The dependent **ResolvedMixedBundle** must consume this syntax witness, collect one global alias/identity/category catalog including typed declarations, build the ordinary skeleton against it without premature complete-model admission, lower typed units once, merge them, admit the whole Project, and construct Index internally from the same tokens/units/lowerer result. Only that result can bind complete Project, Index, file table, original bundle and inherited Budget for composition. Current A Index borrows `BTreeMap<usize,String>`; adapting its private source accessor to witness-owned file references is justified there. Exposing `build(Lowered, spans)` to arbitrary callers is not.
|
||||
|
||||
R `language::resolve_declarations` combines ordinary construction, version migration and final limits; A additionally migrates source7 through `migrate_v7`. Neither is an appropriate “parse ordinary and admit first” shortcut: forward ordinary references may target typed records, and typed subjects/types/calls may target later files. The semantic slice needs a narrowly extracted non-admitting ordinary construction step, complete catalog, and one final model admission. Syntax witness tests cannot prove these relationships or satisfy intended-Project equality.
|
||||
|
||||
Coordinated version7→8 blockers for production are: reconcile root schema7 with private schema8 definitions/analysis and Scenario payload; preserve frozen older DTO/source gates and the source3 old-envelope boundary; choose the one public dispatch/migration change; stabilize missing global/parameter IDs and reindex actual returned bytes; retain required categories and ordinary complete/compact edit behavior; supply complete mixed lowering/index provenance and supported-edit diff gate; compose original edits once and recompile/admit/compare the entire actual output; pass migration/history/checked-save and resource calibration gates. None requires a new metamodel or blocks this private explicit-ID syntax slice. Root should coordinate them, not accept `arcadia 8` early to make a fixture pass.
|
||||
|
||||
## Rejected shortcuts and cost comparison
|
||||
|
||||
| Approach | Decision |
|
||||
| --- | --- |
|
||||
| Shared scanner/cursor + existing grammar extraction + same-parse ordinary positions | Recommended: moderate localized factoring; directly tests mixed boundaries and retains ownership. Limit deliverable to syntax until semantic construction is ready. |
|
||||
| Parse ordinary and typed projections independently, then combine models/indexes | Reject: masking preserves numeric offsets at best but loses actual-source token/ownership proof; substring/concatenation creates local offsets; separate parses reset or double-charge resources and cannot establish cross-domain global resolution. A clever remap does not repair these invariants. |
|
||||
|
||||
Also reject whole-file legacy tokenization (typed punctuation fails/typed number domain changes), silent retries with larger budgets, counter subtraction after rescanning, caller-supplied numeric file remapping, and treating equal bytes/shared lifetimes as proof of the same semantic parse. A full replacement edit AST is unnecessary for this step.
|
||||
|
||||
## Six observable first-slice fixtures
|
||||
|
||||
All are proposed, unrun. Use independently authored source literals and expected span/substring tables rather than expectations extracted from the result itself.
|
||||
|
||||
1. **Interleaved CRLF/Unicode:** entry description/comment, ordinary nested element, typed calculation with `1-2` and `1e-2`, ordinary record with negative coordinates after it. Verify exact original substring at every selected ordinary/typed/header/value span, lexical owners, and byte-identical complete input. Explicit `-12.5` ordinary span must include the minus and full atom. No output Project claim.
|
||||
2. **Complete include binding:** root + nested-path module + shared dependency reached twice; mixed declarations after include prefixes in two files with identical local offsets/spellings. Check unique scan count, fixed FileKey/path mapping, exact include spans; cycle, missing, escaping and unreachable-file negatives return no complete witness. Entry/path/map replacement is not an accepted constructor operation.
|
||||
3. **Dispatch and grammar separation:** `unit`/`calculation` used as allowed ordinary aliases, all short typed declaration kinds, typed roots between nested ordinary blocks. Reject typed lexical nesting, long derived analysis names, fragment version headers and source7 at this private source8 entry. Existing public source3–7 and public source8 rejection remain unchanged.
|
||||
4. **Number/position compatibility:** ordinary signed/exponent JSON values and typed exact ratio/scientific expressions, with comments between legal typed tokens. Ordinary `+1`, split-sign forms not admitted by the old grammar, malformed/nonfinite JSON values reject. Typed values beyond JSON precision retain exact values/literal spans. Existing ordinary token compatibility tests plus independently stated old outcomes prevent broadening by accident.
|
||||
5. **Aggregate budget and failure cleanup:** one-file and split-file variants with exact byte/token/ordinary-storage/reference/numeric ceilings and plus-one failures; include trivia; add an earlier ordinary allocation so a later typed declaration crosses the shared ceiling, and reverse producer order. Previously latched failure returns no witness. Test-only scanner visitation/Exact conversion counters demonstrate one scan/one conversion; unchanged counters alone do not. Run retained 128-KiB typed depth/rejection cleanup controls when parser ownership changes warrant them.
|
||||
6. **Opaque syntax scope:** explicit-ID positive across all declaration/parameter kinds; remove one ID in each domain and require refusal with original bundle unchanged. Read-only ordinary EditValue and typed occurrence syntax inspect the same witness; no external AST/Lowered/FileKey-map constructor exists. Unresolved forward ordinary/typed references can be retained syntactically, but do not assert they resolve. A following semantic slice must add reordered cross-file forward references, repeated/reordered calls, reused parameter UUIDs, catalog collisions, wrong-session batch rejection and independent whole-Project equality.
|
||||
|
||||
First patch completion means these syntax/ownership/resource fixtures and unchanged ordinary compatibility tests pass on an immutable Windows source pin with fresh review. It does not mean mixed renames, source8 save, full S3/S4, public schema activation, or all semantic references work.
|
||||
@@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,90 @@
|
||||
# Private mixed Project contract
|
||||
|
||||
**Accepted design, 2026-09-23; implementation remains gated by syntax acceptance.** This document specifies required behavior and proposed acceptance oracles; it reports no pending gate or fixture as passed. Implementation facts refer to `a578ac98a06772a60bec00ae287e65650680d119`, paths under `crates/oa-core/src/`. The [independent review](reviews/mixed-project-contract-20260923.md) informed the retained-site and diagnostic-allocation requirements below.
|
||||
|
||||
This slice supplies an admitted private Project with retained original-source provenance, a dependency toward the [project goal](../PROJECT_GOAL.md). It extends the [mixed-parser ownership contract](../harness/analysis-mixed-parser-proposal-20260923.md#minimal-private-interfaces-and-ownership) and [review corrections](../harness/analysis-mixed-parser-review-20260923.md#corrections-and-acceptance-conditions), while preserving the [original-span namespace/resource/acceptance invariants](../harness/analysis-original-span-proposal-20260922.md#namespace-resource-and-acceptance-invariants) and [reviewed boundary separation](../harness/analysis-original-span-review-20260923.md#concrete-next-implementation-boundaries). It does not activate public source8 or deliver mixed editing.
|
||||
|
||||
## 1. Result, authority and order
|
||||
|
||||
Consume actual `ParsedMixedSyntax`. A successful opaque result owns the complete Project, mapped warnings, successful static admission limits/usage and retained syntax/lowering provenance. It retains the actual borrowed SourceBundle, exact entry, complete canonical paths and original bytes, canonical numeric-file-key table, exact ProjectLimits and the original Budget. No separately supplied Project, aliases, Lowered, tokens, file remap, replacement Budget or widened limits may establish authority. No mutable Project or edit constructor escapes this read-only boundary.
|
||||
|
||||
Required sequence: complete headers/signatures → ordinary construction once → typed body lowering once → checked disjoint moves into complete Project → retained model limits → one static/architectural admission route → accepted result. No rescanning, Exact conversion, ordinary decoder duplication, source emission/reparse, UUID invention, or migration/admission of a partial skeleton. Missing explicit IDs remain refused by syntax. Failure returns no usable partial witness.
|
||||
|
||||
Seed the entry Project first. Thereafter process canonical file order and original declaration-start order within each file, merging ordinary/typed header occurrences. Detect alias collision before ID collision when both apply, preserving both source owners. Validate complete catalog uniqueness before Project map insertion. Ordinary construction and typed lowering follow this order restricted to their respective declarations; normal validator order stays unchanged. Syntax/include traversal order is unchanged. This is a phase policy, not a promise of earliest physical error across phases.
|
||||
|
||||
Catalog categories include project, ordinary objects, neutral definitions and typed layer roots. Parameter identities/names remain scoped to their calculation; equal parameter UUIDs in different calculations or equal to a global UUID are permitted. Ordinary alias projection derives solely from this complete catalog. Preserve declaration occurrence→file mapping through ordinary conversion errors; UUID lookup cannot distinguish rejected duplicates.
|
||||
|
||||
## 2. Shared construction and retained-site handoff
|
||||
|
||||
Extract the existing `language.rs:1667 resolve_declarations` construction path, including deferred node attachment. Preserve **both Project and legacy_elements scratch** for the existing source3 tail. Existing source3–7 wrappers retain migrations, required fields, defaults, Scenario MixedLegacy fallback, lexical-parent conflict behavior and diagnostics. Public parser/version acceptance remains unchanged. Use borrowed declaration/unit views over retained per-file ASTs, rather than cloned flattened ASTs or a second ordinary decoder. Existing typed-only lower callers retain their wrapper behavior, including diagnostic precedence.
|
||||
|
||||
`lower.rs:113 Lowered` separates model maps from occurrence/expression vectors. Move its typed maps disjointly into Project once; do not retain another typed model. Move these three things into the sealed result **together and unchanged**:
|
||||
|
||||
- the one global `Lowered.expressions` arena shared across all files/declarations;
|
||||
- the paired occurrence vector, whose `expression` indices address that arena, and each expression's parent-index/Child edge;
|
||||
- the canonical numeric-file-key table referenced by both vectors and retained files.
|
||||
|
||||
Do not independently sort/compact vectors, join separately numbered per-file arenas or renumber files. Every owner, field, scoped target and original whole-file span retains its meaning. Preserve actual tokens, typed AST, ordinary ordered positions and lexical ownership beside the sites. Numeric arena positions remain private; they are not persistent IDs.
|
||||
|
||||
This retained handoff has not performed Index's physical-span, call-site or independent syntax-edge verification. A later typed Index must consume the sealed accepted result, derive names/scoped parameters from complete Project once, and verify original syntax/sites without lexing, lowering or admitting the Project again. Neither the existing numeric-map Index nor its updater is changed in this slice.
|
||||
|
||||
## 3. Resource contract
|
||||
|
||||
Keep cumulative parsed bytes/tokens/syntax entries/Exact work unchanged. Ordinary active references add once to the existing reference counter. Preserve caller graph/record/step/file/include limits; complete nested model records remain checked at final model admission. Static analysis work remains its existing separate meter.
|
||||
|
||||
A private auxiliary ledger tracks checked-add live totals `(entry_slots, occurrence_slots, owned_text_bytes)`. Before allocating or copying an in-scope representation, check the **aggregate of all live reservations** through the inherited Budget: `lowering_entries(total)`, `lowering_occurrences(total)` and `index_bytes(total)`. Overflow or any nonlatching check failure aborts. An allocation move transfers its reservation; copies coexist and both count. Release only when the represented ownership ends. Borrowed text costs zero copied bytes, but its container slots still count. Logical slots do not claim exact allocator capacity or heap/RSS metering.
|
||||
|
||||
Entry slots cover syntax/storage metadata, catalog/map/vector/work entries and expression sites. Occurrence slots cover lowerer occurrence records, using the existing entries-plus-reference ceiling. Each slot belongs to one domain. Owned text covers all separately owned in-scope String bytes, including copied keys, paths and retained diagnostic text. Original source bytes are borrowed and already cumulatively admitted; they are not recounted as copied auxiliary text. The auxiliary byte ceiling is distinct from cumulative source bytes.
|
||||
|
||||
| Representation / lifetime | Required reservation |
|
||||
| --- | --- |
|
||||
| Retained syntax, tokens, positions, file references and lexical ownership | Fixed all-file baseline: retain/reconstruct mixed metadata subtotal, plus parsed syntax-entry storage. Avoid counting tokens/positions twice. Existing dropped value-end-map subtotal may remain a conservative overestimate. Sum owned strings by a bounded walk of parsed structures, not a source rescan; counting scratch reserves before growth. Baseline stays live in accepted result. |
|
||||
| Complete catalog, ordinary alias projection, diagnostic location registry | Count every distinct map/set/container entry; reserve owned key copies before cloning. Borrow names where existing APIs permit. Projection drops after ordinary construction; catalog drops after lowering once retained locations no longer depend on it. |
|
||||
| Ordinary construction coordination | Borrowed ordered occurrence/file views and deferred-node vector reserve before growth. Nodes move into diagrams; coordination storage then drops. The active-reference hook below runs before field cloning. |
|
||||
| Typed lowering | Reserve lower occurrence/expression sites and Resolver work/temporary structures before growth across all files. Site vectors and their reservations remain in the accepted result; temporary work reservations end after use. Model maps move once. |
|
||||
| Diagnostic mapping and retention | Source mappings, output/retained diagnostic containers, related-location entries, transferred retained strings and newly copied strings share the still-live syntax/sites/locations reservations. Reserve before copy/insertion/retention. Compute line/Unicode column from borrowed file prefixes, or reserve any new cache explicitly. |
|
||||
|
||||
This is **auxiliary** accounting, not preallocation admission of every ordinary serde/model allocation. Existing architectural validation, its indexes and its produced raw `Vec<Issue>`/issue-owned strings are explicitly outside this preallocation ledger, as are the architecture/wire allocations excluded by the static meter. An optional cap checked after raw Issue production is only post-production checking. A raw Issue vector must not remain uncharged in the accepted witness: map/move its contents only after acquiring retained reservations, or drop it. Transferring a String avoids a copy but still requires its new retained reservation; copying requires an additional reservation before the copy. If mapped/retained storage cannot fit, return a resource failure, not a success with truncated warnings.
|
||||
|
||||
Retained caller max_records/max_graph_objects are enforced on complete Project before success. Deferred nested model checks are not described as preallocation checks. These exclusions must remain visible in code documentation and evidence; neither this ledger nor static events constitutes whole-resolution CPU/allocation metering.
|
||||
|
||||
## 4. Active ordinary reference reservation
|
||||
|
||||
Add a narrow private hook at the start of each ordinary declaration's construction iteration, **before** the existing `fields.iter().map(Ast::resolve).collect()` and any resulting JSON/model vectors. Borrow witnessed arrays selected by DeclKind and these exact existing body/tag paths:
|
||||
|
||||
| Declaration | Active ordered array |
|
||||
| --- | --- |
|
||||
| Process, FunctionalChain, Scenario element | top-level `steps` |
|
||||
| Occurrence element | `body` → externally tagged `Branch` object → `occurrences` |
|
||||
| ContextualLink relation | `source.references`, then `target.references` |
|
||||
|
||||
These selectors mirror `ParseLimits::check_model` and `ElementBody::steps`. In declaration/item order, charge each occurrence once through the retained `Budget.reference`, including repeated targets and UUID items as well as @references. Charge neither unique-target count nor separate per-file allowances. Locate refusal at the first unaffordable item in its original file; use stored extent or an explicit item-start/field fallback.
|
||||
|
||||
Absent/default-empty arrays cost zero. For malformed shapes, conservatively reserve recognizable active arrays and let existing conversion diagnose invalid shapes/items; do not add a decoder just for accounting. A private resource failure can precede malformed-item conversion. Existing public wrappers retain ordinary behavior through a no-op hook.
|
||||
|
||||
Exclude scalar parent/owner, endpoint occurrence, purpose fields, unrelated arrays named references, already charged typed fields and **all historical Trace baseline snapshots**. Baseline/model storage still participates in final model limits. The counter therefore equals parsed typed references plus active ordinary steps/contextual-chain items. Final check_model validates the complete model without charging that counter again.
|
||||
|
||||
## 5. One admission route, complete warnings and locations
|
||||
|
||||
After checked merge and complete model limits, use a narrow shared internal validator route, shared by mixed resolution and the existing `validation::validate` wrapper. Run `admit_structure_checked` once. On success, extract owned static limits/usage, drop the Project-borrowing environment, then run `validate_structure` once and preserve its complete raw warning/error result for mapping. On static failure preserve existing short-circuit behavior. Do not additionally call `analysis::admit`, which would repeat static/architecture work. Existing standalone admit/validate public behavior must remain compatible; no cached/self-borrowing environment enters the new witness.
|
||||
|
||||
Static limits use the existing declared profile and must be recorded with usage; they cannot silently replace or reset the syntax/model policies. A shared internal result carries successful static metadata and complete issues to mapping. Architectural Issue production has the exclusion in §3; subsequent mapped/retained allocation does not.
|
||||
|
||||
Retain every warning on successful acceptance. Any error refuses the witness. Locations cover ordinary and typed globals plus calculation-scoped parameters/fields, using actual canonical file ownership and full-file offsets. Preserve typed failure file keys and ordinary occurrence mapping. An unmapped semantic field falls back to its owning declaration explicitly. Never choose a file by coincident local byte offset, globalize ParameterId or fabricate a precise field span.
|
||||
|
||||
## 6. Discriminating acceptance oracles
|
||||
|
||||
All are requirements for authored fixtures and execution, not reported results. Expected models, spans, warning content and thresholds must be independently stated; formatting/lowering the tested input cannot generate its own oracle.
|
||||
|
||||
1. **Complete bidirectional model:** tiny OA and SA bundles with ordinary node→later typed property and typed subject→later ordinary work element. Compare entire independently built Project, including ordinary defaults, diagrams and definitions. Reordered presentation retains intended semantics and original source ownership.
|
||||
2. **Catalog and legacy boundaries:** interleaved ordinary/typed duplicate aliases and IDs, including simultaneous collision and entry-project collision, prove alias-first errors with both locations before insertion. Scoped parameter UUID/global reuse succeeds. Separately preserve source3 scratch migration, current required-field errors, lexical-parent conflict and omitted Scenario viewpoint behavior through unchanged public source3–7 wrappers.
|
||||
3. **Full retained-site oracle:** repeated calls with reversed argument-label order, two calculations sharing parameter UUID/name, nested child expressions and coincident local spans in distinct files. Hand-enumerate every `(file, owner, field, parent-edge/path, role, qualified target, original span)`. Resolve private arena positions to these authored structural identities; check every occurrence.expression targets the intended entry. Do not invoke Index or lower again. Include both directions of ordinary/typed references in whole-Project comparison. Model equality alone cannot satisfy this test.
|
||||
4. **Inherited and aggregate limits:** hand-count active ordinary lists/chains plus typed references; exact cap succeeds, cap-minus-one rejects before field cloning with the correct item/file. Repeat ordered occurrences and positive parent/baseline exclusions. Two simultaneously live catalog/projection producers each fit alone but exceed aggregate storage together. Different retained nested-record caps distinguish final admission on identical syntax without replacement limits. Parse/Exact counters remain unchanged; reference delta equals the independent active count.
|
||||
5. **Admission/diagnostic producer:** one exact warning-only complete model preserves that warning; one static failure and one architecture failure return no witness. A tight mapped-diagnostic storage cap fails while retained syntax/sites remain live, including copied path/text or transferred-string reservation. Instrument the narrow internal route or inspect its control flow to prove one static admission and one architecture pass on success; equal outputs alone do not prove this. Do not call raw Issue production preallocation-bounded.
|
||||
6. **Provenance and cleanup:** complete entry/file/path ownership, Unicode/CRLF coordinates, unchanged global arena/file keys, no externally replaceable authorities and no partially usable failed result. Run relevant existing typed-only lower/export, public parser/traversal and small-stack success/rejection/drop controls after shared-code changes. No source8/editing success is inferred from these controls.
|
||||
|
||||
## 7. Deferred dependency and scope boundary
|
||||
|
||||
Next typed-Index work must account for names, owner/physical/path/call maps and syntax-edge verification tables against the retained ledger, use original SourceBundle/tokens through a private read-only view, and refuse/hide that view from the old numeric-map updater. It must derive names once from complete Project plus scoped parameters, rather than reusing both complete Project and former Lowered model maps. Ordinary occurrences are still not provided by a typed Index.
|
||||
|
||||
Public7→8 dispatch/migrations/admission, missing-ID stabilization, ordinary+typed composition against original bytes, output recompile/admission and intended-Project equality, history/checked-save, root Scenario/editor reconciliation and full graphical/textual parity remain coordinated later work. This checkpoint does not claim those capabilities or a complete occurrence index. Parent owns final scope acceptance, decision/publication and gate disposition.
|
||||
@@ -0,0 +1,3 @@
|
||||
*.md -text
|
||||
*.py -text
|
||||
*.json -text
|
||||
@@ -0,0 +1,50 @@
|
||||
# Independent carried-phase contract critique
|
||||
|
||||
2026-09-24. Source-only review of clean private source `18073a6f2eabce83fc83997f094e331eec835a16`. Reviewed initial draft SHA256 `085c0a23fa1a2e6835ba9beb72e83b17a49bdb8e7eb588c3bf36f2aa7c498264`, revised concrete seam SHA256 `ffe011589b904403cfd30bc5bb8c504259e8c7bbde51a1a14ea458c4b5ffdeb5`, and published domain audit SHA256 `a345d5d9c52c245cc1e7d43787612470a87e5aeaf673e4a7944a737b3066dc22`. No production changes, builds or application execution. Code references below are relative to `crates/oa-core/src/`.
|
||||
|
||||
## Recommendation and selected resolutions
|
||||
|
||||
Accept a **private phase-check prerequisite**, subject to the concrete guard/type review and real-path tests below. It can preserve inherited policy, carry an existing logical baseline and seed resolution without claiming admission before every parser allocation. Parent selected the two resolutions raised during review: preserve old entry timing through a shared parser body; make the new carried route enforce combined checks even at C=0. Bind the continuation to a retained owner/borrow guard and the actual source bundle. Production nonzero construction may remain absent until the emitter's owning transition is specified; this prerequisite need not implement that emitter.
|
||||
|
||||
This selection explicitly leaves the final execution contract's before-growth obligations open. It does not waive them or reinterpret every heap allocation as a logical ledger entry. Model/serde, raw validator heap, allocator capacity/RSS and native stack frames retain the published exclusions. New output buffers, path keys, entry strings and their logical map entries remain in scope when introduced.
|
||||
|
||||
The revised concrete `CarriedInput<'s>` / `RetainedSnapshot` proposal meets the minimal lifetime shape: input fixes the bundle, retained backing borrows the allocation-owning snapshot, and the input guard stays inside existing syntax through resolve/index. For this prerequisite parent selected **all new backing constructors cfg(test)** pending a genuine production transition. Borrowed C=0 policy capture from a still-live old witness is a policy/phase test, not proof that old B vanished. No production constructor should imply that false transition.
|
||||
|
||||
One acceptance correction remains to the reviewed revised draft: the minimal retained owner contains only a SourceBundle, so its exact C is `(F, 0, sum(source UTF-8 bytes) + sum(path-key UTF-8 bytes) + entry UTF-8 bytes)`. Count the entry string separately from its same-spelled map key. Do not add an arbitrary occurrence owner to satisfy draft §6.2: nonzero occurrence and unreachable-overflow coverage can be labeled arithmetic/fault-injection tests, not real positive owner provenance. Parent selected this narrower correction; production occurrence carry remains zero for the proposed owner.
|
||||
|
||||
## Consequential findings
|
||||
|
||||
1. **Zero carry is not automatically old parser compatibility.** Existing `mixed.rs:277–280,321–330` checks M alone; `project/accounting.rs:233–249` first checks U+M during resolution. Both scalars grow monotonically during parsing. A combined parser check can therefore reject an old syntax-only success with `max(U,M) <= cap < U+M`, although that syntax could never successfully resolve at the same cap. In a multi-file failure it can also preempt a later malformed unit/include diagnostic. Preserve the old wrapper's checks exactly; the distinct carried entry must not special-case zero C to bypass its combined policy. Both modes should share grammar, traversal and projection code. The unchanged full-success claim is justified by the old resolver's U+M admission, not by assuming parser-only diagnostic equivalence.
|
||||
|
||||
2. **A non-Clone scalar token is not an ownership proof.** Visibility prevents arbitrary callers manufacturing C; it does not keep represented allocations alive or prevent passing another bundle later. The chosen opaque guard should borrow/own the allocation-owning aggregate, fix its actual bundle reference, and survive inside the parsed witness and consequently its consuming resolved/indexed owner. Merely borrowing a scalar Slots/policy wrapper is insufficient. Parsing should not accept an independently replaceable bundle beside an already bound continuation. Constructors must establish owner/bundle/C identity; borrowing prevents mutation/drop while the witness lives. No self-reference is needed while the owner is external. Until a genuine output transition exists, cfg(test) construction from retained actual fixture storage proves accounting propagation only, not emitted-output provenance. This is a review condition on the concrete seam, not a request to implement future emission now.
|
||||
|
||||
3. **Phase-only language must be exact.** `mixed.rs:297–317` already lexes and builds the unit before the prospective M check; `:319` counts projection slots before `:329` checks them. Syntax text is traversed and admitted later in `project/accounting.rs:259–352`. Thus a successful carried parsed witness establishes the specified C+U+M boundary and admission of C's own text/occurrences; it does not establish C.text plus all newly retained syntax text until resolution. Project contract §3's broad before-allocation language is concretized by its retained-syntax bounded-walk row; parser proposal's temporary-container requirement also remains relevant. Adoption must state the limited prerequisite and unresolved stronger timing obligations explicitly, as the parent selected. No stronger guarantee follows from seeding a Ledger.
|
||||
|
||||
## Accounting and policy obligations
|
||||
|
||||
Keep C, snapshot Usage and noncharging phase checks distinct. At initial file admission check C.entries+M; at carried preprojection/completion check C.entries+U+M using checked arithmetic. Admit C's text and occurrence dimensions initially. Retain the existing token-count metadata component exactly once and the existing conservative dropped value-end subtotal. Raw token work and metadata slots are different dimensions, not a reason to charge two metadata components (`mixed.rs:39–58,321–330`).
|
||||
|
||||
`project.rs:438–442` currently creates a zero Ledger before `accounting::syntax`. Replace that seed only for the carried witness. Then the existing walk reserves U+M, syntax text T and its bounded work once; later phases continue the same ledger. Parser checks are not retained reservations. Do not first add U+M into C and then run the old syntax admission, or release C with temporary lowering scratch. With sufficient headroom, final retained slots must equal old resolved slots plus C componentwise.
|
||||
|
||||
Capture exact Limits values through a read-only internal seam, preserving all six fields, and exact ProjectLimits including model/file/include/depth policy (`budget.rs:7–23,36–70`; `source_project.rs:52–69`). Do not subtract C from Limits: bytes, entries and references also govern independent work events. New-snapshot Usage starts fresh legitimately; it must not replace/reset the consumed original witness's counters. All included files share one new Budget.
|
||||
|
||||
The same numeric byte ceiling governs source-byte work and logical owned text separately. Carried output text plus copied paths/entry and new syntax text can consequently refuse even when the emitted source byte total alone fits. That is an expected consequence of inherited policy, not evidence of double charging. Tests and later emission claims must not promise that every size-valid rename will admit.
|
||||
|
||||
## Minimal strong acceptance
|
||||
|
||||
- A real fixture with `max(U,M) <= cap < U+M` must distinguish legacy syntax success followed by resolution refusal from carried C=0 preprojection refusal. Include later-file failure precedence or explicitly pin the affected diagnostic policy. Ordinary old entry points retain existing outcomes.
|
||||
- A retained fixture owner with hand-counted nonzero entries/text and zero occurrences must traverse actual parsing/resolution. Compare whole Project, warnings, canonical files and fresh work/numeric Usage with zero carry; verify exact final +C retention and unchanged owner bytes. Source binding is established by the type/constructor and cannot be replaced by another equal-looking bundle argument. Nonzero occurrence arithmetic is a separately labeled fault-injection control.
|
||||
- Independently authored exact/cap-minus-one boundaries must distinguish initial C+file metadata, preprojection C+U+M, and a later resolver failure. Every claimed late case must clear actual predecessor phases. A syntax-boundary success is not automatically a resolved success.
|
||||
- A quoted/position-copy fixture must test C.text+T at the existing resolver walk and name that timing honestly. Preserve reserved counting scratch and retained-warning admission; no raw-validator preallocation claim.
|
||||
- Test exact tightened policy retention across all Limits fields and caller traversal/model restrictions, separate new-snapshot Usage, consumed failure with diagnostics only, and borrow/drop scope. Checked-add overflow tests unreachable under valid hard ceilings may be direct helper tests; do not mislabel them successful real-owner admissions.
|
||||
- Existing mixed syntax/project/index/rename regressions remain required. Preserve the 16 inherited full-suite failures, formatting failure and upstream environment-sensitive stack limitation. This slice makes no new small-stack guarantee.
|
||||
|
||||
The smallest materially different alternative is unconditional combined checks in all legacy callers. It removes one explicit mode but changes syntax-only failure timing; parent rejected that compatibility cost. Resolver-only seeding is smaller still but misses the chosen parser aggregate checkpoints. Per-producer reservation is a stronger separate increment; it is not needed to prove this deliberately narrower prerequisite.
|
||||
|
||||
Reviewed source SHA256: `mixed.rs` = `f83c1f04566b175bd83dedaabef4a541a1e0bc9a284308e7499885bad59ee414`; `mixed/project.rs` = `3f6aded6bff521d7991c491ded3001698874fc1a667951e91941669afa2aadd6`; `mixed/project/accounting.rs` = `3ee9ff1ecddae29b35062dff4738322c7941ded773d128c20d37eae2baaf30f6`; `budget.rs` = `53167c3be1744f16efcf4b927533eb243458816ee26b381037dd3bf846aba0dd`.
|
||||
|
||||
## Final selected contract readback
|
||||
|
||||
Reviewed `harness/analysis-carried-phase-contract-20260925.md`, final SHA256 `d17c28a8bb138063c8c5fbf3ed5850f3c1531047d217dffa7274e8d6339fb6b9`. **Accepted for bounded implementation; no remaining material design contradiction.** The selected text now fixes both constructors as fixture-only, ties actual retained bundle ownership to the guard, preserves legacy timing, requires combined checks on the explicit carried route even at C=0, and limits positive retained provenance to exactly F entries, zero occurrences and actual source/key/entry bytes. Nonzero occurrence and impossible-overflow controls are explicitly fault injection. Final wording scopes §4 to the carried route and exempts the labeled arithmetic controls from §6's real-path requirement.
|
||||
|
||||
Earlier findings above are retained as rationale and are resolved by these selected limits. Source/type implementation review and runtime gates remain pending; this acceptance does not approve emission, accepted rewritten output, a production consuming transition, or stronger parser before-growth guarantees. This critique is frozen against the final contract hash above.
|
||||
@@ -0,0 +1,111 @@
|
||||
# Carried storage domain audit
|
||||
|
||||
2026-09-24. Read-only inspection of private source `18073a6f2eabce83fc83997f094e331eec835a16` in `.local/as3batch`. This is a design audit, not an accepted contract or implemented carried parser. No source changes, Cargo, commits or Gitea actions. Parent owns scope and acceptance decisions. Code paths below are relative to `crates/oa-core/src/`.
|
||||
|
||||
## Finding and recommended boundary
|
||||
|
||||
Carry the **existing three-dimensional logical auxiliary metric**, not a newly inferred whole-heap metric. Preserve `(entry_slots, lower_occurrence_slots, owned_in_scope_text_bytes)` and the exact inherited policy. A successor must not hide emitted output behind a fresh zero-baseline parser/resolver ledger. Conversely, neither user editing requirements nor accepted contracts require accounting allocator capacity, every serde allocation, BigInt limbs, compiler stack frames, RSS or raw validator heap.
|
||||
|
||||
The narrow next dependency can introduce a private, constructor-controlled surviving baseline plus aggregate checks at the current parser and resolver phase boundaries. It must say precisely whether it preserves the existing **phase-check** guarantee or additionally strengthens selected parser producers to pre-growth reservation. Existing source does not establish preallocation accounting for every parser transient or retained syntax String. Therefore “all parser allocations already counted; just seed resolve” and “must instrument all heap allocation before proceeding” are both unsupported conclusions.
|
||||
|
||||
The smallest honest proposal has two distinct decisions:
|
||||
|
||||
1. Adopt carried ownership/aggregate **within the existing declared domain**, preserving the existing metric and explicit exclusions. Keep all current syntax/work counters separate from the carried live auxiliary baseline.
|
||||
2. If the execution contract requires aggregate refusal **before each counted parser representation grows**, add narrowly named hooks for those representations, or a proven conservative reservation before their production. This is an explicit temporal strengthening of current parser checks, not permission to broaden the domain to model/serde/validator heap. Do not claim it is already implemented.
|
||||
|
||||
## Authority and the actual user need
|
||||
|
||||
The user-owned application goal requires graphical/text/API editing parity and reliable persistence; it does not specify a physical heap meter. Accepted original-span/mixed contracts derive resource, provenance and failure invariants supporting that need. Their precise logical metric is an accepted engineering policy, not a paraphrase to silently replace with a larger or smaller one.
|
||||
|
||||
Relevant accepted documents:
|
||||
|
||||
- `harness/analysis-mixed-parser-proposal-20260923.md`, “Budget and parser invariants”: one complete-parse Budget; original bytes/raw tokens charged once; ordinary declaration/field/value/list storage bounded separately from final model records; aggregate metadata; no rescanning/reset. Its review §3 explicitly calls lowering/index functions noncharging phase checks and distinguishes syntax versus model counts.
|
||||
- `harness/analysis-mixed-project-contract-20260923.md` §3: checked aggregate live auxiliary triples, moves transfer reservations, copies coexist, borrowed text zero copied bytes, logical slots **not allocator capacity or heap/RSS**. Explicitly excludes ordinary serde/model allocation preadmission and architectural validator/raw Issue allocation. Retained mapped diagnostic data must become charged.
|
||||
- `harness/analysis-mixed-index-contract-20260924.md`, “Live storage and failure policy”: preserve previous domain; inventory the specific new maps/path/work structures; no raw model/validator/RSS claim.
|
||||
- `harness/analysis-ordinary-index-contract-20260924.md`, “Storage and depth”: retained increment `1+D+A`, scratch reverse globals/typed physical keys/live work, no new frame interpretation or recharging parse/Exact work.
|
||||
- `harness/analysis-mixed-rename-plan-contract-20260924.md`, “Storage and combined sizing” and “Mandatory successor”: two plan maps `R+M`, E equality scratch, output F map entries and owned bytes/path keys/entry, exact inherited per-snapshot policy and explicit old-owner transition; surviving output baseline participates in verification. It does not repeal prior heap exclusions.
|
||||
|
||||
The last document deliberately requires an aggregate surviving-storage boundary. A fresh parser/resolver pass independently fitting the same numeric cap is insufficient when output or old auxiliary state remains live. It does not require cumulative input+output parse-work counters: exact policy is reused for each deliberate snapshot, while each snapshot reports its own work Usage.
|
||||
|
||||
## Existing dimensions and scope
|
||||
|
||||
| Quantity | Actual meaning | Evidence |
|
||||
| --- | --- | --- |
|
||||
| `Budget::usage.bytes/tokens/entries/references` | Cumulative work/grammar counters for one snapshot; bytes once per scanned file, every raw token including discarded trivia, declared syntax entry events, typed/active ordinary references. Not live memory. | `analysis_source/budget.rs:6–14,27–35,84–125`; `lex.rs:19–45`; `mixed.rs:94–97`; `project.rs:403–434`. |
|
||||
| Exact numeric work / deepest frame | Separate measured numeric operations and maximum grammar depth. Neither is auxiliary slots nor heap bytes. | `budget.rs:127–141`; `syntax.rs:46,150,223`; typed/ordinary existing grammar policies. |
|
||||
| Auxiliary entries | Logical syntax metadata + syntax-entry baseline, catalogs/projections/locations, coordination, raw expression sites, charged maps/sets/vectors/path nodes and bounded work frontiers. | `mixed/project/accounting.rs:1–70,233–249`; `project.rs:437–543`; accepted contracts above. |
|
||||
| Auxiliary occurrences | Lowered occurrence records; budget ceiling entries+references. Later index/ordinary/edit maps are **entries**, not another occurrence charge. | `budget.rs:160–166`; `accounting.rs:94–103`; `project.rs:528–543`; index contract formula. |
|
||||
| Auxiliary text | Separately owned in-scope strings, paths, names and retained diagnostics; borrowed original source bytes not copied auxiliary text. Output becomes separately owned carried text for the next parse. | `accounting.rs:124–128,259–352`; `project.rs:593–627`; project contract §3; rename successor contract. |
|
||||
| Output complete byte limit | Sum of all final file bytes, including untouched files, checked under inherited source-byte policy. This is not itself a live-storage reservation. | `ordinary_index/rename.rs:267–308`; rename contract. |
|
||||
| Static/model admission | Separate caller record/graph/step limits and static work policy. Not relabeled auxiliary entries. | `project.rs:565–583`; `mixed.rs:228–234,98–118`; project contract §3/5. |
|
||||
|
||||
`Ledger::reserve` computes checked live+delta and checks all three ceilings before installing the new totals; release uses checked subtraction (`accounting.rs:6–70`). It counts logical entries rather than Rust object sizes. Vec spare capacity, BTree node layout and inline enum byte size do not add logical slots. Copying an in-scope String adds its length, not capacity; an Arc share adds its enclosing map entry but not another shared Path node.
|
||||
|
||||
### Explicit exclusions, not accounting defects
|
||||
|
||||
- Complete model maps/Expr/value payload allocations and ordinary serde conversion/model construction are outside preallocation auxiliary accounting (`accounting.rs:72–79`; project contract §3). Final model limits still apply.
|
||||
- Architectural validation indexes and produced raw `Vec<Issue>`/owned issue strings are excluded until mapping/retention. `project.rs:583–588` calls validation; thereafter reservations precede retained destination slot/path/text production. Never call raw validation preallocation bounded.
|
||||
- Exact numeric internals/BigInt limb allocation are controlled by their own numeric policy, not represented as auxiliary string bytes or slots. No accepted inventory assigns every arithmetic heap object a slot.
|
||||
- Allocator capacity/overhead/RSS and stack-frame bytes are not this metric. The observed environment-sensitive upstream small-stack parse limit must remain a separate empirical limitation; it is not repaired by a carried Ledger.
|
||||
- Transient failure diagnostics have the documented escape needed to report resource refusal (`project.rs:160–177`). They are not silently retained in a successful witness.
|
||||
|
||||
These exclusions do not excuse a new in-scope output buffer, map, copied path, planning list or retained diagnostic merely because some other allocation is excluded.
|
||||
|
||||
## Parser implementation: what is checked and when
|
||||
|
||||
`ParsedMixedSyntax` retains Budget, exact ProjectLimits, bundle borrow, canonical files and scalar metadata (`mixed.rs:39–58`). `parse_with_profile` creates one Budget and rejects any widening against caller-derived maximum (`:244–268`). The current checks are:
|
||||
|
||||
1. Complete input file bytes checked through `index_bytes`; file count initializes metadata and is checked before `Traversal::new` (`:269–284`). Scanning later cumulatively charges bytes and raw tokens (`lex.rs:19–45`). The precheck is not another work charge.
|
||||
2. Shared ordinary `State::entry` delegates grammar event charging (`mixed.rs:94–97`); typed declaration/expression parser uses the same Budget (`declarations.rs:261,290,473,539,608`; `syntax.rs:46,150,223`). Ordinary parser hooks charge its declared field/value/list/declaration events.
|
||||
3. After each unit parse, metadata adds retained significant tokens, value-end map count, projected ordinary-position slots and lexical-owner count, then checks before materializing the positions (`mixed.rs:319–340`). `ordinary_position_slots` uses seven conservative declaration/header slots, field slots and walked value/container slots (`:379–400`). Dropped value-end entries can remain conservatively represented in metadata.
|
||||
4. Only on resolving does `accounting::syntax` reserve `metadata + usage.entries` together, then walk retained structures to reserve their owned text and counting-work slots (`accounting.rs:233–352`). Resolver currently begins with `Ledger::default()` (`project.rs:437–442`). Catalog/lowering/index phases continue that ledger.
|
||||
|
||||
Consequences that must not be obscured:
|
||||
|
||||
- Existing parse checks syntax-entry usage and metadata separately; the full sum is checked by resolution. Adding a baseline only to `resolve` does not make the earlier parser checks aggregate.
|
||||
- Much retained syntax text exists before the bounded accounting walk reserves it. Typed name `.to_owned()` and quoted decoding are at `cursor.rs:67–95`; ordinary AST fields/names and position key/reference clones are other producers. Calling the later accounting walk “before all syntax String allocation” would be false.
|
||||
- There are actual parser temporaries not separately enumerated by the retained scalar metadata: traversal folded-path/visited/active/visit structures (`source_project/traversal.rs:9–16,59–87,97–180`), `ordinary_position_slots` counting Vec (`mixed.rs:382–396`), projection `ends` Vec and delimiter stack (`language.rs:1022–1030`). They have surrounding file/token/grammar/depth controls, but that is not a proved independent live Ledger reservation for every container.
|
||||
- The position projection clones field keys and reference strings (`language.rs:1048–1090`). Those retained copies **are** included by the later syntax text walk; this distinguishes delayed accounting of in-scope retained data from unproven universal transient accounting.
|
||||
|
||||
The parser proposal's general “bound temporary containers before allocation” wording is stronger than a claim that every temporary is independently represented in the current metric. The accepted Project contract concretizes the retained baseline and specific work accounting without asserting full parser heap enumeration. Parent should record any temporal/domain clarification explicitly rather than retroactively labeling every unenumerated traversal allocation either fully covered or forbidden.
|
||||
|
||||
## Smallest carried-baseline design proposal
|
||||
|
||||
Use a narrow private continuation carrying scalar `Slots` and exact `Limits`/ProjectLimits from a consumed owning transition. No caller-supplied reset, profile widening or arbitrary baseline fabrication. Existing ordinary entry points use zero carried slots and keep behavior. Do not add a generic allocator framework or alter model/public APIs.
|
||||
|
||||
For an execution successor, let O be the live output bundle's F entries plus UTF-8 strings, copied canonical key strings and entry path. Let B be old auxiliary storage while it remains live. Reserve output against B during emission. After the documented drop of old syntax/index/plan owner, carry O into verification; if old data is retained, carry B+O instead. Model/intent borrows retain their declared exclusion, not a second hidden auxiliary baseline.
|
||||
|
||||
For verification parser checks, maintain disjoint scalars:
|
||||
|
||||
- C = surviving carried entries/text/occurrences, never parse-work Usage;
|
||||
- U = current snapshot syntax-entry events;
|
||||
- M = established parser metadata subtotal (file references, significant tokens, value-end bookkeeping/position/lexical-owner slots, with documented conservative retained overcount);
|
||||
- T = current snapshot counted owned syntax text, at whichever producer/phase boundary the refined contract actually guarantees;
|
||||
- W = only explicitly inventoried auxiliary scratch reservations, not an invented “all runtime allocations” proxy.
|
||||
|
||||
Required aggregate checks are `C.entries + U + M + W.entries`, `C.text + T + W.text` and `C.occurrences + W.occurrences`. Checked arithmetic and inherited ceilings apply; new snapshot work counters still start at zero and are never used to debit C. Avoid charging significant tokens twice by treating token work and metadata storage as distinct counters, and avoid charging value-end conservative metadata twice when actual tables drop.
|
||||
|
||||
Narrow growth seams if parent selects pre-growth aggregate guarantees:
|
||||
|
||||
| Seam | Minimal responsibility / caution |
|
||||
| --- | --- |
|
||||
| New snapshot budget construction and grammar entry events | Preserve exact private Limits and ProjectLimits; carry C separately; entry-event checks include retained M and selected scratch. Existing numeric/byte/token work semantics unchanged. |
|
||||
| Lexer retained significant-token push and file metadata | Admit counted token/file slots against C+U+M before retained growth; raw trivia work remains separate and does not allocate a retained token. |
|
||||
| Mixed value-end insertion and lexical-owner push | Count newly owned logical records before growth or prove a conservative pre-reservation; release or retain documented overcount consistently. |
|
||||
| Position preprojection/count walk | Add C+U to the existing projection precheck; explicitly reserve any new counting scratch. If adding bounds for existing `ends`/delimiter scratch, state the new named logical reservation rather than claim it was previously exact. |
|
||||
| Counted syntax text producers | Either reserve exact decoded/copied bytes before the in-scope copy with a bounded decoder/count seam, or reserve a proven conservative whole phase bound. Raw-token spelling length is not automatically the exact decoded-string length; name/field/projection copies coexist and each counts. Do not reparse/convert Exact to estimate them. |
|
||||
| Resolve handoff | Replace the internal zero start with the carried ledger. Transfer/reconcile already reserved U/M/T once; do not run old `syntax()` admission as an additive double charge. Its bounded walk can verify counts and derive LowerStorage under the same carried baseline. |
|
||||
| Mapped warnings, final equality and output-owning result | Retain current diagnostic reservations; reserve verified E equality scratch against surviving storage; drop temporary syntax/model-borrowing environments at an explicit transition. Returning owned output is not returning a self-referential syntax witness. |
|
||||
|
||||
An incremental **phase-check-only** carried seam is smaller: add C to each existing parser phase check and syntax reconstruction, and seed resolver with C. It preserves the old timing limitations and must be named accordingly. It is not sufficient evidence for a newly promised before-every-growth parser invariant. If that stronger temporal invariant is essential for the imminent execution contract, implement the selected counted producer hooks before calling emission/re-admission accepted; this is a bounded prerequisite, not grounds for whole-model allocator interception.
|
||||
|
||||
## Acceptance and explicit decisions to revisit
|
||||
|
||||
1. Parent should name the exact retained/temporary syntax charge table and temporal guarantee. Are traversal/path and projection scratch to become newly enumerated auxiliary representations now, or do their current independent file/token/depth bounds remain an explicit limitation? Either answer needs a written scope decision; do not quietly infer an all-heap requirement.
|
||||
2. Does carried parsing promise aggregate before-growth on counted syntax Strings, or only at the established syntax-to-resolver phase? If the former, decoded string and projection-copy hooks are necessary; a fresh Ledger plus postparse recount cannot prove it.
|
||||
3. Preserve exact prior Limits, caller ProjectLimits and snapshot provenance without exposing arbitrary profile/baseline constructors. A dedicated new-snapshot continuation should report new Usage separately, not reset or subtract the original witness's counters.
|
||||
4. Test nonzero carried baselines at actual growth/phase boundaries, comparing exact cap/cap-minus-one through the real predecessor path; include output text plus copied path/entry bytes. Carry zero must preserve established behavior. Hand-count named containers, not allocator capacities.
|
||||
5. Test dropped-old-owner versus simultaneous-old-owner transitions, string moves/copies and no double charge; verify no failed output/admission result escapes. Include all-file sizing and complete actual-output model equality. Do not conflate planned size with accepted bytes.
|
||||
6. Keep legacy/model/raw-validator exclusions and existing stack limitations visible. Whole-RSS or full parser/model allocation containment would be a distinct future requirement with its own design, evidence and cost; it is not automatically the next smallest editing dependency.
|
||||
|
||||
No stronger guarantee is proven by this audit. The recommended decision is to carry the declared logical domain faithfully, strengthen only the named parser timing gaps needed by the successor, and document remaining exclusions and phase limits rather than alternate between zero-baseline acceptance and universal heap accounting.
|
||||
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"scope": "Literal lexical counts, not parser admission or allocation measurement.",
|
||||
"shapes": {
|
||||
"tiny": {
|
||||
"files": [
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 78,
|
||||
"significant_tokens": 10,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 2,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 78,
|
||||
"total_tokens": 10,
|
||||
"max_file_tokens": 10,
|
||||
"output_path_bytes": 24
|
||||
},
|
||||
"rich_oa": {
|
||||
"files": [
|
||||
{
|
||||
"file": "a.arcadia",
|
||||
"bytes": 213,
|
||||
"significant_tokens": 31,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
},
|
||||
{
|
||||
"file": "b.arcadia",
|
||||
"bytes": 213,
|
||||
"significant_tokens": 31,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
},
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 474,
|
||||
"significant_tokens": 93,
|
||||
"max_delimiter_depth": 4,
|
||||
"string_tokens": 11,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 900,
|
||||
"total_tokens": 155,
|
||||
"max_file_tokens": 93,
|
||||
"output_path_bytes": 42
|
||||
},
|
||||
"rich_sa": {
|
||||
"files": [
|
||||
{
|
||||
"file": "a.arcadia",
|
||||
"bytes": 213,
|
||||
"significant_tokens": 31,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
},
|
||||
{
|
||||
"file": "b.arcadia",
|
||||
"bytes": 213,
|
||||
"significant_tokens": 31,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
},
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 548,
|
||||
"significant_tokens": 103,
|
||||
"max_delimiter_depth": 4,
|
||||
"string_tokens": 13,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 974,
|
||||
"total_tokens": 165,
|
||||
"max_file_tokens": 103,
|
||||
"output_path_bytes": 42
|
||||
},
|
||||
"category_route64": {
|
||||
"files": [
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 3124,
|
||||
"significant_tokens": 914,
|
||||
"max_delimiter_depth": 10,
|
||||
"string_tokens": 39,
|
||||
"max_quoted_token_bytes": 49
|
||||
}
|
||||
],
|
||||
"total_bytes": 3124,
|
||||
"total_tokens": 914,
|
||||
"max_file_tokens": 914,
|
||||
"output_path_bytes": 24
|
||||
},
|
||||
"wide1024": {
|
||||
"files": [
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 3247,
|
||||
"significant_tokens": 2074,
|
||||
"max_delimiter_depth": 3,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 3247,
|
||||
"total_tokens": 2074,
|
||||
"max_file_tokens": 2074,
|
||||
"output_path_bytes": 24
|
||||
},
|
||||
"deep127": {
|
||||
"files": [
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 805,
|
||||
"significant_tokens": 404,
|
||||
"max_delimiter_depth": 129,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 805,
|
||||
"total_tokens": 404,
|
||||
"max_file_tokens": 404,
|
||||
"output_path_bytes": 24
|
||||
},
|
||||
"grouped127": {
|
||||
"files": [
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 430,
|
||||
"significant_tokens": 277,
|
||||
"max_delimiter_depth": 129,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
}
|
||||
],
|
||||
"total_bytes": 430,
|
||||
"total_tokens": 277,
|
||||
"max_file_tokens": 277,
|
||||
"output_path_bytes": 24
|
||||
},
|
||||
"include_paths": {
|
||||
"files": [
|
||||
{
|
||||
"file": "dir/left.arcadia",
|
||||
"bytes": 28,
|
||||
"significant_tokens": 3,
|
||||
"max_delimiter_depth": 0,
|
||||
"string_tokens": 1,
|
||||
"max_quoted_token_bytes": 19
|
||||
},
|
||||
{
|
||||
"file": "dir/right.arcadia",
|
||||
"bytes": 28,
|
||||
"significant_tokens": 3,
|
||||
"max_delimiter_depth": 0,
|
||||
"string_tokens": 1,
|
||||
"max_quoted_token_bytes": 19
|
||||
},
|
||||
{
|
||||
"file": "main.arcadia",
|
||||
"bytes": 134,
|
||||
"significant_tokens": 16,
|
||||
"max_delimiter_depth": 1,
|
||||
"string_tokens": 4,
|
||||
"max_quoted_token_bytes": 38
|
||||
},
|
||||
{
|
||||
"file": "shared.arcadia",
|
||||
"bytes": 10,
|
||||
"significant_tokens": 0,
|
||||
"max_delimiter_depth": 0,
|
||||
"string_tokens": 0,
|
||||
"max_quoted_token_bytes": 0
|
||||
}
|
||||
],
|
||||
"total_bytes": 200,
|
||||
"total_tokens": 22,
|
||||
"max_file_tokens": 16,
|
||||
"output_path_bytes": 71
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
# Exploratory critique: topology-preserving verification envelope
|
||||
|
||||
2026-09-24; source base `ee500908e3d77182ddd54e12524f9b6c6eb43b60` and reviewed private rename planner. Read-only investigation; no implementation or Cargo. Paths below begin at `crates/oa-core/src/`. This is not an accepted architecture or runtime cap result.
|
||||
|
||||
**Conclusion:** a parser-only conservative envelope is a viable alternative to intrusive parser accounting, provided actual emitted bytes are authenticated before relying on original topology, and the envelope explicitly covers transient copies. Neither original resolved B nor B plus the source-length delta is a demonstrated bound. Prefer a small independent envelope proof/count experiment before choosing parser instrumentation; do not yet ship a guessed multiplier.
|
||||
|
||||
## Topology argument and malformed output
|
||||
|
||||
`model.rs:1739–1746` allows only ASCII letter/underscore followed by ASCII alphanumeric/underscore names, excluding reserved spellings. This is exactly the raw Word alphabet (`language/raw_tokens.rs:61–70`). Replacing an entire authenticated Word with another such name preserves the token's class and its boundaries against unchanged surrounding bytes. It cannot create a quote, comment marker, delimiter, whitespace or numeric token. All syntax keywords, punctuation, literals and include strings remain untouched. The original typed/ordinary maps identify name grammar positions; final simultaneous namespace validation preserves qualified identities through swaps. Consequently token count, AST/position/expression topology, nesting and the include graph remain the same; byte offsets and stored name lengths change.
|
||||
|
||||
This reasoning applies to the **specified edit stream**, not arbitrary bytes produced by a buggy emitter. Before dropping the original owner, compare the actual complete output entry/path set and every file against the concatenation of original untouched slices and authorized replacement strings. Do this as a checked streaming comparison, with no second output buffer or re-lexing. Output must already have its F/content/path/entry reservations before construction. Reject a mismatch before parsing; keep the authenticated output privately owned and immutable through verification. A hash or a promise that the emitter is correct is not this guard. Without it, a malformed output could introduce arbitrarily different topology within the byte cap and invalidate an old-topology envelope before the parser refuses it.
|
||||
|
||||
Actual output parsing/resolution/whole-Project equality remain mandatory after this guard. The guard preserves non-name bytes; semantic equality alone cannot. Malformed-emitter controls would intentionally stop at the guard, whereas independent parser refusal tests exercise the parser separately.
|
||||
|
||||
## Concrete terms absent from a simple retained-B bound
|
||||
|
||||
| Carrier | Required contribution / source |
|
||||
| --- | --- |
|
||||
| Retained syntax and name text | Enumerate original syntax nodes/text and translate authenticated name lengths. Ordinary Reference spellings exist in **both** Ast and projected EditKind (`language.rs:1087`); a single source-byte delta undercounts their growth. |
|
||||
| Projection token ends and delimiters | `edit_positions_from_tokens` allocates `ends` with one slot per significant token and a delimiter stack (`language.rs:1023–1035`) while tokens/AST/value-end metadata already exist. Add these transient terms; they are not established by retained final index counts. |
|
||||
| Projection counting walk | `mixed.rs:379–405` has an additional Vec of Ast references. Its frontier is bounded by original ordinary value count; it runs before projection. Use a phase maximum instead of automatically summing both scratch peaks. |
|
||||
| Typed declaration scratch | `declarations.rs:284–300` owns parameter-name and parameter-ID sets plus a borrowed field-name set. Names are cloned separately from retained parameter Reference strings. Override target names have another set (`:604–610`). |
|
||||
| Typed expression scratch | `syntax.rs:15–39,225,393–401` has task/value vectors, sequence vectors, cloned call-label duplicate-detection keys and conversion overlap. Bound suspended nested sequences by original argument/node/frame counts; E alone is not a proved multiplier for all these containers. |
|
||||
| String scanning/decoding | The raw scanner validates quoted strings using a temporary decoded String (`raw_tokens.rs:127`); the parser later decodes them again (`language.rs:1194–1201`, `cursor.rs:82–95`). Unchanged literal token lengths give a conservative maximum for transient decoded text, including UUID strings not retained as strings. |
|
||||
| Traversal/path work | Same include graph means actual F/include counts and paths are unchanged. Nevertheless folded keys, stack/active/visited/children and cloned target/origin paths coexist (`source_project/traversal.rs:8–17,55–92,96–191`). Path normalization also allocates component Vecs, uppercase component strings and joined paths (`source_project.rs:120–164`). Count these explicitly. Unicode lowercase expansion must be measured/bounded, not assumed byte-neutral. |
|
||||
| Collection transitions | Parsed canonical BTreeMap to file Vec (`mixed.rs:374`) and sequence collection conversions require an explicit logical-live overlap rule. No allocator-capacity/RSS claim follows from logical slots. |
|
||||
|
||||
These terms are finite and source-derived. Include scratch can be bounded using actual authored include-edge count plus F and maximum/path-sum lengths, rather than default maximum limits. Name growth needs role-weighted copy counts or a separately proved conservative maximum multiplicity; several carriers demonstrably require **two** simultaneous copies. No complete universal multiplicity was proved in this bounded investigation.
|
||||
|
||||
An ordinary-heavy route/array fixture is particularly important: significant token count can grow substantially while retained name/index additions remain small. The projection's extra token-end vector therefore cannot be justified merely by pointing to later name/index headroom. This rejects the proposed *inference* B≥earlier parser peak; it is not a claim that a particular measured fixture exceeded B. A formal phase accounting or measurement-backed bound is still needed.
|
||||
|
||||
## Minimal compatible use and comparison
|
||||
|
||||
Use this envelope only for parsing first. After the authenticated old owner drops, reserve **O+Vparse**, where O is all owned output slots/text and Vparse is the proved parser peak under transformed name lengths. Parse under the exact inherited per-snapshot Limits/ProjectLimits. Then transfer the admitted retained syntax subtotal into the existing resolver with carried O, releasing only the envelope excess. The resolver still needs its narrow baseline seam; final whole-Project equality still needs E. Do not reserve Vparse forever alongside the resolver's own syntax reservation or silently forget O at handoff.
|
||||
|
||||
| Choice | Useful caps / proof / maintenance |
|
||||
| --- | --- |
|
||||
| Topology envelope + exact-byte guard | Avoids pervasive parser edits and preserves existing parse semantics. Can use actual original shape and phase maxima, so potentially useful under normal profiles. Conservative copies can reject tight profiles. Duplicates an inventory of parser allocations and must change whenever those sites change. |
|
||||
| Carried-ledger parser path | Charges actual live phases and can admit cases rejected by a loose envelope. Broader implementation/testing surface, especially shared parser/traversal seams. Allocation changes remain closer to their checks, reducing long-term proof drift. |
|
||||
| Reserve hard limits or an unexplained B/byte multiple | Reject: hard-limit reservation plus nonempty output often leaves no admissible headroom; unexplained multipliers have no safety proof. |
|
||||
|
||||
**Next discriminating step:** independently enumerate Vparse entries/text for a tiny project, rich OA/SA, ordinary-heavy64-route-point category, wide/deep typed expressions, nested calls, long renamed parameters and include-heavy paths. Count copy multiplicities and phase overlap from source, including the guard's own zero-container walk. Demonstrate a realistic inherited cap that passes emission and O+Vparse, plus cap-minus-one refusal before parsing; compare with a tighter actual-live estimate to quantify false rejection. No such executable acceptance experiment was run here. If the count walker becomes a second parser lifecycle implementation or rejects ordinary useful cases, choose carried-ledger instrumentation instead.
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
# Rename verification envelope: bounded feasibility result
|
||||
|
||||
2026-09-24. Source-only investigation of private parser base `ee500908e3d77182ddd54e12524f9b6c6eb43b60`; no production edits, Cargo or parser execution. Current rename-plan acceptance is separate.
|
||||
|
||||
**Decision: stop the envelope candidate and recommend the carried-ledger parser path.** A topology-specific envelope is mathematically possible, but no complete safe Vparse entries/text formula or useful aggregate cap has been established here. Closing the remaining terms requires a parallel model of nearly every parser allocation lifecycle. This meets the requested stop criterion; the partial bounds below must not be used as a verification admission gate.
|
||||
|
||||
The reason is proof and maintenance cost, not a claim that every conservative envelope would fail ordinary default-profile examples. The supplied small literals could plausibly fit generous caps. That observation is not an aggregate storage proof or a measured admission result.
|
||||
|
||||
## Valid precondition retained
|
||||
|
||||
The exact-byte guard remains sound: before old-owner drop, compare complete output paths/entry and each actual file against the original untouched slices plus validated replacement names. Use a streaming comparison without another output buffer. Count and reserve all output content/path/entry bytes and F map slots before construction. Keep verified output privately immutable until parsing.
|
||||
|
||||
Only under that guard do whole ASCII/nonreserved Word replacements preserve token classes/count, AST topology, include graph, expression structure, literals and depth (`model.rs:1739–1746`, `language/raw_tokens.rs:61–70`). Arbitrary malformed emitter output must fail the guard **before** the old-topology bound is applied. Parsing/admission/normal full-Project equality are still required afterward. A checksum or independently supplied output bundle is not this guard.
|
||||
|
||||
## Explicit bounds established, and their limits
|
||||
|
||||
Use checked arithmetic. Let T be significant-token count for one currently parsed file, E its typed expression-node count, A its ordinary AST value count, F complete file count, and K actual authored include edges. Retained original syntax/tokens can supply these counts without parsing new bytes. For tighter typed bounds, use tokens in a retained root's full original span instead of whole-file T.
|
||||
|
||||
1. **Projection:** token-end Vec has exactly T entries; its delimiter stack has at most T entries (`language.rs:1023–1035`). Thus **Vprojection_scratch.entries ≤2T** is explicit and safe for these two containers. A tighter term is T+maximum unmatched brace/bracket depth. New position records themselves must already be included in the retained-syntax allowance. The preceding `ordinary_position_slots` walk has at most A pending borrowed values (`mixed.rs:379–405`); use **max(A,2T)** for these nonoverlapping scratch walks, not A+2T.
|
||||
2. **Pratt task Vec:** for one binding, let X be Expression tasks, B binary-continuation expansions and N sequence-child collections. Expression pushes at most3 tasks; a binary continuation pushes3; Next/Collected together push3 per child. Each Expression consumes a distinct starting token, each binary expansion a distinct operator token, and N≤X. Total pushes are at most **1+3X+3B+3N ≤1+6T** (`syntax.rs:38–295`). Live task entries cannot exceed total pushes. This is a proved coarse bound for **that Vec only**. It is not a bound for sequence/value vectors, call-name sets, retained expressions, literal metadata or text.
|
||||
3. **Copied reference growth:** an ordinary Reference owns its spelling in both Ast and projected EditKind (`language.rs:1338–1341,1087`). If that alias grows by d bytes, these two retained copies grow by **2d**, although emitted source grows by d. Parameter-name, override-target and call-label duplicate sets own additional copies (`declarations.rs:293,610`; `syntax.rs:225`). A single unweighted source-length delta is therefore unsound. Full text accounting needs explicit per-role copy multiplicity, including simultaneous temporary names.
|
||||
4. **Output:** independently of Vparse, exact output reservation is **O.entries=F**, **O.text=C+P**, where C is all final source-content bytes and P is entry-path bytes plus every file-key's bytes. None may disappear when the old witness drops.
|
||||
|
||||
Original resolved/indexed B can upper-bound its own retained syntax subtotal, but does not prove these extra earlier scratch peaks. In particular, projection token ends coexist with retained tokens/AST, and may dominate ordinary-only examples having few name records. No experiment here establishes B≥parser peak.
|
||||
|
||||
## Concrete literal comparisons
|
||||
|
||||
[envelope_literal_counts.py](envelope_literal_counts.py) and [ENVELOPE-LITERAL-COUNTS.json](ENVELOPE-LITERAL-COUNTS.json) perform independent literal lexical counts only. They do not import/run the application lexer/parser, inspect produced syntax, or measure allocation. The scanner recognizes all bytes in these specific fixtures. Rich literals reproduce the accepted fixture's900/974 bytes; expanded category is the corrected SHA39435798…15fc literal plus64 route points,3,124 bytes. Wide/deep literals use the accepted lowerer-test constructions (`lower/tests.rs:846–858`); their new complete bundle wrappers were not run. Parentheses-only and include-path examples are exploratory literals.
|
||||
|
||||
| Shape | F | Content C | Significant tokens total / largest file | Derived E | Output C+P before length-changing renames |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| Empty project | 1 | 78 | 10 / 10 | 0 | 102 |
|
||||
| Rich OA, including nested calls | 3 | 900 | 155 / 93 | 15 | 942 |
|
||||
| Rich SA | 3 | 974 | 165 / 103 | 15 | 1,016 |
|
||||
| Category plus64 route points | 1 | 3,124 | 914 / 914 | 0 | 3,148 |
|
||||
| One1,024-item typed list | 1 | 3,247 | 2,074 / 2,074 | 1,025 | 3,271 |
|
||||
|127 nested abs calls | 1 | 805 | 404 / 404 | 128 | 829 |
|
||||
|127 redundant parenthesis groups | 1 | 430 | 277 / 277 | 1 | 454 |
|
||||
| Four-file diamond include graph | 4 | 200 | 22 / 16 | 0 | 271 |
|
||||
|
||||
E here is source-derived expression shape, not new runtime output. Token totals exclude trivia; they are not Budget's raw-token Usage (which charges trivia too). The include example has4 authored edges and two occurrences of `../shared.arcadia`; path copies are71 bytes for output alone, despite only200 content bytes.
|
||||
|
||||
These discriminate the candidate:
|
||||
|
||||
- Grouping changes Pratt control work without adding semantic Expr nodes; E-only parser scratch is insufficient. Retained token spans/counts are needed.
|
||||
- Route64 has no typed expressions but still914 token ends plus the projection stack. Name-map headroom cannot stand in for this term.
|
||||
- Whole-file `1+6T` allows12,445 task entries for the wide list, although sequential list items have a small actual task frontier. Using per-root T removes surrounding declaration tokens but not the fundamental width/peak mismatch. Recovering a useful tight bound requires matching Pratt scheduling, suspended sequences and expression shape.
|
||||
- Rich OA's nested calls keep outer sequence argument values/key sets while the inner call is parsed; charging only the largest individual call's labels is insufficient. Include normalization and traversal work are independent again.
|
||||
|
||||
No total cap or cap-minus-one claim follows from these partial figures. In particular, adding known O and a partial scratch term does not establish a cap that admits all parser/resolve predecessors.
|
||||
|
||||
## Why the remaining formula mirrors the parser
|
||||
|
||||
A nominal phase formula would be:
|
||||
|
||||
`Vparse = max(folded-path setup, retained-syntax-prefix + traversal-live + current-file phase scratch, final file-table transition)`
|
||||
|
||||
with separate entries/text maxima. This is a **template with unproved terms**, not an explicit safe bound. Filling those terms requires all of the following:
|
||||
|
||||
- Pratt tasks plus the outer values Vec, every suspended Sequence.values and owned key set, and collection transitions (`syntax.rs:15–29,239–255,393–401`). The 6T task proof does not cover them.
|
||||
- Declaration field-name/parameter-name/parameter-ID sets and case override sets, including which coexist with which expression work (`declarations.rs:284–325,604–629`).
|
||||
- Ordinary open-declaration indices, recursive field-key locals and clone/move boundaries (`language.rs:1238–1269,1469–1528`).
|
||||
- Numeric literal token Vecs retained outside semantic E nodes (`analysis_source.rs:45–58`, `cursor.rs:112–121,164–168`) and transient normalized ratio text (`cursor.rs:152–160`). These were additional carriers found during the attempted closure; excluding exact-number heap does not automatically exclude their auxiliary Vec/String allocations.
|
||||
- Quoted-string scanner validation, parser decoding/UUID temporaries and projected reference/key copies; a single final decoded-text sum does not specify the transient maxima.
|
||||
- Traversal folded-key creation, stack/children transfer, active/visited/current paths and origin copies, plus `resolve_include` component Vec, uppercase component checks and joined path (`traversal.rs:55–191`; `source_project.rs:120–164`). Unchanged graph bounds them but does not supply copy counts automatically. Unicode folded path lengths also need a real bound.
|
||||
- Parsed BTreeMap→Vec and other transition overlap, rejection/cleanup policy, and a clear choice of which logical slots are already represented by existing syntax-entry/metadata counters rather than counted again.
|
||||
|
||||
A counter walker must therefore mirror the parser's declaration variants, ordinary AST/projection shape, typed scheduling, literal forms and shared traversal implementation. Broad summed totals avoid scheduling simulation only by sacrificing the phase precision that makes tight admission useful. A complete trusted formula would also need revision when any of these internal copies changes, although the language and rename topology stay identical.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Select the **private carried-ledger parser increment**, keeping the exact byte guard as useful emitter verification rather than as authority for an incomplete memory envelope. Put checks at the growth/transition sites and transfer authenticated retained reservations to the resolver; preserve existing exact per-snapshot Limits/ProjectLimits, work counters and model/serde exclusion policy. Do not make a global parser rewrite or public source8 change part of that increment.
|
||||
|
||||
This still requires a bounded carrier inventory, but keeps each reservation/release beside the operation it governs and measures actual live phases. It avoids shipping and maintaining a second parser lifecycle description plus looser false refusals. If a future profiled workload motivates an envelope, reopen it with a complete independently checked formula and useful cap evidence, not the partial inequalities in this report.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Mixed rename execution: minimal source seams and hazards
|
||||
|
||||
2026-09-24. Investigation only, against private base **`ee500908e3d77182ddd54e12524f9b6c6eb43b60`** and the reviewed working rename planner. No implementation, Cargo, commits or Gitea actions. Current planning acceptance remains primary. Paths below begin at `crates/oa-core/src/`.
|
||||
|
||||
**Recommended direction:** consume the verified plan; validate the complete current snapshot; emit one owned complete bundle under the existing aggregate ledger; explicitly drop the old auxiliary owner; verify the output with the exact inherited per-snapshot policy and the surviving output reservation; return an owning bundle/model result after temporary verification syntax drops. Reuse parsing, resolution, validation and model equality. Do not reuse the public updater or add a second general edit framework.
|
||||
|
||||
There is **no carried-baseline parser/resolver API today**. Adding a baseline only to `resolve` would not satisfy the successor contract: output already coexists with parser allocations before resolution begins. This is the principal unresolved implementation seam.
|
||||
|
||||
## Reusable pieces and necessary narrow changes
|
||||
|
||||
| Actual seam | Reuse / required change |
|
||||
| --- | --- |
|
||||
| `ordinary_index/rename.rs:6–13,163–174,259–315` | Plan owns the complete old witness, external desired borrow and two authenticated maps. Reuse its exact current-bundle check and combined sizing. Execution must consume this authority, not take independently supplied edits or a Budget. Line refs identify the reviewed draft; future formatting may move them. |
|
||||
| `analysis_source/update.rs:195–219` | Useful copying algorithm: walk original sorted ranges, append untouched slices and replacement names, append tail. Do not directly adopt its numeric-file result, extra length map or independent Budget argument. |
|
||||
| `source_project.rs:19–23,52–59` | Output owns `entry: String` and `BTreeMap<String,String>`; ProjectLimits includes file, include-depth, include-edge and model limits. All must survive; source-byte limit alone is insufficient policy. |
|
||||
| `analysis_source/budget.rs:6–14,36–64` | Limits is Copy but private inside Budget. Add only a private read-only exact-profile extraction seam. A deliberate new snapshot gets a new Budget with those Limits; never zero or replace counters inside a still-live old witness. |
|
||||
| `analysis_source/mixed.rs:38–47,244–268` | ParsedMixedSyntax retains ProjectLimits, Budget, canonical files and metadata. `parse_with_profile` preserves an explicit profile but currently constructs a fresh independent Budget; `parse` reconstructs defaults and must not be used for tightened-policy continuation. |
|
||||
| `mixed/project.rs:438–443` | Resolver currently starts `Ledger::default()` then accounts syntax. A new private entry point must receive the parser's authenticated surviving reservation/baseline rather than fabricate another independent ledger. Keep the old wrapper behavior for existing callers. |
|
||||
| `mixed/project/accounting.rs:234–369` | Reuse syntax traversal/lowering-count logic, but specify one owner for syntax entry/text reservations. If the new parser already reserved them, this routine must not charge the same retained storage again; its live walk slots and later lowering scratch still count. |
|
||||
| `mixed/project.rs:595–644` | Actual validation transfers owned warnings after reservation and records actual static admission limits/usage. A narrow consuming extraction may move Project/warnings/metadata out and drop syntax/raw sites. Do not clone the desired Project or return old warnings as if output were re-admitted. |
|
||||
|
||||
## Output storage and original-coordinate emission
|
||||
|
||||
Let **L** be the planner's current live ledger (already old B plus R+M). Let **F** be complete file count, **C** the checked sum of final source-content bytes, and **P = entry.len + sum(path.len)** for copied output path strings. The new owned output requires at least:
|
||||
|
||||
`O = Slots { entries: F, occurrences: 0, text: C + P }`.
|
||||
|
||||
The owning SourceBundle struct itself is inline; entry text still counts even though the same path spelling also exists as a map key. Unchanged files are copied and counted. Reserve the whole checked O before constructing any output String/path/map entry, keeping L live. A per-file reservation can also be sound but adds more interleavings to verify. A currently built String can belong to its already reserved destination slot; document this rather than charging it inconsistently twice.
|
||||
|
||||
Repeat the streaming per-file sizing walk if necessary; no F-entry length table is required. Use the validated sorted original physical keys. Copy original slices and borrowed replacement names directly, without formatting, rescanning references or applying one name swap after another. Full Word spans preserve @/$, comments, whitespace, historical content and all non-name bytes. Allocation capacity is not the logical text metric, and `with_capacity` is not itself a budget check.
|
||||
|
||||
Keep separate checks for final content C under the inherited complete source-byte policy and **live auxiliary text L.text+C+P** under the ledger. Passing the former does not imply the latter. Conversely, parsed Usage.bytes is a work/input measure: do not add it as another owned source-buffer copy when O already accounts that buffer. Existing caller-owned old source and desired Project remain external borrowed memory under the established logical policy; this is not an RSS bound.
|
||||
|
||||
The immediate emission peak is **L+O**. After emission succeeds, save only required policy/metrics/E scalars and the desired borrow, drop old syntax/index/maps/names/edits, and only then release their reservations. Carry O forward as live storage. A fresh ledger that forgets O is incorrect even after all old auxiliary state is dropped. A private consumed handoff can move the ledger and release its known old subtotal; it should not expose a public factory accepting arbitrary caller-reported baseline Slots.
|
||||
|
||||
## Why parser accounting is the consequential seam
|
||||
|
||||
Current mixed parsing has an intentionally staged policy:
|
||||
|
||||
- `lex.rs:20–55` charges source bytes/raw tokens, then allocates retained significant tokens. Token Usage is separate from auxiliary entries.
|
||||
- `mixed.rs:96–97,277–283` charges ordinary syntax entries and checks initial file metadata independently.
|
||||
- Each whole file is lexed and parsed before `metadata` adds its tokens, value-end map, projected positions and lexical owners (`mixed.rs:297–330`).
|
||||
- `ordinary_position_slots` allocates its own traversal Vec before the projection reservation (`mixed.rs:379–405`); canonical BTreeMap→Vec conversion occurs at `:374`.
|
||||
- Shared Traversal owns folded-path validation strings, stack/active/visited/children containers and cloned paths/locations (`source_project/traversal.rs:8–17,55–92,96–191`), bounded through its existing ProjectLimits policy rather than the mixed Ledger.
|
||||
- Only later does `accounting::syntax` reserve **metadata+Usage.entries**, traverse decoded owned text and reserve its own work slots (`accounting.rs:109–118,234–280`), after resolver has started a new ledger.
|
||||
|
||||
Thus passing O only into `resolve` checks too late, and independently reducing a local metadata ceiling is not a complete proof: syntax entries, retained metadata, owned decoded text and parser scratch coexist. The narrow successor work must identify the parser's authoritative live subtotal, check **O plus that subtotal before relevant allocation**, and transfer that subtotal into the resolver without charging it twice. Work counters and auxiliary reservations need distinct handling; merely subtracting O from the Limits object would silently alter the per-snapshot policy and conflate domains.
|
||||
|
||||
Two compatible candidates merit consideration:
|
||||
|
||||
1. **Private carried-ledger parsing path:** thread a private accounting context through existing mixed parser growth seams, retain its ledger in the syntax witness, and reuse resolver accounting with an explicit already-reserved-syntax handoff. Reuse actual lexer/parser/project semantics; do not create a second parser. This is the clearest proof but touches more than an emitter wrapper. Inventory token/AST/position text, temporary work and file-table transition overlap once.
|
||||
2. **Conservative verification envelope reserved before parsing:** potentially fewer parser changes, but only sound with a proved envelope for every parser/resolver temporary and text copy under the output/profile. The existing original metadata/E counts alone do not bound decoded-text copies, Traversal scratch or corrupted-output shapes. Reserving the whole current hard limit in every domain would frequently make any nonempty O impossible. Do not claim this shortcut is available without an independent bound and useful-cap evidence.
|
||||
|
||||
Prefer candidate1 unless candidate2 receives a concrete source-derived proof. The contract must explicitly state treatment of existing Traversal/projection/conversion scratch; adding new copied paths or a new temporary container cannot disappear behind an old exclusion. This is a bounded accounting decision at real allocation sites, not a request to redesign parsing or retroactively claim every existing caller had an aggregate parser ledger.
|
||||
|
||||
## Actual output admission and final equality
|
||||
|
||||
Use the exact inherited Limits **and** ProjectLimits for the deliberate new parse. Original parse Usage/numeric units are historical metrics; output has separate measured counters. Preserve static admission policy and use the existing complete `validation::validate_with_usage` result, not a name-only check. The consumed-old-owner transition avoids needing two full syntax/index owners simultaneously; O remains live throughout new parsing, lowering, warnings and comparison.
|
||||
|
||||
No new typed or ordinary index is required merely to accept output: resolve/admit actual bytes, then compare the **entire Project with normal `PartialEq`**, including the renamed aliases/parameter names. Do **not** call the planner's `same_project`, which deliberately exempts those fields and would accept an admissible but incompletely renamed output.
|
||||
|
||||
Retain original E as a checked scalar before dropping the old witness. The plan already proved desired expression shapes equal to original; the intended target supplies the same frontier bound even when actual output is wrong. Reserve E against the new live verification ledger before full Project equality, release after its vectors drop. This is an additional comparison phase, not a reason to retain old raw arenas. Existing all-carrier signed-zero equality applies; non-name source-byte preservation comes from exact copying and byte oracles, not from semantic equality alone.
|
||||
|
||||
Malformed output must fail parsing/resolution; admissible-but-wrong aliases or another payload must fail whole-target equality. Failure returns only located diagnostics and destroys output/verification state. Do not debug-format arbitrary target expressions or adopt history/save before success.
|
||||
|
||||
## Owning result without self-reference
|
||||
|
||||
A temporary inner verification scope can borrow the newly owned SourceBundle, resolve it, compare it, and then consume the resolved owner into owned Project, warnings and copied policy/usage metadata. Drop temporary syntax/raw arenas before moving SourceBundle into an owning accepted result. None of the moved fields borrow output strings, so this requires no self-referential wrapper, Pin or unsafe code. Actual warnings contain owned paths/messages (`project.rs:603–620`). Preserve their reservations until the corresponding result fields move/drop; do not release still-retained warning strings as though all resolver auxiliary storage vanished.
|
||||
|
||||
This result should make no reusable-index claim. A future edit would parse/index again unless a separately justified caller-owned-output borrowing API is chosen. Reusing public CompiledSourceProject (`source_project.rs:111–117`) would misleadingly require its different SourceIndex/stabilization conventions; prefer a narrow private accepted result with the capability actually established.
|
||||
|
||||
An explicit unchanged execution outcome can return the original AuthoredMixedProject after the full current-snapshot check, without output copies or new parsing. A changed outcome can own the new bundle/model/warnings. No-op planning may already have needed E headroom; no-op execution does not retroactively waive that check.
|
||||
|
||||
## Discriminating next evidence
|
||||
|
||||
Before implementation acceptance, require independent exact complete output bytes for mixed/scoped swaps and comments/Unicode, including growing and shrinking edits whose combined total fits; unchanged files must be included. Tighten bytes/entries/numeric/frame and ProjectLimits independently to prove exact policy retention. Isolate L+O, O+parser storage, O+resolver scratch/warnings, and O+resolved+E boundaries with successful predecessors. Include malformed output, valid-but-wrong name output, stale untouched-file/entry/path changes, late failure/drop and no-op unchanged ownership. The current planner tests do not establish these execution guarantees.
|
||||
@@ -0,0 +1,47 @@
|
||||
"""Independent literal counts only; does not import/run any application parser."""
|
||||
from pathlib import Path
|
||||
import json, re, hashlib
|
||||
root=Path(__file__).resolve().parents[2]
|
||||
out=Path(__file__).parent
|
||||
def uid(n): return f'00000000-0000-0000-0000-{n:012}'
|
||||
def doc(body): return f'arcadia 8;\nproject p "Project" id "{uid(1)}" {{\n{body}\n}}\n'
|
||||
def rich(sa):
|
||||
prop,work=('sa_property','sa_function') if sa else ('oa_property','oa_activity')
|
||||
diagram='layer Sa;' if sa else ''
|
||||
extra=f'sa_system s "System" id "{uid(6)}" {{}}' if sa else ''
|
||||
main=doc(f'include "b.arcadia"; include "a.arcadia";\nnode n id "{uid(4)}" {{ diagram @d; element @v; }}\n{prop} v "Value" id "{uid(3)}" {{ subject @w; type Number; base @f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6); }}\n{work} w "Work" id "{uid(2)}" {{}}\ndiagram d "Diagram" id "{uid(5)}" {{ {diagram} }}\n{extra}')
|
||||
files={'main.arcadia':main}
|
||||
for file,alias,name,n,op in [('a.arcadia','f','F',10,'+'),('b.arcadia','g','G',11,'-')]:
|
||||
files[file]=f'calculation {alias} "{name}" id "{uid(n)}" {{\ninput x id "{uid(1)}" : Number;\ninput y id "{uid(12)}" : Number;\nresult Number; body $x {op} $y;\n}}\n'
|
||||
assert len(main.encode())==(548 if sa else 474)
|
||||
assert len(files['a.arcadia'].encode())==len(files['b.arcadia'].encode())==213
|
||||
return files
|
||||
pattern=re.compile(rb'(?P<space>[ \t\r\n]+)|(?P<comment>//[^\n]*)|(?P<string>"(?:[^"\\]|\\.)*")|(?P<word>[A-Za-z_][A-Za-z_0-9]*)|(?P<number>[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)|(?P<op>[<>!=]=)|(?P<punct>[{}();,\[\]:=@$+*/<>!\-])')
|
||||
def count(files):
|
||||
result=[]
|
||||
for path,text in sorted(files.items()):
|
||||
raw=text if isinstance(text,bytes) else text.encode()
|
||||
cursor=0; significant=0; depth=0; peak=0; strings=0; stringmax=0
|
||||
for m in pattern.finditer(raw):
|
||||
assert m.start()==cursor,(path,cursor)
|
||||
cursor=m.end()
|
||||
if m.lastgroup in ('space','comment'): continue
|
||||
significant+=1
|
||||
if m.lastgroup=='string': strings+=1; stringmax=max(stringmax,len(m[0]))
|
||||
if m[0] in (b'{',b'[',b'('): depth+=1; peak=max(peak,depth)
|
||||
if m[0] in (b'}',b']',b')'): depth-=1; assert depth>=0
|
||||
assert cursor==len(raw) and depth==0
|
||||
result.append({'file':path,'bytes':len(raw),'significant_tokens':significant,'max_delimiter_depth':peak,'string_tokens':strings,'max_quoted_token_bytes':stringmax})
|
||||
return {'files':result,'total_bytes':sum(x['bytes'] for x in result),'total_tokens':sum(x['significant_tokens'] for x in result),'max_file_tokens':max(x['significant_tokens'] for x in result),'output_path_bytes':len('main.arcadia')+sum(len(p.encode()) for p in files)}
|
||||
category=(root/'.local/as3batch/crates/oa-core/src/language/analysis_source/mixed/project/ordinary_index/tests/fixtures/categories.arcadia').read_bytes()
|
||||
assert hashlib.sha256(category).hexdigest()=='3943579866157c7b5d95ce9edcb2d643058826b9af44257557e2864f130d15fc'
|
||||
route64=category.replace(b'routes [{ edge @link; }];',b'routes [{ edge @link; waypoints ['+b', '.join([b'{ x 0; y 0; }']*64)+b']; }];')
|
||||
assert len(route64)==3124
|
||||
shapes={'tiny':{'main.arcadia':doc('')},'rich_oa':rich(False),'rich_sa':rich(True),'category_route64':{'main.arcadia':route64}}
|
||||
shapes['wide1024']={'main.arcadia':doc(f'calculation wide "Wide" id "{uid(82)}" {{ result List(Number); body ['+', '.join(['1']*1024)+']; }')}
|
||||
shapes['deep127']={'main.arcadia':doc(f'calculation deep "Deep" id "{uid(81)}" {{ result Number; body '+'abs('*127+'1'+')'*127+'; }')}
|
||||
shapes['grouped127']={'main.arcadia':doc(f'calculation grouped "Grouped" id "{uid(81)}" {{ result Number; body '+'('*127+'1'+')'*127+'; }')}
|
||||
shapes['include_paths']={'main.arcadia':doc('include "dir/left.arcadia"; include "dir/right.arcadia";'),'dir/left.arcadia':'include "../shared.arcadia";','dir/right.arcadia':'include "../shared.arcadia";','shared.arcadia':'// shared\n'}
|
||||
results={k:count(v) for k,v in shapes.items()}
|
||||
(out/'ENVELOPE-LITERAL-COUNTS.json').write_text(json.dumps({'scope':'Literal lexical counts, not parser admission or allocation measurement.','shapes':results},indent=2)+'\n')
|
||||
print(json.dumps({k:{x:v[x] for x in ['total_bytes','total_tokens','max_file_tokens','output_path_bytes']} for k,v in results.items()},indent=2))
|
||||
@@ -0,0 +1 @@
|
||||
*.md -text whitespace=cr-at-eol
|
||||
@@ -0,0 +1,70 @@
|
||||
# Independent critique: mixed rename planning
|
||||
|
||||
2026-09-24. Read-only source review at **`ee500908e3d77182ddd54e12524f9b6c6eb43b60`**. Reviewed [RENAME-PLAN-SOURCE-MAP.md](RENAME-PLAN-SOURCE-MAP.md), SHA256 `ed868523110b6eef996132589450042c6c649984cb870494d1c1e0c05d118c77`. No implementation, Cargo, commits or Gitea activity. Paths below begin at `crates/oa-core/src/`. Parent owns the accepted contract.
|
||||
|
||||
**Recommendation:** adopt the consumed-source/borrowed-target planning design, subject to the precise rules below. The original-expression-site scratch bound is valid for the complete current Project type graph. No hidden historical expression counterexample was found. Output emission and readmission require additional lifecycle seams; a verified plan alone must not be called accepted output.
|
||||
|
||||
## Whole-target gate and representation
|
||||
|
||||
The proposed whole-target exclusions cover the actual Project fields (`model.rs:1654–1672`), all global alias-bearing records, calculation parameter names, and nested diagram-node aliases (`:1518–1530,1582–1591`; `analysis/types.rs:29–41,78–89`). Require exhaustive borrowed struct destructuring without `..` at these exclusions. Compare collection lengths before zipped iteration, every ordered map key, each record's own ID, and each parameter's ID at the same Vec index. This rejects records moved between diagrams, substituted map keys with unchanged record IDs, parameter reorder/reidentity, body-variant changes and every non-name payload mutation. Do not identify target records by their proposed spellings.
|
||||
|
||||
Opaque payload equality is appropriate after these checks. No generic model diff, normalized clone, serde round trip or temporary target mutation is needed. Large target-only collections should fail lengths/variants before walking; diagnostics should describe the rejected field/category rather than debug-format an arbitrary target tree. Target memory is externally owned and is not silently admitted or counted as a new owned Project.
|
||||
|
||||
Consuming AuthoredMixedProject and borrowing immutable `&Project` avoids a duplicate model and guarantees target stability through safe Rust. A sparse `BTreeMap<Target,&str>` points only into that external target, never into the plan's own source field; a physical edit map owns only keys and qualified Targets. There is no self-reference. Original source/target references must remain read-only, with no loose-map constructor, legacy adapter, replacement Budget or partial-batch installation path.
|
||||
|
||||
Compare final names across **all** qualified catalog members, including unchanged names. The key is `(None,name)` for globals and `(Some(calculation_id),name)` for parameters; this matches existing `update.rs:41–74`. Equal parameter IDs in different calculations remain distinct. Validate changed byte lengths with checked arithmetic before scanning names, then existing `valid_alias`. Simultaneous swaps are legal; changed-to-unchanged collisions reject. Check sparse target membership against the authenticated catalog rather than relying on names alone.
|
||||
|
||||
Generate edits by streaming both authenticated occurrence families into one sorted physical map. Replacement authority is the whole alias Word only, never the reference's @/trivia extent. Exact-set verification can rescan the unique original families and compare required key/Target pairs plus the total count, without a second seen set. Check spans/source spelling and nonoverlap before export; count equality alone is insufficient.
|
||||
|
||||
## Expr equality scratch: complete reachability proof
|
||||
|
||||
At this source, Project reaches `analysis::Expr` through exactly four root families:
|
||||
|
||||
| Root | Definition / production |
|
||||
| --- | --- |
|
||||
| Calculation body | `analysis/types.rs:85–94`; `lower.rs:512–542` calls `self.binding`. |
|
||||
| EngineeringProperty base | `model.rs:667–671`; `lower.rs:568–577`. |
|
||||
| AnalysisCase override values | `model.rs:673–677`; `lower.rs:619–662`. |
|
||||
| AnalysisCheck predicate | `model.rs:679–682`; `lower.rs:591–614`. |
|
||||
|
||||
`binding` (`lower.rs:686–699`) either returns Unbound or invokes expression lowering. Each `Work::Visit` emits exactly one ExpressionSite before constructing that node; all Expr variants' children are scheduled (`:768–858`). Resolver retains the resulting arena verbatim when merging typed definitions/elements (`mixed/project.rs:507–561`). Let **E** be this retained arena length, not the number of roots or occurrences.
|
||||
|
||||
The historical path is closed: Trace → TraceBaseline → SemanticBaseline → FacetReview (`model.rs:1634–1650`; `semantic/types.rs:84–134,164–174,258–260`). Its facet payload catalog contains no analysis Binding or Expr. Historical `Binding` is `LifelineBinding`, two IDs; annotation/message `expression` is String (`model.rs:526–536`). Defaults/real bounds/operation/contextual payloads likewise contain no Expr. Ordinary constraint/event/state expressions are strings. No arbitrary serde_json::Value or boxed Project payload introduces another analysis-expression root.
|
||||
|
||||
`Expr::eq` (`analysis/expression_lifecycle.rs:170–270`) starts with one pair and iteratively replaces a popped pair by corresponding child pairs. Pending pairs form a frontier of distinct nodes in the original tree. List lengths and call lengths/keys are checked before paired child insertion; fixed-arity variants push only their matching children; variant mismatch stops. It never recursively invokes Expr equality while that Vec is live. Sequential parent/container equality calls therefore cannot overlap these work vectors. Each work-vector cardinality is at most its original tree's node count, hence **≤E**, even for a huge/deep mismatching target.
|
||||
|
||||
Reserve E logical scratch entries before any such comparison and release after all comparisons have returned and their vectors dropped. With **E=0**, no original Expression variant exists: compare parent variants first and reject target-only Expression without entering Expr equality. `Exact` equality is bounded normalized structural equality, not arithmetic (`analysis_numeric/exact.rs:24–36`); no numeric meter charge is needed for it. The E proof concerns logical live pairs, not Vec capacity, heap bytes or RSS. Future additions to the payload type graph require renewing the reachability proof.
|
||||
|
||||
Controls should cover a wide matching list/call frontier, deep equal/mismatching trees, target-only deep expression against Unbound, E=0 historical traces and late refusal/drop. Conservative E reservation may reject an otherwise unchanged target when inherited auxiliary headroom is insufficient. Do not promise unconditional no-op success.
|
||||
|
||||
## Scalar equality decision
|
||||
|
||||
The source map's geometry example was incomplete: signed zero also occurs in DataValue::Real and DataTypeDefinition real bounds (`model.rs:310–344`), ordinary defaults (`:615–627`), and historical Data/Field reviews (`semantic/types.rs:94–100`). A geometry-only bitwise matcher would not enforce a universal bitwise rule.
|
||||
|
||||
Parent selected **existing whole-model PartialEq semantics everywhere**, including +0/-0 equivalence, while preserving every original non-name source byte. This is coherent and avoids a bespoke matcher. A target differing only in zero sign can therefore be semantically equal and produce no scalar edit; do not claim bitwise target representation identity. NaN targets do not compare equal to admitted finite originals. Include signed-zero controls in both geometry and an ordinary/historical real carrier so the policy remains explicit.
|
||||
|
||||
## Simpler candidates and accounting decision
|
||||
|
||||
| Candidate | Judgment |
|
||||
| --- | --- |
|
||||
| Borrow target; sparse names + physical map | Preferred: exact retained increment R+M entries, no name copies or typed-path clones; explicit lifetime. |
|
||||
| Own target and copy changed names | Sound if independent ownership becomes necessary, but copies name bytes and owns a second full model. No current need justifies it. |
|
||||
| Resolve every target name directly per edit | Saves R slots but repeated parameter Vec searches can become quadratic. Not the simpler bounded choice. |
|
||||
| Pairwise final-name collision scans | Saves Q scratch slots at quadratic work cost. Prefer one borrowed qualified-name set. |
|
||||
| Reuse both legacy producer batches or normalize/clone whole Project | Adds containers, provenance and accounting, or obscures unsupported mutations. Reject for this bounded task. |
|
||||
| New metered Expr equality helper | Could reduce conservative scratch refusals, but duplicates/refactors proven matching logic. Defer unless E overreservation demonstrably blocks useful cases. |
|
||||
|
||||
For separated phases, the proposed incremental peak `max(E,R+Q,R+M)` is sound: equality reservation dies before changed-name collection; namespace set dies before edit collection. A combined implementation must account actual overlap. No-op planning remains subject to its actual phase reservations. Planning must preserve parse Usage, numeric units and frame metric; local storage checks do not recharge those counters (`budget.rs:139–165`).
|
||||
|
||||
## Concrete obligations before emission/readmission
|
||||
|
||||
These are contract requirements for the subsequent seam, not a proposed implementation now:
|
||||
|
||||
1. **Exact policy:** preserve all inherited Limits and ProjectLimits. `mixed.rs:223–268` currently reconstructs defaults or creates a new Budget; plain `parse()` would lose tightened policy. Deliberate output parsing should use the exact inherited **per-snapshot** profile, with fresh output usage explicitly reported separately. Never reset the original live witness or describe post-reparse numeric/parse counters as unchanged. This is not a cumulative old+new parsing budget unless separately specified.
|
||||
2. **Complete preflight:** checked final file lengths and total include unchanged files. Compute per-file removed/replacement totals before final addition so transient growth does not defeat a valid combined shrink/grow result. Keep all edits in original coordinates and emit each original file once. Reserve F output-map entries, source bytes, copied canonical path keys and entry path before their allocations; optional length maps need additional slots. Output-size validation alone is not a simultaneous live-storage bound.
|
||||
3. **Documented consumed transition:** decide exactly when old index/syntax/maps are dropped. Output buffers coexist with old B+R+M during emission and remain owned through verification. Dropping old auxiliary state can reduce the verification baseline, but does not make retained output strings/maps free. A carried ledger/baseline must include every surviving auxiliary allocation before parsing and resolving output. Current `resolve` starts `Ledger::default()` (`mixed/project.rs:438–442`), and parser metadata checks are separate (`mixed.rs:278–335`); merely wrapping those current entry points in two independently passing limits does not establish aggregate live storage.
|
||||
4. **Actual verification:** parse/resolve/admit emitted bytes and compare the whole resulting Project with the immutable intended target. Retain E as a scalar if the old witness has been dropped and reserve equality scratch against the verification baseline too; the validated target's unchanged Expr shapes supply the same bound. A structurally invalid output and a valid-but-wrong output must reach their respective distinct refusals, with no partial usable result.
|
||||
5. **Return lifetime:** a ResolvedMixedProject borrows its bundle; ordinary owning fields cannot safely return both bundle and borrowing witness. A later narrow consumed-parts result may own output/model/warnings after temporary syntax drops, or a caller-owned output can support a borrowing witness. Specify which guarantee is returned; do not imply a reusable index survives when it was discarded. No-op execution may return an explicit unchanged owner rather than pretend owned copies are free.
|
||||
6. **Staleness and installation:** if execution accepts a current SourceBundle, compare entry, entire canonical file set, paths and exact bytes with the retained snapshot, including untouched files. This detects stale supplied snapshots; atomic disk/history/GUI adoption is separate and is not granted by a pure plan.
|
||||
|
||||
Proceed with a clearly named planning dependency once these planning rules are incorporated. Keep emission/readmission unimplemented until its policy, aggregate baseline and returned ownership are specified. This preserves the required whole-output gate without inventing a new framework or weakening full-edit parity requirements.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Mixed whole-target rename planning: source map and proposed dependency
|
||||
|
||||
2026-09-24. Read-only research against clean private source **ee500908** (`Repair ordinary-index fixtures to exercise intended validation`) in `.local/as3batch`. No source edits, Cargo, runtime experiments, commits or Gitea actions. Parent owns adoption, compilation and integration. Paths/line numbers below refer to that private commit and begin at `crates/oa-core/src/` unless stated otherwise. This report is a proposal, not an accepted contract or implementation claim.
|
||||
|
||||
The accepted root `harness/analysis-ordinary-index-contract-20260924.md` requires a whole independently supplied target Project, allowed global/scoped renames only, simultaneous namespace validation, original-coordinate edits from both families, actual-output parse/resolve/admission and whole-target equality. Full structural/scalar editing, identity changes, migration and GUI/save parity remain later requirements. A rename-planning dependency must not claim that these are completed.
|
||||
|
||||
## What exists and what does not
|
||||
|
||||
| Source seam | Verified behavior and consequence |
|
||||
| --- | --- |
|
||||
| `language/analysis_source/mixed/project/ordinary_index.rs:27–77` | `AuthoredMixedProject` owns the typed owner and ordinary map; read-only views return the entire Project, original SourceBundle/files, complete qualified names, typed occurrence/expression maps and physical ordinary records. This is the correct consumed input. It has no rename authority or legacy adapter. |
|
||||
| `language/analysis_source/mixed/project.rs:18–26` | The retained resolved owner holds original syntax/Budget, complete Project, warnings, static admission metadata, raw expression/occurrence arenas and the aggregate Ledger. A narrow child inside the owner can split borrows during planning without exposing replacement sources or budgets. |
|
||||
| `language/analysis_source/update.rs:15–19,23–75` | Existing typed Plan borrows legacy Index, owns a supplied rename-name map and edit Vec. Final namespace keys are `(None, name)` for globals and `(Some(calculation_id), name)` for parameters; this already permits simultaneous swaps and shared parameter spelling across calculations. It validates alias syntax via `valid_alias`. It does **not** compare a complete target Project. |
|
||||
| `language/analysis_source/update.rs:78–111` | The legacy producer filters unchanged targets, copies typed keys (including shared Path references), sorts locations and clones names. This is a useful behavioral reference, but new mixed map/vector entries must use aggregate entry-slot accounting rather than this producer's local occurrence ceiling. |
|
||||
| `language/analysis_source/update.rs:119–168` | Existing validation compares all numeric source files, checks membership/spelling/uniqueness/order and verifies the exact complete qualified edit set. Mixed provenance additionally contains original entry and canonical paths; do not project it down to the old numeric-map input. |
|
||||
| `language/analysis_source/update.rs:173–222` | Legacy output sizing includes every supplied file and checked arithmetic; application emits each original source once in order. Its lengths map and new buffers are not reserved against retained mixed storage. Reuse behavior, not these local budget assumptions unchanged. |
|
||||
| `language/analysis_source/update.rs:227–323` | Composition holds the inherited Budget by reference, exports only an intact complete borrowed batch and intentionally postpones standalone typed-output sizing. Its input remains legacy Index, not the complete mixed witness. OriginalEdit is inspection, never independently transferable authority. No current helper accepts both occurrence families. |
|
||||
| `model.rs:1654–1672,1763–1781` | Project contains project alias plus definitions, elements, relations, diagrams/nested node placements, artifact links and traces. `identities()` allocates a Vec; streaming these fixed collections avoids another uncounted temporary catalog. |
|
||||
| `analysis/types.rs:29–41,78–89` | Definition alias is global. Calculation parameters are an ordered Vec with scoped ParameterId, name and value_type. Parameter name alone may change; parameter ID, order, type, result and body must remain fixed. |
|
||||
| `model.rs:241–248,1092–1098,1518–1530,1582–1591,1602–1612,1642–1651` | All other global alias-bearing records have a shallow alias field; their remaining payloads are immutable under rename-only intent. Diagram node maps need a separate alias-aware walk. Trace baselines and artifact owner/URI/revision/fragment are not names. |
|
||||
| `analysis/expression_lifecycle.rs:170–270` | Expr::PartialEq is iterative but allocates `pending: Vec<(&Expr,&Expr)>`; it is **not allocation-free**. List/call lengths are checked before adding paired children; call keys are checked. Parent bodies' derived PartialEq invokes this implementation. |
|
||||
| `model.rs:671,677,682` and `analysis/types.rs:85–89` | Current analysis Bindings live in calculation bodies and engineering property/check/case payloads. Their original expression trees have retained raw-site arenas. This offers a source-derived upper bound for the existing Expr equality work Vec, subject to an explicit proof/test rather than ignoring its allocation. |
|
||||
| `model.rs:1739–1746`, `language.rs:1205,1282`, `language/analysis_source/cursor.rs:67–78` | Both ordinary and typed names ultimately use the same ASCII identifier/reserved-name predicate. Renaming cannot introduce punctuation, Unicode names, empty strings or reserved aliases just because replacements are UTF-8. |
|
||||
| `language/analysis_source/budget.rs:6–14,36–64,139–165` | Budget owns private exact Limits, parse Usage, numeric meter and failure latch. New Budget starts Usage/numeric work at zero. Local lowering/text checks do not mutate cumulative parse counters. No current read-only exact-profile getter or budget-transfer parse seam exists. |
|
||||
| `language/analysis_source/mixed.rs:223–268` | `parse` reconstructs a default source8 profile from ProjectLimits; `parse_with_profile` permits only tightening and then always calls `Budget::new(profile)`. Neither is an already-accounted continuation of the original Budget. Reusing `parse` would lose private tightened profile values. |
|
||||
| `language/analysis_source/mixed/project/accounting.rs:6–70` | Ledger checks additions in entry, occurrence and text domains before allocation, then releases explicitly. It is an auxiliary logical-live-storage policy, not model heap or RSS. Rename state must continue this baseline. |
|
||||
| `source_project.rs:640–755,868–893` | Public update recompiles mutable public state, formats declarations, reparses old/new text, applies ordinary edits, performs a later-coordinate structural pass and recompiles output for complete Project equality. This is neither the private original-coordinate producer nor a replacement for the whole-target rename gate. The final equality requirement is the right acceptance precedent. |
|
||||
|
||||
## Smallest useful next owner
|
||||
|
||||
**Recommendation for parent adoption:** consume AuthoredMixedProject, borrow one immutable complete desired Project for the plan's lifetime, produce an opaque read-only `MixedRenamePlan<'source,'target>`. Names are illustrative. Construction either returns the complete plan or diagnostics; failure consumes/drops the attempted source owner. The desired Project is not mutated, normalized or partially applied. Its immutable borrow prevents safe caller mutation while the plan exists; its pointer/lifetime alone is not edit authority.
|
||||
|
||||
Suggested fields are only:
|
||||
|
||||
- owned original `AuthoredMixedProject<'source>`;
|
||||
- `&'target Project` containing the independent whole intended state;
|
||||
- a sparse `BTreeMap<Target, &'target str>` for changed final names;
|
||||
- one `BTreeMap<(file,start,end), Target>` containing every changed ordinary/typed alias token in original coordinates.
|
||||
|
||||
No field borrows another field of the returned object. Names borrow the external desired Project, while map keys/targets own only small values. No cloned Project, cloned name Strings, cloned typed paths, occurrence-family adapter arrays or duplicated original file table is needed. Read-only inspection can derive old token text from the owned original witness and replacement text from the borrowed desired-name map. No independently fabricable constructor, mutable map, Deref-to-legacy-Index or external batch installation method should exist.
|
||||
|
||||
This is a proposed **planning dependency**, not permission to omit subsequent emission/readmission. Planning can include a full combined output-length preflight without emitting. If parent chooses to implement emission/readmission in the same milestone, settle the verification-lifetime and budget questions below first, and keep the planning invariants unchanged.
|
||||
|
||||
### Representation candidates
|
||||
|
||||
| Candidate | Assessment |
|
||||
| --- | --- |
|
||||
| Consumed source + borrowed whole target + sparse borrowed final names + physical edit map | Recommended minimum. No self-reference or duplicate Project; changed names and edits have exact entry-only storage. Immutable target lifetime is explicit. Whole-source physical uniqueness already exists, so a second typed-path key representation is unnecessary for token-only edits. |
|
||||
| Consumed source + consumed target + owned copied changed names + physical map | Sound alternative if owning target intent is operationally necessary. Avoid self-references by copying R changed names; explicitly charge their UTF-8 bytes while the whole owned target remains live. Simpler external lifetime but duplicated name bytes. Parent wording should state whether target consumption is actually required. |
|
||||
| Consumed source/target, no name map; look up every target directly in the desired model | Saves R slots but repeatedly searches global collections and linearly searches parameter Vecs for each occurrence. Could become quadratic for many repeated calls/large signatures. Prefer a bounded sparse lookup over this accidental cost. |
|
||||
| Reuse two legacy producer batches and a collector | Adds different provenance wrappers, typed-key/path clones, multiple containers and duplicated completeness work. No need to materialize two independent producers for this same sealed snapshot. Preserve legacy behavior separately; do not weaken its nominal API. |
|
||||
| Clone/serde-convert Project, erase or replace aliases, then ordinary equality | Rejected default: duplicates large model/JSON structures, obscures unsupported-field checks and adds allocation/drop work. Mutating the caller's target temporarily is also unnecessary. |
|
||||
| New generic AST/model diff or structural-edit framework | Not justified for fixed shallow alias exceptions. The accepted input already provides semantic identity and original occurrence ownership. |
|
||||
|
||||
## Complete target gate
|
||||
|
||||
Walk corresponding old/desired fixed model collections with borrowed iterators. Check each map length and each ordered map key before comparing records. Check record IDs as fields, not merely map keys. Do not collect Project::identities(). Require:
|
||||
|
||||
1. Same schema_version, project ID, project name/description and every collection/key/category.
|
||||
2. Definitions: same ID, display name, description and DefinitionBody variant. QuantityKind/Unit bodies equal in full. Calculations have same parameter length and **same parameter ID at each Vec position**; compare each parameter value_type, result and body. Only definition.alias and each scoped parameter.name may differ.
|
||||
3. Elements: same ID/name/description/parent/body; only alias differs.
|
||||
4. Relations: same ID/name/description/body; only alias differs.
|
||||
5. Diagrams: same ID/name/description/layer/projection/view_options/routes and same node-map keys. Each node keeps ID/element/position/size/collapsed/port_anchors; only diagram/node aliases differ.
|
||||
6. Artifacts and traces: every field including endpoints, baseline, history, URI and prose equal except alias.
|
||||
|
||||
Implement the shallow exclusions with **exhaustive struct destructuring without `..`** where practical, so adding a field to Project/Definition/Parameter/Element/Relation/Diagram/NodePlacement/ArtifactLink/Trace causes the gate to require a decision at compilation. Delegate unchanged opaque payloads to existing equality rather than duplicate every enum. A false comparison is an unsupported-change diagnostic, never a silently ignored diff. Target is not admitted independently first: shape/payload equivalence to admitted original plus final-name checks is the bounded plan gate; actual emitted output still needs its own full admission.
|
||||
|
||||
### Equality allocation and scalar semantics
|
||||
|
||||
Using body `==` invokes the existing Expr work Vec. A proportionate candidate is to reserve **E scratch entry slots**, where E is the retained original raw expression-site count, before this gate and release after all equality calls have returned/dropped their internal vectors. Comparisons are sequential, and each simultaneous Expr pair belongs to an original tree; current Eq checks paired child counts before growth, so pending pairs cannot exceed that original tree's node count <=E. Empty E means no old Expr comparison is invoked; mismatched Binding/DefinitionBody variants must refuse before trying to traverse a target-only tree. The reservation is a conservative bound, not an exact live-pop meter. Require an independent proof/control for wide lists/calls and deep trees; do not claim that an iterative equality method allocates nothing. If parent rejects conservative reservation, a small budgeted reuse seam in expression_lifecycle is preferable to copying that full matcher into rename code.
|
||||
|
||||
Other derived payload equality and model allocations remain under the established logical auxiliary/model-heap distinction, but the new gate must not quietly put its own temporary collections outside accounting. Very large desired maps/parameter Vecs should fail their length comparisons before traversal. Check candidate replacement name length sums against inherited bounds **before** scanning/copying long strings; borrowed raw target memory is not a reason to permit unbounded replacement-validation work.
|
||||
|
||||
Specify equality meaning explicitly: existing Project::PartialEq treats +0.0 and -0.0 equal in geometry. If “no scalar change” requires bitwise floating identity rather than existing semantic equality, node/route geometry needs a stricter gate. NaN/nonfinite originals are already rejected by admission. Do not silently present structural PartialEq as byte-identical model representation.
|
||||
|
||||
## Names and exact edit completeness
|
||||
|
||||
After the gate, stream names by stable identity to collect only changes. Global Target(id) covers the complete global catalog. Parameter Target(calculation_id,parameter_id) stays separate even when its UUID equals a global or another calculation's parameter.
|
||||
|
||||
Validate final names simultaneously across the **entire** qualified catalog, not only renamed members. Use existing `valid_alias` and a temporary borrowed set `(scope,final_name)`, where scope is global None or owning calculation ID. Drop this set before edit collection when possible. A changed name cannot collide with an unchanged name in the same namespace. A global and a parameter may share spelling; separate calculations may reuse parameter spelling. Every target in the sparse map must be present in the original catalog; target-gate identity equality should make absence an invariant refusal.
|
||||
|
||||
Then iterate both authenticated occurrence families. For a changed target, insert its exact physical alias location into the one edit map; ordinary targets are Global(record.target), typed targets use their existing qualified Target. Reject existing keys before insertion. The original indexes already enforce nonempty full-token spans and cross-family physical uniqueness. Retain neither ordinary full extent as replacement authority nor a copied typed path. @/$ markers, whitespace, line comments, display text, historical UUIDs, includes and all unselected bytes remain outside edits.
|
||||
|
||||
Before export/emission, validate the exact required set: scan both source families and check each required physical key has the correct qualified target; unchanged occurrences must have no edit. Compare total required count with edit-map len to exclude extras. This avoids a separate seen set because the source set and map are each physically unique. Recheck original spelling against original qualified names, whole-token membership and monotone/nonoverlapping physical order; any corruption must fail before output. A borrowed inspection record cannot install a subset, pair with another source owner or replace desired names.
|
||||
|
||||
### Supported and rejected examples
|
||||
|
||||
- Rename project p->mission, ordinary activity w->work and typed property v->value in one target: update all their header/reference occurrences in both families, including ordinary node.element@v and typed property.subject@w.
|
||||
- Swap global f/g and swap parameters x/y inside calculation f simultaneously: allowed when final namespaces are unique. Apply all replacements against original spans; never sequentially resolve intermediate spellings.
|
||||
- Rename one calculation's x while another calculation's x and global x remain unchanged: permitted; IDs/scopes determine occurrences.
|
||||
- Whole target equal to original: successful empty plan, unchanged parse/numeric/frame Usage, no emitted bytes during planning. A sparse entry saying the same name need not exist at all because intent comes from the whole target.
|
||||
- Rename f->g while global g remains g: reject collision, even if g has no reference uses.
|
||||
- Rename one parameter to an unchanged sibling's name: reject; the same name in a different calculation is allowed.
|
||||
- Rename plus display-name edit, body value 1->2, changed unit scale, parameter reorder/insertion/type, relation endpoint, node position, diagram ownership, trace baseline or schema/ID change: reject the **whole** target before any output. Reidentity, missing-ID stabilization and movement have no route through this API.
|
||||
- Retained source entry/path/file-set or untouched file differs in a supplied current snapshot: reject stale snapshot, even if every touched token still matches.
|
||||
- Same semantic desired Project but source style changes requested implicitly: source style is not part of target rename intent; all original trivia remains exact.
|
||||
|
||||
## Ledger and output preflight
|
||||
|
||||
Let B be inherited retained ledger; Q all qualified global+parameter names; R changed qualified targets; M changed physical tokens across both families; E old expression sites; F original files. Under the recommended borrowed-target/two-map plan:
|
||||
|
||||
- added retained storage: **R+M entry slots, zero occurrence slots, zero copied name bytes**;
|
||||
- equality scratch: explicitly reserved E upper-bound entries, released before name collection;
|
||||
- namespace scratch: Q entries while R changed-name entries exist; release after the set drops;
|
||||
- no typed Path allocation/clone, extra source table, identity Vec, family adapter table or seen-edit set;
|
||||
- no new Budget::frame, parse/reference/Exact charges in planning.
|
||||
|
||||
A clean phase order gives a conservative added peak `max(E, R+Q, R+M)` with no copied replacement text, provided gate/name passes really do not overlap those temporaries. Any implementation that combines phases must count the actual overlap instead. The owned-target/owned-name variant additionally retains sum UTF-8 bytes of R copied final names. Reservation checks must precede growth; failure drops the whole attempt. Test caps with fixtures where this phase's bound actually exceeds all earlier parser/resolver/index peaks—the ordinary-index work demonstrated why stage-local arithmetic alone is insufficient.
|
||||
|
||||
For combined sizing, walk canonical files and sorted edit keys together. Checked subtraction/addition computes each final file length; sum **all** output file lengths, including unchanged files. The scalar maximum/total can be computed without a retained F-entry lengths map; emitting later can repeat the same bounded calculation. Validate the final combined output bound, not a hypothetical typed-only intermediate, so one producer's shrink can compensate another's growth. Shrink does not reduce currently live B/R/M storage.
|
||||
|
||||
Actual SourceBundle construction adds F map entries plus all new source bytes, canonical path-key copies and the entry-path copy. Those owned path/text allocations need explicit reservations too; model/validator heap exclusion does not make a copied SourceBundle free. If lengths are retained, add F slots. If Vec sorting is chosen instead of a BTreeMap, ordinary stable `sort_by_key` may allocate sort scratch; choose an in-place unstable order or reserve its scratch. There is no need for that choice with the proposed physical map.
|
||||
|
||||
A future pure emitter can require a complete current `&SourceBundle` and compare it to the retained original bundle (entry, canonical path keys, exact file set and bytes) immediately before use. No caller-supplied replacement Budget/profile. This detects stale supplied snapshots; it does not by itself provide atomic disk/history/GUI installation, which belongs to later owner integration.
|
||||
|
||||
## Emission/readmission questions that must not be hidden
|
||||
|
||||
1. **Same policy versus cumulative work:** parse_with_profile currently starts a new Budget even when its Limits match. Reusing parse() loses tightened profile values; passing the old charged Budget to a new parser would count original+output bytes/tokens/Exact work cumulatively and can reject an otherwise in-profile near-limit rename. Parent must define whether re-admission is a same-policy per-snapshot parse with a separately bounded transaction peak/work total, or a cumulative operation budget. Recommendation: preserve exact inherited Limits/caller policy, keep all live allocations in one transaction accounting boundary, and explicitly specify work counters for the deliberate new snapshot parse. Do not silently reset counters or claim unchanged numeric work after actual-output parsing. Planning alone must leave all Usage untouched.
|
||||
2. **Live overlap:** output strings coexist with the old witness until emission finishes; actual verification may also create new syntax/arenas/maps while old state survives. Current resolve creates its own fresh Ledger and has no external baseline reservation seam. Either drop old auxiliary state at a documented consumed transition before compiling (retaining only needed intent/policy/output) or add a narrow accounted verification seam that includes the retained old baseline. Do not add two individually passing ledgers and call that an aggregate bound.
|
||||
3. **Returned ownership:** a new ResolvedMixedProject borrows the emitted SourceBundle. Returning both as ordinary fields of one owning struct would be self-referential. A narrow acceptance result can own output SourceBundle plus the resolved Project/warnings/metadata **after** dropping temporary syntax/index, via a private consuming parts seam; it must not claim to retain a reusable source index. Another option is a callback-based borrow after installing output ownership, but that is a wider integration choice. Reindexing the accepted output for the next edit is a separate lifecycle/work cost to state, not a hidden free operation.
|
||||
4. **No-op execution:** an empty plan can preserve the original owner without parsing/emitting identical bytes. If the downstream API always returns a newly owned bundle, that entails copies and their bounds even for no-op. Prefer an explicit unchanged outcome for eventual execution; settle its type before promising zero-allocation no-op apply.
|
||||
5. **Target/equality policy:** decide borrowed versus consumed desired Project, and existing structural PartialEq versus bitwise geometry equality. These affect API/storage and exact supported/rejected examples, not rename token logic.
|
||||
|
||||
These are concrete seam decisions, not reasons to weaken the whole-output admission/equality gate. A planning-only dependency can be implemented before them if its output is honestly only a read-only verified plan. An emitted result cannot be called accepted until actual original-coordinate output is parsed, completely resolved/admitted and compared with the whole independent target, with no usable partial result after failure.
|
||||
|
||||
## Discriminating acceptance before edit execution
|
||||
|
||||
Require independent exact plans for whole-project/scoped swaps, both reference directions, repeated/reordered calls, all ordinary categories, same parameter UUID across calculations/global, comment-separated markers and Unicode/CRLF. Include no-op and changed-to-unchanged collision. Reject one mutation from each non-rename field group and map/parameter identity/order change; include target-only deep/wide payload damage to prove bounded equality behavior. Check entire old and desired Projects remain unchanged and the exact whole target is retained by the plan lifetime.
|
||||
|
||||
Corruption controls should distinguish missing/extra edit, wrong qualified target, duplicate/overlapping location, stale touched and untouched files, changed entry/path/file set, invalid UTF-8 location and safe diagnostic fallback. Existing sealed original completeness plus exact plan equality supports missing planned-edit rejection; it does not claim arbitrary coordinated corruption of the original lowerer/projection.
|
||||
|
||||
Hand-count B plus R/M/E/Q peaks, candidate replacement-byte checks and eventually output F/path/text growth. Assert planning parse/numeric/frame usage unchanged, with actual later reparse counters separately specified. Use exact cap/cap-minus-one cases that demonstrably pass predecessors. Small-stack tests must exercise equality, success/drop and representative late refusal rather than only parsing.
|
||||
|
||||
Preserve legacy update/Composition oracles in `language/analysis_source/update/tests.rs:134,212,257,275,304,327,508,563,622,688,714`; do not rewrite them to accept mixed authority. Subsequent emitter tests need exact whole-file outputs, combined growing/shrinking bound cases including untouched files, malformed and admissible-but-wrong output controls reaching actual Project equality, and no history/save adoption on late failure.
|
||||
@@ -0,0 +1,192 @@
|
||||
# Complete-target mixed rename planning contract
|
||||
|
||||
2026-09-24. Accepted successor to verified private source
|
||||
`ee500908e3d77182ddd54e12524f9b6c6eb43b60`, after
|
||||
[source mapping](analysis-mixed-rename-plan-20260924/RENAME-PLAN-SOURCE-MAP.md) and
|
||||
[independent critique](analysis-mixed-rename-plan-20260924/RENAME-PLAN-CRITIQUE.md).
|
||||
This document does not change user-owned requirements. Implementation and
|
||||
runtime acceptance remain separate gates.
|
||||
|
||||
The user requires complete graphical/text/API editing parity. This dependency
|
||||
verifies whole-model rename intent and complete original-coordinate token edits.
|
||||
Output emission/admission, other scalar and structural edits, public source8,
|
||||
history and checked persistence remain required subsequent capabilities.
|
||||
|
||||
## Inputs, ownership and result
|
||||
|
||||
Consume one opaque `AuthoredMixedProject` and immutably borrow one independently
|
||||
supplied desired `Project` for the returned plan's lifetime. The original owner
|
||||
retains its exact SourceBundle, canonical files, complete admitted model,
|
||||
warnings, both occurrence families, qualified names and inherited limits/ledger.
|
||||
Never accept replacement source, profile, occurrence maps or caller edit batches.
|
||||
Failure returns diagnostics and drops the consumed attempt; no partial plan
|
||||
escapes. The desired Project is neither changed nor normalized.
|
||||
|
||||
The returned private plan owns the original witness and exactly two maps:
|
||||
|
||||
- changed qualified `Target` to a borrowed desired-name `str`;
|
||||
- original physical `(canonical_file, alias_start, alias_end)` to qualified Target.
|
||||
|
||||
The desired Project is an external immutable borrow, not a field that another
|
||||
field borrows. No whole-Project/name clone, typed Path copy, separate per-family
|
||||
batch, duplicate source table or legacy Index conversion is needed. Read-only
|
||||
inspection derives replacement text from the retained name map and original
|
||||
token text from the original witness. Inspection records cannot install a subset
|
||||
or transfer authority to another source owner.
|
||||
|
||||
Borrowing the desired model avoids copying names and model state. Consuming a
|
||||
desired model and copying changed names remains a justified alternative only if
|
||||
a real integration owner needs independent target lifetime. A generic model diff,
|
||||
serde conversion, alias-erased Project clone and two legacy producer adapters
|
||||
introduce unnecessary storage or authority boundaries for this scope.
|
||||
|
||||
## Whole-target gate
|
||||
|
||||
Compare fixed collections by length, ordered key and each record's own identity.
|
||||
Walk borrowed collections; do not allocate `Project::identities()` or clone
|
||||
payloads. Use exhaustive struct destructuring without `..` for the records whose
|
||||
alias/name fields are exempted, so added fields require an explicit decision.
|
||||
|
||||
Only global aliases and calculation-parameter names may differ. Require:
|
||||
|
||||
1. Project schema, ID, display name, description and complete collection sets.
|
||||
2. Definitions' IDs, display names, descriptions and body variants. QuantityKind
|
||||
and Unit payloads compare in full. Calculations retain parameter count and
|
||||
each parameter's ID **at the same ordered position**, value type, result and
|
||||
body. Only definition alias and scoped parameter name are exempted.
|
||||
3. Elements' IDs, display names, descriptions, parents and full bodies; relations'
|
||||
IDs, display names, descriptions and full bodies.
|
||||
4. Diagrams' IDs, display names, descriptions, layer, projection, view options,
|
||||
routes and node-key sets. Each node retains ID, element, position, size,
|
||||
collapsed state and port anchors. Only diagram/node aliases are exempted.
|
||||
5. Artifacts' and traces' full non-alias fields, including endpoints, historical
|
||||
baselines, URI, revision, fragment and prose.
|
||||
|
||||
Equality follows existing whole-model PartialEq semantics. In particular,
|
||||
positive/negative floating zero are equivalent in all existing carriers,
|
||||
including scalar data and historical facets, not just geometry. This does not
|
||||
authorize rewriting any non-name source bytes. The emitter must preserve those
|
||||
bytes exactly. Nonfinite originals are excluded by existing admission.
|
||||
|
||||
Opaque unchanged payloads may use existing equality after checking variants and
|
||||
container sizes. Their expression comparator is iterative **and allocates** a
|
||||
work Vec. Reserve E scratch entry slots before this gate, where E is the total
|
||||
retained original raw expression-node/site count. Sequential comparisons have
|
||||
at most a frontier of E distinct old nodes. List/call sizes are checked before
|
||||
pairing, and variant mismatches refuse before traversing a target-only tree.
|
||||
When E=0, no Expr comparison may be invoked. Release this reservation only after
|
||||
the equality calls and internal vectors finish. This conservative bound can
|
||||
require headroom even for no-op intent; do not promise every accepted owner can
|
||||
plan under an exactly exhausted profile.
|
||||
|
||||
Current reachability must be proved from all four roots: calculation body,
|
||||
engineering-property base, analysis-case overrides and analysis-check predicate.
|
||||
Historical semantic payloads use their distinct lifeline binding and string
|
||||
expression fields. An added Expr carrier requires revisiting the bound. If that
|
||||
proof fails, add a narrow budgeted equality seam rather than duplicating a full
|
||||
expression matcher or treating its allocations as free.
|
||||
|
||||
## Final namespaces and exact edits
|
||||
|
||||
After releasing comparison scratch, collect only changed qualified names. Check
|
||||
their cumulative UTF-8 byte lengths against the inherited source-byte limit
|
||||
before validating their characters; borrowed external strings do not justify
|
||||
unbounded scanning. Use the existing ASCII/reserved-word alias predicate.
|
||||
|
||||
Validate final names across the entire original catalog simultaneously. Global
|
||||
aliases share one namespace. Parameters share a namespace only within their
|
||||
owning calculation. Identity is qualified even if UUIDs or spellings coincide.
|
||||
Every changed target must exist in that catalog. Use a borrowed temporary set of
|
||||
`(scope, final_name)` with explicit entry reservations. Drop it before collecting
|
||||
edits. A no-change result may reuse the already accepted original namespaces.
|
||||
|
||||
Walk both complete authenticated occurrence families. For each changed target,
|
||||
insert its whole alias-token range and qualified identity into the single edit
|
||||
map, reserving before insertion and refusing a duplicate physical key. Ordinary
|
||||
records resolve to Global; typed records retain their existing qualified target.
|
||||
Markers, trivia, prose, historical UUIDs, includes and unrelated bytes are never
|
||||
replacement ranges.
|
||||
|
||||
Validate membership, original spelling, nonempty whole UTF-8 token spans and
|
||||
monotone/nonoverlapping physical order. Rescan both original occurrence families
|
||||
to require every changed occurrence exactly once with the right target and no
|
||||
unchanged occurrence; compare total required count with edit-map length to rule
|
||||
out extras without an extra seen set. A changed alias with only its header still
|
||||
requires that header edit. Complete-set authority cannot be reduced to a caller's
|
||||
selected edit list.
|
||||
|
||||
Expose a private complete-current-bundle validation seam for the eventual
|
||||
emitter: entry, canonical path keys, exact file set and every file's bytes must
|
||||
equal the original witness, including untouched files. A supplied snapshot check
|
||||
alone does not promise an atomic filesystem/history installation.
|
||||
|
||||
## Storage and combined sizing
|
||||
|
||||
Let B be the inherited live ledger, Q the complete qualified-name count, R changed
|
||||
targets, M changed physical occurrences and E the bound above. The selected phase
|
||||
order has added peak `max(E, R + Q, R + M)` when namespace checking is required.
|
||||
Successful retention is exactly R+M entry slots, zero occurrence slots and zero
|
||||
copied text bytes. Count any implementation-added temporary container explicitly.
|
||||
Reserve before growth; release after the logical entries/containers cease to be
|
||||
live. Parsing/frame/reference/numeric Usage is unchanged by planning.
|
||||
|
||||
Compute each final file length while merging canonical files and sorted edits.
|
||||
Sum that file's removed and replacement byte totals separately using checked
|
||||
arithmetic, then subtract removed bytes before adding replacements. Sum all
|
||||
final files, including untouched files, and
|
||||
check the inherited complete output-byte limit. Do not enforce a separate typed
|
||||
intermediate size: one family's shrink may offset the other's growth. A lengths
|
||||
map is unnecessary; a later emitter may repeat the bounded sizing walk. Shrink
|
||||
does not reduce the still-live B/R/M reservations.
|
||||
|
||||
## Required behavior and acceptance
|
||||
|
||||
Support complete project/ordinary/typed alias changes, simultaneous global swaps,
|
||||
scoped parameter swaps, repeated/reordered call labels, cross-family references,
|
||||
same spelling in distinct scopes and no-op intent. Reject collision with an
|
||||
unchanged member in the same scope, invalid aliases, unknown/changed IDs,
|
||||
parameter reorder/add/remove/type change and every non-name semantic mutation.
|
||||
Reject the entire target before output; no partial success or repaired identity.
|
||||
|
||||
Use independently authored complete physical edit maps and final-name sets.
|
||||
Include OA/SA, canonical cross-file order/coincident offsets, Unicode/CRLF,
|
||||
line-comment-separated references, all ordinary categories and historical UUID
|
||||
exclusion. Verify unchanged original/desired Projects, exact desired borrow,
|
||||
original bundle authority, inherited Usage and R+M retention.
|
||||
|
||||
Attempt one unsupported mutation in every exempted-record field group; include
|
||||
target-only deep/wide expression damage, mismatched list/call sizes and zero-E
|
||||
variant changes. Verify the conservative equality bound with wide and deep old
|
||||
trees and signed-zero equivalence in geometry/scalar/historical carriers.
|
||||
Corrupt missing/extra/wrong-target edits, overlap, stale touched/untouched files,
|
||||
entry/path/file-set and UTF-8 spans, requiring safe original diagnostics.
|
||||
|
||||
Hand-count realistic B+scratch peaks and cap/cap-minus-one cases that actually
|
||||
pass predecessor phases. Exercise small-stack gate comparison, success/drop and
|
||||
late refusal. Preserve existing legacy Plan/Composition tests, all private
|
||||
baseline outcomes and explicit known full-suite/formatting failures.
|
||||
|
||||
## Mandatory successor: accepted rewritten output
|
||||
|
||||
An opaque plan is not accepted edited source. The next execution contract must
|
||||
emit every file once from original coordinates, own complete output strings/path
|
||||
keys/entry with F map slots and all copied bytes accounted, parse/resolve/admit
|
||||
those actual bytes, and compare the entire resulting Project with desired intent.
|
||||
It must reject admissible-but-wrong output as well as malformed output.
|
||||
|
||||
Preserve the exact inherited policy for each deliberate snapshot parse; do not
|
||||
use a default profile or silently reset a live witness. Specify new-snapshot work
|
||||
counters and one aggregate live-storage boundary. Output coexists with B during
|
||||
emission. Before verification, either drop the consumed old auxiliary owner at a
|
||||
documented transition while retaining output/intent/policy, or explicitly charge
|
||||
both owners together. A fresh independent Ledger cannot hide live output storage.
|
||||
Parser metadata and resolver storage need the carried surviving baseline. The
|
||||
final whole-Project equality also needs its E scratch reservation even if the
|
||||
old witness has already dropped; retain E as scalar verified metadata.
|
||||
|
||||
Returning an owning bundle alongside syntax that borrows it would be self-
|
||||
referential. Prefer a narrow owning accepted result after temporary verification
|
||||
syntax drops, or explicitly justify another lifetime design. No-op execution
|
||||
should preserve the original owner through an explicit unchanged outcome. No
|
||||
usable partial result or history/save adoption may escape failed verification.
|
||||
These are constraints for the successor, not an already implemented execution API.
|
||||
@@ -0,0 +1,47 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,121 @@
|
||||
# Ordinary original-coordinate occurrence successor: source map
|
||||
|
||||
2026-09-24. Local-only bounded research by `/root/mixed_index_source_review` (GPT-6 Astra). Parent owns contract adoption, implementation, integration and publication. No source edits, Cargo, runtime checks, or posts. This report does not reopen the accepted typed index.
|
||||
|
||||
## Recommendation and evidence version
|
||||
|
||||
The next useful dependency is a **private, consumed owner of the complete authored name-occurrence set**: retain accepted `IndexedMixedProject`, add ordinary/project alias headers and every ordinary authored `@alias` leaf, and keep both occurrence families bound to its original complete bundle and inherited ledger. Do this before adapting edit production. It can reuse the retained ordinary position trees without another parser, ordinary decoder, formatter, or new generic indexing framework.
|
||||
|
||||
Then implement a precisely gated **global/scoped rename-only** original-coordinate composition route using this owner and one independently supplied complete target Project. Ordinary scalar changes, insertions, type changes and structural moves are later explicit operation families. This sequencing avoids promising that the existing general ordinary producer already obeys a new mixed one-pass protocol. It is a bounded dependency toward full parity, not an alternative end state.
|
||||
|
||||
All source references below are relative to the repository at `.local/as3batch`, clean branch `codex/analysis-mixed-index-956atf-20260924`, commit **`93eb6117f95353d25d594d59780018f197c51672`**. References are to `crates/oa-core/src/` unless prefixed `tests/`. Governing root documents read:
|
||||
|
||||
- `harness/analysis-mixed-index-contract-20260924.md`, SHA-256 `A344C69068DCE09A9B03BD3002020C87AFC563C7B4CC859522DDA0D4048CD3FB`.
|
||||
- `harness/analysis-mixed-project-contract-20260923.md`, SHA-256 `D10D3EB32122FDF0E6570962C98871D6907E9FE59DBD6ECCF00DF64082E7382F`, especially retained syntax/site handoff and aggregate accounting.
|
||||
- `harness/analysis-original-span-review-20260923.md`, SHA-256 `F7200342EA280EF96E80914E336AF0203AEAB530A5255E57D10AA8E763DBE05F`, especially exact diff gates, producer normalization, full-snapshot authority and combined output checks.
|
||||
|
||||
Recommendations below are proposals for parent adoption. Source facts and inherited requirements are identified separately.
|
||||
|
||||
## Source-grounded seam map
|
||||
|
||||
| Existing seam | Verified capability and implication |
|
||||
| --- | --- |
|
||||
| `language/analysis_source/mixed.rs:39`, `:49` | `ParsedMixedSyntax` owns the exact bundle borrow, caller limits, canonical `files`, Budget and metadata; each `FileSyntax` retains full-file significant tokens, ordinary `SourceUnit`, typed declarations, `positions: Vec<(Id, EditDeclaration)>`, and lexical-owner indices. No remapping or duplicate source table is needed. |
|
||||
| `language/analysis_source/mixed.rs:316`, `:332`, `:357` | Ordinary positions are already projected once from that file's retained tokens and original AST after aggregate metadata preflight; the complete result retains those positions. Calling `edit_declarations` again would discard this advantage and charge/work outside the witnessed path. |
|
||||
| `language.rs:926`, `:943` | `EditDeclaration` has full-file span/body/header-role spans, lexical owner, and a recursive `EditValue` tree. `EditKind` distinguishes Reference, HistoricalUuid, Atom, Record and List. This is enough to enumerate ordinary name tokens and preserve original nesting without reconstructing the generic model schema. |
|
||||
| `language.rs:1068`, `:1076`, `:1100` | Projected Reference/HistoricalUuid spans start at the marker and end at the second significant token; ordinary declaration header maps already expose the alias token. Stabilized IDs are required. A Reference's entire span is not the replacement span: it can contain `@`, whitespace and comments. |
|
||||
| `language.rs:895`, `:1437` | `SourceHeader` records the project/header/body/description but no header-role token map. Project alias is the one missing small position projection. Its original header start and complete token stream are already retained. |
|
||||
| `language.rs:761`, `:782`, `:799` | Admitted ordinary `Ast::Reference` resolves through the global alias catalog; quoted strings in reference fields are refused. Arrays and records recurse through the same resolver. Ordinary live name uses are not guessed from arbitrary strings or UUID-looking text. |
|
||||
| `language/semantic_source.rs:13`, `:34`, `:87` | Semantic Trace baselines reject `@alias` and require historical `uuid "..."` in typed reference slots. Those UUID leaves are not current alias references. Other baseline fields pass through ordinary resolution; the occurrence walker should follow actual `EditKind`, not blindly exclude every field named baseline. |
|
||||
| `language/analysis_source/mixed/project.rs:38`, `:43`, `:83`, `:91` | The accepted typed index consumes its resolved witness; the output retains original bundle, canonical files and complete qualified names. A private child module beside this owner can borrow retained fields during construction without exposing replaceable provenance. It need not create a legacy numeric-map Index. |
|
||||
| `language/analysis_source/mixed/project.rs:405` | `active_references` only meters selected steps/occurrence/contextual-chain arrays. **It is not a completeness selector for alias occurrences.** Scalar parents, view references, route endpoints, artifact owners and trace endpoints also need rename occurrences. Reusing this hook would omit valid ordinary uses. |
|
||||
| `source_project.rs:93`, `:417` | Public `SourceIndex` catalogs declaration/body/field/include locations and lexical ownership, not all name/reference tokens. Its fields are public. It is neither the missing occurrence index nor a trustworthy mixed constructor input. |
|
||||
| `source_project.rs:640`, `:647`, `:735` | The public updater recompiles mutable public state, then reparses every original file with `edit_declarations`. It formats old/new declarations and parses those formatted texts to produce a generic syntax diff. This route cannot simply be called on private mixed source8. |
|
||||
| `source_project.rs:1043`, `:1075` | `SyntaxUpdate::value` already demonstrates correct preservation for Reference→Reference: replace the last significant alias token only. Reuse that behavior, using retained full-file tokens; do not copy its per-fragment `significant()` rescanning into the new index. |
|
||||
| `source_project.rs:1104`, `:918` | Other syntax-kind changes erase individual significant tokens and insert replacement text at the same original start, retaining trivia. Their insertion/deletion pairs do not obey a blanket no-shared-boundary rule without producer-local normalization. This is why rename-only is a precise first scope. |
|
||||
| `source_project.rs:539` | Existing `apply_edits` groups every equal `(start,end)` span by concatenating replacement strings, then applies backwards. That permissiveness is not an acceptable cross-producer authority rule for duplicate nonempty replacements. |
|
||||
| `source_project.rs:868`; `source_project/source_structure.rs:34`, `:61` | Ordinary scalar edits are applied before the structural updater reparses their result. Those structural spans are in later coordinates. Preserve this public behavior until a separate verified integration replaces it; it is outside the original-coordinate one-pass proof. |
|
||||
| `language/analysis_source/update.rs:78`, `:118`, `:169`, `:227` | Existing typed Plan/Composition cleanly separate complete name/edit membership validation from standalone output length checks, but still require legacy `Index` and caller numeric sources/Budget. Their algorithm is useful; their nominal input authority is deliberately incompatible with mixed input. |
|
||||
| `source_project.rs:877` | Existing final acceptance recompiles actual emitted bytes and compares the entire resulting Project to intent. The private mixed route needs the equivalent complete parse/resolve/admission/equality boundary, with no public source8 dispatch implied. |
|
||||
|
||||
The retained scanner in `language/analysis_source/lex.rs:18` charges raw tokens, including trivia, and retains significant token spans. Reference indexing can therefore binary-search the original `@` token, require the immediately following significant token to be a Word with exact catalog spelling, and preserve all intervening comments without allocating a new token stream.
|
||||
|
||||
## Proposed next-index contract
|
||||
|
||||
### Scope and ownership
|
||||
|
||||
Consume the accepted typed-index owner into another private nominal wrapper, or use an equivalent internal consumed construction step that retains all its fields. Name its capability precisely: complete **authored name occurrences**, not complete scalar/structural editing authority. No public or sibling-fabricable input accepting a Project, token table, occurrence list, source remap or replacement Budget. Do not clone the existing catalog or typed maps; move/retain them once. Avoid self-references: new records own IDs, roles and spans; temporary reverse catalog maps borrow names only during construction.
|
||||
|
||||
The new ordinary set consists of:
|
||||
|
||||
1. The project alias header, once.
|
||||
2. Each ordinary declaration alias header, once, including elements, relations, diagrams, nodes/placements, artifacts and traces actually represented by those declarations.
|
||||
3. Every `EditKind::Reference` in every ordinary declaration field tree, including nested records/lists and repeated equal targets. Resolve each spelling to `Target::Global` through the already admitted complete catalog, which includes typed globals. Ordinary references never resolve through parameter-only name entries.
|
||||
|
||||
It excludes display names, descriptions, comments, string literals, enum words, include path strings, declaration identity strings and `HistoricalUuid` leaves. Implicit lexical parenthood is a semantic relation with **no alias token**; do not manufacture a reference for it. Explicit `parent @name` is an ordinary reference and must be indexed. Current mixed syntax permits nested ordinary declarations but explicitly refuses typed headers nested in ordinary bodies (`mixed/tests.rs:448`); do not widen that grammar as part of indexing.
|
||||
|
||||
### Minimal construction/verification
|
||||
|
||||
- Iterate canonical files and their retained ordinary positions. Check the declaration position/ID/header against the corresponding sealed ordinary declaration rather than resolving owner from a coincident offset or the outermost enclosing span. Nested parent declaration spans overlap child spans, so broad range scanning is not a valid ownership rule.
|
||||
- Use the existing ordinary header alias span. Project header needs only a narrow retained-token projection anchored at `SourceHeader.span.start`: validate `project`, the following whole alias token and its equality to the retained Project alias. There is no need to call `edit_header(source_slice)`, which lexes again (`language.rs:951`), or build a second complete header grammar. A shared borrowed token-role helper is reasonable only if it remains small and preserves ordinary parser behavior.
|
||||
- Walk `EditValue` Record/List iteratively, reserving each live walk slot. An encountered Reference must have valid UTF-8 full-file range, marker `@`, precisely the expected following whole Word alias token and canonical target spelling. Store/edit the alias token span alone. Track the owning declaration and retain its original file. Require field/declaration containment where justified; do not confuse overlapping declaration bodies with reference ownership.
|
||||
- Reject duplicate physical token ownership across the combined typed and ordinary sets, including ordinary headers. Count the project header and every global declaration exactly once across the two producer families. A reverse global-name map excludes scoped parameters and borrows the existing names.
|
||||
- Continue using explicit safe fallback diagnostics for an unowned/invalid numeric file or malformed span. No panic-prone slicing during error transport. Failure consumes/drops the whole attempted owner and exposes no usable partial index.
|
||||
|
||||
Completeness is obtained by exhaustive traversal of the sealed retained parser projection and independently authored output oracles. The existing parser/projection is the trusted emission source. A new reference map does not, by itself, prove arbitrary damage that consistently removes the same reference from retained AST and position tree. If runtime detection of arbitrary projection omissions is required, specify a separate AST↔position walk and account for it; do not silently claim that a token-spelling check proves it.
|
||||
|
||||
### Key representation: consequential but bounded choice
|
||||
|
||||
| Candidate | Tradeoff against requirements |
|
||||
| --- | --- |
|
||||
| One ordinary map keyed by canonical `(file, alias-token start, alias-token end)`, values contain declaration owner, Header/Reference role and global target | Recommended for this snapshot-bound rename dependency. Repeated references remain distinct; deterministic physical ordering is immediate; keys need no copied field strings or new path tree. Identity is explicitly ephemeral to this exact immutable snapshot, never a persistent model/command identity. Retained EditValue trees remain the richer structural source for later operations. |
|
||||
| Owned structural ordinary keys with record-field/list-index path, comparable to typed paths | Better for structural diagnostics and future field editing, but adds a new edge type, persistent-path storage/drop policy, field-name ownership and duplicated tree metadata before a consumer requires it. Reconsider when a concrete scalar/subtree editing contract needs stable structural keys; list indices still do not supply semantic row identity across edits. |
|
||||
| Reuse generic `SyntaxUpdate` as the ordinary index or run public `update_bundle` | Produces broad changes but reparses/formats, lacks retained occurrence authority and includes later-coordinate structural processing. Rejected as the next private original-coordinate seam. |
|
||||
| Scan all original Word tokens for catalog names | Superficially small but changes prose/enums/include/header roles incorrectly, cannot establish owner and cannot distinguish historical semantics. Reject. |
|
||||
|
||||
Do not force ordinary roles/keys into typed `Field`/`Child` enums. Two sealed occurrence families can share checked source/token lookup and physical-edit validation without a public generic indexing framework. Any helper extraction must leave the accepted typed semantics intact.
|
||||
|
||||
### Aggregate storage proposal
|
||||
|
||||
Continue the retained mixed Ledger/Budget; accepted typed maps and raw arenas remain live. If the recommended one-map representation has D ordinary declarations and A ordinary Reference leaves, its additional retained entry count is **`N = 1 + D + A`**, zero new lowerer-occurrence slots and zero new owned-name bytes. This formula assumes inline owner/role/target/span records and no copied structural path. Any extra retained map/vector must be added explicitly.
|
||||
|
||||
Scratch must include the borrowed reverse global-name map Gg, an efficient cross-producer physical-token lookup for T existing typed locations if used, live iterative walk slots W, and any owner/header/AST↔position validation table actually allocated. A design can use the new map itself for ordinary duplicate-token detection and a T-slot scratch set for typed collision lookup; there is no need to retain a second ordinary physical set. Then a conservative simple peak is baseline plus `N + Gg + T + W`; actual prefix/phase peaks must be hand-counted for cap tests. This is a proposal, not a measured cap.
|
||||
|
||||
Reserve before every growth/copy; release scratch only after its allocation is dropped. Borrowed names require map entry slots but no copied text charge. New index records belong to entry slots under the existing contract; do not recharge the old `Budget.reference` parser/active-step counters or lowerer occurrence domain. Do not call `Project::identities()` merely to build another name Vec. If structural keys are chosen instead, inventory their owned field strings and unique path nodes before accepting the alternative.
|
||||
|
||||
The ordinary tree was already admitted under its existing depth policy; an iterative reference-only walk need not introduce a new frame interpretation. Preserve inherited frame limits, never widen them, and do not confuse live work-slot reservations with `Usage.deepest_frame`. If an explicit depth check is added, specify whether it uses original ordinary depth or a structural path depth; `Budget::frame` may update the high-water mark, but index scratch does not change parsed byte/token/entry/reference counts. The existing baseline, raw typed arenas and typed persistent Path reservations must survive unchanged throughout this successor.
|
||||
|
||||
## Subsequent rename composition seam
|
||||
|
||||
This section establishes dependencies, not permission to broaden the next index patch.
|
||||
|
||||
1. **Single intent:** derive global aliases and calculation-scoped parameter names by stable identity from one complete target Project and the complete source owner. Validate final global/scoped namespaces simultaneously, permitting swaps. Do not accept independent ordinary and typed final-name maps that can disagree.
|
||||
2. **Exact diff gate:** for the first rename route require equality of every old/new Project part except the expressly allowed aliases/parameter names. Global IDs/categories, parameter IDs/order/types, all expressions/bindings/subjects, arrays/order, geometry, names/descriptions, baselines, ownership and all other fields remain equal. Do not silently ignore a scalar change because no occurrence changed. An explicit gate is narrower and clearer than the phrase topology-preserving. The comparison strategy should be chosen before implementation; copying/masking a whole model has allocation implications, while borrowed structural comparison needs complete field coverage.
|
||||
3. **One owner/profile:** keep the complete entry, canonical paths, file set, bytes, caller limits, complete old model and index authority bound together. A batch from a different owner cannot be installed merely because touched token bytes or numeric keys match. Bind producer objects to this owner rather than weakening legacy `Index` typing. The existing borrowed `OriginalEdit` is only an inspection record (`update.rs:292`), not transferable authority.
|
||||
4. **Small shared algorithms:** reuse/extract private final-name validation, token-membership and edit-order/completeness logic from `update.rs:35`, `:79`, `:117` behind authenticated wrappers when implementing composition. Keep legacy `Plan` behavior and its standalone output preflight. The mixed route must use aggregate live plan storage against its retained ledger, not simply inherit old per-map checks or build a temporary numeric-source `BTreeMap` copy.
|
||||
5. **Original edits only:** both families produce alias-token replacements in original file coordinates. This rename-only set has nonempty whole-token ranges and needs no zero-width insertions. Reject duplicates/overlaps across producers; every changed target's entire authenticated occurrence set must be present, including ordinary→typed and typed→ordinary references. Preserve all other bytes exactly.
|
||||
6. **Combined preflight/output:** count retained plan records, owned replacement names and scratch before allocation; then compute complete combined per-file and aggregate output lengths, including unchanged files, before constructing output. A shrink may compensate output growth, but cannot erase live source/index/plan storage or prior parse/numeric costs. Emit each file once from original bytes in ascending span order. No `Plan::apply` typed-first intermediate followed by ordinary offsets.
|
||||
7. **Actual result acceptance:** parse/resolve/admit the emitted complete bundle under the retained policy and compare the entire Project to the independent target. Return/install nothing on failure. New output gets its own bounded parse pass; do not reset original usage to hide redundant work. Public source8, checked-save/history and GUI activation are later gates.
|
||||
|
||||
When adding ordinary scalar operations, define exactly allowed leaf/header forms and a reviewed same-producer normalization for type changes and ordered insertion groups. `SyntaxUpdate` has comment-preserving behavior worth retaining, but its current compound edits require that extra contract. Never relax duplicate/overlap rules globally to accommodate one producer. When adding structural movement/deletion, redesign composition of its ownership pieces in original coordinates or provide a separately verified transformation; the current reparse-after-scalar phase is not evidence for one-pass original-coordinate correctness.
|
||||
|
||||
## Required independent evaluators and concrete risks
|
||||
|
||||
For the proposed **read-only ordinary occurrence index**:
|
||||
|
||||
- Hand-enumerate every ordinary/project header and every Reference tuple `(canonical file, owner, role, global target, full reference extent, alias-token span, spelling)` in tiny OA and SA mixed bundles. Include interleaved typed roots, nested ordinary declarations, explicit and implicit parents, reversed include traversal versus canonical file order, coincident offsets across files, Unicode/CRLF and same-spelling comments/prose. Compare complete sets, not selected counts. Expectations cannot come from builder, formatter or lowerer.
|
||||
- Extend the current independent rich fixture (`mixed/project/tests.rs:253`): its `node n` references ordinary diagram d and typed property v, while typed property v refers to ordinary work w. Enumerate ordinary project/node/work/diagram headers and references in addition to the already accepted typed maps. Shared parameter UUID/global identity remains distinct and cannot enter the ordinary reverse alias map.
|
||||
- Add category/shape coverage beyond that small fixture: relation endpoints and nested contextual chains, diagram routes/view options, artifact owner, live trace endpoints, nested records/list repeats, and semantic historical UUIDs that coincide with a renamed live target. The latter must remain absent from alias occurrences. Include paths and display/prose alias text stay untouched.
|
||||
- Prove `@ /* comment */ alias` indexes only the alias token and preserves marker/trivia; test wrong marker, non-Word token, partial alias range, wrong name/global target, duplicate physical token, owner/file mismatch and UTF-8-split/out-of-range locations reaching intended checks. Distinguish per-record corruption checks from sealed-emission completeness assumptions.
|
||||
- Hand-count retained N and peak scratch with accepted typed/maps/syntax baseline still present. Exact cap and cap-minus-one must isolate index growth, not an earlier parse. Parse bytes/tokens/entries/references/Exact work remain unchanged; any frame metric change must have an explicit permitted reason. Success and representative late failure/drop run on the existing small-stack harness.
|
||||
- Preserve exact bundle pointer/bytes/entry/file keys, entire Project, warnings and static admission metadata; no mutable authority or legacy updater conversion escapes. Run only affected existing suites after implementation; retain explicit inherited failure dispositions.
|
||||
|
||||
For **later rename composition**, separately require exact authored whole-output oracles: simultaneous global/scoped swaps; repeated/reordered typed calls; both reference directions and untouched unrelated files; project/ordinary/typed header renames; same-name no-op; comments/prose/historical UUID unchanged; mixed growing and shrinking replacements with exact combined output cap; stale entry/path/unrelated file; cross-owner batch pairing; missing/duplicate edits and forged physical positions; target containing any unsupported change; and atomic late failure. A parseable/admissible damaged result must fail whole-Project equality, so earlier parse errors do not stand in for the equality gate.
|
||||
|
||||
Existing public regression anchors (same commit, under `crates/oa-core/tests/`) are `source_project.rs:496` cross-file alias uses, `:843` exact CRLF/scalar/header preservation, `:877` comments after `@`, `:926` kind changes, `:999` scalar/record conversion, `:1030` reference reorder comments; `source_identity_updates.rs:37` origin ownership and `:81` identity swaps; `source_nested_updates.rs:49` nested token preservation and `:244` nested identity/alias swap plus cross-file movement. These demonstrate existing behavior to preserve, not proof that the new private route already supports those broad edits.
|
||||
|
||||
## Remaining choices and completion boundary
|
||||
|
||||
Parent should settle ordinary key identity and the exact read-only output surface before implementation. The recommended physical-token key is enough for rename completeness and does not claim semantic identity across edits. Decide whether runtime AST↔position omission verification adds justified value beyond sealed origin plus independent oracles. Either choice must state its guarantee and charge its scratch; it must not be inferred from a misleading test name.
|
||||
|
||||
Once this index is accepted, the highest-value next milestone is the precisely gated complete-target rename compositor with actual emitted-bundle admission/equality. Scalar editing, typed subtrees, parameter insertion/deletion/reorder, repaired deletion, reidentity, file ownership/movement, missing-ID stabilization/reindexing, migration, history/checked-save and GUI/API parity remain required. Neither the index nor a private rename milestone completes source8 or the user-owned project specification.
|
||||
@@ -0,0 +1,147 @@
|
||||
# Complete authored-name occurrences: private successor contract
|
||||
|
||||
Accepted bounded design, 2026-09-24, based on private source
|
||||
`93eb6117f95353d25d594d59780018f197c51672`, after parent source inspection,
|
||||
[seam research](analysis-ordinary-index-20260924/source-map.md) and
|
||||
[independent critique](analysis-ordinary-index-20260924/critique.md).
|
||||
Issue 7 owns work status. This does not alter prerelease source `715036e`.
|
||||
|
||||
The user requires complete graphical/text/API parity. This dependency adds
|
||||
ordinary name occurrences to the accepted typed index, followed by a separately
|
||||
specified rename compositor. It does not redefine parity as renaming, activate
|
||||
public source8 or claim scalar/structural editing support.
|
||||
|
||||
## Chosen capability and alternatives
|
||||
|
||||
Consume `IndexedMixedProject` into an opaque private owner that retains it and
|
||||
one ordinary occurrence map. The owner provides read-only views of original
|
||||
bundle/files, complete Project, warnings, existing typed maps and new ordinary
|
||||
records. No mutable replacement state, legacy Index/updater conversion, public
|
||||
factory from loose parts or independently transferable edit authority.
|
||||
|
||||
Use physical keys `(canonical file, alias-token start, alias-token end)` for the
|
||||
new map. Each inline value contains owning declaration ID, global target ID,
|
||||
Header/Reference role and the original full occurrence extent. For headers the
|
||||
extent is the alias token; for references it includes `@` and intervening trivia.
|
||||
These are snapshot keys, not persistent semantic identities. Preserve the richer
|
||||
retained position trees for subsequent structural work. Do not force ordinary
|
||||
keys into typed expression `Field`/`Child` types.
|
||||
|
||||
This materialized map makes complete coverage inspectable before edit authority
|
||||
is added. A fused traversal/rename planner could avoid retained map slots, but
|
||||
would combine still-uncertain ownership coverage with intent/diff/output logic.
|
||||
Revisit that tradeoff only after evidence demonstrates a useful simplification.
|
||||
Owned structural key paths would duplicate retained metadata without a current
|
||||
consumer and introduce extra string/path/drop accounting; defer them. Whole-word
|
||||
source scans and public `SyntaxUpdate` are unsuitable: the former cannot identify
|
||||
reference roles; the latter reparses, formats and later applies structural edits
|
||||
in transformed coordinates.
|
||||
|
||||
## Complete scope
|
||||
|
||||
Add exactly one project alias header, each ordinary declaration alias header,
|
||||
and every actual `EditKind::Reference` leaf in every ordinary declaration field
|
||||
tree. Include scalar and nested/list references, repeated targets, routes/view
|
||||
options, artifact/trace endpoints and references from ordinary syntax into typed
|
||||
globals. Resolve only through `Target::Global` names in the existing complete
|
||||
catalog; scoped calculation parameters never enter this reverse lookup.
|
||||
|
||||
Exclude comments, descriptions, display names, string literals, enum words,
|
||||
include paths, identity strings and `HistoricalUuid` leaves. Do not exclude a
|
||||
whole field by name merely because some fields use historical references.
|
||||
Implicit lexical parenting has no authored alias token; explicit `parent @x`
|
||||
does. Preserve the existing restriction against typed declarations nested in
|
||||
ordinary bodies. Do not use `active_references`: it only meters selected ordered
|
||||
model-step references and is not an alias occurrence selector.
|
||||
|
||||
Typed occurrences stay unchanged. Across both families, every global declaration
|
||||
header appears once and no physical alias token has two owners. Parameters keep
|
||||
their existing calculation-scoped identity even when UUIDs coincide with globals.
|
||||
|
||||
## Construction and verification
|
||||
|
||||
Reuse sealed `FileSyntax.positions`, ordinary AST and original significant
|
||||
tokens. No reparse, fragment lexer, source mask, model copy or formatter.
|
||||
|
||||
1. Iterate canonical files and their ordinary declaration/position pairs. Check
|
||||
matching IDs, owner and header containment against that declaration occurrence.
|
||||
Nested declaration spans overlap: their parent range cannot determine ownership.
|
||||
2. Project header lacks a role map. Project only its alias from retained tokens
|
||||
anchored at `SourceHeader.span.start`: require `project`, the following complete
|
||||
Word token, containment in that header and exact admitted project spelling.
|
||||
Ordinary header alias spans already exist; verify complete Word identity and
|
||||
the corresponding global declaration before insertion.
|
||||
3. Walk Record/List values iteratively. The synthetic root `fields` span includes
|
||||
braces (`body.start-1..body.end+1`); do not require it inside the body interior.
|
||||
Actual field/value/reference spans must remain within their justified parent
|
||||
and owning declaration. Nested declarations are separate flat occurrences,
|
||||
not children discovered through broad span scans.
|
||||
4. For a Reference, require a valid original UTF-8 extent and a significant `@`
|
||||
token at its start. The next significant token must be a whole Word whose end
|
||||
equals the retained Reference end, spelling equals the retained reference,
|
||||
and global catalog target agrees. Store only that Word as the alias location,
|
||||
retaining the full extent inline. Comments/whitespace between marker and Word
|
||||
remain outside replacement authority.
|
||||
5. Reject duplicate physical alias tokens across ordinary and typed families,
|
||||
repeated declaration headers, wrong owners/files/targets, partial or malformed
|
||||
tokens, and absent global headers. Full-token validation makes separate
|
||||
overlapping partial-token ownership invalid before insertion.
|
||||
6. Failure drops the consumed attempt with no partial owner. Preserve known
|
||||
canonical file attribution. Invalid file keys or invalid UTF-8 spans use the
|
||||
explicit safe diagnostic fallback already established by the typed constructor.
|
||||
|
||||
Completeness relies on exhaustive traversal of the sealed parser projection,
|
||||
checked against independent full-set oracles. Do not add another AST/position
|
||||
emitter merely to claim runtime detection of arbitrary coordinated corruption.
|
||||
Per-record validation does not prove arbitrary omissions from trusted emission;
|
||||
name this boundary accurately in tests and documentation.
|
||||
|
||||
## Storage and depth
|
||||
|
||||
Retain the entire inherited ledger, typed maps/paths, raw arenas, syntax and
|
||||
warnings. With D ordinary declarations and A reference leaves, the one-map design
|
||||
adds exactly **N = 1 + D + A entry slots**, zero lowerer occurrence slots and zero
|
||||
owned-name bytes. IDs, roles and two spans are inline. Added retained containers
|
||||
or copied strings would require a revised explicit accounting decision.
|
||||
|
||||
Count the borrowed reverse global map G, typed physical-location lookup T and
|
||||
all live iterative work slots W as scratch entries. A header-seen flag can live
|
||||
in each reverse-map value; avoid an uncounted extra set. New-map membership
|
||||
handles ordinary duplicates. Conservative coexistence is inherited baseline plus
|
||||
`N + G + T + W`; tests must hand-count actual phase peaks, not assume this upper
|
||||
bound is always simultaneously reached. Reserve before growth, and release only
|
||||
after the corresponding allocation is dropped.
|
||||
|
||||
Do not recharge parsed bytes/tokens/entries/references, Exact work, raw lowerer
|
||||
occurrences or model-step counters. The ordinary tree already satisfies its
|
||||
depth-64 parser policy. This iterative reference walk introduces no new
|
||||
`Budget::frame` interpretation or raised limit; parsed Usage remains unchanged.
|
||||
Workspace stack/lifecycle guarantees remain bounded by actual tested cases.
|
||||
|
||||
## Acceptance before subsequent edits
|
||||
|
||||
Independently enumerate complete header/reference records for small OA and SA
|
||||
mixed bundles, including both reference directions, nested ordinary declarations,
|
||||
explicit/implicit parents, noncanonical include traversal, coincident cross-file
|
||||
offsets, Unicode/CRLF, marker comments and alias-like prose. Extend the accepted
|
||||
rich fixture and separately cover ordinary categories absent from it: relation
|
||||
endpoints, contextual chains, routes/view options, artifacts and traces, including
|
||||
historical UUIDs equal to live identities. Expected maps must not derive from the
|
||||
index, formatter or lowerer.
|
||||
|
||||
Require targeted corruptions to reach the intended marker/token/target/owner/file,
|
||||
physical uniqueness and safe diagnostic checks. Hand-count retained and peak
|
||||
storage with typed baseline still live; isolate exact-cap/cap-minus-one failures
|
||||
from earlier parsing. Preserve complete Project, bundle identity/bytes/entry,
|
||||
canonical file keys, warnings, static admission metadata and parse/numeric usage.
|
||||
Exercise success and late failure on the existing bounded-stack harness. Retain
|
||||
all prior typed-index outcomes and explicitly report inherited full-suite/format
|
||||
failures. No public API or source8 activation is part of this change.
|
||||
|
||||
The next separate contract must gate a complete independent target Project to
|
||||
allowed global/scoped renames only, validate final namespaces simultaneously,
|
||||
produce both families' complete nonoverlapping edits in original coordinates,
|
||||
preflight combined storage/output including untouched files, emit each file once,
|
||||
then parse/resolve/admit actual output and compare the whole Project to intent.
|
||||
Scalar changes, structural moves, insertion/removal, reidentity, stabilization,
|
||||
migration, history/checked save and UI/API parity remain required later work.
|
||||
@@ -0,0 +1,76 @@
|
||||
# S3 original-span composition proposal
|
||||
|
||||
**Proposal, not an accepted decision or implementation.** Read-only source inspection on 2026-09-22: private analysis `1b1c3e3abb6fc3d0934c9dbfbd21fddc8ae4f594` in `.local/ai3`; ordinary updater at root `4ffff0d9d94bd1875e6b316b84ac11e5c5c9657c`. No compiler, source mutation, public activation, metamodel change or critic delegation. Parent owns adoption/integration.
|
||||
|
||||
Requirements come from `harness/analysis-source8-20260913/analysis-source8-repair-design-r2-20260913.md`, “Source pipeline and exact editing,” and the S3/S2 handoffs `.local/analysis-source8-s3-index-handoff-20260913.md` / `.local/analysis-source8-s2-implementation-plan-20260913.md`. Earlier plans describe intended interfaces; the implementation facts below take precedence for what currently exists.
|
||||
|
||||
## Observed seams and smallest useful scope
|
||||
|
||||
Private `analysis_source/update.rs` already retains qualified occurrence keys and original locations, validates complete simultaneous final namespaces, exact original numeric-file map/bytes, token spelling, complete required edit membership and overlap. It exports only whole-file `Plan::apply`. `Index::parse` consumes typed-only files; `Index::build` is private and trusts its own lowerer's occurrence completeness. `Writer::expression(owner, field, expr, Parent)` exists for later subtree changes; a rename needs no writer invocation.
|
||||
|
||||
Root `source_project.rs` already collects ordinary original-coordinate `Edits = BTreeMap<LogicalPath, Vec<(Span, String)>>` before `apply_edits` (lines271,679,1050). `SyntaxUpdate` uses complete old/new comparison values plus separate compact insertion values; preserve that distinction. Project-header slices explicitly add the header's file offset once. Current `apply_edits` groups identical spans by concatenating text, including nonempty replacements, and validates/mutates one file at a time. That is not a sufficient mixed-producer validation boundary.
|
||||
|
||||
After scalar application, `source_structure::update` can reparse and relocate pieces using updated coordinates; it returns immediately when no structural change is needed. Therefore the first integrated slice should explicitly cover stable-ID, topology-preserving global/scoped renames and ordinary scalar edits with disjoint ownership. Reject/defer additions, deletions, moves, reidentity and typed subtree changes at this slice's entry. The existing public updater keeps its current broader behavior until those operations have a compatible composition design; do not claim that its structural second phase already uses the new single-application protocol.
|
||||
|
||||
## Two candidates
|
||||
|
||||
| Candidate | Preservation and ownership | Cost / limitation |
|
||||
| --- | --- | --- |
|
||||
| A. Opaque validated typed edit batch + bundle-owned compositor | Keep Index/Plan provenance; ordinary and typed producers own disjoint spans in one original snapshot. Existing ordinary complete/compact semantics stay in place. | Small adapter and merge boundary; genuine mixed parsing and shared budgets still required before public use. Recommended first slice. |
|
||||
| B. Replace both producers with one shared semantic edit-plan/AST representation | Could eventually centralize token, subtree, insertion and relocation ownership. | Requires migrating ordinary EditValue/SyntaxUpdate, structural comment ownership and typed paths at once; substantially more compatibility risk before the first rename benefit. Revisit only when demonstrated structural composition needs justify it. |
|
||||
|
||||
Applying typed output before ordinary offsets is invalid under either design. Canonicalizing a mixed file as a bridge would destroy required authored preservation.
|
||||
|
||||
## Candidate A: concrete interface and file plan
|
||||
|
||||
1. **`analysis_source/update.rs`: export an opaque borrowed batch.** Proposed signatures are sketches, not existing APIs:
|
||||
|
||||
```rust
|
||||
Plan::validated_original_edits(&self, current, budget)
|
||||
-> Result<ValidatedRenameEdits<'_>, Error>
|
||||
ValidatedRenameEdits::iter(&self)
|
||||
-> impl ExactSizeIterator<Item = OriginalNameEdit<'_>>
|
||||
```
|
||||
|
||||
`OriginalNameEdit` exposes read-only `location: {file, original_span}`, `original: &str`, `replacement: &str`, and `occurrence: &OccurrenceKey`. All fields/constructors remain private with getters; records and batch borrow the Plan/index. Validate the whole batch before returning it. The bundle collector accepts the batch itself and iterates every record; it does not accept a caller-selected subset as a complete rename. An empty/no-op batch is valid. Revalidate complete source equality at final application, not merely iterator construction.
|
||||
|
||||
Factor today's `validate` into (a) ownership/spelling/order/completeness validation and (b) output-length preflight. Keep standalone `Plan::renames`/`apply` behavior. For mixed planning, add a narrowly named composition constructor sharing (a), without checking a fictitious typed-only intermediate output size. Otherwise a typed expansion can be rejected even when a simultaneous ordinary shrink makes the actual final bundle fit. Plan-record/name-memory bounds still apply before allocations, and final combined-output bounds are mandatory. Do not use a fresh Budget to bypass the intermediate check.
|
||||
|
||||
2. **`source_project/original_edits.rs` (new private module): bind and merge.** A `SourceSnapshot` borrows the complete original `SourceBundle`, including entry path and every file. A private file table maps each numeric typed file key to exactly one canonical LogicalPath from that snapshot, fixed by the parse session. No recomputation from a different traversal and no caller-supplied unchecked file map. The collector stores typed provenance and ordinary owner/role beside each borrowed/owned replacement until validation completes.
|
||||
|
||||
Collect ordinary `(span, text)` records through an internal adapter that records their expected original substring and source owner; typed records retain their full qualified key. Ordinary owns ordinary headers/fields/references and project header/description; typed owns typed headers and typed occurrences, including references to ordinary targets. Explicitly exclude typed declaration spans from generic SyntaxUpdate so both producers never independently own the same token. A shared physical span is a collision, not a deduplication opportunity.
|
||||
|
||||
Preflight every file before allocating output: exact entry/files/bytes equality, known mapped file, half-open UTF-8 boundaries, expected old bytes, producer ownership, complete typed set, checked counts/text sizes, sorted disjoint spans, per-file and aggregate final lengths. Reject duplicate nonempty ranges even when their replacements agree. Initially reject ambiguous insertions at a replacement boundary and multiple insertions at one position; existing ordinary insertion groups can enter only after their producer explicitly coalesces them in a defined order into one witnessed insertion. The new boundary must not inherit arbitrary concatenation of equal nonempty spans from `apply_edits`.
|
||||
|
||||
Emit each file once by copying untouched original slices and final replacements in ascending original order. Return a new candidate bundle only after complete validation; preserve the input on all failures. This is the sole text application for the supported mixed slice. Entry/include strings, authored paths, comments, literal spellings, line endings and untouched files remain exact.
|
||||
|
||||
3. **`source_project.rs`: route the narrow scalar slice.** Extract/retain ordinary edit collection before the existing application point. Add typed batches there, resolve their file keys through the snapshot, and call the new compositor once. Guard the supported scope before any output construction; no declaration relocation/default-file work is hidden in the adapter. Preserve the stale check that recompiles publicly mutable `CompiledSourceProject` fields and checks index/model/bundle, or replace it only with an equally strong opaque checked-snapshot boundary as part of separately reviewed work.
|
||||
|
||||
4. **Later `language.rs` / `analysis_source/index.rs` integration:** one opaque parsed-bundle result must carry full-buffer tokens, typed declaration units, lowerer result and file table from the same parse. Construct Index through that provenance, not a newly exposed raw `build(Lowered, spans)` seam. All offsets remain file-relative full-original-buffer byte offsets, including typed declarations after includes or ordinary declarations. Never remove/include-mask bytes, concatenate fragments, or rescan a substring and silently treat its offsets as full-file offsets. Existing local-slice ordinary helpers translate their known base exactly once. No typed rename offset receives a second include/header adjustment.
|
||||
|
||||
## Namespace, resource and acceptance invariants
|
||||
|
||||
Global aliases share the complete project namespace. Scoped names are keyed by `(calculation Id, ParameterId)`; stable simultaneous final-name validation must include unchanged ordinary globals and unchanged parameters. Reused parameter UUIDs across calculations and UUID equality with a global remain legal. Occurrence identity retains owner, binding field (including override property), complete structural call path, role and qualified target. Call labels bind to the callee, never caller scope or text alone. Rename-only changes preserve authored parameter/call-argument order; reordering unrelated model vectors is outside the narrow rename plan.
|
||||
|
||||
Use one inherited parse budget across all reachable ordinary/typed units; charge original bytes/tokens/literals once. Adapter validation does not reset/recharge parsing or numeric work. Combine ordinary+typed edit-record and owned replacement-text counts before reserving the merged list; do not treat each producer passing its own ceiling as aggregate admission. Preflight the complete final bundle against both inherited source8 output bounds and caller ProjectLimits, including unchanged files. A fresh aggregate budget belongs only to the next complete candidate parse. The existing phase byte check is a bounded text-size policy, not an exact heap-allocation accounting claim.
|
||||
|
||||
For an integrated candidate, recompile the **actual emitted complete bundle**, run existing structural/static admission through its normal validator (no redundant manual second admission), and require the entire resulting Project to equal the independently intended Project before returning/installing source/history. A parseable output that omits an unchanged definition is failure. Pure adapter tests cannot certify this currently unavailable mixed public path. Preserve the closed public dispatch and checked-save boundaries until the parser/lowerer/migration/acceptance work is integrated and verified.
|
||||
|
||||
## Prerequisites versus deliverables available now
|
||||
|
||||
**Implementable now on the private analysis branch:** borrowed validated batch export, split validation/preflight internals, and tests for binding/completeness/no output construction. A private composition evaluator can combine this batch with independently authored ordinary edit witnesses and full-buffer expected strings. That demonstrates the merge algorithm, not production ordinary edit generation or mixed compilation. No public schema switch, native GUI, metamodel extension or full S4 completion is needed for this bounded deliverable.
|
||||
|
||||
**Actually blocking production mixed integration:** root4ffff is still schema7 and has neither the private analysis model/language integration nor the private raw scanner; its tokenizer still rejects typed punctuation/converts ordinary numbers. Reconcile the analysis contribution with current ordinary CompleteForEdit/Compact work instead of replacing current root files wholesale. A real mixed `parse_unit`/edit-position branch, one shared scanner/cursor/bundle budget, full global/signature lowering and opaque Index provenance are required. Stabilize missing global/parameter IDs into exact returned files and reindex before granting edit authority. Complete-output source8 compile/admission, legacy bridge/migration and checked-save acceptance remain required public gates. Root identity correspondence also needs a distinct definition category before enabling reidentity; current fallback category is node placement. These are dependencies, not permission to invent a new model or activate source8 in this adapter.
|
||||
|
||||
**Not blockers for the read-only batch:** subtree writing, comment salvage for removed nodes, parameter insertion/deletion, declaration movement/new-file ownership, migration activation, evaluation and further metamodel work. Keep them out of the initial patch. The existing Writer supplies the future changed-subtree primitive once its real parent/side context and structural ownership are integrated.
|
||||
|
||||
## Six independent falsifiers (all proposed, unrun here)
|
||||
|
||||
1. **Same-file offset cascade.** Independently authored mixed CRLF source with Unicode trivia, an ordinary global header/reference before a calculation and an ordinary scalar field after it. Simultaneously lengthen a global alias, shrink a parameter name and change the later scalar. Assert the exact entire expected file literal, all untouched bytes and intended Project; applying either producer first must fail the oracle.
|
||||
2. **Include/file-coordinate binding.** Root includes two nested-path modules; typed and ordinary declarations share a module after an include/comment prefix, and the same numeric offsets occur in another module. Exact expected full bundle verifies edits land in the owning file at its original absolute offset. Wrong/missing/reordered key-to-path mapping rejects before output; include spellings and ownership stay exact.
|
||||
3. **Repeated/reordered calls and namespace swaps.** Two calculations reuse parameter IDs/names, one equals a global UUID. Include two reordered calls to one callee and one to the other, with separate comments. Swap the first callee's two parameter names and two global aliases simultaneously. Independently enumerate every declaration/use/label span: four labels for the repeated callee remain distinct; the other callee's labels, strings and argument order remain unchanged. Add a final-name collision negative control.
|
||||
4. **Whole-snapshot and Unicode staleness.** After planning, independently mutate an unrelated file/comment, add/remove a file, or change entry while preserving file text. Each fails before output. Separately forge a span inside a multibyte scalar or attach a valid-looking token from another owner; equal spelling/length must not authorize it. A byte-identical current snapshot is the positive control.
|
||||
5. **Producer overlap.** Ordinary whole-field replacement contains a typed rename; equal nonempty spans from both producers; duplicate typed occurrence; insertion at a replacement boundary. Each is rejected atomically. Adjacent disjoint ranges and one explicitly coalesced insertion are positives. No replacement concatenation, silent dropping or producer-order choice is allowed.
|
||||
6. **Aggregate output and acceptance.** Independent multi-file edits each fit a producer-local ceiling but exceed the combined cap by one byte; require refusal with unchanged input. Exact-cap positive and typed-growth/ordinary-shrink compensation positive enforce final-output accounting. At integration, deliberately omit an otherwise valid unchanged definition/reference edit from the emitted candidate: exact-output recompile/admission plus whole-Project equality must refuse it. No model projection or compiler success alone can pass.
|
||||
|
||||
All positive adapter fixtures also assert source/numeric usage is unchanged by export/merge and that exporting does not construct whole-file typed output. Integrated variants add complete output recompile, intended-Project equality and history/save refusal on failure.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Original-span source8 adapter: fresh independent design review
|
||||
|
||||
2026-09-23 — delegated Astra critic; local-only artifact, parent owns adoption and publication.
|
||||
|
||||
**Disposition: proceed with the bounded private adapter, with the clarifications below.** The proposed opaque rename batch plus complete-snapshot compositor is compatible with eventual real mixed source8. A wholesale edit-AST replacement is not justified by the inspected rename problem. No P1 defect was established in this unimplemented proposal. The main risks are accidentally promising more ordinary edits than the collision rules admit, treating matching lifetimes/bytes as complete parse provenance, and allowing the narrow slice to stand in for full source8 editing.
|
||||
|
||||
## Evidence and limits
|
||||
|
||||
Reviewed `.local/analysis-source8-s3-original-span-adapter-proposal-20260922.md`, SHA-256 `8f99e8ea1ba522371c1e5df1a19ae94ceedeecfacfc96dc5345e0d24f623a9d`; the S2/S3 handoffs; accepted r2 exact-editing requirements in `harness/analysis-source8-20260913/analysis-source8-repair-design-r2-20260913.md` from the analysis checkout; and the actual source below.
|
||||
|
||||
- A = `1b1c3e3abb6fc3d0934c9dbfbd21fddc8ae4f594`, `.local/ai3`, clean at inspection.
|
||||
- R = `4ffff0d9d94bd1875e6b316b84ac11e5c5c9657c`, requested ordinary-source pin. Root advanced to `cc3d6a48751ac5ab08e727cfd31c2b261bf8ade3` during review; independent Git comparison showed no differences from R in `source_project.rs`, `source_project/source_structure.rs`, or `language.rs`, so reads remain valid for R.
|
||||
- Source/design review only. No compiler, runtime, GUI, production changes, or Gitea writes. The proposed falsifiers are unrun; this review is not evidence of a working mixed parser or updater.
|
||||
|
||||
## Actionable clarifications
|
||||
|
||||
1. **P2 — define the supported ordinary edit set before routing it to the new compositor.** Proposal lines 13 and 47 promise topology-preserving ordinary scalar changes, while line 43 rejects insertion at a replacement boundary. R's `crates/oa-core/src/source_project.rs:1360–1371` deliberately handles a syntax-kind change by calling `erase_syntax` and inserting new text at the original start; `erase_syntax` (`:1101–1113`) emits individual token deletions, leaving trivia. Thus an existing producer can issue a meaningful insertion/deletion pair sharing a boundary. Stable model IDs alone do not exclude this form of syntax change. Either initially allow only explicitly enumerated leaf/header edits whose producer shape is supported, rejecting other changes *before* formatting/planning, or normalize this ordinary-owned compound operation into a single witnessed replacement with the same comment-preservation result. Do not simply relax cross-producer overlap checks. Add a positive oracle for that normalization before broadening the advertised scalar set.
|
||||
|
||||
R's `apply_edits` (`:679–718`) also concatenates all equal-span replacements. The proposal correctly refuses to carry that rule into a mixed ownership boundary. Preserve defined same-position insertion ordering inside one ordinary producer; reject duplicate nonempty replacements from any producer unless a distinct, reviewed compound-operation rule justifies them. Run ordinary compatibility fixtures against the adapter when it becomes a production route, since a stricter validator can expose previously tolerated producer output. No evidence found here establishes that all ordinary duplicate spans are intentional or that they are all bugs.
|
||||
|
||||
2. **P2 — make the batch/snapshot relationship and intended rename set constructor invariants.** A's `analysis_source/update.rs:15–19` binds a plan to an Index, and `index.rs:122–128` binds the Index to numeric-keyed source strings. Neither object currently binds itself to a `SourceBundle.entry`, canonical-path table, checked ordinary Project, or parse-budget profile. `Index::parse` (`index.rs:147–178`) intentionally accepts an independently supplied ordinary Project for the private typed-only harness. Rust borrowing prevents dangling references; a shared lifetime does not prove that two borrowed objects came from the same parse session. The proposal's opaque parsed-bundle requirement is therefore essential, not documentation around otherwise sufficient lifetimes.
|
||||
|
||||
For production composition, use one checked parsed-bundle witness that owns or borrows the exact complete bundle, ordinary model, typed index, file table and inherited limits. Create the collector and its complete rename intent from that same witness plus the independently supplied target Project. Permit only the witnessed typed batch for that index, with all global and scoped changes derived by stable identities; do not independently accept several batches whose individually valid final-name maps disagree. Final equality must still catch omitted ordinary references. Keep the old typed-only constructor test/staging-only. Add a negative control pairing a valid batch with another parse session/file table having equal numeric keys/spellings but different ownership, and a positive byte-identical complete snapshot control. No public raw `build(Lowered, spans)` is needed.
|
||||
|
||||
3. **P2 — turn the initial scope restriction into a precise diff gate and a bounded completion path.** “Topology-preserving” is not enough to identify supported changes. Require a gate over complete old/new Projects: unchanged global IDs and categories, declaration/lexical ownership, typed bodies/types/subjects/override structure, parameter IDs/order and all unsupported fields, allowing only the specific global/scoped names and ordinary leaf changes implemented in the first slice. An unrelated model-vector reorder, body edit, repaired deletion, or reidentity must not get silently ignored or regenerated. Return a specific unsupported-operation result before output construction. Keep those cases visible as unfinished source8 functionality.
|
||||
|
||||
The accepted r2 contract, “Source pipeline and exact editing” points 5–8, additionally requires subtree edits and retained removed-node comments, scoped parameter changes, global reidentity, explicit definition categories, file ownership, and complete acceptance. The S2 plan's S3 responsibility paragraph adds repaired deletion, missing-ID insertion/reindexing and history. A passing rename compositor does not complete those obligations. Before public activation, either implement their source8 paths or retain a clearly private experimental entrypoint; keeping the existing source7 updater intact does not by itself provide these operations for a source8 model.
|
||||
|
||||
## Resource and acceptance conclusions
|
||||
|
||||
The typed-growth/ordinary-shrink concern is real. A's `Plan::renames` calls `validate` at `update.rs:89`; `validate` calculates a typed-only aggregate output and applies `index_bytes` (`:154–170`). Consequently, export cannot simply call the existing constructor under the final combined-output ceiling. Accept the proposed split into ownership/completeness validation and standalone output preflight, while preserving standalone `renames`/`apply` behavior.
|
||||
|
||||
The composition path should retain the inherited profile rather than accept a more permissive ambient Budget. If callers can tighten limits, use the intersection; do not allow composition to widen the parsed session's ceilings. Existing private tests deliberately construct new Budgets for boundary probes (`update/tests.rs`, `output_and_plan_limits_are_aggregate_and_do_not_reset_parse_work`), which is not proof of production profile binding. Count aggregate records/owned replacement text before merged reservations, then compute the actual combined per-file and whole-bundle output lengths, including unchanged files, before allocating output. A shrink can compensate output growth, but cannot erase already incurred parse, name-storage, record, or numeric costs. Retaining old parse counters unchanged through export is correct; a complete candidate reparse gets its own complete bounded pass. An unchanged usage counter alone does not prove that no redundant parsing occurred, so keep the single-parser control flow inspectable.
|
||||
|
||||
The final acceptance boundary is correctly chosen: compile the actual emitted complete bundle, use normal full structural/static admission, compare the entire resulting Project to independent intent, and install nothing on failure. R already checks stale public fields (`source_project.rs:790–802`) and whole-Project equality (`:1058–1071`); preserve those guarantees. Equality is necessary but cannot prove source preservation or edit provenance: retain independently authored exact-output and unchanged-byte oracles too. When choosing the negative omission fixture, keep the damaged output parseable/admissible (for example, omit an unreferenced definition) so the test actually exercises whole-Project equality instead of only an earlier parser error.
|
||||
|
||||
## Concrete next implementation boundaries
|
||||
|
||||
1. **Private batch patch:** only the typed update module and its focused tests need change initially. Export a borrowed, opaque, complete validated batch; separate composition planning from standalone final-size preflight; prove no whole-file output is constructed. Exercise same-name no-op, full swaps, missing/duplicate occurrence, stale source, and typed-growth/ordinary-shrink compensation with independently authored ordinary witnesses. This is a meaningful deliverable now and needs no public dispatch change.
|
||||
2. **Private compositor patch:** implement complete snapshot/file-map binding, owned ordinary-operation normalization for the explicit supported set, aggregate checks and one ascending copy pass. Exercise all-file atomic rejection, Unicode boundaries, wrong session/map, duplicate nonempty spans, ordered insertion groups, adjacent ranges, exact cap and cap-plus-one. Handwritten ordinary witnesses certify this algorithm only, not production ordinary edit collection.
|
||||
3. **Real mixed parse prerequisite:** compose one raw scanner/cursor and bundle budget with ordinary and typed declaration parsing; collect full cross-file globals/signatures, lower once, retain full-buffer offsets and same-parse index provenance. Stabilize missing global/parameter IDs into the returned documents and rebuild indexes before granting editing authority. Preserve ordinary signed-number/legacy behavior and complete/compact edit semantics. Do not build a substring/masked-source bridge or expose raw lowerer/span fabrication to make the compositor appear integrated.
|
||||
4. **Integrated narrow edit slice:** derive both producers from that checked parse and complete target, enforce the precise diff gate, emit once, and verify the whole candidate. Add independently authored mixed CRLF/Unicode files, cross-file ordinary-to-typed and typed-to-ordinary renames, final namespace swaps, scalar changes on both sides of typed declarations, exact bundle output and whole-Project equality. Include no-op equality and stale unrelated-file/entry refusal.
|
||||
5. **Complete required editing and publication:** extend the ownership protocol to typed subtree changes, scoped-parameter insertion/deletion/reorder, same-batch repaired deletion, reidentity, movement/new-file ownership and stabilization/migration; verify history and checked-save failure atomicity. The existing structural second pass (`R:source_project/source_structure.rs:34–84`) reparses updated text and cannot simply be declared part of the original-coordinate one-pass proof. Design and verify its composition explicitly. These are remaining delivery gates, not grounds to postpone the useful private batch patch.
|
||||
|
||||
The proposal is appropriately cautious about public activation and does not weaken the required model semantics. With the scope/provenance clarifications above, implementation of the private adapter should now provide more value than another general redesign exercise.
|
||||
|
||||
## Immediate export-only acceptance boundary
|
||||
|
||||
Parent's narrower first implementation is accepted: **typed opaque batch export and validation split only; no mixed `source_project` compositor, real mixed parser, or public activation in this patch.** Steps 2–5 above describe dependent work, not additional scope for this patch.
|
||||
|
||||
The composition constructor must share final-namespace, qualified-target, complete-occurrence, original-source, token-spelling, order/overlap and active-budget checks with the existing standalone path. It may defer **only the hypothetical typed-only final output-length check**. It must still bound rename-map records, owned final-name bytes and edit records before allocation. Export revalidates exact supplied current numeric file keys and bytes and returns an opaque read-only view borrowing the Plan; it cannot return/install a candidate Project or grant ordinary-file ownership. Keep constructors and internal edit fields private. An empty batch is valid. This private batch remains tied to the existing typed-only index provenance; it must not claim the future complete-bundle/session guarantee.
|
||||
|
||||
Use one caller-supplied inherited Budget throughout the private test operation, with no fresh permissive budget inside the new constructor/export. This patch need not redesign Budget or Index to store a production parse-session profile. That stronger ownership is deferred with the real parsed-bundle witness and must be settled before production composition. `Budget::active()` remains mandatory, including a previously latched parse/numeric failure.
|
||||
|
||||
Minimum focused acceptance oracles:
|
||||
|
||||
1. The existing standalone `Plan::renames` and `Plan::apply` keep rejecting typed-only output exceeding the profile. Under that **same profile**, the composition constructor/export accepts the otherwise valid growing batch when its plan/name/record storage fits. Independently calculate an ordinary shrink sufficient to place a hypothetical complete result exactly at the cap, and explicitly label this as deferred-final-size arithmetic, not a compositor test or accepted output. This proves why only output preflight was split.
|
||||
2. Source/name-memory/record bounds remain effective on composition construction: invalid alias, final namespace collision, unknown qualified target, over-limit renamed-name bytes and edit count fail. A shrinking hypothetical ordinary edit cannot authorize an over-limit plan. Exact-bound positives and plus-one negatives should isolate the intended bound.
|
||||
3. Export rejects missing/changed/extra source files or altered unrelated bytes, a forged/wrong token location, duplicate occurrence and incomplete edit membership. Use module-private damage controls to exercise checks inaccessible to normal callers. Failure returns no batch and leaves input unchanged.
|
||||
4. A simultaneous global/scoped swap exposes exactly the independently enumerated original file/span/old spelling/new spelling/qualified key tuples in deterministic order. Include repeated call labels and same UUIDs in distinct parameter/global scopes. Same-name/no-op input exports zero edits.
|
||||
5. Construction/export leave parse usage and numeric work unchanged; no whole-file typed output is materialized or `Plan::apply` invoked along the export path. Verify this through the narrow implementation's control flow plus tests of exposed records, rather than treating unchanged counters alone as proof of allocation behavior.
|
||||
6. Existing standalone rename, stale-index, namespace and output-limit regressions retain their original oracles. The new type exposes read-only accessors and no mutable record, arbitrary batch constructor, or caller-selected subset acceptance API. Exact complete model/bundle equality remains a later integration gate, not an assertion that this export patch can establish.
|
||||
|
||||
Passing these oracles is sufficient to deliver the private export patch. It is not sufficient to close S3/S4 or claim graph/text/source8 functionality. The next dependency is concrete complete parsed-bundle provenance and ordinary-operation normalization, followed by the compositor and actual mixed parser path.
|
||||
@@ -0,0 +1,104 @@
|
||||
# Public read-only mixed source8 validation
|
||||
|
||||
Baseline `7b06b8ea1b7ef902ee0b3d0ec2971a9a7a1f1acd`, local-only while Gitea
|
||||
publication is blocked. This bounded outcome advances the user's textual linting
|
||||
and programmatic model requirements without claiming application editing parity.
|
||||
The [implementation map](analysis-public-read-design-20260925/IMPLEMENTATION-MAP.md)
|
||||
and [independent critique](analysis-public-read-design-20260925/CRITIQUE.md) compare
|
||||
diagnostics-only, borrowed, owned and full editable-compilation alternatives.
|
||||
The [acceptance review](analysis-public-read-design-20260925/ACCEPTANCE-REVIEW.md)
|
||||
pins independent fixture, model, warning and boundary-diagnostic oracles.
|
||||
|
||||
## Selected interface and authority
|
||||
|
||||
Expose only `language::check_mixed_bundle(&SourceBundle, ProjectLimits)` returning
|
||||
`Result<language::CheckedMixed<'_>, Vec<SourceDiagnostic>>`. The opaque, non-Clone
|
||||
result offers `project() -> &Project` and `warnings() -> &[SourceDiagnostic]`.
|
||||
Define it beside the existing resolved owner and re-export the type/function
|
||||
through private modules. Keep its fields and constructor private. It directly
|
||||
retains the actual ResolvedMixedProject; no model substitution or second parse.
|
||||
|
||||
The result borrows the actual complete input bundle for its lifetime. It grants
|
||||
validation and immutable queries, not an editable source index, stabilized output,
|
||||
save authority, ownership extraction or history installation. Preserve the real
|
||||
syntax/expression/occurrence/storage owners while the witness lives. Do not add
|
||||
unused public methods, artificial runtime reads or broad lint suppression merely
|
||||
to accommodate retained internal fields.
|
||||
|
||||
Accept only schema8 with explicit UUIDs for project, every ordinary and typed
|
||||
declaration, and typed parameters. Preserve canonical logical paths, include
|
||||
traversal and detached-file rejection. Return complete admitted OA/SA models and
|
||||
actual located warnings in existing order; errors return no partial successful
|
||||
result. Preserve exact original bytes, comments and line endings. No missing-ID
|
||||
generation, migration, filesystem discovery, formatter or write operation occurs.
|
||||
Use clear public diagnostics for the schema/explicit-ID requirements rather than
|
||||
describing the supported API as private test machinery.
|
||||
|
||||
## Policy and production dependency boundary
|
||||
|
||||
Construct fresh borrowed C=0 authority from the actual bundle and caller policy.
|
||||
Derive internal Limits once by the existing source8 formula: caller source-byte
|
||||
and step-reference limits, remaining ParseLimits fields UNLIMITED. Internal
|
||||
entries therefore remain capped at262144 independently of caller model records;
|
||||
the latter still governs actual final-model admission. Keep the existing hard
|
||||
token, frame, numeric, byte and reference ceilings. Do not expose an arbitrary
|
||||
profile or raw Slots constructor. Preserve Some(Borrowed) and select both text
|
||||
and entry producers, then complete resolution/admission with the same policy.
|
||||
|
||||
Promote only the required parse/lower/resolve dependency cone. Parser mixed state
|
||||
and shared helpers must compile in production coherently while existing ordinary
|
||||
callers still select None. Keep private edit/index/emission machinery, fixture
|
||||
constructors, retained snapshots and Pending-backed authority under cfg(test).
|
||||
Use item-level gating from the reviewed map. Necessary retained allocation or
|
||||
admission-evidence fields may have individually documented non-test dead-code
|
||||
allowances; do not suppress whole modules/structs or weaken -D warnings.
|
||||
|
||||
This remains the existing logical storage policy, not an all-heap/RSS guarantee.
|
||||
Independently bounded traversal, delimiter/Pratt/duplicate-name scratch and
|
||||
established model/validator/numeric internals retain their documented scopes.
|
||||
Preserve generic depth64, typed depth128, DEPTH_128_VALIDATED=false and the
|
||||
unresolved full-pipeline small-stack limitation. Linux remains user-deferred.
|
||||
|
||||
## Observable acceptance
|
||||
|
||||
- A real non-test integration consumer uses the exported API on substantial OA
|
||||
and SA multi-file fixtures with independently authored complete model oracles,
|
||||
located warnings, nested ownership, cross-file/scoped references and Unicode/CRLF.
|
||||
Reuse valid authored fixtures/oracles without deriving expected models from
|
||||
the candidate parser or writer. Check all original bytes on success/refusal.
|
||||
- Negative cases cover missing UUIDs in each required class, unsupported versions,
|
||||
invalid paths/includes/cycles/detached files, malformed and duplicate/unresolved
|
||||
or wrong-kind references. Assert actual diagnostic paths/spans and meaningful
|
||||
error categories. Keep long ordinary analysis-constructor rejection explicit.
|
||||
- Prove the real production constructor selects borrowed zero carry, both producer
|
||||
modes and every derived limit through narrow internal observation; preserve
|
||||
existing discriminating producer cap tests. Public tests exercise caller source,
|
||||
file, edge/depth and final-model/step restrictions. The minimal78-byte fixture
|
||||
reaches input admission before its C0 text44/43 boundary, so do not mislabel a
|
||||
source-byte rejection as a producer-boundary test or reuse pending O152/151 caps.
|
||||
Preserve existing diagnostic mapping and phase precedence: the early byte check
|
||||
reports `invalid_source` with `Source8 index/output byte limit exceeded.`, not
|
||||
Traversal's later `source_limit`. Use the reviewed exact spans/categories for
|
||||
file, edge and depth boundaries rather than assuming a uniform limiter layer.
|
||||
- Compile-fail documentation demonstrates that the result cannot outlive or permit
|
||||
mutation of its source. Include a concise real usage example and public API
|
||||
documentation in the established language documentation; distinguish this
|
||||
bounded read contract from full source8 editing and application support.
|
||||
- Run core library, the new non-test integration target, relevant existing
|
||||
ordinary integration/stack controls, doctests, strict core all-target Clippy and
|
||||
formatting disposition. Production Parser layout now includes mixed state:
|
||||
previously test-only success is insufficient to qualify ordinary non-test
|
||||
callers. Investigate concrete stack/runtime changes; no larger stack or relaxed
|
||||
budgets. Reuse other valid evidence only when component inputs are unchanged.
|
||||
|
||||
Existing parse/compile, source-file loader, CLI, desktop, server, formatting,
|
||||
update, save and history contracts remain separate. Current CLI discovery parses
|
||||
ordinary syntax and unconditionally constructs editable compilation even for
|
||||
Check; a new Rust API alone cannot enable mixed CLI checking. Reject a fake index,
|
||||
regex include scanner or nominal command that fails before this checker. A later
|
||||
CLI/discovery adapter or full editing adoption requires its own concrete outcome.
|
||||
|
||||
Parent owns compiler execution, synthesis, acceptance and publication. Bounded
|
||||
implementation and independent source/oracle review may proceed on a distinct
|
||||
local branch; no shared ownership or publication success is implied by this
|
||||
contract while Gitea writes remain unavailable.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Public mixed read: independent acceptance review
|
||||
|
||||
Read-only review of selected `harness/analysis-public-read-contract-20260925.md`, its IMPLEMENTATION-MAP/CRITIQUE, and immutable implementation baseline `7b06b8ea1b7ef902ee0b3d0ec2971a9a7a1f1acd`. No source edit, compiler, executable or network operation. This is a proposed evaluator contract, not public-API acceptance.
|
||||
|
||||
## Disposition and concrete diagnostic correction
|
||||
|
||||
The selected `language::check_mixed_bundle` / opaque non-Clone `CheckedMixed<'_>` is a coherent bounded read capability. Retaining the actual resolved owner and borrowing the complete bundle preserves existing authority without inventing an editable index or output ownership. No fundamental design blocker found. Production wiring and non-test behavior still require actual verification.
|
||||
|
||||
One source-backed correction to the implementation map's suggested78/77 oracle is necessary. `mixed.rs:345–358` checks `budget.index_bytes(total_source_bytes)` **before** `Traversal::new`. `budget.rs:310–313` emits `Source8 index/output byte limit exceeded.`; `mixed.rs:78` maps its start through ordinary_error to code `invalid_source`. Thus E at caller77 returns `main.arcadia`, span0..1, line1 column1, Error severity, no object/field/related locations, exactly that message. It does not reach Traversal's later `source_limit` branch. Parent explicitly selected preserving this existing mapping, not a new error taxonomy. Distinguish parser one-character transport from full traversal/resolver spans.
|
||||
|
||||
## Existing semantics that must actually cross the production seam
|
||||
|
||||
- `mixed.rs:239–260` checks typed declaration identity and each calculation parameter identity after parsing; missing parameter ID reports the owning declaration start, not an invented exact absent-ID span. `language.rs:1291+` refuses omitted project/ordinary IDs at the parser's current token. Test each class separately with all earlier required IDs present.
|
||||
- `mixed.rs:283–288` derives source8 Limits from only caller source bytes and step references, with remaining ParseLimits fields UNLIMITED. Therefore internal entries are262144, bytes=min(caller,64MiB), tokens=min(bytes,1048576), references=min(caller,500000), frames256 and numeric work50000000. Caller max_records remains a separate model-admission control, not syntax-entry capacity. Preserve all other original ProjectLimits fields for traversal/model admission.
|
||||
- `carried::parse_entry_producers` invokes parse_impl with **Some(guard),true,true**. The new constructor must select an actual borrowed guard with zero carry, not None, a fake pending output or a separately supplied policy. Zero carry excludes caller-owned source bytes from carried storage; input-byte admission and text/entry producer accounting remain active.
|
||||
- `Traversal::new` validates canonical paths, file counts and case collisions; next()/finish() enforce include existence/cycles/depth and reject detached supplied files. Root depth is0; includes advance depth by1. Duplicate edges count even if a file is visited only once. `finish()` attributes unreachable-file refusal to the detached path with default span. Do not silently filter the supplied map.
|
||||
- `project.rs:596–665` maps actual validation issues in their existing order, reserves mapped diagnostics, rejects any Error issue without returning a successful owner, and retains complete model/warnings/syntax/storage. Warning columns count Unicode scalars, while spans count UTF-8 bytes. Existing fallback to whole owning declaration remains intentional when a validation field has no authored field span.
|
||||
|
||||
## Non-test complete-model and warning fixtures
|
||||
|
||||
Use a real `oa-core/tests/public_mixed_read.rs`-style integration target importing only public API/model types. Cargo integration tests link the normal non-cfg(test) library; no `#[path]` access to private modules, public fixture constructor, writer-generated expected model or parser-produced expected Project. A small integration support module may transcribe already independently authored literals and whole model constructors.
|
||||
|
||||
1. **Rich OA and SA three-file models.** Reuse the literal content and independent model construction of `mixed/project/tests.rs::rich_bundle` / `rich_model`, not its `accepted()` parser helper. This includes ordinary Work and diagram/node references to typed property, property subject back to ordinary Work, calculations f/g across files, nested calls with reordered x/y arguments, and scoped parameter UUIDs reused across different owners (including a UUID equal to the global project UUID). Expected expressions must be constructed by semantic parameter IDs, not textual argument order. Compare the entire Project, all maps/body fields/IDs, and all warnings, not just definitions or named objects. Keep explicit IDs in every class.
|
||||
2. **Nested ordinary ownership.** Add a small authored nested counterpart, or transplant a proven nested ordinary fixture without reconstructing expectations from its parse: OA entity→actor and SA system→component with fixed IDs. Expected parent is explicit in the independent model while source uses nesting. Compare the complete Project. Keep this separate if nesting would alter the rich Work warning set; do not accidentally remove a leaf warning by adding a Work child.
|
||||
3. **Unicode/CRLF attribution.** Apply a literal Unicode comment and CRLF variant with expected model unchanged, then independently count bytes/scalars. Existing small source `arcadia 8;\r\nproject p "港🌊" id "00000000-0000-0000-0000-000000000001" { oa_activity w "Work" id "00000000-0000-0000-0000-000000000002" {} }\r\n` has Work span76..141, line2,column60. This is a useful separate exact warning fixture rather than guessing offsets after a broad rich rewrite.
|
||||
|
||||
For unallocated named Work, pin **both** warnings in order: `unallocated_leaf`, fieldSome("allocation"), message `Allocate leaf 'Work' to a performer.`; then `work_without_behavior_context`, fieldNone, message `Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.` Both Warning severity, object UUID suffix2, empty related locations, same actual whole Work declaration span/path/line/column. This avoids the prior false empty-warning and one-warning assumptions. Any added historical trace must be deliberately authored with independently checked endpoints; do not assume a reused example contains traces. Historical tests can remain separate if required rather than make the primary rich fixture unwieldy.
|
||||
|
||||
Before every success or error call, retain a complete clone of the literal SourceBundle (or an independently saved raw byte map), and compare it afterward. Assert exact entry string, key set and every UTF-8 string including comments/newlines; no generated IDs, migrated header or stabilization. For successful result, inspect project/warnings while result is alive; drop it explicitly before testing later source mutability. A later ability to clone the public Project does not grant verified save authority.
|
||||
|
||||
## Finite public policy oracles
|
||||
|
||||
E is exactly `arcadia 8;\nproject p "Project" id "00000000-0000-0000-0000-000000000001" {\n\n}\n` in `main.arcadia`:78UTF-8 bytes, whole Project with fixed UUID1/nameProject/aliasp and all maps empty, no warnings. With other policy roomy,78 admits source and the known existing zero-carry resolver/storage peaks fit;77 fails the initial byte check with the exact diagnostic above. Its zero-carry text peak44/43 is **not reachable** through public source-byte policy because the78-byte input fails first. Owned-output152/151 and warning161/160 caps are also not public borrowed-zero examples. Do not expose a profile knob merely to reproduce them.
|
||||
|
||||
H three-file include chain is independently authored:
|
||||
|
||||
```text
|
||||
main.arcadia = "arcadia 8;\nproject p \"Project\" id \"00000000-0000-0000-0000-000000000001\" {\ninclude \"part.arcadia\";\n}\n"
|
||||
part.arcadia = "include \"last.arcadia\";\r\n"
|
||||
last.arcadia = "//é\r\n"
|
||||
```
|
||||
|
||||
Lengths101/25/6 total132; same complete empty Project as E, no warnings. Use roomy model/storage limits while varying only one public field:
|
||||
|
||||
| Boundary | Exact intended observation |
|
||||
| --- | --- |
|
||||
| Source132/131 |132 permits complete input;131 fails initial budget byte check, main0..1,line1col1, invalid_source/index-output-byte message. |
|
||||
| Files3/2 |3 fits;2 fails Traversal at main0..0,line1col1, project_limit, `Source project exceeds 2 files.` |
|
||||
| Include depth2/1 |2 fits root0→part1→last2;1 fails at part's include span0..23,line1col1, project_limit, `Include depth exceeds 1.` |
|
||||
| Include edges2/1 |2 fits;1 fails earlier mixed parser include counter in part, span0..1,line1col1, project_limit, `Include graph exceeds 1 edges.` It is not the later full-span Traversal edge diagnostic. |
|
||||
| Detached file | With roomy limits, add syntactically valid unreachable file: unreachable_file on that file, default0..0,line1col1, `Supplied source file is not reachable from the entry file.` |
|
||||
|
||||
Invalid paths/case collisions/missing files/cycles should similarly use tiny independent fixtures so upstream file/byte failures cannot mask the intended branch. For a cycle, all files/IDs and syntax must otherwise be valid; assert referring include location and actual cycle category. Distinguish source grammar prechecks from final semantic model limits: small max_records may fail while counting declarations before resolution. A final-model-specific test needs a known nested model record/ordered-step contribution that is not exhausted by declaration prechecks. Reuse existing independently counted diagram/node or ordered-flow cases; pin the full expected model and count definition first. Do not call a declaration refusal final-model admission evidence. Reference-bearing typed fixtures need enough model step allowance to isolate the intended earliest reference branch, with an independently counted authored reference total; an empty E/H fixture cannot prove positive reference enforcement.
|
||||
|
||||
Internal bridge observation should invoke the **same constructor used by the exported API**, observe borrowed-zero guard + both producer metadata options and every derived limit, then resolve with that same policy. Deliberately small but sufficient caller max_records distinguishes262144 internal entry cap from model records. Keep existing discriminatory producer tests unchanged. Observation is wiring evidence, not an external public producer-cap failure or all-heap guarantee.
|
||||
|
||||
## Negative and compile-time authority tests
|
||||
|
||||
Remove exactly one project ID, one ordinary declaration ID, one typed declaration ID and one parameter ID from otherwise valid literals in separate cases. Require expected public-facing ID requirement message and source location; do not rely only on Err. Preserve parent-selected existing code/span transport. Add schema3/7/9 refusal with valid remaining syntax, unresolved typed global ref, duplicate global alias/UUID, duplicate scoped parameter, wrong-kind ref, malformed syntax and long ordinary analysis-constructor refusal. Strongly distinguish valid scoped-ID reuse from invalid duplicates within one owner. Success controls for each base fixture prevent malformed test setup from manufacturing negative results. Compare original bytes for every refusal.
|
||||
|
||||
Compile-fail documentation must force a **later use** of the result, otherwise nonlexical lifetimes may legitimately end its source borrow before mutation. Cover moving a CheckedMixed out of a scope containing its source, and mutating bundle.files while calling checked.project()/warnings() afterward. Use only real public imports and a valid fixture helper mirrored by a positive compiling usage example; compile_fail alone would pass for a misspelled API or unrelated error. Also verify no public fields/constructor/into_project/index or Clone implementation is accidentally exposed; no mutable accessor. Avoid additional compile-fail infrastructure if ordinary rustdoc examples suffice.
|
||||
|
||||
## Gate scope
|
||||
|
||||
Run actual non-test integration consumer plus core library, relevant ordinary source integrations and required stack controls, doctests, strict all-target Clippy and format disposition. Production Parser layout and mixed hook cfg changes mean previously successful cfg(test) parsing cannot qualify ordinary non-test callers. Preserve failed runs and investigate concrete changes without increasing stack or budgets. Reuse old runtime evidence only for demonstrably unchanged component inputs.
|
||||
|
||||
This contract promises a Rust complete-bundle API, not CLI/discovery/desktop/server support. Existing CLI still discovers and compiles ordinary editable source before returning Check; no CLI feature should be claimed from this API. Preserve depth64/typed depth128 policies, DEPTH_128_VALIDATED=false, prior full-pipeline stack limitation and user-deferred Linux work. No broader all-heap instrumentation or new public error taxonomy is needed for this slice.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Independent public mixed-read critique
|
||||
|
||||
Source-only proposal against `0c07f53ab517626f536f79dbaa2885a587bf1db7`; source advanced during this review to `7b06b8ea1b7ef902ee0b3d0ec2971a9a7a1f1acd` with only the separately reviewed r3 migration test/note correction. Production findings apply to both. Read the prior versioned ordinary-source8 design maps, actual callers and private admission seams. This critique was written before reading the new IMPLEMENTATION-MAP; the implementer's brief coordination message disclosed its borrowed-result candidate. No builds, source edits or publication. Current ordinary compatibility acceptance remains separate.
|
||||
|
||||
## Recommendation and user outcome
|
||||
|
||||
Select an explicit **read-only check of a supplied, complete, explicit-ID source8 bundle**, using the strong producer parser and complete resolver. Return an opaque borrowed result exposing `&Project` and located warnings, backed by the actual resolved witness. This is the smallest coherent public library capability for an external author, integration or AI tool to determine whether typed calculations/analysis plus ordinary architecture describe a valid model. It advances the textual linting and programmatic-model needs in PROJECT_GOAL.md:64–71,83,96. It is not yet application import, disk-project checking or graphical/text editing parity.
|
||||
|
||||
That limited user value must be stated honestly: a new Rust API plus a real external integration test is a usable developer-facing outcome, but it does not improve the existing desktop or CLI automatically. If the selected checkpoint instead promises a shell user can check a mixed project directory, include the actual CLI/discovery adapter now. Do not add a nominal CLI branch that fails before reaching the checker. Full compile/index adoption and repeated owned rename are unnecessary prerequisites for a read-only library result.
|
||||
|
||||
## Consequential choices
|
||||
|
||||
| Candidate | Benefit | Concrete cost or constraint |
|
||||
| --- | --- | --- |
|
||||
| Diagnostics-only check, dropping the witness before return | Smallest output contract; appropriate if the sole consumer needs pass/fail/warnings | Throws away the already admitted model; later model queries must parse again. Owning warning extraction needs an explicit drop/move boundary. It does not solve disk discovery. |
|
||||
| Opaque borrowed resolved result — recommended | Reuses the existing owner and complete model, source lifetime, warning inventory and ledger without another copy or storage transfer | Keeps syntax/expression/occurrence metadata live. Expose no mutable bundle/model, index/updater or generic constructor. The borrow must prevent changing/dropping input while the result is live. Avoid exposing internal resolver types as the permanent public interface. |
|
||||
| Owned read result containing moved Project/warnings | Useful for long-lived model-only query/import consumers; permits releasing syntax promptly | Requires a deliberate extraction/storage contract. It is still not editable compiled authority and cannot be called AcceptedRename: no emitted output was verified. No need to clone a bundle or charge output O unless this result actually owns one. Defer until a consumer needs ownership. |
|
||||
| Replace public parse/compile dispatch immediately | Broadest apparent reach | `compile_bundle` promises stabilized returned bytes, migration and a matching SourceIndex. Typed identity/index/writer/update coverage is incomplete; silently using an empty index or refusing valid ordinary omitted-ID input would violate those promises. Reject this candidate for the present slice. |
|
||||
|
||||
The borrowed candidate does not need to index occurrences merely to validate: `mixed/project.rs:29..53` already owns the admitted Project and warnings; indexing at60+ is a separate operation. Keeping a private wrapper around that owner also avoids creating an adoption capability accidentally. A user can always clone an exposed Project through existing public model APIs; this does not authenticate that clone for source saving. Existing downstream validators must remain in place.
|
||||
|
||||
## Required boundaries grounded in current code
|
||||
|
||||
**Initial authority and limits.** `mixed/carried.rs:43` currently has only a real pending-backed production constructor; the borrowed-zero constructor is fixture-only at191+. `parse_entry_producers:137` selects both producer modes, whereas `mixed.rs:279..305` uses the weaker legacy phase route. Add a deliberate initial borrowed-input constructor deriving policy from supplied ProjectLimits through the existing maximum-profile derivation. Do not expose arbitrary Limits/Slots, manufacture PendingRename or call the weaker route simply because its signature is convenient. C=0 means no previous verifier-owned allocation carry is claimed; it does not assert that the caller's source bundle uses no memory. It must not be reused to erase a pending owner's existing carry during verification.
|
||||
|
||||
Preserve exact caller file/include/source/model/reference constraints. The private profile additionally caps auxiliary tokens/entries/frames/numeric work; explicitly select and document these as this entry point's policy, including that auxiliary entries are not the caller's model-record count (`mixed.rs:283..289,317..338`). Existing logical-domain exclusions remain: this is not total heap/RSS accounting or every allocation before growth. Do not promise that every ordinarily valid unbounded model passes this bounded checker. No resource-profile or depth qualification follows merely from making the API public.
|
||||
|
||||
**Language and identity.** The initial contract should say source8 only, already explicit project/declaration/parameter IDs, no migration or stabilization. `language.rs:1291+` and `mixed.rs:239..259` presently enforce those IDs. This is a bounded checker scope, not a redefinition of ordinary compile's missing-ID behavior. Preserve whole ordinary/typed global names, scoped parameters, model validation and original file/span attribution. Do not infer syntax kind from whether the resolved Project happens to contain definitions: dispatch needs to be an explicit API decision, not a lossy model-based guess. Define treatment of supplied unreachable files according to the actual traversal/source-byte policy; do not advertise every supplied file as semantically checked without confirming traversal coverage.
|
||||
|
||||
**Production compilation.** `language.rs:6..9` currently gates analysis_source, and Parser state/hooks are separately gated. Promoting only the module cannot establish a real read path. Restrict the dependency promotion to parsing/resolution and necessary shared types; keep fixture authority and test fault injection gated. Do not publicly expose legacy typed-only update APIs just because their module is in the dependency graph. A non-test oa-core integration consumer is mandatory evidence.
|
||||
|
||||
**Existing caller separation.** `source_project.rs:111,287` defines the much stronger CompiledSourceProject contract. `source_files.rs:495,529` uses ordinary `inspect_includes` and later ordinary compile. CLI `lib.rs:213..305` loads that snapshot, runs ordinary lint and unconditionally compiles even for Check; its Prepared owns a CompiledSourceProject at175. Thus neither a new core checker nor substituting lint alone enables actual CLI mixed checks. A future CLI adapter must preserve syntax-based include discovery, path/edge/depth/byte limits, original-coordinate diagnostics and no-write behavior, while avoiding the legacy compile/stabilization branch. Regex include scanning or a fake Prepared is not an acceptable shortcut.
|
||||
|
||||
**No write/adoption inference.** The public formatter still omits definitions (`language.rs:522..607`), while generic updates use old/new formatting and whole-output recompilation (`source_project.rs:640..877`). Disk save revalidates the complete compiled tuple (`source_files.rs:849+`); desktop apply/history and server preparation similarly depend on it (`oa-desktop/src/document.rs:299..395`, `oa-server/src/store.rs:117..173`). Keep these guards and their present typed refusals. No conversion from the new result to these types is needed or justified. Reader success cannot authorize a lossy save, update, import, or history commit.
|
||||
|
||||
## Minimal strong acceptance
|
||||
|
||||
1. A non-test public integration consumer actually calls the new entry point on substantial complete mixed OA and SA bundles; independently authored whole Projects and complete located warnings match, including historical traces, nested ordinary owners, scoped parameters and cross-file references. Test genuine short typed forms and long analysis constructors under the explicitly selected mixed grammar.
|
||||
2. Exact original bundle bytes remain unchanged across success/refusal, including Unicode, mixed LF/CRLF, comments, includes and unused supplied-file policy. No stabilization, migration, output formatter, source index or disk operation is invoked. Retained result lifetimes and private fields enforce immutable source binding; no public tuple constructor.
|
||||
3. Exercise unresolved/duplicate global and scoped names, malformed syntax, invalid paths/includes/cycles, included-file diagnostics, omitted IDs under the declared scope, unsupported versions, caller limits and selected producer cap/cap-minus-one controls. Match errors/warnings to actual files/ranges; do not substitute success-only model equality for diagnostics tests.
|
||||
4. Ordinary public parse/compile/migration/update/save behavior and explicit typed refusals remain unchanged through their existing APIs. Preserve ordinary depth64, typed expression depth128 and the independent JSON DEPTH_128_VALIDATED=false gate. Reuse prior evidence only for byte-identical components; run actual promoted production builds and relevant stack controls because cfg/layout changes can alter frames even with equivalent semantics.
|
||||
5. If the outcome is claimed as CLI functionality, add real multifile CLI success, warning and invalid/refusal cases, exact exit/report semantics and unchanged disk bytes through the actual discovery path. Otherwise explicitly leave CLI/desktop/server adoption open and supply a small public API usage example; do not label library-only acceptance as application support.
|
||||
|
||||
No fundamental obstacle requires full editing adoption before this bounded read capability. The unresolved prerequisites are deliberate initial authority/policy, the explicit-ID language scope, production dependency promotion and the chosen real consumer. Those decisions should be fixed in the contract before implementation; they cannot be inferred from the private rename verifier's success.
|
||||
|
||||
## Subsequent proposal comparison
|
||||
|
||||
After writing the independent critique above, read IMPLEMENTATION-MAP.md. Its opaque borrowed resolver wrapper and strong initial C=0 constructor align with the recommendation; no new blocker was found. One wording should become explicit in the selected contract: “missing authored IDs follow existing parser semantics” means **refusal** for project, ordinary/typed declaration and parameter IDs, not UUID generation or compile stabilization. Public API documentation should say this directly.
|
||||
|
||||
The detached-file question has a concrete existing answer: `source_project/traversal.rs:185..200` rejects any supplied file not visited from the entry, and `mixed.rs:503` invokes that finish check. Preserve this refusal. Aggregate supplied source bytes/path validation precedes traversal; successful complete-bundle admission therefore cannot silently ignore a detached file. No new disconnected-file interpretation is needed.
|
||||
@@ -0,0 +1,262 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Private syntax text producer prerequisite
|
||||
|
||||
Source baseline: `8d52dab97c92cc31baae9f20d8c324b55818aa5d`.
|
||||
Selected after independent critique. This prerequisite addresses the named text
|
||||
timing gap in the carried-phase and emission contracts. It grants no accepted
|
||||
rewritten-output, public source8, save/history or installation authority.
|
||||
|
||||
## Scope and mode
|
||||
|
||||
Preserve all existing parser entry points, including the explicit carried-phase
|
||||
route, with their existing limits, charge events and diagnostics. Add a separate
|
||||
private fixture-constructible text-producing route. Its actual bundle, carried
|
||||
owner and exact Limits/ProjectLimits come from the existing opaque authority;
|
||||
arbitrary caller-provided baselines and policy widening remain impossible.
|
||||
Zero carried storage still selects this mode explicitly.
|
||||
|
||||
The guarantee is limited to the retained syntax String inventory already walked
|
||||
by `mixed/project/accounting.rs`, plus these named temporary result strings:
|
||||
raw-scanner JSON validation, quoted decode slack, consumed UUID spellings and
|
||||
local producer copies awaiting transfer or drop. Moves do not reserve again.
|
||||
Each simultaneous owned copy reserves its own logical UTF-8 length. Typed
|
||||
duplicate-name sets, traversal, parser entry/metadata
|
||||
producer timing and other previously documented scratch remain separate open
|
||||
domains. Model conversion, architectural validation, decoder internal scratch,
|
||||
allocator capacity/overhead and native stack are not represented by these logical
|
||||
String lengths. Internal Exact reconstruction/formatting and BigInt storage
|
||||
remain under existing numeric policy, with unchanged work charges; this exclusion
|
||||
does not cover retained AST String/Word/Reference values or copied syntax names.
|
||||
No universal heap claim is permitted.
|
||||
|
||||
## Admission and lifetime
|
||||
|
||||
Before every in-scope copy, check the prospective total carried text C plus
|
||||
live producer text and named temporary text against the existing byte ceiling,
|
||||
using checked arithmetic. Failed reservation changes no totals. These are storage
|
||||
counts, never source-byte/token/entry/reference/numeric work charges. Entry and
|
||||
occurrence phase checks retain their existing behavior.
|
||||
|
||||
Before the existing quoted String decoder, reserve P, the UTF-8 payload length
|
||||
excluding exactly the two quotes. Valid JSON has decoded length D <= P: ordinary
|
||||
UTF-8 copies equally, simple escapes contract, BMP escapes yield at most three
|
||||
bytes from six, and surrogate pairs yield four from twelve. On success release
|
||||
P-D. This conservative rule may refuse escaped text whose decoded bytes fit;
|
||||
that is intentional only in the new route. No second decoder or exact-number
|
||||
conversion is introduced. Scanner validation reserves inside the shared scan
|
||||
body after token extent discovery and before serde validation, then drops the
|
||||
result before refunding P. Unclosed tokens never invoke that decoder. Refusal
|
||||
may precede malformed-escape classification in the new route; legacy precedence
|
||||
must remain unchanged. No resumable refused scanner state is exposed.
|
||||
|
||||
Retained String producers include typed names/references/quoted fields; ordinary
|
||||
header/include/declaration/AST names, quoted text and words; both retained copies
|
||||
of declaration field keys; nested keys; and projected keys/reference names.
|
||||
Static header roles, source slices, literal spans and copied UUID values are not
|
||||
owned text. All successful consumed spellings must drop before refund: ordinary
|
||||
optional IDs, typed identities, and ordinary HistoricalUuid values. The ordinary
|
||||
declaration-kind word must either remain borrowed with unchanged parsing/error
|
||||
behavior or be accounted while live and released. Nested field key handling
|
||||
must account the clone overlap and release its discarded local original, or use
|
||||
a reviewed equivalent move without silently changing duplicate/error semantics.
|
||||
Project and typed duplicate descriptions already refuse before replacement;
|
||||
they do not create a successful overwrite exemption.
|
||||
|
||||
Use small scalar state in the existing Budget and narrowly scoped producer hooks.
|
||||
Do not duplicate full policies or introduce owner-sized inline state. A returned
|
||||
String may provisionally count as owned T until its consumer transfers or drops
|
||||
it; temporary decode slack and scanner results stay separately identifiable.
|
||||
Successful
|
||||
syntax return has no outstanding named temporary reservation. Independently
|
||||
reconcile retained T to the existing complete syntax inventory. Resolution seeds
|
||||
C once, transfers T once and retains the established U/M and bounded counting
|
||||
work semantics. Its text walk must independently sum/compare rather than charge
|
||||
T again. Existing routes retain their existing progressive text walk.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Preserve all prior actual outcomes, public/legacy malformed-token precedence,
|
||||
complete Project/Usage parity and exact carried-phase caps.
|
||||
- Check raw/escaped Unicode, simple escapes, surrogate pairs, empty strings,
|
||||
malformed escapes and unpaired surrogates. Assert reserve-before-decoder and
|
||||
drop-before-refund ordering through a bounded hook observer where needed.
|
||||
- Independently derive complete owner and peak counts for real fixtures using one
|
||||
unchanged profile through parse/resolve. Distinguish arithmetic fault injection
|
||||
from real provenance. Include scanner temporary release, all three UUID
|
||||
consumers, ordinary/projected key and reference overlap, nested fields and
|
||||
multi-file accumulation. A final retained count alone is not a peak oracle.
|
||||
- Verify exact final T, W=0, once-only C/T transfer, original source and desired
|
||||
data unchanged, and no accepted-output/extraction route.
|
||||
- Run new focused cases, the unchanged full library disposition, strict core
|
||||
all-target Clippy and format comparison. Investigate stack regressions and
|
||||
measure relevant changed prologues; do not enlarge existing worker stacks.
|
||||
|
||||
Later work still needs entry/metadata producer timing and a finite decision on
|
||||
remaining scratch, actual-output verification, justified equality work and an
|
||||
owning accepted-result transition. This prerequisite does not waive them.
|
||||
@@ -0,0 +1 @@
|
||||
*.md -text
|
||||
@@ -0,0 +1,64 @@
|
||||
# Independent retained-text producer critique
|
||||
|
||||
Reviewed proposal and current `8d52dab97c92cc31baae9f20d8c324b55818aa5d` producers, prior NEXT-PRODUCER-HOOKS/CRITIQUE, existing syntax text walk and carried-phase contract. Design-only; no source edits, compiler, network or parser execution.
|
||||
|
||||
Disposition: the explicit stronger mode, retained-text scope, named scanner result temporary and raw-payload bound form a useful bounded prerequisite. Do not expand it to U/M producers, duplicate-name sets or traversal. Before coding, make the successful-discard inventory and transfer semantics below concrete. It is not accepted-output verification or completion of broader before-growth requirements.
|
||||
|
||||
## Required lifecycle clarification
|
||||
|
||||
The proposal explicitly identifies ordinary optional_id and typed identity, but there is a third successful UUID spelling consumer: `language.rs::Parser::value_inner`'s `uuid` branch. It calls quoted(), parses an Id, returns Ast::HistoricalUuid and drops the decoded String. Hooking quoted without refunding this path leaks36 into final T and breaks independent reconciliation. Name this producer/consumer pair explicitly, including historical UUIDs nested in arrays/records. No projected text reservation applies to the copied Id.
|
||||
|
||||
For each charged shared producer, distinguish transfer, discard and duplication. Direct names/quoted results moved into retained AST/header/reference structures retain the charge. Optional/typed/historical UUID spellings remain charged until after their actual drop. Nested ordinary fields clone the key into a map while the local key remains alive; reserve the clone before creation, then refund the local original after drop on successful completion. Top-level field keys instead survive in two maps, so both remain charged. Projected keys/references create further live copies. Error-only abort paths need no reusable successful ledger, but scanner validation must release correctly before another token can be processed.
|
||||
|
||||
Avoid a generic rule that refunds every field-local name, counts every clone as retained forever, or replaces later mismatch with a corrective subtraction. Producer T must independently equal the established final inventory. Duplicate-field errors abort before success; they are not justification for ignoring ordinary successful temporary copies.
|
||||
|
||||
The ordinary declaration-kind String and existing typed parameter/call-label/override duplicate-set copies are not part of retained T. The proposal explicitly excludes coordination copies. Keep that limitation precise; shared name/quoted hooks do not automatically account downstream `.clone()` calls. This slice must not claim all parser String allocation has been covered.
|
||||
|
||||
## Reservation and handoff shape
|
||||
|
||||
Scalar state on the shared Budget is a reasonable design because scanner, typed cursor and ordinary State already borrow it. Do not copy C authority or full policy into recursive frames. Initialize the scalar carried text only through the consumed legitimate guard and exact inherited profile; no independent C setter or public arbitrary budget entry.
|
||||
|
||||
Define whether an unclassified returned String counts provisionally as owned T until its consumer drops it, or is W until an explicit transfer. Either can implement correct live totals, but documentation/tests must agree: a method called retained-text observation must not count discarded UUIDs at successful syntax return. W slack must be zero and independently walked retained text must equal the final producer total. Moves are accounting-neutral; copies coexist; release follows actual ownership end.
|
||||
|
||||
Resolver should seed C once and transfer T once, then use the existing bounded syntax walk to independently sum/compare text while retaining its lower-node/occurrence computation and accounted work frontier. That walk must not reserve the same T again. Its legacy and carried-phase-only text actions stay unchanged. An inconsistent producer tally is a failure, never repaired into acceptance. No extra generic AST clone, independent traversal container or second decoder is needed.
|
||||
|
||||
## Scanner and raw-payload policy
|
||||
|
||||
D<=P is sound for valid JSON UTF-8 string payloads and the selected escape/surrogate cases. Reserve P before the current decoder; reconcile successful output D, then release remaining live reservation after dropping validation/identity strings. This is a logical result-length bound, not serde scratch/capacity metering. Conservative rejection of escaped text whose D fits but P does not is a real new-mode policy and should be accepted explicitly.
|
||||
|
||||
Scanner validation happens before grammar consumes any of that file's strings. The scanner hook must run after finding the token extent but before its existing serde call. A closed invalid string can therefore receive a resource error before invalid-escape classification in stronger mode; an unclosed token never reaches that decoder. Preserve the unchanged Iterator/no-op scanner path and ordinary diagnostic precedence for legacy and phase-only modes. Do not accidentally latch stronger-mode failure into an unrelated reusable legacy scanner API.
|
||||
|
||||
Each successful scanner validation temporary ends before grammar decoding, so P must not accumulate across tokens. However retained T from earlier files remains live when scanning later files. Include a multi-file case that discriminates this overlap; releasing scanner W must not release previous-file T or C.
|
||||
|
||||
## Independent finite oracles
|
||||
|
||||
These counts are source-derived, not obtained from the proposed implementation.
|
||||
|
||||
1. **Existing empty E:** exact existing78-byte main.arcadia source; actual owned C=(1,0,102), final T8. Scanner maximum validation P36 gives text138. Grammar retains alias1/name7 before decoding UUID36, producing maximum **146**. Drop UUID and final C+T=110; resolver catalog maximum112. Therefore entries17 and bytes146 complete the whole path; bytes145 must refuse at ordinary project UUID decode, provided the selected hooks cover only the stated domain. Legacy phase-only complete cap112 and its original diagnostics must remain unchanged. The UUID token spans33..71; ordinary parser transport turns a start33 resource error into33..34, not the complete token span.
|
||||
|
||||
2. **Escaped project fixture:** use the E document constructor, replace display name `Project` with twenty literal source escapes `\u0061`, and set body to `description "` + twenty literal `\u0061` escapes + `";`. Each decoded value is20 ASCII `a` bytes, each raw payload120. Exact source bytes326; copied key12+entry12; C.text350, C.entries1. T is alias1+name20+description20=41. Scanner peakP120; grammar name peak1+120=121; UUID peak1+20+36=57; description peak1+20+120=141. Thus combined text peak **491**, cap490 refuses at the description quoted token after earlier phases fit. Syntax has U2 and M14 (13 significant tokens+F1), so owned syntax entries17 and project catalog peak21. With entries21, bytes491 also admits complete resolution: retained text391, catalog peak393, no declarations/lower expressions or warnings. Expected Project has name and description each20 `a` characters. This proves slack refunds and scanner nonaccumulation without letting UUID36 preempt the intended escape bound. Ordinary description quoted token begins200 and ends322; normal ordinary-error transport at start200 is200..201.
|
||||
|
||||
3. **T45 copy oracle caution:** the existing activity `description "é"` final text45 remains correct: project8 + activity alias/name2 + field_spans key11 + AST key11 + literal2 + projected key11. But new-mode C+44 fails **earlier at activity UUID**, whose live subtotal is8+2+36=46. It cannot be reused as a projected-key producer refusal with the old field span. Keep the old phase-only test unchanged; use roomy new-mode T45 reconciliation, or design a later-copy-dominant fixture with independently counted earlier peaks before asserting that refusal site.
|
||||
|
||||
4. Add one historical UUID and one nested record to discriminate consumed spelling refund versus local-key clone refund; one ordinary @reference verifies AST and projected spelling count twice; one typed scoped-name/call-label case verifies retained move versus explicitly excluded coordination clone. Do not multiply permutations once each distinct ownership action is covered.
|
||||
|
||||
5. Direct arithmetic tests cover quoted P/D examples, overflow and invalid refund. Label arbitrary scalar headroom injections as helper tests. Actual pipeline positive/negative caps must include the real complete bundle C and earlier scanner/UUID/retained peaks. Malformed input controls should assert both legacy error stability and explicitly selected stronger-mode precedence.
|
||||
|
||||
## Stack and scope
|
||||
|
||||
Retain the recent binding/prefix/continuation extraction and slim guard. Adding even a few Budget scalars changes inline type sizes and ancestor frames, so inspect actual compiler output and repeat established stack controls after implementation. Do not introduce a heavyweight per-String wrapper or stored callback merely for automatic refunds without reviewing its concrete frame/lifetime cost. A scoped scanner callback borrowing Budget avoids stored callback ownership; exact Rust signatures still require implementation review.
|
||||
|
||||
No new universal stack bound follows. The future verifier still owes actual-output semantic equality, original-E safety against both operands, output owner provenance and the remaining selected entry/scratch timing guarantees. This narrower text prerequisite advances one real gap without recasting every parser allocation as part of it.
|
||||
|
||||
## Parent CONTRACT-DRAFT follow-up
|
||||
|
||||
Read the parent's CONTRACT-DRAFT.md and the implementer's reported lifecycle clarification. The draft now explicitly covers all three UUID consumers, kind-word borrow/accounting choice, nested-key overlap, duplicate-description rejection, separate fixture mode and legacy diagnostics. No further ownership/authority blocker found for this bounded prerequisite.
|
||||
|
||||
One scope sentence should be corrected before acceptance: grouping **numeric reconstruction** with “separate open domains” suggests new unresolved text-accounting work that the selected metric never required. State instead that internal Exact numeric reconstruction/formatting and BigInt storage remain controlled by the existing numeric policy and excluded from this logical syntax-text inventory, with work charges unchanged. That exclusion must not extend to retained AST String/Word/Reference text or copied syntax names merely because they occur near numeric parsing. Traversal/coordination and entry-timing limitations can remain the separately open domains.
|
||||
|
||||
The E146/145 and escaped fixture491/490 counts above assume the declaration-kind word is irrelevant (these are project-only sources), all named UUID Strings drop/refund on success, and the existing complete syntax inventory remains unchanged. They do not depend on the proposed implementation's output. T45 should remain a generous-cap reconciliation example, not an asserted projected-copy threshold. No draft approval should imply final PendingRename verification or a blanket parser-allocation guarantee.
|
||||
|
||||
Pre-execution coordinate correction: the exact 78-byte E document's UUID quoted
|
||||
token is 34..72 and its ordinary diagnostic is 34..35. The earlier 33..71 /
|
||||
33..34 in this review was a source-character-count typo. Literal-only readback
|
||||
and the authored test use 34 correctly; the 146/145 storage caps are unchanged.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Named syntax-text producer contract — proposal
|
||||
|
||||
2026-09-25. Design only, not accepted requirements or implementation. Source pin `8d52dab97c92cc31baae9f20d8c324b55818aa5d`; paths below are repository-relative under `crates/oa-core/src/`. Builds/runtime/publication remain parent-owned. This refines the named text rows of `NEXT-PRODUCER-HOOKS.md` and the domain audit; it does not implement PendingRename verification or close every parser timing obligation.
|
||||
|
||||
## Smallest useful next slice
|
||||
|
||||
Add an explicit private **text-producing mode** that checks owned syntax text before its producer allocates/copies it, plus the shared scanner's validation-only decoded String. Keep the current legacy and carried-phase-only entry points and checkpoints intact. Enable the stronger mode only through an internally controlled fixture route for now, bound to the actual carried bundle/guard and exact inherited policy. A legitimate zero C still uses the stronger rules; do not enable/disable by its numeric value. The later PendingRename transition can select this mode only under its own accepted ownership contract.
|
||||
|
||||
This is independently useful: a successful stronger-mode syntax witness proves its counted retained text existed only after checks against the still-live carried text. It does **not** yet prove producer timing for all entry slots, traversal scratch or model/validator allocations. It does not expose an accepted output or change public source8 dispatch.
|
||||
|
||||
### Exact domain
|
||||
|
||||
- C is existing carried live Slots, immutable provenance. Its text includes all owned output sources, canonical keys and entry spelling. It is not work Usage.
|
||||
- T is the same retained syntax String inventory currently counted by `mixed/project/accounting.rs:233–352` and Walk::drain (`:146–230`): ordinary project/header aliases/names/description, include paths, declaration aliases/names, AST field keys/String/Word/Reference text, separate field_spans keys, projected record keys/reference names, and the typed declaration/parameter/reference/type/expression string inventory. Each simultaneously owned retained copy counts its own UTF-8 length. Static header-role names, source slices and numeric literal spans are not copied text.
|
||||
- W is only named temporary text selected in this slice: scanner validation result, outstanding quoted-decode reservation slack, consumed UUID spelling, and local copies made by these hooks before transfer/refund. On successful syntax return W=0 and charged retained T equals the original independent retained-text inventory.
|
||||
- Every proposed reservation checks `C.text + T + W.text + delta <= Limits.bytes`, with checked arithmetic. This storage use does not increment bytes/tokens/entries/references/numeric work Usage, shrink the Limits object or reinterpret source-byte work. Existing carried entry/occurrence phase checks remain unchanged.
|
||||
|
||||
This is a logical string-length metric, not capacity/RSS/all heap. Existing raw model construction/serde model conversion, architectural validator heap, exact-number limbs, allocator overhead and native stack remain outside this metric. **The scanner's returned decoded String is included despite being created by serde**; it is not covered by a generic serde exemption. Internal serde decode scratch/capacity is not represented separately by T/W here and must be stated as excluded implementation scratch, not claimed covered by one result-String reservation. Typed duplicate-name coordination sets and traversal/ordinary-open-stack/projection-walk scratch retain their previously documented separate bounds/limitations; they are not silently included or certified by this text slice. Newly introduced containers would require an explicit additional reservation/design decision; the proposed hook state needs only scalar counts.
|
||||
|
||||
## Quoted text policy: select raw payload reservation with refund
|
||||
|
||||
For a complete JSON string token let P be its UTF-8 byte length between the quotes, and D the decoded String byte length. Valid JSON guarantees D<=P: raw UTF-8 bytes copy unchanged; each simple escape consumes two source bytes and yields one; a non-surrogate six-byte `\uXXXX` yields at most three UTF-8 bytes; a twelve-byte surrogate pair yields four. Empty strings have P=D=0. JSON does not normalize Unicode or expand entities. Invalid escapes/surrogates do not produce a successful value.
|
||||
|
||||
Before the **existing** decoder call reserve P. On successful decode, check D<=P and release P-D; move the D charge with the String. If it is validation-only or a consumed identity/historical UUID spelling, drop the value before releasing its remaining reservation. A failed decode drops the decoder result and releases its attempted reservation before reporting failure where the scanner continues classifying tokens. No witness escapes a parser failure; there is no partial successful ledger to repair afterward.
|
||||
|
||||
This conservative policy can refuse a string whose decoded payload alone fits. That is an explicit new-mode admission rule: e.g. available storage 5 cannot admit `"\u0061"` (P6,D1), while available6 can reserve and later retain only1. Existing entry points do not gain that refusal. Do not report rawpayload policy as exact decoded-fit acceptance or hide its new error timing. Use the quoted token span internally for reserve refusals, preserving existing safe original-file transport. Current ordinary_error/located parser transport may report a one-byte public diagnostic at its start; this text slice does not silently change that diagnostic convention.
|
||||
|
||||
| Candidate | Benefit | Cost / reason not selected |
|
||||
| --- | --- | --- |
|
||||
| Exact D pre-count by an allocation-free JSON string grammar | Escaped strings admit at exact decoded-fit storage | Duplicates escape/surrogate/invalid-input interpretation or adds a second content pass; must track the actual serde dialect and error precedence. More code and compatibility proof than this bounded slice warrants. |
|
||||
| Count via serde visitor | Appears to reuse serde grammar | Visitor callbacks can occur after serde has built escaped-string scratch or produced an owned result; counting there is not a pre-growth check. Merely using a custom Visitor does not prove early reservation. |
|
||||
| Reserve raw P before the existing decoder, reconcile D | Simple proved bound, one existing decode per current consumer, no numeric reparse or multiplier | Conservative refusal must be accepted explicitly; library scratch/capacity is outside the selected logical result-text metric. Recommended. |
|
||||
|
||||
Do not add a second decoder or a third scanner-validation pass. If exact decoded-fit compatibility is required, that is a consequential different contract decision before implementation.
|
||||
|
||||
## Concrete reusable seams
|
||||
|
||||
The natural owner is the already shared Budget, because raw lexing, typed Cursor and ordinary mixed State borrow that one object. A private optional scalar producer-text state can expose reserve, reconcile/refund and final retained-text observation. It must not copy full Limits/ProjectLimits or add an owner-sized enum to each witness: use Budget's existing exact limits and the existing carried authority. State growth and parser stack controls must be measured after implementation, given the prior debug-frame regression.
|
||||
|
||||
Use named methods conceptually equivalent to `reserve_text(bytes, span)`, `release_text(bytes)` and quoted begin/finish transfer; exact signatures are implementation choices. Refund uses checked subtraction, not saturation. Reserve errors do not install new totals. Moves are neutral; copies reserve before creation. Keep retained and selected temporary subtotals distinguishable so W=0 and retained inventory equality are checkable. No arbitrary public setter, caller-supplied unrelated C or fresh policy reset is introduced.
|
||||
|
||||
| Producer / actual source | Required operation and lifecycle |
|
||||
| --- | --- |
|
||||
| `raw_tokens.rs:107–130`, allocation at126 | Inside the same scanner, after finding a closing quote but **before** existing serde String validation, reserve P. Let validation finish and drop its String, then refund P. An after-`next()` adapter is too late. Preserve unclosed-token behavior: no decoder and no decoded-result reservation if no close was found. |
|
||||
| `analysis_source/lex.rs:19–52` | Keep source-byte charge and raw-token charge before scanner advancement, including trivia. Call the hooked scanner only in the stronger mode. Retained significant tokens remain under the existing token bound; this patch must not introduce another tokens.len entry charge. |
|
||||
| `analysis_source/cursor.rs:67–95` | Reserve exact spelling length before name/reference `.to_owned`; quoted calls reserve P then reconcile to D. Reference-work charge/cursor advance/error order stays unchanged. |
|
||||
| `analysis_source/declarations.rs:405–434` identity; `language.rs:1211–1237` ordinary optional_id and `:1322–1332` historical uuid | The quoted UUID String is not retained syntax text. Keep it charged through UUID validation/parsing, drop it, then release D on success. No second UUID or Exact parse. Invalid identity aborts as before unless the earlier named storage refusal occurs. |
|
||||
| `language.rs:1195–1210,1256–1275,1368–1374` | Ordinary quoted, identifier, field key, Ast Word producers reserve before allocation. A hook at mixed State makes the legacy path a no-op. Account retained quoted literals even when stored inside `serde_json::Value::String`: this is AST text, not excluded model conversion. |
|
||||
| `language.rs:1245` nested fields; `:1518–1525` declaration field/field_spans | Each actual retained key copy is separate. Initial key transfers to one final owner. Reserve exact key.len before clone; refund original local if it drops rather than entering field_spans. Avoid hidden key clones in a convenience helper. A possible move-after-duplicate-check optimization requires separate error/order review, not a new metric exemption. |
|
||||
| `language.rs:1047–1090` Positions fields/reference clone | Add a narrow fallible copy hook at each existing owned key/reference clone, aggregated with the still-live AST text. Preserve the shared legacy API via its no-op wrapper. Atom projection does not copy quoted payload; HistoricalUuid copies an Id, not a String. No extra decoded-text charge for either. |
|
||||
| Other ordinary transient spellings and overwritten values | Inventory every successful-return discard of a charged producer result and refund it after drop; retain actual copied objects only once. Unrelated existing coordination copies absent from T are explicitly outside this slice, not silently charged as retained. |
|
||||
|
||||
A minimal scanner seam is an internally shared `next_with_string_hook` body with one scoped callback/event for reserve/refund around **its existing** validation call. `Iterator::next` invokes the same body with an infallible no-op hook, so public/legacy tokens and malformed-token handling remain unchanged. The mixed lexer callback mutably borrows the single Budget for the duration of `next`; no callback is stored, no second scanner traverses the source and no validation String escapes the scanner. One callback with reserve/release events avoids two simultaneous mutable borrows of Budget. Alternate concrete signatures are acceptable if they preserve this timing and shared scan body.
|
||||
|
||||
The rawscanner hook may reserve after lexical cursor advancement to the known closing quote; that is still before the named String producer. A refusal terminates the stronger parse with no token/witness, not a resumable partially advanced scanner API. Reserve errors win over subsequent invalid-escape errors only in stronger mode; this ordering is deliberate and testable.
|
||||
|
||||
## Inspected replacement and discard cases
|
||||
|
||||
These are actual source facts, not an assumption that every successful String copy survives:
|
||||
|
||||
- **Project description** (`language.rs:1560–1579`): header.description.is_some rejects the second field before syntax_entry, quoted decoding or assignment. The first valid assignment replaces only the initially empty String, which has logical length0. There is no successful overwritten nonempty project description to refund. `header.take()` on a rejected duplicate drops its existing header during whole-parse failure; no successful witness remains.
|
||||
- **Typed description** (`analysis_source/declarations.rs:301–317`): the borrowed-key `seen` set rejects a duplicate field before the field match/quoted decoder/description assignment. The Option starts None. Thus each successful typed description has exactly one retained String; no blanket replacement subtraction is justified.
|
||||
- **Declaration-kind word** (`language.rs:1587–1589`, still lexically in scope through declaration push at1631): its current to_owned String is not in final T. Prefer replacing only this needless copy with the original source slice `self.current().text(self.source)`, passing that borrowed word to declaration_kind and the unchanged unknown-kind diagnostic. The current Lexeme is a copied span; the borrowed text belongs to the source, not mutable Parser state. Preserve the same kind lookup and error formatting/order. This removes an otherwise new W lifetime without inventing a metric exemption. If inspection/compiler lifetimes prevent this exact borrow, reserve exact word.len before its existing allocation and explicitly drop/refund at the same safe point; do not leave its bytes in final T.
|
||||
- **Nested map key clone** (`language.rs:1242–1252`): field() produces an original key; fields.insert(key.clone(), value) retains a second allocation; the local original drops at loop end. Mark the original key's existing T charge as W (transfer, no aggregate delta), reserve the clone into T before copying, insert it, then explicitly drop/refund the original W. On a successful iteration one key length survives. In the top-level declaration case (`:1518–1525`), the original instead moves into field_spans while the clone stays in fields: both remain T. Do not apply the nested refund to that two-owner case.
|
||||
- **Duplicate field insertion**: nested/top-level insertion may replace a previous key/value immediately before returning the existing duplicate-field error. There is no successful replacement continuation. Keep existing diagnostic behavior/order and drop the failed parse; do not add a complex subtree refund traversal solely for a witness that cannot escape. Any newly prior storage refusal belongs only to the explicitly stronger mode.
|
||||
- **Every successful quoted UUID discard found in this parser**: ordinary optional_id (`language.rs:1211–1237`), ordinary historical `uuid` Ast branch (`:1322–1332`), and typed Cursor::identity (`analysis_source/declarations.rs:405–434`). Each temporarily retains its decoded spelling through validation/Id parsing, then returns only an Id and source spans. Mark its decoded charge temporary, explicitly drop the String, and refund D. HistoricalUuid does not become a counted text reference during projection (`language.rs:1090`) or inventory (`accounting.rs:146–170`). Typed parameter identities use the same Cursor identity path. These are three distinct consuming sites sharing the same quote producer, not three extra decoder passes.
|
||||
- **Excluded coordination clones remain explicit**: typed parameter_names (`declarations.rs:293`), override target names (`:610`) and Pratt sequence.keys (`syntax.rs:244`) own duplicate-check copies that do not occur in final T. This retained-text prerequisite does not claim to meter those existing scratch sets. Any later inclusion must reserve both entries and copied text before insertion and refund at actual drop; applying a blanket name-producer charge to these clones without release would be wrong.
|
||||
|
||||
The minimal live state can be a few scalar counts owned once in Budget, with narrow transfer/refund methods; it need not wrap every String in a lifetime-carrying type or refactor parser witnesses. Its representation and new helper frames still require measurement against the repaired parser's demonstrated roughly13 KiB numeric-path headroom improvement. No design can spend that margin based solely on source intuition.
|
||||
## Once-only resolver transfer and reconciliation
|
||||
|
||||
At successful stronger syntax return retain scalar T with Budget/text mode and require no live temporary reservation. Do not charge T as Usage. In resolve, seed the existing ledger with C once, then transfer/reserve known T once along with the established U+M path. Change the existing bounded syntax walk's text action in this mode to checked independent summation/reconciliation, rather than another text reservation. Require the independently walked retained String inventory to equal producer T before a resolved witness escapes. Keep its existing lower-node/occurrence counting and already-accounted work frontier; do not introduce a second complete AST clone or unbounded count traversal.
|
||||
|
||||
Legacy and existing phase-only mode keep their current incremental text walk. Stronger-mode full T remains live during the walk, so work peaks can tighten compared with the old progressive reservation; this is honest simultaneous ownership, not a compatibility promise. Entry-slot producer timing is still not changed by this slice. C must not be rebased away or added twice. M's token-end metadata remains its single established component, not a new charge for every significant token and projection table independently.
|
||||
|
||||
## Finite acceptance cases
|
||||
|
||||
1. **Unchanged APIs:** same raw scanner token stream/spans/classes and legacy parser errors/models/Usage under existing tests, including malformed strings, trivia, Unicode/CRLF and source8 phase timing. Existing carried-phase tests keep their exact prior caps/diagnostics. Stronger mode is explicit, including C0.
|
||||
2. **Bound cases:** independently hand-count empty payload0/0; `"a"`1/1; raw `"é"`2/2; `"\\"`2/1; `"\n"`2/1; `"\u0061"`6/1; `"\u96ea"`6/3; `"\uD83D\uDE00"`12/4. Test exact P and P-minus-one headroom as hook arithmetic; do not mislabel arbitrary scalar baselines as real owner provenance.
|
||||
3. **Actual minimal path:** independent critic derived existing empty-project E with C.text102: scanner UUID result peaks at102+36=138; grammar retains alias1+display name7 before its UUID decode, so the selected producer peak is102+1+7+36=146. With sufficient entries17, inherited byte146 should pass and145 should refuse that grammar UUID temporary, leaving final retained T8 (C+T110) on success. This is a proposed real-path oracle, not a run result; preserve current located-span conventions. A real retained bundle fixture with two long escaped names/descriptions (each P greater than UUID36) distinguishes scanner temporary release from cumulative retained T. Derive complete C and all earlier peaks independently before selecting pipeline caps. Exact new-mode pass/refusal must use one inherited profile from entry through resolve, never mutate the live budget.
|
||||
4. **Named temporaries:** repeated scanner validation does not retain its decoded strings; identity spellings disappear from final T; ordinary and typed UUIDs do not add36 each to final syntax. Raw validation occurs before grammar decoding but their result strings do not overlap. Invalid escape and unpaired-surrogate cases refund attempted scanner text and emit no syntax witness.
|
||||
5. **Duplicate copies:** the existing ordinary `description "é"` inventory T45 is a discriminating final oracle: header8 + alias/name2 + field_spans key11 + AST key11 + decodedé2 + projected key11. Atom payload is not copied into positions. This is a roomy final reconciliation test, not a C+45/C+44 producer-cap oracle: a preceding declaration UUID causes a temporary text peak46, so C+44 can fail earlier and must not be asserted to reach projected-key allocation. Use a separately hand-counted later-copy-dominant fixture to isolate that hook. Include nested record keys, explicit @reference clone, typed scoped names and included files; reconcile final producer T against the independent existing syntax inventory.
|
||||
6. **New refusal semantics:** long escaped input with D fitting but P exceeding available storage refuses at the quoted token before decoder growth in stronger mode; ample storage yields the same whole Project/Usage as legacy. Test resource refusal versus malformed escape ordering explicitly. Do not promise exactdecoded acceptance.
|
||||
7. **Ownership/accounting:** checked overflow and invalid refund fault injection are labeled arithmetic tests; moves do not charge again; copies do; successful W0; resolver transfers C/T once. Actual complete bundle identity and exact Limits/ProjectLimits remain guarded. No hidden owned output extraction or adopted result.
|
||||
8. **Regressions:** unchanged deep/wide parser and 128 KiB controls, meaningful measured native-frame headroom, all old failure dispositions, and exact numeric work. This slice cannot claim universal allocation containment, solve remaining traversal/entry-producer timing, or substitute byte/length tests for eventual actual-output semantic equality.
|
||||
|
||||
## Decisions requiring acceptance before code
|
||||
|
||||
Select rawpayload conservative admission versus exactdecoded-fit compatibility; explicitly adopt the returned scanner String into W while excluding internal decoder scratch from this logical metric; decide whether the new mode must remain distinct from existing phase-only carried entry; and accept the exact list of still-open entry/traversal/coordination timing obligations. The recommendation is the explicit stronger mode, raw P/refund D, named result-String metric and once-only reconciled transfer above. If the predecessor's broad producer requirement is interpreted as every parser temporary already being in scope, this partial text slice must remain an identified prerequisite—not a silent weakening or final output-verification acceptance.
|
||||
@@ -0,0 +1,4 @@
|
||||
*.md -text
|
||||
*.py -text
|
||||
*.txt -text
|
||||
*.json -text
|
||||
@@ -0,0 +1,97 @@
|
||||
# Independent carried-phase oracle
|
||||
|
||||
Source inspected: `18073a6f2eabce83fc83997f094e331eec835a16`, before carried implementation. Accepted scope: `harness/analysis-carried-phase-contract-20260925.md`. Expectations below are literal source/grammar/accounting counts, not parser output, measured thresholds or generated model expectations. No Cargo or application evaluator was run.
|
||||
|
||||
## Exact fixtures
|
||||
|
||||
All strings below use Rust escape notation; no BOM. `entry = "main.arcadia"`.
|
||||
|
||||
**E**, existing `project::tests::single("")`, has one file:
|
||||
|
||||
```text
|
||||
main.arcadia = "arcadia 8;\nproject p \"Project\" id \"00000000-0000-0000-0000-000000000001\" {\n\n}\n"
|
||||
```
|
||||
|
||||
**H**, a three-file include chain, has these exact files:
|
||||
|
||||
```text
|
||||
main.arcadia = "arcadia 8;\nproject p \"Project\" id \"00000000-0000-0000-0000-000000000001\" {\ninclude \"part.arcadia\";\n}\n"
|
||||
part.arcadia = "include \"last.arcadia\";\r\n"
|
||||
last.arcadia = "//\u{00e9}\r\n"
|
||||
```
|
||||
|
||||
The last source contains actual U+00E9, not literal backslash escape characters. Its UTF-8 length is **6**: two slashes, two bytes for U+00E9, CR and LF. Traversal order is main, part, last; retained canonical file order is last, main, part. Both fixtures describe only the same project: schema8, UUID suffix1, alias `p`, name `Project`, empty description and all model maps empty. No warnings, expressions or lower occurrences are expected.
|
||||
|
||||
| Quantity | E | H |
|
||||
|---|---:|---:|
|
||||
| File/map entry count F | 1 | 3 |
|
||||
| Individual source byte lengths | 78 | 101,25,6 |
|
||||
| Total source work bytes | 78 | 132 |
|
||||
| Owned path-key bytes | 12 | 36 |
|
||||
| Owned entry-path bytes | 12 | 12 |
|
||||
| Actual retained owner C entries | 1 | 3 |
|
||||
| Actual retained owner C occurrences | 0 | 0 |
|
||||
| Actual retained owner C text | 102 | 180 |
|
||||
|
||||
There is one entry-path allocation in addition to each map key. Source bytes are already included in C.text; parsing charges their work once but does not add them again to live text. No arbitrary prior-owner storage is counted by this minimal fixture.
|
||||
|
||||
## Parser arithmetic
|
||||
|
||||
E significant tokens are exactly `arcadia`, `8`, `;`, `project`, `p`, quoted name, `id`, quoted UUID, `{`, `}`: ten. Nine whitespace runs give nineteen raw scanner events. The project charges one syntax entry. There are no value ends, ordinary position slots, lexical owners, references, frames or Exact operations. M is one file reference plus ten significant-token metadata slots =11; U=1.
|
||||
|
||||
H main has the same ten significant tokens plus include/string/semicolon =13. It has eleven whitespace runs, hence24 raw scanner events. Part has3 significant tokens and2 whitespace runs, hence5 raw events. Last has one comment (including CR) and one LF whitespace event, hence2 raw events and0 significant tokens. Total scanner events31. The project and two includes charge U=3. All value-end/ordinary-position/lexical-owner contributions remain zero.
|
||||
|
||||
| H checkpoint | U | M | Owned C.entries+U+M | Borrowed-zero U+M |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Before traversal | 0 | 3 | 6 | 3 |
|
||||
| Main preprojection | 2 | 3+13=16 | 21 | 18 |
|
||||
| Part preprojection | 3 | 16+3=19 | 25 | 22 |
|
||||
| Last preprojection/final syntax | 3 | 19+0=19 | 25 | 22 |
|
||||
|
||||
E initial owned file sum is2; preprojection/final sum13. Successful new-snapshot Usage is independent of C: E `(bytes78,tokens19,entries1,references0,deepest_frame0)`, H `(bytes132,tokens31,entries3,references0,deepest_frame0)`, numeric work0 for each.
|
||||
|
||||
Discriminating entry-cap cases, with other limits generous:
|
||||
|
||||
- E owned: cap13 returns syntax; cap12 refuses the preprojection sum even though C1, U1 and M11 each fit separately. Do not call cap13 a complete resolve pass.
|
||||
- H owned: cap25 returns syntax; cap24 refuses at part, after main's21 passed. Cap20 refuses at main. These catch missing prior-file U/M and incorrect file attribution.
|
||||
- E borrowed-zero carried: cap12 returns syntax; cap11 refuses preprojection. Legacy cap11 must still return syntax, then fail initial resolver U+M admission12. This distinguishes explicit carried mode from a numeric `C == 0` bypass and from inadvertently changing legacy timing.
|
||||
- Initial owned C+F: E cap1 refuses sum2; H cap5 refuses sum6. Their C values separately fit. Cap2/E or cap6/H clears only the initial checkpoint, not the full parser. If an observable ordering sentinel is needed, use E with test-only ProjectLimits.max_files=0: cap1 gets the initial lowering refusal, cap2 reaches traversal's `project_limit` refusal. Do not describe that deliberately invalid-policy fixture as an admitted positive owner.
|
||||
|
||||
## Resolve and text arithmetic
|
||||
|
||||
Syntax accounting retains U+M entries and T text. E T=alias1+name7=8. H T=8+two include strings12 each=32. These fixtures have no accounting work-stack items: there are no declaration positions, AST values or expressions to visit. The project catalog temporarily retains alias map1 entry/text1, owner map1 entry, and lower tables2 entries/text1. Its peak adds4 entries/2 text. All four entries and both alias copies are subsequently released; no mapped warnings add storage.
|
||||
|
||||
| Exact storage | E zero | E owned | H zero | H owned |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Syntax/final retained entries | 12 | 13 | 22 | 25 |
|
||||
| Maximum resolver entries | 16 | 17 | 26 | 29 |
|
||||
| Syntax/final retained text | 8 | 110 | 32 | 212 |
|
||||
| Maximum resolver text | 10 | 112 | 34 | 214 |
|
||||
| Final lower occurrences | 0 | 0 | 0 | 0 |
|
||||
|
||||
Thus independent combined full-path pairs are E `(entries17,bytes112)` fit versus entries16 or bytes111 refusal; H `(entries29,bytes214)` fit versus entries28 or bytes213 refusal. Each failed coordinate is varied independently with the other sufficient. In both entry failures parser admission passes; the failure is the project lower-table catalog reservation. A zero-C complete resolve fits at the failed owned cap, so carry participation is directly discriminated. Successful final live slots must equal E `(13,0,110)` and H `(25,0,212)`, exactly normal base plus C once; this catches seeding zero, doubling C, or retaining parser checks as extra reservations.
|
||||
|
||||
Text timing can be tested separately: E owned bytes110 admits syntax accounting but later catalog needs112; bytes109 admits C102 and original source78 and completes parsing, then fails while accounting project name (C102+alias1+name7=110). Bytes102/101 tests C text admission at fit/fail;102 is only admission-fit, not full-resolution-fit. H owned bytes212 admits syntax text but catalog needs214; bytes211 fails when part's include text takes180+8+24=212. Canonical ordering means part's include text12 is counted after main's header/include, not before. Both quoted names and paths have already been decoded by the time syntax text accounting refuses. These are not before-decoding guarantees.
|
||||
|
||||
## Exact diagnostic expectations
|
||||
|
||||
Preserve existing transport distinction: parser `ordinary_error` then `located` converts the error's starting offset to a one-character span; resolver `Failure::typed` explicitly restores the full typed span.
|
||||
|
||||
- Parser aggregate/file-slot/C-admission errors at default span become `main.arcadia`, span0..1, line1 column1, code `invalid_source`, no related locations. H cap24 preprojection error is **part.arcadia**, span0..1, line1 column1; H cap20 is main0..1.
|
||||
- Entry resource message: `Source8 lowering entry limit exceeded.` Text resource message: `Source8 index/output byte limit exceeded.`
|
||||
- E legacy cap11 syntax succeeds, then resolve's initial U+M error is main **0..0**, line1 column1, not parser0..1.
|
||||
- Project catalog entry/text refusals above are main **11..73**, line2 column1, code `invalid_source`, same resource message. The header starts at `project` offset11 and ends immediately before `{` offset73.
|
||||
- E bytes109 syntax-text refusal uses that header11..73. H bytes211 syntax-text refusal is **part.arcadia**, include span **0..23**, line1 column1 (its include is the final12-byte addition).
|
||||
- H source include spans are main75..98 and part0..23. They are useful independent include-depth/edge attribution controls.
|
||||
|
||||
## Policy and ownership controls
|
||||
|
||||
Use all six distinct captured Limits values and all ProjectLimits fields, compare exact policy snapshots, and separately exercise real tightened work limits. Do not reconstruct a default profile or subtract C from entry/text limits as a replacement policy.
|
||||
|
||||
- H borrowed-zero bytes132 passes source work; bytes131 refuses complete-source precheck, main0..1. H owned cannot isolate the132-byte source boundary because its C.text180 is already larger; use borrowed mode honestly.
|
||||
- E raw-token19 fits and18 refuses final newline; H31 fits and30 refuses last-file LF at byte5, giving last.arcadia span5..6, line1 column5. C does not consume token events.
|
||||
- H max_files3 versus2 and include depth2 versus1 test retained file/depth policy; max_include_edges2 versus1 tests the second include. Preserve normal traversal/parser diagnostic codes rather than replacing them with storage errors. Keep entry and byte storage limits large enough to reach those checks.
|
||||
- E/H have zero new references, frames and numeric work. Exact snapshot equality can detect widened fields, but these fixtures **cannot** behaviorally prove positive reference/frame/numeric enforcement. Reuse the established admitted reference/nested-value/Exact fixtures with tightened captured policies for those tests; do not pretend empty fixtures exercise them. A preceding witness's nonzero Usage must not be copied into this snapshot.
|
||||
- Every retained positive owner owns exactly the actual bundle counted above, remains alive through returned syntax/resolved guards, and cannot be swapped for an unrelated bundle. Failure returns only diagnostics. Successful owner provenance has occurrence C=0; nonzero occurrence and unreachable arithmetic-overflow injections are explicitly fault-injection tests, not fixture storage or successful constructor evidence.
|
||||
|
||||
No new implementation was inspected or executed. This oracle establishes expected phase behavior only; it neither accepts an emitter, grants editing/install authority, claims universal small-stack behavior, nor closes predecessor before-growth obligations.
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"baseline": "18073a6f2eabce83fc83997f094e331eec835a16",
|
||||
"inputs": 553,
|
||||
"unchanged_old_outcomes": 246,
|
||||
"added_passed": 12,
|
||||
"full_passed": 242,
|
||||
"identical_failure_blocks_after_pid_only_normalization": 16,
|
||||
"identical_fmt_sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d",
|
||||
"receipts": {
|
||||
"carried-focused-fa7a980-1": {
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"exit": 0,
|
||||
"outcomes": 12,
|
||||
"listing": 0,
|
||||
"log_sha256": "2d8058db7f66c8cf875d6fd1ffe89d15c49ee16a6bb25dc6b97be5fbfa321946",
|
||||
"result_sha256": "2dc067b342ba6409c4ae21b540ee133732c314416b3b7e888b8c9ec7e03a67a9"
|
||||
},
|
||||
"carried-full-fa7a980-1": {
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"exit": 101,
|
||||
"outcomes": 258,
|
||||
"listing": 0,
|
||||
"log_sha256": "26b946c38db53e7dc589771e1829908dff3596cbf947ecce2442d1bf1d1896af",
|
||||
"result_sha256": "6b6ec7a335e8c1d03ec5c584e3fe8b444839e27cf3afb9f84bced33c73563743"
|
||||
},
|
||||
"carried-list-fa7a980-1": {
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"exit": 0,
|
||||
"outcomes": 0,
|
||||
"listing": 258,
|
||||
"log_sha256": "ee1c0a5367f277720407fb30a33ccdaef68b58fed3c578caceffbae7ef4035c4",
|
||||
"result_sha256": "8f739ce87c1a700bc9a51ea70b7dd8d3f77267123d5883f3cd8a36cc2a4e2c01"
|
||||
},
|
||||
"carried-clippy-fa7a980-1": {
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"exit": 0,
|
||||
"outcomes": 0,
|
||||
"listing": 0,
|
||||
"log_sha256": "a16886fc9c1af0f8074c7f2ba51cbb1983f4d493f40faf3164d94b28c64b055d",
|
||||
"result_sha256": "06390bd5ae88d86cb1d24a7e17b0a57096f0a90a84482cfee4a7aa6febdbf3df"
|
||||
},
|
||||
"carried-fmt-fa7a980-1": {
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"exit": 1,
|
||||
"outcomes": 0,
|
||||
"listing": 0,
|
||||
"log_sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d",
|
||||
"result_sha256": "ad79d2092b8182f3df68ed383f7ad32b3fa48afb029fa13da1ca0463203fa213"
|
||||
}
|
||||
},
|
||||
"scope": "Read-only committed-input/raw-log/artifact comparison; no Cargo execution."
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Independent package readback
|
||||
|
||||
**PASS for preservation, binding and reported evidence scope.** Reviewed against source `fa7a980418ef99d772e67c66c28dfa7b5181f875`; the private worktree names that commit and has no tracked modifications. No material package defect or README overclaim found.
|
||||
|
||||
The unchanged ZIP has **53 unique members, 458,509 bytes**, SHA256 `2eca143b706458c1c0217af715fa6f17c01a0b9f85a5313d6a231dabe1aba7c9`. All CRCs pass. Every member name, byte count and hash matches the manifest; 51 file members equal their original evidence and both patch members equal fresh immutable Git diffs (18073→fa7 and d11→fa7). All eight readable mirrors equal their archive and original review-folder bytes. All nine local Markdown links resolve. The archived selected contract equals the root contract, SHA256 `875b26eb850ab75d6e09222be37327a87a5b4c4a6f0557adf9723984f945d5f5`.
|
||||
|
||||
Independent raw reconciliation confirms **12 focused passes; 258 listed tests; full 242 passed / 16 failed; all nine previous stack-named controls passed**. All 246 prior outcomes are unchanged, and all 16 failure bodies match after normalizing only numeric thread identifiers. Strict Clippy exits 0. Formatting exits 1 with the same eight blocks and exact baseline log SHA256 `c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d`.
|
||||
|
||||
Final receipt source, input, log and captured-launcher bindings reconcile. All 553 declared inputs match immutable source blobs and current raw working bytes. The current artifact matches 42,223,104 bytes and SHA256 `c990e77015f2e4535003875abe7d49199cead803ee60677d86cdf056da7d8298`. This audit does not independently reverify remote publication or authenticate unrecorded build environment.
|
||||
|
||||
The initial d11 full abort is preserved with **124 completed passes**, exit3221225725, and its distinct artifact identity. Its focused 12-pass result is not substituted for a complete run. Debugger log/launcher/source/artifact bindings agree; the trace contains the overflow in exact-number parsing and an explicit child kill, so debugger exit0 is correctly not reported as a passing test. Both prologue records bind their respective artifacts. Reading their recorded instructions confirms the stated selected-frame reductions sum to 1,568 bytes, distinguishing the real worker from its same-named 56-byte harness shim. These observations and the completed final regression run do not prove sole causation or a universal stack bound. The older rename full-pipeline setup observation remains explicitly unresolved.
|
||||
|
||||
README scope is accurate: fixture-only constructors, logical phase accounting and delayed syntax-text admission; no emitter, accepted rewritten output, public source8, preview integration, Linux/WSL or universal before-growth claim. Earlier pending source-review statements remain historical evidence alongside the final runtime review. The toolchain record is identified as reused, and the initial executable is identified rather than claimed included in the ZIP.
|
||||
|
||||
Reviewed README SHA256: `0749813ee3606da5893874c692b253bcb7f1bb7864f0448ea102d499a3b951aa`; manifest SHA256: `355fa085134cbba38d119df46b9cb5dbfc009224d005002b5b29ea87886b5e87`.
|
||||
|
||||
Local reproducible inspection: `.local/analysis-carried-phase-review-20260925/inspect_package.py`, SHA256 `f3cafe8f5f212cbab82b444e9c2e40ad90b0b1ef26d5539bbe90709bcff1e6d3`; result `PACKAGE-READBACK.json`, SHA256 `dc009ff9c65b694136cae68c2a20150d01e9b86ce2fd708cc34f0bd2f9535a07`. No archived code, Cargo, test executable or network operation was executed; the prior runtime checker/output was not rerun or overwritten. This report is outside the immutable archive.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Private carried parser phase accounting
|
||||
|
||||
Source **fa7a980418ef99d772e67c66c28dfa7b5181f875** is pushed and ref-verified
|
||||
on `codex/analysis-carried-phase-956atf-20260925`. It implements the limited
|
||||
[carried-phase contract](../../analysis-carried-phase-contract-20260925.md).
|
||||
The private path binds the actual source bundle, allocation owner and exact
|
||||
inherited policy, checks combined logical storage at specified parser phases,
|
||||
then seeds the existing resolver ledger once. Original parser entry points keep
|
||||
their prior checkpoints. New constructors remain fixture-only: this is not an
|
||||
emitter, accepted edited output, public source8 or a published preview change.
|
||||
|
||||
Windows gnullvm, rustc/Cargo 1.98.1: **12 new tests pass**, strict core all-target
|
||||
Clippy passes, and the actual listing contains **258 names**. The full library
|
||||
remains **FAILED: 242 passed / 16 failed**. All 246 prior outcomes and all 16
|
||||
failure bodies match the previous checkpoint after normalizing only numeric
|
||||
thread identifiers. Formatting remains **FAILED**, with the byte-identical
|
||||
eight inherited diff blocks in five files. Linux/WSL checks were not run.
|
||||
|
||||
The [independent runtime review](RUNTIME-REVIEW.md) verifies all 553 declared
|
||||
inputs against immutable Git and raw working bytes, exact launchers, logs and
|
||||
the 42,223,104-byte test artifact, SHA256
|
||||
`c990e77015f2e4535003875abe7d49199cead803ee60677d86cdf056da7d8298`.
|
||||
[Source review](SOURCE-REVIEW.md), [test review](TEST-REVIEW.md) and the
|
||||
[independent oracle](CARRIED-PHASE-ORACLE.md) cover exact policy and fresh Usage,
|
||||
complete OA/SA parity, owned bundle lifetime, once-only retained storage,
|
||||
multi-file limits, original diagnostic locations and postparse text accounting.
|
||||
|
||||
The 78-byte empty source fixture owns 102 source/key/entry bytes and one file
|
||||
map entry. Its carried syntax cap is 13 entries; complete resolution needs
|
||||
17 entries / 112 bytes and retains (13 entries, 0 occurrences, 110 text bytes).
|
||||
The three-file Unicode/CRLF fixture owns (3, 0, 180), needs complete caps
|
||||
29 / 214, and retains (25, 0, 212). Each cap-minus-one control reaches its
|
||||
specified real phase. Borrowed carried-zero mode intentionally refuses a
|
||||
combined syntax total earlier than the unchanged legacy mode. Nonzero carried
|
||||
occurrences and impossible overflow values are explicitly fault injection,
|
||||
not claims of real bundle-owned occurrence storage.
|
||||
|
||||
The [stack investigation](STACK-DIAGNOSIS.md) preserves an initial full-run
|
||||
abort at `d11b99bb` after 124 completed passes. Its focused 12 cases had passed;
|
||||
the existing 128 KiB ordinary-index control then overflowed during parsing.
|
||||
LLDB reproduced the exact artifact's active numeric parsing path. The repair
|
||||
transfers policy into the existing Budget/syntax fields and retains a smaller
|
||||
backing guard, reducing duplicate inline state without adding heap storage.
|
||||
The final full run completes and all nine prior stack-named controls pass.
|
||||
Their source, stack allowances and expected behavior were not weakened.
|
||||
Selected prologues shrink by 1,568 bytes in aggregate; this is not a complete
|
||||
stack measurement or a universal guarantee. The separate older rename-test
|
||||
full-pipeline 128 KiB setup observation remains unresolved.
|
||||
|
||||
[evidence.zip](evidence.zip) contains **53 members, 458,509 bytes**, SHA256
|
||||
`2eca143b706458c1c0217af715fa6f17c01a0b9f85a5313d6a231dabe1aba7c9`.
|
||||
[manifest.json](manifest.json) pins each member. The archive preserves initial
|
||||
and final gates, exact launchers, debugger/prologue evidence, baseline records,
|
||||
source patches, contract snapshots and reviews. Eight readable review/checker
|
||||
files are exact archive mirrors. Historical test executables are identified by
|
||||
receipts; the initial one was retained locally but is not included in this ZIP.
|
||||
The toolchain version text is an unchanged earlier capture, not a new probe.
|
||||
|
||||
Reproduce the final gates from the identified source with the project Windows
|
||||
toolchain, one compiler job, `CARGO_INCREMENTAL=0`, and no lifecycle or
|
||||
RUST_MIN_STACK override:
|
||||
|
||||
```text
|
||||
cargo test --locked --offline -p oa-core --lib -- --list
|
||||
cargo test --locked --offline -p oa-core --lib language::analysis_source::mixed::carried::tests:: -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-core --lib -- --test-threads=1
|
||||
cargo clippy --locked --offline -p oa-core --all-targets -- -D warnings
|
||||
cargo fmt --all -- --check
|
||||
```
|
||||
|
||||
Replay helpers retain the producing machine's layout and must be read before
|
||||
reuse. The [readback checker](inspect_runtime.py) verifies recorded evidence
|
||||
without launching Cargo or the test executable. Receipts bind declared inputs
|
||||
and recorded environment fields, not exhaustive environment state or
|
||||
authenticated build provenance. A debugger exit zero after killing its stopped
|
||||
child is not a passing ordinary test.
|
||||
|
||||
This prerequisite counts the established logical auxiliary domain at named
|
||||
phase boundaries. It neither establishes nor waives stronger parser
|
||||
before-growth obligations. Output construction, the real consumed-owner
|
||||
transition, actual-output equality, editing/history/persistence and application
|
||||
integration remain required work under issue #7.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Independent carried-phase runtime readback
|
||||
|
||||
Reviewed final source `fa7a980418ef99d772e67c66c28dfa7b5181f875`. Disposition: the12 added tests pass and all246 prior outcomes are unchanged. The completed oa-core library run has242 passes and16 inherited failures; the full suite and formatter are not green. No Cargo, product executable or debugger was executed during this review.
|
||||
|
||||
## Method and source binding
|
||||
|
||||
Read `inspect_runtime.py` before executing it with bundled Python `-I -B` and arguments `fa7a980418ef99d772e67c66c28dfa7b5181f875 fa7a980 12`. Its subprocess calls are read-only Git queries. It refuses an existing readback output. No checker correction was necessary. Additional read-only inspection covered launcher behavior, all recorded environment fields, initial aborted records, retained old binary, debugger/prologue evidence and prior archive membership.
|
||||
|
||||
- Checker:7452 bytes, SHA-256 `bc9065192356d06f909abd3af06da2bffddbf88cce04524490bf8c5c404b84da`.
|
||||
- Generated `CARRIED-PHASE-RUNTIME-READBACK.json`:2216 bytes, SHA-256 `0003162f0524e6debecdadd0a2f13b86c67b56db92e5ab60360a876130a445fa`.
|
||||
- All553 declared files match immutable Git blob bytes and current raw disk bytes. Tracked working tree is clean and HEAD is the exact final source. Every gate's manifest equals the independently reconstructed source/path/length/SHA inventory; manifest SHA-256 `b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203`.
|
||||
- Final actual Cargo test artifact:42,223,104 bytes, SHA-256 `c990e77015f2e4535003875abe7d49199cead803ee60677d86cdf056da7d8298`. Current bytes match the receipts and actual Running path in raw logs.
|
||||
- Captured final launcher SHA-256 `51f590750896843210e02df971c7396bf379494e1605bd059ef017e6e4d41ec5` matches its before/after pins. It records actual subprocess return status, verifies inputs before/after, captures immutable helper bytes, and returns nonzero on detected source/helper changes. It does not turn the inherited failures into success.
|
||||
|
||||
The recorded environment is identical for the five final gates: jobs1, incremental0, isolated target `.local/analysis-checked-save-target-20260913`, Cargo/Rustup homes under `.local/toolchain`, and absent RUSTFLAGS, RUSTC, RUSTUP_TOOLCHAIN, RUST_MIN_STACK and ARCADIA_CODEC_LIFECYCLE_PHASE. This is declared-source and recorded-environment evidence, not a complete compiler/toolchain provenance attestation or a scan of every possible untracked dependency.
|
||||
|
||||
## Final raw outcomes
|
||||
|
||||
| Gate suffix `-fa7a980-1` | Exact scope | Result |
|
||||
|---|---|---|
|
||||
| carried-focused | locked/offline oa-core lib, carried test module, one test thread |12pass,0fail,246filtered; exit0 |
|
||||
| carried-full | locked/offline oa-core lib, one test thread |242pass,16fail,0ignored,0filtered; exit101 |
|
||||
| carried-list | same lib target, `--list` |258 unique names; exit0 |
|
||||
| carried-clippy | locked/offline oa-core all-targets, `-D warnings` |exit0 |
|
||||
| carried-fmt | `cargo fmt --all -- --check` |exit1, unchanged baseline bytes |
|
||||
|
||||
Raw outcome rows equal receipt outcomes with no duplicate names. The listing exactly equals full-run names; focused names exactly equal the12 added successful names. All246 prior18073a6 outcomes match by name/status. All16 failure blocks match after normalizing only the numeric thread PID (plus CRLF transport and outer whitespace); no source locations, messages, stack bodies or assertions were generalized away. Format bytes match exactly, SHA-256 `c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d`.
|
||||
|
||||
Prior full/fmt raw logs and receipts were additionally compared byte-for-byte with their members in `harness/experiments/analysis-mixed-rename-plan-20260924/evidence.zip` (584235 bytes, SHA-256 `1c041d181540b474e14e80677cfe287d305951eaee48e492de7f59dcdea2391c`). This avoids relying solely on an editable baseline summary. The machine readback records exact final raw log and receipt hashes for all five gates.
|
||||
|
||||
All nine stack-named prior tests report `ok` in the final full log, including the ordinary-index small-stack case that aborted initially. This is observed execution for this source/artifact/environment, not a universal stack bound.
|
||||
|
||||
## Preserved initial failure and diagnostic scope
|
||||
|
||||
Initial source `d11b99bb4ab1c817951557551db3a3c7cbd5c425` focused run passed12 (raw SHA `f04ee0473478866bc614fa794cd50af6aa2c1f5d56b9e3c1f5a65112933b144b`). Initial full run has only124 completed outcome rows and aborts in `ordinary_index::tests::small_stack_success_and_late_header_failure_leave_no_partial_owner` with exit3221225725 /0xc00000fd STATUS_STACK_OVERFLOW. It has no normal completed full-suite result and must not be relabeled as the16-failure baseline disposition. Raw SHA `705752b2f18d5897719f689083227aa1e2df4e17f6bc07747490337681ef00fe`; its unchanged input-manifest SHA is `8bfaff6784f616a550b98b3a8170781e85fe4715a0b20308d896423c73f4992c`.
|
||||
|
||||
Preserved `artifacts/d11b99b-oa_core.exe` matches42,221,568 bytes / SHA-256 `dccfaee7f43e563fe26517c6a5454cd06f849d7b72d1127a12d28779100e9016`. Debugger raw log SHA `d3ede485caa0714030e7f95f10a64590334df4219ec836d4daf23db0cbea8138` matches its receipt. It shows0xc00000fd with heap/String formatting beneath Exact::parse_decimal/parse_literal, cursor exact_literal, declaration parsing, mixed parse_impl and prior helper callers. LLDB process exit0 is not an application test pass; the debugger killed the stopped process.
|
||||
|
||||
Recorded prologues show fixed worker reservation0x1e48 becoming0x1b08, parse_impl0x2b88 becoming0x2b28, parse_with_profile0x138 becoming0xc8, accepted0x6d8 becoming0x598, and indexed0x6a8 becoming0x5d8. These are static prologue observations, not total runtime stack consumption or proof that one frame alone caused the abort. The final smaller guard retains owner binding and transfers policy without copying it into every later witness. The accompanying test delta changes only access to that guard; exact cases and expectations remain intact (see TEST-REVIEW.md).
|
||||
|
||||
No claim here accepts production output emission, mixed editing/install authority, universal before-allocation admission or broader workspace/package/native runtime behavior. The result supports this private carried-phase prerequisite with its inherited failures and documented timing/stack limitations preserved.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Independent carried-phase production source review
|
||||
|
||||
2026-09-25. **No concrete correctness blocker found; compilation and runtime acceptance pending.** Reviewed uncommitted production changes over `18073a6f2eabce83fc83997f094e331eec835a16` in `.local/as3batch`. Tests were still being authored and are outside this source-review verdict. No source edits, Cargo, application execution or network actions were performed.
|
||||
|
||||
Authority: selected `harness/analysis-carried-phase-contract-20260925.md`, SHA256 `d17c28a8bb138063c8c5fbf3ed5850f3c1531047d217dffa7274e8d6339fb6b9`; independent `CARRIED-PHASE-ORACLE.md`, SHA256 `56d1b57f4322c74bfd52f46483e337213fb6f8edf26d5756228b6e34c83692fd`. Paths below are under `crates/oa-core/src/language/analysis_source/`.
|
||||
|
||||
| Reviewed production file | Exact working-file SHA256 |
|
||||
| --- | --- |
|
||||
| `mixed/carried.rs` | `b376844c42660fec462def3e839ed99db272e5752ba137c885e69cad01c29e6c` |
|
||||
| `mixed.rs` | `78422c978f9eaf490145ec13bf68928a87966e83370fbf7e5076282e1d578b8b` |
|
||||
| `budget.rs` | `24656fe30fe17b3d7ae295b2e1eeb0a5e5e7bc4fbc4f30cdd95e3e72e1b54f66` |
|
||||
| `mixed/project.rs` | `951dfceb111faa10bf795ec73646b794b08cca81e450b02f13a987a49d9f36ee` |
|
||||
|
||||
## Correctness and authority findings
|
||||
|
||||
- **Bound owner and lifetime:** `carried.rs:6–43` keeps policy/owner fields private; CarriedInput is neither Clone nor Copy. Retained backing borrows the actual allocation-owning RetainedSnapshot. The bundle method derives the reference from that backing. `parse_carried` takes only the input, derives bundle and exact policy, and moves the guard into the parser (`:65–69`). Syntax retains the optional guard (`mixed.rs:46–50,401–408`); existing consumed resolve/index ownership retains syntax. There is no returned self-referential owning bundle or exposed guard-removal method. Rust lifetime/type checking still needs compilation.
|
||||
- **Construction is fixture-only:** policy capture, retained fixture construction/input and borrowed input construction are all cfg(test) (`carried.rs:71–119`). The retained fixture counts exactly F entries, zero lower occurrences and the actual entry/key/source UTF-8 bytes with checked additions. It does not claim preallocation admission of its fixture allocation. No production nonzero or zero-carry transition is enabled; no emitter authority is implied.
|
||||
- **Internal parser seam:** `parse_impl` accepts separate arguments and could be misused by future internal code, but its current two callers are fully accounted for: legacy passes None; private parse_carried derives all values and Some(input) from the same guard. No intended API currently allows substitution. This is a sufficient current private caller invariant, not a concrete vulnerability requiring an input-enum redesign. Re-review any future caller or constructor against this invariant.
|
||||
- **Exact policy and independent work:** `Budget::limits` (`budget.rs:67–70`) returns the immutable complete Limits value. Policy capture retains complete ProjectLimits too. The shared parser constructs one new Budget using those values and preserves the previous maximum-policy validation. There is no policy subtraction, default reconstruction, per-include reset, or modification of an existing Budget. Carried slots never enter Usage or numeric work counters.
|
||||
- **Explicit mode preserves legacy checks:** `parse_with_profile` delegates with None. The initial and per-file branches preserve its old independent metadata checks; it gets no new completion check. Some(input) always performs combined checks, including borrowed zero carry (`mixed.rs:282–301,348–358,396–400`). Grammar, scanning, ordinary projection and traversal remain shared and unchanged. Thus the oracle's legacy E cap11 versus carried-zero cap11 distinction is represented directly rather than hidden behind `C == 0`.
|
||||
- **Checked, noncharging aggregation:** `CarriedInput::check` composes C+U+M with existing checked Slots::add and validates all three dimensions through a temporary zero Ledger (`carried.rs:45–61`). The temporary Ledger retains no reservation in the returned witness. All errors propagate immediately through the existing safe diagnostic path. Continuation C is checked before complete-source precheck/traversal; initial C+file metadata is checked before Traversal::new; per-file prospective metadata is checked before position projection; final check follows successful traversal. The old token/value-end/position/owner metadata components occur once.
|
||||
- **Once-only resolver transfer:** `project.rs:438–449` seeds live Slots from the retained guard, or zero for legacy, then calls the unchanged syntax admission once. The existing syntax walk adds U+M, owned text and bounded scratch. Existing catalog/lower releases subtract their recorded local reservations, not C. There is no new release/reset path for the baseline. Resolved retention should therefore equal the zero-carry result plus C exactly; actual cap boundaries still require runtime verification.
|
||||
- **Failure attribution and ownership:** parser failures use the entry or current-file closure at the appropriate checkpoint; resolver errors retain existing canonical file/span transport. The guard and partial syntax are consumed/dropped on refusal, while the external fixture owner remains alive under its own scope. No partial witness, reusable continuation or accepted edited output escapes. Default parser span transport remains distinct from resolver full-span transport as the oracle documents.
|
||||
|
||||
## Temporal scope and stack risk
|
||||
|
||||
This implements phase checks, not admission before every parser allocation. Unit ASTs/tokens and counting scratch already exist before the per-file check; new retained syntax text is accounted only by the existing resolver walk. Existing model/serde/raw-validator and physical allocator/RSS exclusions remain unchanged. No fresh source rescans, Exact conversions, model clones, heap work containers or per-include budgets were introduced by the production path.
|
||||
|
||||
Adding inline CarriedInput to ParsedMixedSyntax and adding a shared parse wrapper can change debug stack frames even on the legacy route. From source field widths on the intended x64 target, the borrowed enum payload is approximately 112 bytes (bundle reference8 + Limits48 + ProjectLimits56), versus a retained reference8; actual enum/Option and frame layout is compiler-dependent and was not measured here. This is a concrete reason to retain compiler/strict-Clippy and existing small-stack regression gates, not evidence of a regression or justification for speculative boxing. Existing upstream environment-sensitive parse-stack failure remains unresolved and separate.
|
||||
|
||||
## Pending acceptance
|
||||
|
||||
Compile/type-check the guard lifetimes and moves, and run strict Clippy before drawing layout/lint conclusions. Independently exercise oracle E/H boundary pairs, exact parser-versus-resolver spans, new-snapshot work counts, retained +C slots, text timing, all inherited policy fields, and zero-mode rejection timing. Entry/text/occurrence overflow injection must remain labeled separately from positive owner provenance; the actual retained owner has zero occurrences. Test failure/drop and unchanged owner bytes through real parse/resolve paths, and preserve prior private/legacy outcomes, 16 inherited full-suite failures and formatting disposition. This review neither certifies unfinished tests nor accepts final emission/readmission or public source8.
|
||||
|
||||
## Committed test-observer supplemental readback
|
||||
|
||||
Reviewed commit `d11b99bb4ab1c817951557551db3a3c7cbd5c425`. The four working production files match that commit. `mixed/project.rs` now has SHA256 `d0b75ec30c4e433d942d8011f13ddc8321a7c060e35c7b0a320b0979fe22bc40`; the other three file hashes above remain exact. The sole additional change in the previously reviewed project file is the cfg(test) `ResolvedMixedProject::phase_state` observer at lines31–34, returning `(&self.syntax, self.storage.live)`.
|
||||
|
||||
The observer returns an immutable borrow tied to the resolved owner and a copied scalar Slots snapshot. It cannot mutate/reset policy, replace the bundle, extract the guard, release ownership or construct a continuation. It is absent from production builds and provides the intended test visibility into real retained state. No authority issue or new source-review blocker found. This supplement does not claim unchanged runtime behavior: compilation and all required runtime gates remain independently pending. No source edit, compiler or application execution was performed for this readback.
|
||||
|
||||
## Targeted slim-guard repair review
|
||||
|
||||
The subsequent d11b99b full run aborted with exit3221225725 at the existing ordinary-index 128 KiB test, despite the 12 focused tests passing. Read-only inspection of `carried-full-d11b99b-1.result.json` and `carried-debugger-d11b99b-1.log` confirms the reported overflow and a fault stack through Exact parsing, the shared parser body and its new wrapper. It does not establish a single quantified cause. The initial source verdict therefore did not establish legacy runtime compatibility; this regression blocks acceptance until repaired and rechecked.
|
||||
|
||||
Reviewed the frozen uncommitted slim-guard candidate relative to d11b99b and the revised selected contract, SHA256 `875b26eb850ab75d6e09222be37327a87a5b4c4a6f0557adf9723984f945d5f5`. **No source correctness blocker found in this targeted repair; runtime effect remains unproven.** Exact candidate hashes:
|
||||
|
||||
| File | SHA256 |
|
||||
| --- | --- |
|
||||
| `mixed.rs` | `9e67891b6610def59d39376ec78fea6151025e977c88d299dafd97b440ab4e89` |
|
||||
| `mixed/carried.rs` | `32cf742631490a624e0522db82ff1d708e5d730b54a117f254ed3a106f05eca0` |
|
||||
| `mixed/carried/tests.rs` | `794c8e987b43d4a652361bf7e31eff314f917955824efdbb1ba74b0216c4018a` |
|
||||
|
||||
`CarriedInput::into_parts` consumes the original input: Borrowed moves its captured exact policy; Retained copies the exact policy values from its immutable owner. Both derive the same bound bundle and small guard in one match. The new Budget and syntax ProjectLimits own the transferred policy, so dropping the original seed before parsing remains valid. No policy borrow from the dropped seed is introduced. Only `CarriedGuard { Borrowed | Retained(&owner) }` travels through the shared parser and later witness; Borrowed source lifetime remains tied by syntax.bundle, and Retained continues borrowing its allocation owner. Private construction/caller invariants remain intact.
|
||||
|
||||
Slots/check arithmetic, once-only seeding, all phase checkpoints, modes and Usage are unchanged. No heap allocation or new logical container reservation is introduced. Removing duplicated inline policy from later witnesses is a smaller change than adding a policy-owner fixture lifetime or boxing the policy; it directly reduces replicated state while preserving the contract. The extra parser wrapper itself is unchanged and may still matter; only the unchanged regression gates can demonstrate recovery.
|
||||
|
||||
The carried test delta changes only the guard-variant identity check and access to the existing direct overflow checks through `into_parts().2`. Expected values and assertions remain intact. `budget.rs` and `mixed/project.rs` are unchanged from d11b99b. The complete existing `mixed/project/ordinary_index/tests.rs`, including the 128 KiB regression, is unchanged from accepted18073; working SHA256 `04e11463a7d489c9984d165d80718d95da027c7613a5b63180f0eaf4038a0395`. No stack size, old fixture, thread setup or old expected outcome was weakened. Compiler, focused/full and required regression evidence must bind the actual repaired commit before acceptance.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Carried-phase legacy stack regression
|
||||
|
||||
The first candidate `d11b99bb4ab1c817951557551db3a3c7cbd5c425` compiled and
|
||||
passed all 12 new carried-phase tests. Its full library run aborted with
|
||||
`STATUS_STACK_OVERFLOW` (3221225725) at the existing
|
||||
`ordinary_index::tests::small_stack_success_and_late_header_failure_leave_no_partial_owner`.
|
||||
That unchanged 128 KiB control passed in the completed 18073a6 baseline.
|
||||
It recorded 124 completed passes before the abort. The aborted run is not a
|
||||
complete test-suite result or the known 16-failure
|
||||
disposition. Its raw log SHA256 is
|
||||
`705752b2f18d5897719f689083227aa1e2df4e17f6bc07747490337681ef00fe`.
|
||||
|
||||
The exact first artifact is 42,221,568 bytes, SHA256
|
||||
`dccfaee7f43e563fe26517c6a5454cd06f849d7b72d1127a12d28779100e9016`.
|
||||
It was preserved locally before replacement. LLDB reproduced its overflow:
|
||||
Windows heap allocation through formatting, Exact::parse_decimal, Budget::exact,
|
||||
binding, declarations::parse, State::parse_typed, Parser::unit, parse_impl,
|
||||
parse_with_profile, parse, accepted, indexed and the original small-stack worker.
|
||||
No index operation is on the active stack at the fault.
|
||||
The debugger log SHA256 is
|
||||
`d3ede485caa0714030e7f95f10a64590334df4219ec836d4daf23db0cbea8138`.
|
||||
Its exit zero follows an explicit debugger kill of the stopped child and is not
|
||||
a passing test. No other application process was stopped.
|
||||
|
||||
Source-bound disassembly observed these prologue reservations: parse_impl
|
||||
11,144 bytes; parse_with_profile 312; accepted 1,752; indexed 1,704; actual worker
|
||||
7,752. A separate test harness shim shares the worker's demangled name and uses
|
||||
56 bytes; the two records must not be confused. These are selected static
|
||||
prologues, not a complete runtime stack measurement or proof of a sole cause.
|
||||
|
||||
The new retained input duplicated the 104-byte Limits/ProjectLimits policy in
|
||||
each later parsed/resolved/indexed/plan carrier. Independent review selected a
|
||||
smaller representation: consume input, transfer exact policy into the Budget
|
||||
and existing syntax limits, and retain only a small backing-owner guard.
|
||||
This avoids a new external policy lifetime or heap allocation. The wrapper,
|
||||
all resource arithmetic, expected values and existing small-stack tests remain
|
||||
unchanged. The corrected candidate is
|
||||
`fa7a980418ef99d772e67c66c28dfa7b5181f875`.
|
||||
|
||||
The corrected artifact is 42,223,104 bytes, SHA256
|
||||
`c990e77015f2e4535003875abe7d49199cead803ee60677d86cdf056da7d8298`.
|
||||
Its 12 focused cases pass and the complete full run returns 242 passed / 16
|
||||
failed, including passes for all nine prior stack-named controls. The originally
|
||||
aborting test is unchanged. Strict all-target core Clippy passes; formatting
|
||||
retains the byte-identical inherited eight diff blocks. Independent raw baseline
|
||||
comparison is recorded separately in the runtime review.
|
||||
|
||||
Corrected selected prologues are parse_impl 11,048 bytes, parse_with_profile
|
||||
200, accepted 1,432, indexed 1,496 and the actual worker 6,920. Their reductions
|
||||
sum to 1,568 bytes; parse remains 280 and the separate harness shim remains 56.
|
||||
This confirms reduced reservations in the inspected frames and a completed
|
||||
ordinary regression run. It is not a full-stack measurement, proof of a sole
|
||||
cause, or guarantee across every environment.
|
||||
|
||||
This investigation does not resolve the separate earlier rename-test full-pipeline
|
||||
128 KiB setup observation, grant a universal stack guarantee or accept emitted
|
||||
output. Raw launchers, receipts, traces and both source versions are preserved.
|
||||
@@ -0,0 +1,88 @@
|
||||
# Carried-phase stack regression: source analysis
|
||||
|
||||
2026-09-25. Read-only source comparison: accepted predecessor `18073a6f2eabce83fc83997f094e331eec835a16` versus carried commit `d11b99bb`. No source/tests edited, no compiler/debugger/test executable run by this agent. Parent owns the exact-artifact LLDB investigation. These are hypotheses and conditional correction recommendations, not a proven failure cause.
|
||||
|
||||
## Observed boundary
|
||||
|
||||
Parent reports all 12 new carried tests pass, but the full run aborts with Windows STATUS_STACK_OVERFLOW `0xc00000fd` at the **unchanged** existing `ordinary_index::tests::small_stack_success_and_late_header_failure_leave_no_partial_owner`. Predecessor full run completed 230 pass / 16 inherited failures including this test. The new abort is therefore a current acceptance regression requiring investigation; the earlier unrelated environment-sensitive rename prerequisite observation does not waive it.
|
||||
|
||||
The recorded log ends at that test, with no phase markers. It does **not** say which of its three sections failed:
|
||||
|
||||
1. Build rich OA bundle, parse/resolve/index/index-ordinary and drop success.
|
||||
2. Independently build the rich typed index, inject a new unowned name into its map, and require late ordinary missing-header rejection and consumed-owner cleanup.
|
||||
3. Construct the unchanged 127-nested-abs literal (128 expression nodes), then parse/resolve/index/index-ordinary and drop success.
|
||||
|
||||
Source: `mixed/project/ordinary_index/tests.rs:416–445`; helper `indexed` at line6 calls `project/tests.rs:147 accepted`, which calls `resolve(parse(...).unwrap())`. Stack allowance remains128 KiB. The test naturally exercises large value returns through several nested helpers; none of those helpers or fixture sizes changed in d11b99bb.
|
||||
|
||||
## Two concrete source changes affecting stack shape
|
||||
|
||||
### A. One extra shared-body wrapper on the legacy parse chain
|
||||
|
||||
Before: `indexed -> accepted -> mixed::parse -> mixed::parse_with_profile [body]`.
|
||||
|
||||
After: `indexed -> accepted -> mixed::parse -> mixed::parse_with_profile [forwarder] -> mixed::parse_impl [body]`.
|
||||
|
||||
References: `mixed.rs:227–260`; diff18073a6..d11b99bb. `parse_with_profile` now forwards bundle, ProjectLimits, Limits and a new None guard, returning a larger ParsedMixedSyntax Result. Even a tiny Rust forwarding function can have debug-build argument/return temporaries and a native frame. The source does not establish how much stack the compiler allocated or whether any forwarding call was optimized away. Inspect actual frame prologues before assigning blame.
|
||||
|
||||
The new checkpoint calls themselves run with `carried=None` on this existing test. CarriedInput::check, its temporary Ledger, and new carried arithmetic are not executed on the legacy path. Therefore adding a heap allocation inside those checks is not a justified fix for this test.
|
||||
|
||||
### B. Inline guard makes every syntax/result carrier structurally larger
|
||||
|
||||
`ParsedMixedSyntax` gained `Option<CarriedInput>` (`mixed.rs:46–50`). CarriedInput contains SnapshotBacking by value. Its Borrowed variant stores both a bundle reference and the entire SnapshotPolicy by value (`mixed/carried.rs:6–27`); SnapshotPolicy holds all Limits and ProjectLimits fields. Even `None` in a legacy witness needs enough inline space for the type's largest Some variant. This increase propagates through `ResolvedMixedProject.syntax`, `IndexedMixedProject.resolved`, AuthoredMixedProject, Result temporaries and helper return slots.
|
||||
|
||||
On this Windows64 ABI the source policy contains six8-byte Limits fields and seven usize ProjectLimits fields (3 traversal +4 model), i.e.104 bytes of policy payload before the reference/discriminant/alignment. This is field arithmetic, **not a measured Rust enum size or compiler frame size**. Compiler layout/niches and debug temporaries must be measured from the exact artifact. The source is enough to identify a plausible repeated-inline-payload increase, not enough to quantify the resulting peak native stack.
|
||||
|
||||
References: `budget.rs:7–14`, `source_project.rs:52–59`, `language.rs:32–37`, `mixed/carried.rs:6–27`, `mixed/project.rs:17–26,43–46`. The retained variant already holds only a reference; its policy stays in the retained external owner. The borrowed variant is the asymmetry.
|
||||
|
||||
The test-only `phase_state` getter is not invoked by this existing test. The resolver's new scalar Slots seed executes but adds no new heap allocation or recursion. It also receives the now-larger syntax value, so its generated frame may grow even if its changed expression is small.
|
||||
|
||||
## What the parent trace should distinguish
|
||||
|
||||
1. Identify the exact stage from the active call stack: scanner/ordinary or typed parser, Exact numeric work, resolver/catalog/admission, index verification, ordinary late failure mapping, or drop. No test rewriting is needed to read the faulting call chain.
|
||||
2. Capture stack base/limit/current SP if available; record native frame deltas/prologues for the largest active frames, especially parse_impl, parse_with_profile, accepted/indexed test helpers, resolve and the worker closure. A tiny source function is not evidence its debug frame is tiny.
|
||||
3. If inspectable, compare the prechange and new generated frames or type layouts. At minimum confirm whether the added forwarding frame and inline carrier payload are present. Do not run application code through arbitrary debugger expressions solely to infer type size; symbols/disassembly suffice if available.
|
||||
4. A deepest frame inside BigInt/Windows allocation does not itself establish arithmetic recursion as the regression. The added ancestors may have reduced available headroom before an unchanged allocation call. Likewise a drop frame would require checking which owner is being dropped before any parser-only correction is selected.
|
||||
5. Repeat an exact artifact only as needed to establish whether this failure has the same environment sensitivity previously observed. A passing retry alone does not undo the failed full run or establish a fix.
|
||||
|
||||
## Smallest allocation-free correction candidates, contingent on evidence
|
||||
|
||||
### Preferred representation correction if enlarged inline carriers matter
|
||||
|
||||
Move the **borrowed variant's policy payload** to an external immutable fixture backing owner, mirroring the retained variant. For example:
|
||||
|
||||
```rust
|
||||
struct BorrowedSnapshot<'s> {
|
||||
bundle: &'s SourceBundle,
|
||||
policy: SnapshotPolicy,
|
||||
}
|
||||
|
||||
enum SnapshotBacking<'s> {
|
||||
Borrowed(&'s BorrowedSnapshot<'s>),
|
||||
Retained(&'s RetainedSnapshot),
|
||||
}
|
||||
struct CarriedInput<'s> { backing: SnapshotBacking<'s> }
|
||||
```
|
||||
|
||||
All constructors remain cfg(test); fixture code holds the borrowed backing owner while returned syntax/resolved/indexed guards exist, exactly as it already holds RetainedSnapshot. The owner captures exact policy once; CarriedInput borrows it, fixes bundle identity and prevents premature drop. The guard then consists of tagged references instead of a copied104-byte policy payload. No new heap allocation, copied String, logical collection entry or uncharged Box is introduced. The policy is inline scalar state in its external owner, outside every syntax/result copy. Exact guard/layout sizes still need compiler verification.
|
||||
|
||||
This changes no check ordering, C arithmetic, Usage, model/public API, allocation ownership or legacy grammar. It strengthens symmetry of both guard variants and respects the accepted borrow-bound ownership design. Required test adjustments would bind a local borrowed fixture backing before obtaining its input; they should not change any expected models, limits, cap values, spans or stack sizes. Existing small-stack tests must remain completely unchanged.
|
||||
|
||||
This is more justified than boxing ParsedMixedSyntax/Project/whole Result: such boxing introduces a real allocation and a new accounting/lifecycle choice unrelated to the accepted logical scope. Do not silently add a Box to fix a native frame without its design and reservation being reviewed.
|
||||
|
||||
### Smaller forwarding correction if the new wrapper is the material delta
|
||||
|
||||
For default legacy parse, call the shared parse_impl directly with None instead of routing through the newly trivial parse_with_profile forwarder; this restores the old number of parser-body callers on the actual failing indexed->accepted->parse route without duplicating grammar or touching checks. The tight-profile wrapper would still add a frame for its callers, so this is not a general representation fix.
|
||||
|
||||
Alternatively an explicitly forced-inline annotation on the tiny forwarding wrapper can remove that frame if the compiler honors it in this debug configuration. It is a code-generation hint, not a semantic stack guarantee, and must be verified from the new artifact and existing controls. Do not mark the entire large parser body always-inline: it can duplicate/inflate callers and makes the intended correction less predictable.
|
||||
|
||||
Do not simultaneously apply unrelated layout/algorithm changes before the trace identifies the relevant ancestors. A narrow representation correction may be preferable if payload replication affects multiple phases rather than one forwarder.
|
||||
|
||||
## Acceptance after any selected correction
|
||||
|
||||
Preserve the original12 carried expected outcomes, all legacy phase timing, exact output-owner Slots and all nine pre-existing passing stack-named controls with unchanged fixtures/stack allowances. Verify production source review for constructor/lifetime/accounting changes and run parent exact-artifact focused/full gates. Retain d11b99bb's full abort record. A proposed fix is not accepted until the original failed control and required broader run complete at the corrected pin, with inherited failures reported separately.
|
||||
|
||||
No correction is implemented here. Await the exact-artifact trace before selecting between these concrete candidates or investigating another actual phase.
|
||||
|
||||
## Trace update and selected candidate
|
||||
|
||||
Parent subsequently reproduced the exact-artifact failure in numeric parsing with the new parse_impl/parse_with_profile ancestors visible, and recorded prologues11,144/312 bytes respectively (other measured active ancestors accepted1,752/indexed1,704/worker7,752; not a total). Parent selected the independent critic's **smaller** representation correction over the external borrowed-policy-owner alternative above: consume the preparse CarriedInput, transfer policy into Budget + syntax.limits, and retain only a slim Borrowed/Retained-owner guard in syntax. Borrowed mode already keeps bundle identity via syntax.bundle; it needs no duplicated policy owner. This avoids a new fixture lifetime requirement or heap allocation, preserves exact policy after transfer, and removes the large inline policy from legacy carriers as well. Parent authorized that narrow source edit, preserving the wrapper and all existing stack tests. Candidate implementation and notes are submitted for review/gates; this report does not claim causal proof or accepted runtime recovery.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Carried-phase independent test review
|
||||
|
||||
Disposition: ready for parent compilation and runtime gates, with no remaining source-level blocker found. This is a read-only test/oracle review, not test execution or acceptance of compiler results.
|
||||
|
||||
Reviewed `crates/oa-core/src/language/analysis_source/mixed/carried/tests.rs` in `.local/as3batch`, final SHA-256 `26730fd70ec13e0a211a3650e041323bbaf8ba3eb30382273165e9b4b378bc6b`, containing12 tests. Compared with the independent `CARRIED-PHASE-ORACLE.md`, accepted `harness/analysis-carried-phase-contract-20260925.md`, existing parser/projection/accounting implementation, and new carried authority shape. No Cargo, source edits, commits or remote writes were performed.
|
||||
|
||||
## Findings resolved before compilation
|
||||
|
||||
The initial frozen test hash `bbee6aab87f99a98ecc3fdab30cea4b998f405d8e07b36e23e7a9cdb52f9e099` had two concrete fixture/assertion defects:
|
||||
|
||||
1. The OA/SA parity fixture used `oa_engineering_property` and `sa_engineering_property`. The mixed parser explicitly rejects these long names before intended resolution/index parity. Implementer replaced them with accepted `oa_property` and `sa_property`.
|
||||
2. The include-policy test assigned full include span0..23 to both depth and edge refusals. Edge cap1 first fails inside `mixed::State::include`, whose ordinary error transport produces span0..1; depth refusal arises from traversal and retains0..23. Implementer separated the expected spans.
|
||||
|
||||
Both corrections were reread in the final hash above. They alter test inputs/expectations, not production policy.
|
||||
|
||||
## Oracle agreement and phase reachability
|
||||
|
||||
The literal empty and three-file fixtures agree with independently authored counts: owned C `(1,0,102)` and `(3,0,180)`; final U/M `1/11` and `3/19`; scanner work `(78bytes,19tokens)` and `(132bytes,31tokens)`; syntax entry caps13/25; complete resolver entry peaks17/29 and text peaks112/214. Final retained Slots `(13,0,110)` and `(25,0,212)` prove C participates exactly once. Assertions cover complete literal empty Project, empty warnings, exact work counters, canonical file order, actual bundle pointer, retained owner guard and unchanged owner contents after witness destruction.
|
||||
|
||||
Cap-minus-one syntax tests name the actual failing file, including part.arcadia for the cumulative three-file case. Entry/text resolver negatives first unwrap successful parsing and assert catalog header span11..73. The identical zero-baseline profile resolves successfully, providing the needed discriminating positive control. Exact-cap full success is supplied by the first test, not inferred from failure arithmetic.
|
||||
|
||||
Legacy cap11 returns syntax and later fails resolver sum12 at span0..0. Explicit carried borrowed-zero cap11 refuses preprojection at span0..1; cap12 clears syntax. This catches both a numeric-zero bypass and accidentally changing original parser timing. Initial C+file-slot tests include the deliberate max_files0 ordering sentinel, accurately described as a test-only inadmissible target rather than successful predecessor provenance.
|
||||
|
||||
Text refusals occur after parse succeeds and quoted names are demonstrably decoded. Empty bytes109 names the header; chain bytes211 names part's include0..23 because accounting uses canonical file order. The source-size and raw-token tests use borrowed-zero mode so owned C.text cannot preempt the intended work boundary. Their seed empty bundle fits each inherited profile. Traversal limits have an exact positive triple3files/2depth/2edges and separate failing coordinates.
|
||||
|
||||
## Added ordinary-position text oracle
|
||||
|
||||
The one ordinary activity with `description "é";` has retained syntax text45 bytes: project alias/name8, ordinary alias/name2, field-span map key11, AST field-map key11, decoded string2, projected Record key11. The projected scalar is `EditKind::Atom`, so no second literal String is counted there. At C.text+44, prior text34 fits and the final11-byte projected key exceeds the ceiling. Projection's `EditField.span` starts at the description keyword and ends after its semicolon, matching the test's exact expected diagnostic.
|
||||
|
||||
This test proves that particular postparse refusal and copied-key contribution. It does not assert that C+45 admits complete resolution; catalog and potentially mapped diagnostics are later phases. It therefore makes no unsupported exact complete-resolver-cap claim for this fixture.
|
||||
|
||||
## Policy, ownership and limits
|
||||
|
||||
Exact snapshots compare all6 Limits fields and all7 scalar ProjectLimits/model fields. Behavioral controls exercise references0, frames0 and numeric72 refusal, then roomy successful resolution for the same typed forms. The independently specified literal1 meter cost73 is also used for a prior nonzero numeric-work witness and a fresh73-unit reparse, detecting accidental accumulation of prior work. Model caps reach typed-record admission or real reference work; seeds remain admissible under each tightened policy.
|
||||
|
||||
No test invokes a production arbitrary-Slots constructor. Retained owner fixture construction derives C from its actual map/source/path/entry bytes; borrowed construction captures a witness's policy without borrowing that witness's lifetime. Dropping the seed before parsing is consistent with the intended copied immutable policy. Nonzero occurrences and usize overflow are explicitly marked fault injection; they are not represented as real successful owner provenance. Sibling test access through the cfg(test) phase_state method appears consistent with its parent-module visibility; compilation remains the authoritative check.
|
||||
|
||||
OA/SA zero-carried parity now reaches the accepted short-word grammar and compares Project, warnings, storage, Usage/numeric work, both index name/occurrence families and original bundle ownership under Unicode/CRLF input. It is equivalence coverage, not a separate authored whole-model oracle; the empty/chain success tests provide their own literal complete Project.
|
||||
|
||||
The tests and this review do not establish universal before-allocation admission, a stack guarantee, production emitter provenance or editing/install authority. Parent owns actual focused/full/list/Clippy/format evidence and inherited failure reconciliation.
|
||||
|
||||
## Final slim-guard delta
|
||||
|
||||
Reviewed committed delta `d11b99bb4ab1c817951557551db3a3c7cbd5c425..fa7a980418ef99d772e67c66c28dfa7b5181f875`. Final tests SHA-256 `794c8e987b43d4a652361bf7e31eff314f917955824efdbb1ba74b0216c4018a`. The only test changes select `GuardBacking::Retained` instead of `SnapshotBacking::Retained` for the same actual-owner pointer assertion, and obtain the consumed input's guard through `into_parts().2` for the same direct overflow checks. No fixture, numeric expectation, cap, diagnostic, case or assertion was removed or weakened. The policy moves into syntax/Budget while the smaller retained guard keeps the owner borrow. Runtime disposition and the preserved initial stack abort are recorded separately in `RUNTIME-REVIEW.md`.
|
||||
Binary file not shown.
@@ -0,0 +1,134 @@
|
||||
"""Reconcile committed Windows carried-phase gates against raw logs and prior outcomes."""
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
base = Path(__file__).resolve().parents[2]
|
||||
root = base / '.local/as3batch'
|
||||
directory = base / '.local/analysis-carried-phase-gates-20260925'
|
||||
prior = base / '.local/analysis-mixed-rename-plan-gates-20260924'
|
||||
source, stem, expected_added = sys.argv[1], sys.argv[2], int(sys.argv[3])
|
||||
assert 1 <= expected_added <= 100
|
||||
assert re.fullmatch(r'[0-9a-f]{40}', source)
|
||||
assert re.fullmatch(r'[a-zA-Z0-9-]+', stem)
|
||||
sha = lambda raw: hashlib.sha256(raw).hexdigest()
|
||||
|
||||
def git(*args):
|
||||
return subprocess.check_output(['git', '--no-replace-objects', *args], cwd=root)
|
||||
|
||||
def receipt(folder, name):
|
||||
path = folder / (name + '.result.json')
|
||||
data = json.loads(path.read_bytes())
|
||||
raw = (folder / (name + '.log')).read_bytes()
|
||||
assert data['log_sha256'] == sha(raw)
|
||||
return data, raw
|
||||
|
||||
assert git('rev-parse', 'HEAD').decode().strip() == source
|
||||
assert not git('status', '--porcelain', '--untracked-files=no').strip()
|
||||
scope = ['Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', '.cargo', 'build', 'crates', 'assets', 'docs', 'examples', 'harness/fixtures', 'vendor']
|
||||
paths = git('ls-tree', '-r', '--name-only', source, *scope).decode().splitlines()
|
||||
blobs = subprocess.check_output(['git', '--no-replace-objects', 'cat-file', '--batch'], cwd=root,
|
||||
input=''.join(f'{source}:{p}\n' for p in paths).encode())
|
||||
offset = 0
|
||||
expected_inputs = []
|
||||
for path in paths:
|
||||
end = blobs.index(b'\n', offset)
|
||||
_, kind, count = blobs[offset:end].split()
|
||||
count = int(count)
|
||||
raw = blobs[end + 1:end + 1 + count]
|
||||
assert kind == b'blob' and (root / path).read_bytes() == raw, path
|
||||
expected_inputs.append({'path': path, 'bytes': count, 'sha256': sha(raw)})
|
||||
offset = end + count + 2
|
||||
assert offset == len(blobs)
|
||||
prefix = ['cargo', 'test', '--locked', '--offline', '-p', 'oa-core', '--lib']
|
||||
focus = 'language::analysis_source::mixed::carried::tests::'
|
||||
commands = {
|
||||
'focused': prefix + [focus, '--', '--test-threads=1'],
|
||||
'full': prefix + ['--', '--test-threads=1'],
|
||||
'list': prefix + ['--', '--list'],
|
||||
'clippy': ['cargo', 'clippy', '--locked', '--offline', '-p', 'oa-core', '--all-targets', '--', '-D', 'warnings'],
|
||||
'fmt': ['cargo', 'fmt', '--all', '--', '--check'],
|
||||
}
|
||||
verified = {}
|
||||
all_receipts = {}
|
||||
for mode, command in commands.items():
|
||||
name = f'carried-{mode}-{stem}-1'
|
||||
data, raw = receipt(directory, name)
|
||||
assert data['source'] == data['head_after'] == source
|
||||
assert data['mode'] == mode and data['command'] == command
|
||||
assert not data['changed_inputs'] and not data['verification_failures']
|
||||
manifest_raw = (directory / data['inputs']).read_bytes()
|
||||
assert sha(manifest_raw) == data['inputs_sha256']
|
||||
assert json.loads(manifest_raw) == {'source': source, 'inputs': expected_inputs}
|
||||
launcher = (directory / data['launcher_copy']).read_bytes()
|
||||
assert sha(launcher) == data['launcher_sha256'] == data['launcher_sha256_after']
|
||||
assert source.encode() in launcher
|
||||
env = data['environment']
|
||||
assert env['CARGO_BUILD_JOBS'] == '1' and env['CARGO_INCREMENTAL'] == '0'
|
||||
assert env['ARCADIA_CODEC_LIFECYCLE_PHASE'] is None and env['RUST_MIN_STACK'] is None
|
||||
assert data['cwd'] == str(root)
|
||||
text = raw.decode()
|
||||
outcomes = re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)\r?$', text, re.M)
|
||||
assert outcomes == [tuple(x) for x in data['outcomes']]
|
||||
assert len(outcomes) == len(dict(outcomes))
|
||||
members = re.findall(r'^([^\r\n]+): test\r?$', text, re.M) if mode == 'list' else []
|
||||
assert members == data['listing_members'] and len(members) == data['listing_count']
|
||||
assert len(members) == len(set(members))
|
||||
if mode == 'list':
|
||||
assert len(members) == 246 + expected_added
|
||||
if mode in ('focused', 'full'):
|
||||
counts = tuple(sum(v == state for _, v in outcomes) for state in ('ok', 'FAILED', 'ignored'))
|
||||
summary = re.findall(r'^test result: (ok|FAILED)\. (\d+) passed; (\d+) failed; (\d+) ignored; 0 measured; (\d+) filtered out;', text, re.M)
|
||||
assert len(summary) == 1 and tuple(map(int, summary[0][1:4])) == counts
|
||||
assert summary[0][0] == ('FAILED' if counts[1] else 'ok')
|
||||
assert int(summary[0][4]) == (246 if mode == 'focused' else 0)
|
||||
assert data['exit'] == (101 if counts[1] else 0)
|
||||
assert len(data['artifacts']) == 1
|
||||
for artifact in data['artifacts']:
|
||||
actual = Path(artifact['path']).read_bytes()
|
||||
assert len(actual) == artifact['bytes'] and sha(actual) == artifact['sha256']
|
||||
assert str(Path(artifact['path'])).replace('\\', '/') in text.replace('\\', '/')
|
||||
all_receipts[mode] = data
|
||||
verified[name] = {'source': source, 'exit': data['exit'], 'outcomes': len(outcomes), 'listing': len(members), 'log_sha256': sha(raw), 'result_sha256': sha((directory / (name + '.result.json')).read_bytes())}
|
||||
|
||||
old, old_raw = receipt(prior, 'rename-full-18073a6-1')
|
||||
assert old['source'] == '18073a6f2eabce83fc83997f094e331eec835a16'
|
||||
old_actual = re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)\r?$', old_raw.decode(), re.M)
|
||||
assert old_actual == [tuple(x) for x in old['outcomes']]
|
||||
assert len(old_actual) == len(dict(old_actual)) == 246
|
||||
old_out = dict(old['outcomes'])
|
||||
new_out = dict(all_receipts['full']['outcomes'])
|
||||
assert len(old_out) == 246 and len(new_out) == 246 + expected_added
|
||||
assert all(new_out.get(k) == v for k, v in old_out.items())
|
||||
added = set(new_out) - set(old_out)
|
||||
assert len(added) == expected_added and all(new_out[k] == 'ok' and k.startswith(focus) for k in added)
|
||||
assert set(dict(all_receipts['focused']['outcomes'])) == added
|
||||
assert all(status == 'ok' for _, status in all_receipts['focused']['outcomes'])
|
||||
assert set(all_receipts['list']['listing_members']) == set(new_out)
|
||||
assert all_receipts['clippy']['exit'] == all_receipts['list']['exit'] == all_receipts['focused']['exit'] == 0
|
||||
assert all_receipts['fmt']['exit'] == 1
|
||||
|
||||
def failure_blocks(raw):
|
||||
text = raw.decode().replace('\r\n', '\n')
|
||||
return {m[1]: re.sub(r"(?m)^(thread '[^\n]*') \(\d+\) panicked", r'\1 (<PID>) panicked', m[2]).strip()
|
||||
for m in re.finditer(r'^---- ([^\n]+) stdout ----\n(.*?)(?=^---- |^failures:|\Z)', text, re.M | re.S)}
|
||||
|
||||
new_raw = (directory / f'carried-full-{stem}-1.log').read_bytes()
|
||||
old_blocks, new_blocks = failure_blocks(old_raw), failure_blocks(new_raw)
|
||||
assert len(old_blocks) == len(new_blocks) == 16 and old_blocks == new_blocks
|
||||
old_fmt, old_fmt_raw = receipt(prior, 'rename-fmt-18073a6-1')
|
||||
fmt_raw = (directory / f'carried-fmt-{stem}-1.log').read_bytes()
|
||||
assert fmt_raw == old_fmt_raw
|
||||
result = {'source': source, 'baseline': old['source'], 'inputs': len(expected_inputs),
|
||||
'unchanged_old_outcomes': 246, 'added_passed': expected_added,
|
||||
'full_passed': sum(v == 'ok' for v in new_out.values()),
|
||||
'identical_failure_blocks_after_pid_only_normalization': 16,
|
||||
'identical_fmt_sha256': sha(fmt_raw), 'receipts': verified,
|
||||
'scope': 'Read-only committed-input/raw-log/artifact comparison; no Cargo execution.'}
|
||||
destination = Path(__file__).with_name('CARRIED-PHASE-RUNTIME-READBACK.json')
|
||||
assert not destination.exists(), 'Preserve previous readback; use a separately named checker for another source.'
|
||||
destination.write_text(json.dumps(result, indent=2) + '\n', encoding='utf-8')
|
||||
print(json.dumps(result, indent=2))
|
||||
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"source": "fa7a980418ef99d772e67c66c28dfa7b5181f875",
|
||||
"scope": "Private carried-phase prerequisite only. 12 new tests and strict Clippy pass; final full library has 242 passed/16 inherited failures and formatter remains failed. Initial d11 full abort and debugger evidence are preserved; final unchanged stack controls pass. No emitted-output acceptance.",
|
||||
"archive": {
|
||||
"file": "evidence.zip",
|
||||
"bytes": 458509,
|
||||
"sha256": "2eca143b706458c1c0217af715fa6f17c01a0b9f85a5313d6a231dabe1aba7c9"
|
||||
},
|
||||
"members": {
|
||||
"baseline/launchers/843069930cd44278eef940930369b5a85a3b3412e1e50793d78d3d5738298fbe.py": {
|
||||
"bytes": 7674,
|
||||
"sha256": "843069930cd44278eef940930369b5a85a3b3412e1e50793d78d3d5738298fbe"
|
||||
},
|
||||
"baseline/rename-fmt-18073a6-1.inputs.json": {
|
||||
"bytes": 102986,
|
||||
"sha256": "e2c710230fa55bbefb4faeee73dab6b8104ddfb8f0291eef0eba15850799c2ff"
|
||||
},
|
||||
"baseline/rename-fmt-18073a6-1.log": {
|
||||
"bytes": 6446,
|
||||
"sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d"
|
||||
},
|
||||
"baseline/rename-fmt-18073a6-1.result.json": {
|
||||
"bytes": 1881,
|
||||
"sha256": "2f2ed68a8b90f5908d309c7a7cf6fd2d275dc3286a4b5dd518bf0d60e33e13c7"
|
||||
},
|
||||
"baseline/rename-full-18073a6-1.inputs.json": {
|
||||
"bytes": 102986,
|
||||
"sha256": "e2c710230fa55bbefb4faeee73dab6b8104ddfb8f0291eef0eba15850799c2ff"
|
||||
},
|
||||
"baseline/rename-full-18073a6-1.log": {
|
||||
"bytes": 40942,
|
||||
"sha256": "a3fef7c640ec9e59484d15b18a5fc8b9a0c25ca9bf01750b1da4431a101c4eec"
|
||||
},
|
||||
"baseline/rename-full-18073a6-1.result.json": {
|
||||
"bytes": 36268,
|
||||
"sha256": "4228f67a45fca37841607d574af9b676d1c144e3a93f6d0dd34bd9c01c625d34"
|
||||
},
|
||||
"baseline/rename-list-18073a6-1.inputs.json": {
|
||||
"bytes": 102986,
|
||||
"sha256": "e2c710230fa55bbefb4faeee73dab6b8104ddfb8f0291eef0eba15850799c2ff"
|
||||
},
|
||||
"baseline/rename-list-18073a6-1.log": {
|
||||
"bytes": 27578,
|
||||
"sha256": "05e09d5280508a784dd97a894c92b8cdeb202c67592498d253e8f8c33b07e6ae"
|
||||
},
|
||||
"baseline/rename-list-18073a6-1.result.json": {
|
||||
"bytes": 29785,
|
||||
"sha256": "1e58a6c4e907fd02c0c5a3e6de18bca3ef0c36c4a2dde2584e8e51b1837d8cda"
|
||||
},
|
||||
"contracts/CARRIED-PHASE-CONTRACT-CRITIQUE.md": {
|
||||
"bytes": 11334,
|
||||
"sha256": "2bd92bf59002b080914d8ac3725c5cdc54d2fb71b8ac1ca388b3372cf14ef591"
|
||||
},
|
||||
"contracts/analysis-carried-phase-contract-20260925.md": {
|
||||
"bytes": 22812,
|
||||
"sha256": "875b26eb850ab75d6e09222be37327a87a5b4c4a6f0557adf9723984f945d5f5"
|
||||
},
|
||||
"diagnostics/carried-debugger-d11b99b-1.log": {
|
||||
"bytes": 12404,
|
||||
"sha256": "d3ede485caa0714030e7f95f10a64590334df4219ec836d4daf23db0cbea8138"
|
||||
},
|
||||
"diagnostics/carried-debugger-d11b99b-1.result.json": {
|
||||
"bytes": 1245,
|
||||
"sha256": "8299bb3c2567cd40d4c3f49123720b3e049db64aa5445c5273c3a0cb6a370b0e"
|
||||
},
|
||||
"diagnostics/carried-full-d11b99b-1.stack-frames.json": {
|
||||
"bytes": 13050,
|
||||
"sha256": "f45f3e7599aef2119eb9bf9b9632cfcc329680b1ca5fbc1d18db932572d4261a"
|
||||
},
|
||||
"diagnostics/carried-full-fa7a980-1.stack-frames.json": {
|
||||
"bytes": 13090,
|
||||
"sha256": "09a30cf7a1e0f19b9c9ad8757304168f133a748e817b887e5f2fe2d33bc918f3"
|
||||
},
|
||||
"diagnostics/debug_stack_d11b99b.py": {
|
||||
"bytes": 1735,
|
||||
"sha256": "e04f71511f1fd8e41023ec4cb359450481ae53f7b67762feffdac0f19124d391"
|
||||
},
|
||||
"diagnostics/inspect_stack_frames.py": {
|
||||
"bytes": 1889,
|
||||
"sha256": "80372b64f336b73570c1ee790c41646d0d7765e781d3489a4aa682b07515a1a6"
|
||||
},
|
||||
"diffs/18073a6-to-fa7a980.patch": {
|
||||
"bytes": 41709,
|
||||
"sha256": "ffafb480c61e399bd21268f387ef67ee1e2abcd5e2d429cd5f9d89134945a8de"
|
||||
},
|
||||
"diffs/d11b99b-to-fa7a980.patch": {
|
||||
"bytes": 9160,
|
||||
"sha256": "9afe7ca6ea381fda3d5d2a246d767409775398feb45ad685b042f5e671014e07"
|
||||
},
|
||||
"gates/carried-clippy-fa7a980-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203"
|
||||
},
|
||||
"gates/carried-clippy-fa7a980-1.log": {
|
||||
"bytes": 165,
|
||||
"sha256": "a16886fc9c1af0f8074c7f2ba51cbb1983f4d493f40faf3164d94b28c64b055d"
|
||||
},
|
||||
"gates/carried-clippy-fa7a980-1.result.json": {
|
||||
"bytes": 1968,
|
||||
"sha256": "06390bd5ae88d86cb1d24a7e17b0a57096f0a90a84482cfee4a7aa6febdbf3df"
|
||||
},
|
||||
"gates/carried-fmt-fa7a980-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203"
|
||||
},
|
||||
"gates/carried-fmt-fa7a980-1.log": {
|
||||
"bytes": 6446,
|
||||
"sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d"
|
||||
},
|
||||
"gates/carried-fmt-fa7a980-1.result.json": {
|
||||
"bytes": 1882,
|
||||
"sha256": "ad79d2092b8182f3df68ed383f7ad32b3fa48afb029fa13da1ca0463203fa213"
|
||||
},
|
||||
"gates/carried-focused-d11b99b-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "8bfaff6784f616a550b98b3a8170781e85fe4715a0b20308d896423c73f4992c"
|
||||
},
|
||||
"gates/carried-focused-d11b99b-1.log": {
|
||||
"bytes": 2041,
|
||||
"sha256": "f04ee0473478866bc614fa794cd50af6aa2c1f5d56b9e3c1f5a65112933b144b"
|
||||
},
|
||||
"gates/carried-focused-d11b99b-1.result.json": {
|
||||
"bytes": 4193,
|
||||
"sha256": "49b9d49fc8a659fd5c64d95f3d38e38430d078dc13d9b5ddf3256cdf9b9d7ab7"
|
||||
},
|
||||
"gates/carried-focused-fa7a980-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203"
|
||||
},
|
||||
"gates/carried-focused-fa7a980-1.log": {
|
||||
"bytes": 2041,
|
||||
"sha256": "2d8058db7f66c8cf875d6fd1ffe89d15c49ee16a6bb25dc6b97be5fbfa321946"
|
||||
},
|
||||
"gates/carried-focused-fa7a980-1.result.json": {
|
||||
"bytes": 4192,
|
||||
"sha256": "2dc067b342ba6409c4ae21b540ee133732c314416b3b7e888b8c9ec7e03a67a9"
|
||||
},
|
||||
"gates/carried-full-d11b99b-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "8bfaff6784f616a550b98b3a8170781e85fe4715a0b20308d896423c73f4992c"
|
||||
},
|
||||
"gates/carried-full-d11b99b-1.log": {
|
||||
"bytes": 15550,
|
||||
"sha256": "705752b2f18d5897719f689083227aa1e2df4e17f6bc07747490337681ef00fe"
|
||||
},
|
||||
"gates/carried-full-d11b99b-1.result.json": {
|
||||
"bytes": 19576,
|
||||
"sha256": "ead9d4b916d7fa7a1fb868037639e2aea56dedd13d1c841f08167a64bb742261"
|
||||
},
|
||||
"gates/carried-full-fa7a980-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203"
|
||||
},
|
||||
"gates/carried-full-fa7a980-1.log": {
|
||||
"bytes": 42536,
|
||||
"sha256": "26b946c38db53e7dc589771e1829908dff3596cbf947ecce2442d1bf1d1896af"
|
||||
},
|
||||
"gates/carried-full-fa7a980-1.result.json": {
|
||||
"bytes": 38113,
|
||||
"sha256": "6b6ec7a335e8c1d03ec5c584e3fe8b444839e27cf3afb9f84bced33c73563743"
|
||||
},
|
||||
"gates/carried-list-fa7a980-1.inputs.json": {
|
||||
"bytes": 103383,
|
||||
"sha256": "b51682b333d96d91167f4da8e4f8e4f4b1d443fbfc875fead918d0db1e1db203"
|
||||
},
|
||||
"gates/carried-list-fa7a980-1.log": {
|
||||
"bytes": 29100,
|
||||
"sha256": "ee1c0a5367f277720407fb30a33ccdaef68b58fed3c578caceffbae7ef4035c4"
|
||||
},
|
||||
"gates/carried-list-fa7a980-1.result.json": {
|
||||
"bytes": 31333,
|
||||
"sha256": "8f739ce87c1a700bc9a51ea70b7dd8d3f77267123d5883f3cd8a36cc2a4e2c01"
|
||||
},
|
||||
"gates/launchers/51f590750896843210e02df971c7396bf379494e1605bd059ef017e6e4d41ec5.py": {
|
||||
"bytes": 7661,
|
||||
"sha256": "51f590750896843210e02df971c7396bf379494e1605bd059ef017e6e4d41ec5"
|
||||
},
|
||||
"gates/launchers/d0c116f45de7e9fa64dff58d075c44a840f22920f6c835b4867844bafb6c7ab6.py": {
|
||||
"bytes": 7661,
|
||||
"sha256": "d0c116f45de7e9fa64dff58d075c44a840f22920f6c835b4867844bafb6c7ab6"
|
||||
},
|
||||
"launchers/package_evidence.py": {
|
||||
"bytes": 4632,
|
||||
"sha256": "a0d2b0d938f1449e62db4633a0827f990df72e4def454d05dde5f858a1638125"
|
||||
},
|
||||
"notes/prior-toolchain.txt": {
|
||||
"bytes": 536,
|
||||
"sha256": "1f101518dd1f90bc2cba8d26570a762832aba6debebbbe6aa50f97a944590610"
|
||||
},
|
||||
"reviews/CARRIED-PHASE-ORACLE.md": {
|
||||
"bytes": 10107,
|
||||
"sha256": "56d1b57f4322c74bfd52f46483e337213fb6f8edf26d5756228b6e34c83692fd"
|
||||
},
|
||||
"reviews/CARRIED-PHASE-RUNTIME-READBACK.json": {
|
||||
"bytes": 2216,
|
||||
"sha256": "0003162f0524e6debecdadd0a2f13b86c67b56db92e5ab60360a876130a445fa"
|
||||
},
|
||||
"reviews/RUNTIME-REVIEW.md": {
|
||||
"bytes": 6275,
|
||||
"sha256": "b4622756c4f0d8e813fdc6525cef2ded21226813dd859893376feec00e0fab29"
|
||||
},
|
||||
"reviews/SOURCE-REVIEW.md": {
|
||||
"bytes": 11593,
|
||||
"sha256": "33542cc83877f745cdcaa9090f09b6d9e3af9bf903ab424f59952b78f8398b92"
|
||||
},
|
||||
"reviews/STACK-DIAGNOSIS.md": {
|
||||
"bytes": 3471,
|
||||
"sha256": "b62c7607bfb7868d09fade25d6bdcfdda2557e308425826cc21104311530c674"
|
||||
},
|
||||
"reviews/STACK-SOURCE-ANALYSIS.md": {
|
||||
"bytes": 10966,
|
||||
"sha256": "15ad84c58b163e23c728cdc70cbce8f001bf1b736e780cbb66e0bef2ba21c110"
|
||||
},
|
||||
"reviews/TEST-REVIEW.md": {
|
||||
"bytes": 6960,
|
||||
"sha256": "ce7f8acbd3e8ed5e4cb401ac94dc2390f4d002f0c54138cfe855de190cced6a3"
|
||||
},
|
||||
"reviews/inspect_runtime.py": {
|
||||
"bytes": 7452,
|
||||
"sha256": "bc9065192356d06f909abd3af06da2bffddbf88cce04524490bf8c5c404b84da"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*.md -text
|
||||
*.py -text
|
||||
*.txt -text
|
||||
*.json -text
|
||||
@@ -0,0 +1,70 @@
|
||||
# Independent retained-entry oracle
|
||||
|
||||
Basis: source97a8703adc75467a7f8e75f5c6cb00ca542b707c and accepted `harness/analysis-entry-producer-contract-20260925.md`. Counts are authored from literal grammar, not parser output. Only standalone literal string lengths/substrings were calculated; no compiler or parser executed. All sources below use UTF-8 and LF except the explicitly marked chain suffixes. Entry is `main.arcadia`.
|
||||
|
||||
Define ID1 through ID4 as36-character UUIDs `00000000-0000-0000-0000-000000000001` through `...0004`. `doc(body)` is exactly `arcadia 8;\nproject p "Project" id "ID1" {\nBODY\n}\n`, replacing ID1 with its UUID and BODY with the literal body. Source spans are half-open UTF-8 byte offsets. Use generous unchanged byte/token/reference/model policies for entry controls; bytes4096 suffices for these small fixtures and avoids previously established UUID/text preemption.
|
||||
|
||||
## Empty and three-file controls
|
||||
|
||||
E is `doc("")`,78 bytes, SHA256 `48fe360b7b5f57867086e7f6fa47c2913765c1261e558e7ebec688a1f842a65e`. Its significant tokens are exactly `arcadia`, `8`, `;`, `project`, `p`, quoted Project, `id`, quoted ID1, `{`, `}`: ten. U1 is the project event; there are no ordinary values, fields, lexical owners or projected declarations. C.entries1; M=F1+tokens10=11. New entry-mode syntax cap13 succeeds;12 refuses the complete projection/token-end reservation in main at raw default span0..0, ordinary diagnostic0..1, line1 column1. Complete resolver17/16 is a separate boundary; failure there uses project-header span11..73, pathmain, not the syntax0..1 location. Its peak is syntax13 plus four catalog slots; the final retained total returns to13. These are complete-project positives, with empty maps and description, aliasp/nameProject/schema8/ID1.
|
||||
|
||||
H is exactly:
|
||||
|
||||
```text
|
||||
main.arcadia = doc("include \"part.arcadia\";")
|
||||
part.arcadia = "include \"last.arcadia\";\r\n"
|
||||
last.arcadia = "//é\r\n"
|
||||
```
|
||||
|
||||
Source lengths101,25,6, total132. C.entries3, C.text180 (source132 + three12-byte keys +12-byte entry). Significant token counts13,3,0; raw scanner work24,5,2 is separate. U3 is project plus two includes; value maps, owners and projection are zero. M=F3+tokens16=19; combined syntax25. Main boundary reaches C3+U2+M16=21. Part adds U1 and three token-end slots, reaching25; last adds nothing. Syntax25 succeeds,24 refuses at part default span0..0 transported to0..1 (line1 column1). Full resolver29/28 remains separate and fails at main project-header11..73. Traversal is main/part/last; canonical output order last/main/part. Use roomy text4096; do not reuse the old phase-only byte214 cap with newly enabled text producers.
|
||||
|
||||
With an actual explicitly borrowed C0 guard, the corresponding syntax totals are E12 and H22. This is the explicit combined mode, not permission to reuse legacy separated checks. No extra field/file count is added at resolver transfer.
|
||||
|
||||
## Prefix producer refusals
|
||||
|
||||
Owner fixture body is exactly `oa_activity a "A" id "ID2" { }`, source141 bytes. Declaration start75. Immediately before its owner push: C1+F1+U2=4. Cap4 rejects that owner reservation before Vec mutation; raw attribution starts75, ordinary diagnostic75..76, line3 column1. Cap5 merely clears this prefix. A complete syntax needs29: tokens17, U2, owners1, values0, projection7, M26 plus C1.
|
||||
|
||||
Value fixture body is exactly `oa_activity a "A" id "ID2" { description ""; }`, source157 bytes. Description key begins137; empty quoted value149..151. Immediately before its first value-end insertion: C1+F1+U4+owner1=7. Cap7 rejects with raw value span149..151, ordinary diagnostic149..150, line3 column75. Cap8 merely clears this prefix. Full syntax needs37: tokens20, U4, owner1, value1, projection9=7+field1+value1; M32 and C1. A roomy complete syntax positive is required separately from the refused prefix.
|
||||
|
||||
Both aggregate messages are exactly `Source8 lowering entry limit exceeded.` with codeinvalid_source, no related diagnostics. These tests must check unchanged map/Vec on refusal through a finite observer or directly reviewed helper. A final error/count alone does not establish the before-mutation order.
|
||||
|
||||
## Combined syntax-only nested inventory
|
||||
|
||||
Exact complete source:
|
||||
|
||||
```text
|
||||
arcadia 8;
|
||||
project p "Project" id "00000000-0000-0000-0000-000000000001" {
|
||||
oa_activity a "A" id "00000000-0000-0000-0000-000000000002" { payload { items [@p, uuid "00000000-0000-0000-0000-000000000001", { flag true; }]; };
|
||||
oa_activity b "B" id "00000000-0000-0000-0000-000000000003" { }
|
||||
}
|
||||
node n id "00000000-0000-0000-0000-000000000004" { }
|
||||
}
|
||||
```
|
||||
|
||||
Include the final LF. Source344 bytes, SHA256 `83c53d51c2ebca01d5771a3d66cf57037b808f43f4c113daf3404736cdc1d69c`; actual one-file C=(entries1, occurrences0, text368). This is **syntax-only**: arbitrary payload and top-level node are not claimed semantically admissible. Do not unwrap full Project resolution as this fixture's positive control.
|
||||
|
||||
Declarations in ordinary preorder: a at75, b at223 nested inside a, n at289 at project level. Lexical owner occurrence indices are `[None, Some(0), None]`; count3 regardless of UUID uniqueness. Each declaration contributes seven projected envelope slots, including its synthetic body. The node's four-role header still contributes the same conservative seven, not six. The open-declaration coordination stack contributes no additional U/M.
|
||||
|
||||
| Actual Ast value | Start | End | Map insertion order |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| payload Record |145|221|6|
|
||||
| items Array |153|218|5|
|
||||
| @p Reference |154|156|1|
|
||||
| historical UUID |158|201|2|
|
||||
| array member Record |203|217|4|
|
||||
| true Atom |210|214|3|
|
||||
|
||||
All six keys are distinct. Three actual fields are payload, items, flag. Their keys begin137,147,205 respectively. Synthetic declaration bodies are not Ast values and add no seventh value/map entry. Ordinary reference @p contributes one value event, not a typed-reference work charge.
|
||||
|
||||
Significant-token inventory is ten project tokens plus seven a-envelope tokens, nineteen payload tokens, seven b-envelope tokens and six n-envelope tokens =49. The nineteen payload tokens, in order, are: `payload { items [ @ p , uuid "ID1" , { flag true ; } ] ; } ;`. Quoted UUID is one token. Nested declaration closure belongs to its own envelope; a's closure is already in its seven. No comments or EOF token are included.
|
||||
|
||||
U=project1+declarations3+fields3+values6=13. Projection P=declaration envelopes21+fields3+values6=30. M=F1+tokens49+value ends6+owners3+P30=89. Final combined C+U+M=103. Before the complete projection reservation, combined live total24=C1+F1+U13+values6+owners3; tokens49+P30 reserve79 atomically. Consequently syntax103 succeeds and102 refuses in main at default span0..0, transported0..1, before ends/header/field/value projection. Every earlier entry prefix is below102. Use byte4096 and roomy other policies.
|
||||
|
||||
Projected quota consumes7 at a, then payload field1, its Record value1, items field1, Array value1, Reference1, HistoricalUuid1, nested Record1, flag field1, Atom1; then7 at b and7 at n: total30, zero remaining. Quota subtraction does not change M. Map/owner counts are retained conservatively even when their temporary containers drop. No model admission or resolved-entry peak is asserted for this fixture.
|
||||
|
||||
## Internal and compatibility controls
|
||||
|
||||
Repeated value-map key replacement must reserve zero new M and preserve length; label it injected helper behavior, not a source occurrence. Too-small quota, leftover quota, checked arithmetic overflow and latched refusal are also explicit internal controls. Duplicate real fields fail the whole grammar parse, so no successful final BTree inventory discards a counted field. Do not salvage such a failure by refunding to manufacture a successful witness.
|
||||
|
||||
Use existing complete OA/SA fixtures for roomy whole-Project/Usage/numeric parity against the text-only route; the combined fixture above covers the specific retained inventory only. Preserve legacy/carried/text-only timings and policies, source bytes, actual guard lifetime, and all existing small-stack cases. These literals are independent expectations to guide tests, not runtime acceptance evidence.
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"baseline": "97a8703adc75467a7f8e75f5c6cb00ca542b707c",
|
||||
"baseline_archive_sha256": "252ea94e7c7f500a2afb3d0fa47c43a051f39d9c844328337289eea0c463becd",
|
||||
"checker_sha256": "792b2eff0a9288a73bad9495b05ca06927ca0717a176dce5913206ffa9731080",
|
||||
"inputs": 557,
|
||||
"unchanged_old_outcomes": 275,
|
||||
"added_passed": 6,
|
||||
"added_names": [
|
||||
"language::analysis_source::mixed::carried::entry_producer::explicit_zero_and_actual_owner_preserve_complete_oa_sa_and_old_routes",
|
||||
"language::analysis_source::mixed::carried::entry_producer::internal_overflow_latch_and_syntax_work_precedence",
|
||||
"language::analysis_source::mixed::carried::entry_producer::internal_reserve_and_mutate_helpers_leave_collections_unchanged",
|
||||
"language::analysis_source::mixed::carried::entry_producer::nested_inventory_and_prepaid_projection_quota",
|
||||
"language::analysis_source::mixed::carried::entry_producer::owner_and_value_refuse_at_the_original_producer",
|
||||
"language::analysis_source::mixed::carried::entry_producer::real_owner_syntax_and_resolver_boundaries_are_separate"
|
||||
],
|
||||
"full_passed": 265,
|
||||
"full_failed": 16,
|
||||
"identical_failure_blocks_after_pid_only_normalization": 16,
|
||||
"identical_fmt_sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d",
|
||||
"artifact": {
|
||||
"path": "C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\analysis-checked-save-target-20260913\\debug\\deps\\oa_core-416e35542925bed6.exe",
|
||||
"bytes": 42898944,
|
||||
"sha256": "adb0bd907f614c512bc3883dfe9a88ca0e4268638d85f4899ad07a5c1d3ec4e9"
|
||||
},
|
||||
"environment": {
|
||||
"CARGO_TARGET_DIR": "C:/Users/User/Documents/Git/ARCADIA-Studio/.local/analysis-checked-save-target-20260913",
|
||||
"CARGO_BUILD_JOBS": "1",
|
||||
"CARGO_INCREMENTAL": "0",
|
||||
"CARGO_HOME": "C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\toolchain\\cargo",
|
||||
"RUSTUP_HOME": "C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\toolchain\\rustup",
|
||||
"RUSTFLAGS": null,
|
||||
"RUSTC": null,
|
||||
"RUSTUP_TOOLCHAIN": null,
|
||||
"ARCADIA_CODEC_LIFECYCLE_PHASE": null,
|
||||
"RUST_MIN_STACK": null
|
||||
},
|
||||
"receipts": {
|
||||
"entry-focused-2941713-1": {
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"exit": 0,
|
||||
"outcomes": 6,
|
||||
"listing": 0,
|
||||
"log_sha256": "fb1cb5d33b724c54687c56439b01fcf4d1c7a393dd08d9cd789702625acdad06",
|
||||
"result_sha256": "f8b1ad7859ae58f7b9cc618a22e603a922bb1d4ab4c73b84525c4267ea30a88b",
|
||||
"inputs_sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c",
|
||||
"launcher_sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
},
|
||||
"entry-full-2941713-1": {
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"exit": 101,
|
||||
"outcomes": 281,
|
||||
"listing": 0,
|
||||
"log_sha256": "47fef6f46d136be0e53f48f8ff03a96be73635fc4c3f57350c1e641ad44b01c4",
|
||||
"result_sha256": "0bbf4cc28d8832e0cdc4e674296db0b71c7da38a0ac1e3c7ecf34e9d19ab6a62",
|
||||
"inputs_sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c",
|
||||
"launcher_sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
},
|
||||
"entry-list-2941713-1": {
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"exit": 0,
|
||||
"outcomes": 0,
|
||||
"listing": 281,
|
||||
"log_sha256": "4552e8512731a2fb3dbaba02b671c32837018298b5d8b52057af7fa372f2f50e",
|
||||
"result_sha256": "5374aea8aba0790bcfb6fa4dee179a4c5ddc0df2efd602e876acbc8c84ae59d1",
|
||||
"inputs_sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c",
|
||||
"launcher_sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
},
|
||||
"entry-clippy-2941713-1": {
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"exit": 0,
|
||||
"outcomes": 0,
|
||||
"listing": 0,
|
||||
"log_sha256": "3f18ecfb5fac754c6660d217d1f87752ee99a321fff525a6113ff7deb6ee2baa",
|
||||
"result_sha256": "edb45b1706f09e89ab2f0584a9708ab7e808e7f1048bde2b1439c4f0d49d439d",
|
||||
"inputs_sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c",
|
||||
"launcher_sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
},
|
||||
"entry-fmt-2941713-1": {
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"exit": 1,
|
||||
"outcomes": 0,
|
||||
"listing": 0,
|
||||
"log_sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d",
|
||||
"result_sha256": "a7f1c7ec70ec4a6872dc8a387d1a8c5b3b424f125d21a59a6320b3c2ac17c772",
|
||||
"inputs_sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c",
|
||||
"launcher_sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
}
|
||||
},
|
||||
"scope": "Committed declared inputs, pinned baseline archive, raw logs and current artifact bytes; no Cargo/executable execution. Launcher semantics require independent source review."
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Independent entry-producer package readback
|
||||
|
||||
Pass for this finite evidence package; no unresolved material discrepancy. Reviewed source `29417130c71f70c4eaefe8ed4c879efba78eb72c` and the current artifact before releasing the source freeze. This audit used file reads, independent data comparisons and read-only Git. It did not execute archived helpers, Cargo, a compiler, debugger or product/test executable, and did not access the network.
|
||||
|
||||
The immutable archive is exactly **434,046 bytes / 53 unique members**, SHA256 `19a87583a8dc4c22f35999044de5cac2c2c97b04fb457d2c3df3f6d2c054c865`. CRC checks pass; every member name, byte count and SHA256 matches [manifest.json](manifest.json), whose SHA256 is `074fbdf32ef7012a31d56ed723f04813edc5b4c5ba2b9fed260b6f2f7610600c`. Names have no absolute paths or parent traversal. All 51 file-backed members equal their original local files; the other two members exactly equal immutable Git diffs from97a8703 to a629ae0 and2941713. All seven readable mirrors equal both archive and original review files.
|
||||
|
||||
The baseline full/list/fmt members also match the previously frozen text-producer archive, SHA256 `252ea94e7c7f500a2afb3d0fa47c43a051f39d9c844328337289eea0c463becd`. Independently checked all556 baseline and557 initial/final declared inputs against their respective immutable Git blobs. All557 final files also matched raw disk; HEAD was2941713 with no tracked changes. Focused/full/list bind the same current **42,898,944-byte** executable, SHA256 `adb0bd907f614c512bc3883dfe9a88ca0e4268638d85f4899ad07a5c1d3ec4e9`, independently reread without execution. This is declared-input/artifact concordance, not exhaustive compiler or undeclared-dependency provenance.
|
||||
|
||||
Reparsed all nine gate receipts and raw logs, checking log/input/launcher hashes, source stability, exact recorded outcomes and listings. The five README commands equal the final argument arrays. Final results are six focused passes, **265 passed /16 failed**,281 unique listed/runtime names, strict core all-target Clippy exit0 and format exit1. All275 prior outcomes and ten existing stack controls are preserved. All16 failure bodies match97 after replacing only the numeric thread identifier in Rust panic headers. Format output is byte-identical: eight blocks in five files, SHA256 `c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d`. Recorded jobs1/incremental0 and absent stack override agree with the stated environment. The captured launcher records unfiltered combined output and actual return codes; its source/input/helper checks support the stated bindings.
|
||||
|
||||
The initial a629ae0 E0277 compile refusal is preserved, with zero outcomes/artifacts. The exact a629ae0→2941713 diff changes only the quota test's `unwrap_err` extraction to explicit Err/Ok matching and its implementation note; production and assertions remain unchanged. The archived source/test reviews retain both precompile latch repairs and the separate-roomy-owner inventory evaluator correction. None is presented as an erased or successful initial run.
|
||||
|
||||
Read all six baseline/final prologue records and their capture helpers as source. Their source/artifact/helper identities and raw immediates agree with [STACK-OBSERVATIONS.md](STACK-OBSERVATIONS.md): selected parser changes sum2,048 bytes; binding2520 plus prefix11720 stays14,240; continuation13416 is a separate alternative. Projector616→1032 and ordinary584→80+1000 are accurately distinguished from parser phases. Worker7368 and shim56 are not confused. These partial compiler reservations omit other stack costs and do not establish total headroom or a new128KiB strong-mode pipeline guarantee. Prior projector observations are correctly described as newly captured baseline evidence, not retroactively part of the older archive.
|
||||
|
||||
Reviewed README, current STATE/DECISIONS statements and readable reviews for scope; checked102 local Markdown links with no missing targets. Parent corrected the minor README/STATE thread-identifier terminology; archived historical checker labels remain unchanged. Final reviewed README SHA256 is `6a8f82a51b9ed4bee14172c1d17aaea4a2d3cb87a7b9bf1ebd4b9e7802ea99b6`. The documents accurately preserve local-only publication status, failed inherited gates, finite retained-accounting exclusions and unfinished output acceptance/public editing. The reported remote storage failure and last remote commit are contextual prior observations, not independently revalidated by this offline audit.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Private retained-entry producers — Windows evidence
|
||||
|
||||
Tested source **29417130c71f70c4eaefe8ed4c879efba78eb72c**, branch
|
||||
`codex/analysis-entry-producers-956atf-20260925`, based on
|
||||
`97a8703adc75467a7f8e75f5c6cb00ca542b707c`. Source and evidence are **local-only**:
|
||||
Gitea rejected publication with server `No space left on device`. The last
|
||||
confirmed remote evidence commit remains `b2ef3f54`. This does not change the
|
||||
published Windows preview or establish public source8 editing.
|
||||
|
||||
The [contract](../../analysis-entry-producer-contract-20260925.md) adds an explicit
|
||||
combined text/entry producer route from actual carried authority. It preserves
|
||||
U syntax events and M's existing logical file/token-end/value-end/owner/projection
|
||||
inventory. Prospective checks precede selected growth; checked grammar counters
|
||||
and prepaid projection quota replace the old counting-work Vec on this route.
|
||||
Independent final inventory and once-only resolver transfer remain required.
|
||||
|
||||
[evidence.zip](evidence.zip): **434,046 bytes, 53 members**, SHA256
|
||||
`19a87583a8dc4c22f35999044de5cac2c2c97b04fb457d2c3df3f6d2c054c865`.
|
||||
[manifest.json](manifest.json) pins every raw member: original/final gates,
|
||||
launchers, input manifests, predecessor logs, two exact source patches, contract,
|
||||
design reviews and compiler-prologue observations. Seven readable review/checker
|
||||
mirrors match the archive exactly. The executable is identified, not included.
|
||||
Historical absolute paths identify the builder environment, not shared peer files.
|
||||
|
||||
## Observed gates
|
||||
|
||||
Windows x86_64 gnullvm, Rust/Cargo1.98.1, LLVM-MinGW20260908, one Cargo job,
|
||||
`CARGO_INCREMENTAL=0`. No Linux/WSL build or check. Exact argument arrays and
|
||||
environment are in `gates/*.result.json`; readable commands from the pinned checkout:
|
||||
|
||||
```text
|
||||
cargo test --locked --offline -p oa-core --lib entry_producer -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-core --lib -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-core --lib -- --list
|
||||
cargo clippy --locked --offline -p oa-core --all-targets -- -D warnings
|
||||
cargo fmt --all -- --check
|
||||
```
|
||||
|
||||
Six new tests pass; full library **fails with265 passed/16 inherited failed**,
|
||||
281 unique names. All275 prior outcomes and all ten existing stack controls
|
||||
are unchanged. Strict core all-target Clippy passes. Workspace formatting still
|
||||
fails with the byte-identical inherited eight blocks in five files. All16 failure
|
||||
bodies match the97a8703 baseline after numeric thread-identifier normalization only;
|
||||
the previous8d→97 framework-hint difference is not a new exception here.
|
||||
|
||||
All557 declared inputs match immutable Git and raw disk through final gates.
|
||||
Focused/full/list use the same42,898,944-byte executable, SHA256
|
||||
`adb0bd907f614c512bc3883dfe9a88ca0e4268638d85f4899ad07a5c1d3ec4e9`.
|
||||
Initiala629ae01 compilation failed before tests: quota-test unwrap_err required
|
||||
Debug on a successful EditDeclaration vector. Finaltest uses explicit Err/Ok
|
||||
matching; production and expected outcomes are unchanged. Original compiler
|
||||
failure/receipt/source patch remain archived; no initial artifact/pass is claimed.
|
||||
|
||||
## Review and finite scope
|
||||
|
||||
[Source review](SOURCE-REVIEW.md) records two precompile error-latch repairs:
|
||||
preserve the original failure during an overflow request, and check a zero-delta
|
||||
map replacement before mutation. [Test review](TEST-REVIEW.md) preserves the
|
||||
evaluator correction: an inventory walk requires scratch beyond exact syntax
|
||||
caps, so a separate roomy same-source owner is used. No live policy is widened.
|
||||
[Literal oracles](ENTRY-ORACLE.md) cover syntax13/12 and25/24 separately from
|
||||
resolver17/16 and29/28; owner/value prefix refusals4/7; and nested record, array,
|
||||
reference, UUID, nested declaration and node envelopes at syntax103/102.
|
||||
The nested fixture is syntax-only, not a semantically admitted Project.
|
||||
|
||||
[Runtime review](RUNTIME-REVIEW.md), [readback JSON](ENTRY-PRODUCER-RUNTIME-READBACK.json)
|
||||
and [reviewed checker](inspect_runtime.py) reconcile actual logs, baseline archive,
|
||||
names, inputs, launcher semantics and current artifact. [Stack observations](STACK-OBSERVATIONS.md)
|
||||
record selected parser-chain reservation growth totaling2,048 bytes, separate
|
||||
projector changes and unchanged repaired binding/prefix sizes. These are partial
|
||||
compiler prologues, not measured total headroom. New tests use the normal harness
|
||||
stack; old pipeline setup limitations and prior-source repeated runs keep their
|
||||
original scopes. No new universal128KiB guarantee follows.
|
||||
|
||||
Existing traversal/delimiter/open/Pratt/duplicate-name scratch, token storage
|
||||
under its independent ceiling, numeric/decoder internals, model/validator heap,
|
||||
allocator overhead and native stack remain outside this retained metric. Pending
|
||||
projection instrumentation can change under an artificial direct call after a
|
||||
latched error, but actual parser paths immediately propagate and cannot return a
|
||||
poisoned witness. Actual emitted-output admission, whole-intent equality,
|
||||
accepted ownership and public/history integration remain separate unfinished work.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Independent entry-producer runtime readback
|
||||
|
||||
Source `29417130c71f70c4eaefe8ed4c879efba78eb72c` passes the specified bounded regression readback. No checker exception or relaxation was needed. This is not a wholly passing suite:16 inherited tests fail and workspace format exits1. No compiler, test binary, debugger or launcher was executed by this reviewer.
|
||||
|
||||
## Readback identity and gates
|
||||
|
||||
Executed only the prepared read-only `inspect_runtime.py`, using bundled Python `-I -B` with arguments `29417130c71f70c4eaefe8ed4c879efba78eb72c 2941713 6`. Checker SHA256 `792b2eff0a9288a73bad9495b05ca06927ca0717a176dce5913206ffa9731080` was unchanged. Exclusive result `ENTRY-PRODUCER-RUNTIME-READBACK.json` SHA256 `f45c86d42a1d89c4cf2b22342f2c41dcd4514622f0bd2367101f219367d1c66c`; checker exit0.
|
||||
|
||||
| Gate | Exit | Raw evidence |
|
||||
| --- | ---: | --- |
|
||||
| Focused |0|Six entry-producer tests passed,275 filtered |
|
||||
| Full |101|281 unique results:265 passed,16 failed, zero ignored |
|
||||
| List |0|281 unique names, exactly full runtime inventory |
|
||||
| Strict core all-target Clippy |0|Locked/offline `-D warnings` completed |
|
||||
| Workspace format |1|Identical prior raw output, SHA256 `c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d` |
|
||||
|
||||
All275 predecessor outcomes are unchanged. Exactly six new names occur, all passed, and focused is exactly that new set. All16 inherited failure bodies are identical after numeric thread-PID replacement only. There is no backtrace-hint exception: the97 baseline already contains the previously documented hint removal. All ten existing stack-named controls in the final full raw log passed.
|
||||
|
||||
The checker binds baseline source `97a8703adc75467a7f8e75f5c6cb00ca542b707c` full/list/fmt logs and receipts byte-for-byte to the locally committed text-producer ZIP, SHA256 `252ea94e7c7f500a2afb3d0fa47c43a051f39d9c844328337289eea0c463becd`. This review makes no remote publication claim.
|
||||
|
||||
All five receipts bind the clean current source,557 declared inputs, raw Git blob versus disk equality, unchanged inputs through each command, exact commands/environment and the same captured launcher. Manifest SHA256 `3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c`. Final focused/full/list record the same actual current executable,42,898,944 bytes, SHA256 `adb0bd907f614c512bc3883dfe9a88ca0e4268638d85f4899ad07a5c1d3ec4e9`; checker reread those bytes. Individual log/receipt pins are preserved in the readback JSON. Full raw log SHA256 `47fef6f46d136be0e53f48f8ff03a96be73635fc4c3f57350c1e641ad44b01c4`.
|
||||
|
||||
## Launcher review
|
||||
|
||||
Read actual captured launcher SHA256 `43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc`, without executing it. It hardpins2941713, checks clean tracked source and raw declared files before launch, captures exact helper bytes, records unfiltered stdout/stderr and actual process return code, checks source/input/helper identity afterward, and records executable hashes from actual Cargo Running lines. The readback separately re-parses results and rejects duplicate/missing names and incomplete summaries rather than trusting the recorder's summary alone.
|
||||
|
||||
Commands remain locked/offline oa-core library focused/full/list, locked/offline core all-target Clippy, and workspace format. Jobs1/incremental0 and baseline environment match; RUST_MIN_STACK, RUSTFLAGS, custom RUSTC, RUSTUP_TOOLCHAIN and lifecycle override are absent. This establishes recorded declared-input/artifact concordance, not independent compiler provenance or completeness of every undeclared/untracked dependency.
|
||||
|
||||
## Original compile failure retained
|
||||
|
||||
Initial source `a629ae01d49bb3cb482a047eb41832ad4246a5c6` focused attempt exited101 after26.156 seconds, before any tests. Raw E0277 identifies entry_producer.rs:241 `unwrap_err` requiring Debug for successful `Vec<(Uuid, EditDeclaration)>`. Receipt has zero outcomes and no artifacts. Independently hashed raw log `cfd534fb67405666ba7a86aa3aa3164655d803b00d4e80f09893d1e312c2a58a`, receipt `0490608967cc91ac5e666453304a657a01743508d3d98aa9b3e469482b3629f0`; log matches receipt pin.
|
||||
|
||||
The previously reviewed2941713 repair replaces only that extraction with explicit Err/Ok matching, retaining both quota refusal assertions; production unchanged, implementation note updated. Final test SHA256 `ebdcd69eae66103a7ed596356e5f629099399d944b5659ace54edc9f558e7bc9`. Original failed evidence is not replaced by later successful execution.
|
||||
|
||||
## Stack observations and scope
|
||||
|
||||
Read parent STACK-OBSERVATIONS and raw prior/final stack, active and projector JSON disassemblies. Final selected reservations match the stated values: parse_impl12888, parse_with_profile216, parse280, accepted1608, indexed1608, actual worker7368, Parser::unit12456. Their selected changes versus97 sum2048 bytes. Typed/numeric/Pratt selected reservations remain unchanged; binding2520 plus prefix11720 is14240, and continuation13416 is an alternative, not simultaneously added.
|
||||
|
||||
Projector records expand from nine baseline to17 final specializations. Raw mixed projector changes616→1032 (+416). Ordinary old body584 becomes wrapper80 plus producer1000=1080 selected reservation bytes; outer wrapper remains72. Specialized token/value/fields are120/536/216; new quota-consume120; injected quota test has a separate1000-byte specialization. These immediate prologue reservations exclude pushes and other runtime overhead; neither their sum nor record count is total live stack/headroom. Projection occurs after Parser::unit returns, so combining both phases as a single measured chain would be false.
|
||||
|
||||
All old stack controls passed in this full run, but the six new entry tests run on ordinary test-harness stacks; this does not establish a new128KiB strong-mode pipeline guarantee. Prior extra process repetitions, debugger observations and historical failures retain their own source/scope. No additional runtime, retry or stack override was used for this review.
|
||||
|
||||
Admission is limited to these finite retained-entry evaluators and unchanged baseline disposition. It does not establish all-heap accounting, accepted rewritten output, public constructor authority, GUI behavior or unresolved scratch-domain closure.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Independent retained-entry producer source review
|
||||
|
||||
2026-09-25. Reviewed frozen production against baseline `97a8703adc75467a7f8e75f5c6cb00ca542b707c` and selected contract SHA256 `0dd194e155f3ea3b6795601e199c2a63d7edff7644f3a75942801f7329a1751c` (`harness/analysis-entry-producer-contract-20260925.md`). This is local-only source review, before compiler/runtime gates. Test authoring remained in progress.
|
||||
|
||||
Initial frozen files, relative to `crates/oa-core/src/`:
|
||||
|
||||
| File | SHA256 |
|
||||
| --- | --- |
|
||||
| `language.rs` | `eba0d326f70a90ff1ff3097b927dfa3d3efd49b3cf56a0cc55ac14c35d93f248` |
|
||||
| `language/analysis_source/budget.rs` | `f1f3571fac2b6e3891c7d02a3ea1a513122ca3259afbe28fc17315c1c4db2847` |
|
||||
| `language/analysis_source/mixed.rs` | `cab97109e90e51eea690b3579b38faf1cd697244941485bbd851e415b60b25ea` |
|
||||
| `language/analysis_source/mixed/carried.rs` | `0d0f44264a3f1dbc8d80b861c7156ab71bac36cecd86ee4a77ecddfe22f1f5a9` |
|
||||
|
||||
## Resolved internal latch finding
|
||||
|
||||
`Budget::producer_entry_overflow` initially replaced `failed` unconditionally, unlike aggregate checks which first call active(). A direct internal control can latch a limit error and then overwrite it with an overflow error. Recommended narrow repair: return the existing error when present. All actual parser callers propagate their first error immediately, so this is an internal sticky-error consistency finding, not an observed successful-parse bypass or runtime failure.
|
||||
|
||||
Parent-authorized repair independently read back: the helper now returns a clone of the existing failure before constructing/installing overflow. Final `budget.rs` SHA256 is `573636cbe24f9aadfbba1e68625fd9d861ace26c7c85b5b6530c53085e3baf4f`, superseding the initial table's budget hash. All other three production hashes were rechecked and remain exact. The finding is resolved; no remaining concrete source blocker was found. The implementer reports a dedicated internal regression assertion, whose execution remains pending.
|
||||
|
||||
## Prospective accounting and authority
|
||||
|
||||
The new fixture route consumes the same sealed CarriedInput and derives actual bundle, carried guard and exact inherited policies together. It selects both text and entry producers even for explicit C=0. Existing legacy, phase-only and text-only callers select entry mode false. No mutable policy, arbitrary public baseline, owning wrapper or accepted-output route is introduced. The private parse_impl boolean combination is supported by its current controlled callers; no caller enables entries without text/guard authority.
|
||||
|
||||
Existing text/guard and total-source-byte checks run first. C.entries and initial M=F are checked and installed together before Traversal construction. Failed installation leaves optional entry state absent. Budget::entry retains its existing U-only work/active check before the aggregate C+U+M+1 check; U increments only after both pass. reserve_metadata checks the whole prospective total before changing M. Checked aggregate sums prove its subsequent M += delta cannot overflow. Usage remains U alone, with no new token/reference/numeric events. The original nonlatching phase-check helpers are unchanged.
|
||||
|
||||
The disabled reserve_metadata path is an exact accounting no-op: it neither calls active(), changes counters nor adds failure precedence to old routes. All production calls to fallible reserve, projection counting and projector operations propagate immediately. In particular, a value-end refusal exits value() before its projection counter; an owner refusal exits before its seven-slot pending count or declaration insertion. No partial witness escapes.
|
||||
|
||||
## Named producers and independent reconciliation
|
||||
|
||||
State now hides value_ends and lexical_owners from the ordinary parser. Its value_end helper checks key presence, reserves only a new key, then inserts; repeated keys replace the existing endpoint without another M entry. lexical_owner reserves before push and counts occurrences rather than unique IDs. Actual source search finds the only mutations inside these helpers. Their reserved counters match actual map/Vec lengths after every completed file.
|
||||
|
||||
The plain reserved_values/reserved_owners increments are bounded, including when entry mode is off: each successful ordinary value/declaration has an earlier unchanged Budget::entry event; unique successful value offsets and owner occurrences therefore cannot exceed U, which is bounded by the candidate hard entry ceiling (262,144). A repeated map key does not increment. In stronger mode the admitted M bound also applies. They do not approach usize overflow through accepted input. Artificially corrupting those private counters is not real provenance.
|
||||
|
||||
Checked pending projection grows only at the three grammar sites: seven per ordinary declaration, one per completed field, one per completed value. Project headers/includes/descriptions bypass those sites; nested fields and values naturally contribute once. The seven declaration envelope includes its synthetic body and remains seven for a node header. Failed duplicates abort the entire parse, so no successful replacement/refund is hidden.
|
||||
|
||||
The stronger projection boundary atomically reserves significant-token count plus pending projection before constructing ends/headers/fields/values. It does not call the old borrowed-work Vec count. Other modes retain that existing counting path. The scalar prepaid quota consumes seven before header/declaration growth, one before each field and one before each actual value, before recursive children. Synthetic bodies are covered by seven and do not consume an extra value slot. Quota underflow/leftover returns an explicit invariant error; quota consumption never charges or refunds M. Token-end slots are charged once, separate from the existing significant-token storage bound.
|
||||
|
||||
After each file, actual map/owner lengths plus token count and quota-reconciled projection count must match the Budget M delta. The independently accumulated metadata field must equal total producer M at syntax completion. File-record moves preserve F rather than adding a second reservation. Existing resolver code is unchanged: seed C once, then reserve U+M once in its distinct ledger; text transfer/reconciliation remains unchanged. No combined seed followed by duplicate syntax addition exists.
|
||||
|
||||
## Legacy behavior, stack and pending gates
|
||||
|
||||
Without entry mode, grammar projection calls do nothing, quota is None, and the original token-end/value-map/owner/projected metric and phase timing remain. Shared projection retains its traversal, text hooks, spans and identity checks. A new forwarding wrapper and scalar fields do alter native layout even on old paths; no unchanged-stack claim follows from semantic equivalence. Parent must measure Budget/State/projector generic frames as well as prior active parser/wrapper frames, and run all old small-stack controls without allowances or test changes. There is no new heap-backed owner or generic visitor framework.
|
||||
|
||||
Compiler/privacy/borrow checks, independent real cap and span oracles, quota/overflow/internal controls, whole Project/Usage parity, old diagnostic disposition, strict Clippy and format comparison remain pending. This review neither runs nor substitutes for those gates. The retained logical metric excludes allocator capacity, physical file-table overlap, traversal/open-declaration/delimiter/Pratt and duplicate-name scratch, numeric/decoder internals, model/validator heap and native stack. Actual emitted-output verification and accepted ownership remain open.
|
||||
|
||||
## Committed replacement-helper repair and final source binding
|
||||
|
||||
Independently read back production committed in `a629ae01d49bb3cb482a047eb41832ad4246a5c6`, unchanged in current clean HEAD `29417130c71f70c4eaefe8ed4c879efba78eb72c`. The latter changes only the new test file and implementation note for the reported compile-time Debug-bound issue; it changes no production operation. No compiler or test process was run by this reviewer.
|
||||
|
||||
The second internal latch finding is resolved: `State::value_end` now computes whether its key is new, always calls reserve_metadata with delta 0 or 1, and only then increments its new-key counter and inserts/replaces the endpoint. Enabled delta-zero admission calls active() before mutation, preserving the original latched failure and existing map even for replacement. New keys still reserve exactly one M; replacements reserve no additional M. Disabled old modes still receive the same no-op budget hook and preserve their previous accounting/diagnostic behavior.
|
||||
|
||||
Final `mixed.rs` SHA256 is `6db2e6cc414becd32d80868653651e31de3036a6d8bf63a2c7b0c055ca7cc314`, superseding the initial table. The other production hashes were independently rechecked: language.rs `eba0d326f70a90ff1ff3097b927dfa3d3efd49b3cf56a0cc55ac14c35d93f248`; budget.rs `573636cbe24f9aadfbba1e68625fd9d861ace26c7c85b5b6530c53085e3baf4f`; carried.rs `0d0f44264a3f1dbc8d80b861c7156ab71bac36cecd86ee4a77ecddfe22f1f5a9`.
|
||||
|
||||
Bounded internal limitation: State::projection does not first call active(), so a direct fault-injection caller that deliberately continues after a previous error can increment the pending projection scalar when addition fits. That scalar is grammar instrumentation, not U, live M, an allocation or an accepted witness. All actual parser calls immediately propagate earlier errors; the final budget.active() also prevents a poisoned witness from escaping. Overflow still preserves the first latched error through the repaired overflow helper. No reachable parser invariant violation or acceptance bypass was found, so no third repair is required for this prerequisite. This does not promise terminal immutability for every internal instrumentation method under arbitrary post-error calls.
|
||||
|
||||
No concrete source blocker remains. Exact-cap syntax tests and roomy independent counting-walk tests must remain distinct because the walk has its own transient entry frontier; this source review does not authorize changing a live policy to make either pass. Compiler/runtime acceptance and publication remain parent-owned and separately evidenced.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Selected Windows compiler prologues and stack controls
|
||||
|
||||
Actual final source `29417130c71f70c4eaefe8ed4c879efba78eb72c`, Rust1.98.1 gnullvm,
|
||||
unoptimized test profile, one job, no incremental compilation or stack override.
|
||||
Focused/full/list bind the same42,898,944-byte executable, SHA256
|
||||
`adb0bd907f614c512bc3883dfe9a88ca0e4268638d85f4899ad07a5c1d3ec4e9`.
|
||||
Parent captured symbols and64-byte entry disassembly through llvm-nm/objdump;
|
||||
each helper verifies the actual executable against its source-bound receipt first.
|
||||
These are read-only observations, not debugger/runtime frame measurements.
|
||||
|
||||
| Selected reservation | Baseline97a8703 | Final2941713 | Delta |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| mixed::parse_impl |11560|12888|1328|
|
||||
| mixed::parse_with_profile |200|216|16|
|
||||
| mixed::parse |280|280|0|
|
||||
| project::tests::accepted |1528|1608|80|
|
||||
| ordinary_index::tests::indexed |1560|1608|48|
|
||||
| Actual ordinary small-stack worker closure |7176|7368|192|
|
||||
| Same-named test shim |56|56|0|
|
||||
| Parser::unit |12072|12456|384|
|
||||
| State::parse_typed |6952|6952|0|
|
||||
| declarations::parse |22664|22664|0|
|
||||
| syntax::binding |2520|2520|0|
|
||||
| syntax::prefix |11720|11720|0|
|
||||
| syntax::continue_task |13416|13416|0|
|
||||
| Exact::parse_decimal |2296|2296|0|
|
||||
| Exact::parse_literal |952|952|0|
|
||||
| Budget::exact |632|632|0|
|
||||
| Cursor::exact_literal |776|776|0|
|
||||
|
||||
The changed selected reservations sum to2,048 bytes. This is not the complete
|
||||
call-chain size, native stack headroom or all live compiler temporaries. The
|
||||
prefix and continuation phases are alternatives: do not add both to binding.
|
||||
The previously repaired binding/prefix sum remains14,240 for those two entries.
|
||||
|
||||
Projection is a separate phase after Parser::unit returns. The old mixed
|
||||
with_text projector reserved616 bytes; the new direct with_producers mixed
|
||||
specialization reserves1,032 (+416). The ordinary nonmixed with_text body was584;
|
||||
its new forwarding wrapper80 plus producer body1,000 gives1,080 selected bytes
|
||||
(+496 across that chain). Existing outer edit_positions_from_tokens remains72.
|
||||
Specialized Positions::token/value/fields remain120/536/216 respectively; new
|
||||
quota consume reserves120. The injected-quota test has its own1,000-byte
|
||||
specialization. Closure ordinals change with source and are not semantic IDs.
|
||||
|
||||
Baseline projector observations were captured from the actual97 executable
|
||||
before this build overwrote it; they belong to this checkpoint's evidence, not
|
||||
the previously frozen text-producer archive. Existing baseline parser/active
|
||||
observations are copied unchanged. Raw symbol/address/output records and the
|
||||
three inspect helpers are included in the evidence archive.
|
||||
|
||||
The actual full294 run completes265 passed/16 inherited failed. All ten existing
|
||||
stack-named controls pass; no stack allowance, existing test or limit is relaxed.
|
||||
New entry cases use the ordinary test harness stack, not a separately promised
|
||||
128KiB strong-mode pipeline. Earlier source checkpoints' extra fresh-process
|
||||
repetitions and historical setup overflows retain their own scopes. No new
|
||||
debugger run, repeated process loop, complete headroom proof or universal
|
||||
stack-safety claim is made here.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Independent entry-producer test review
|
||||
|
||||
Reviewed six functions in `crates/oa-core/src/language/analysis_source/mixed/carried/entry_producer.rs` against the accepted entry contract and independently authored ENTRY-ORACLE.md. Current reviewed test SHA256 `67839578b8969ed22a749445f41af057223126ad68f504018aeed7021636fc66`. Baseline production97a8703; implementation is locally pending. No compiler, parser, binary or debugger executed by this reviewer. Compilation/runtime acceptance remains with the parent.
|
||||
|
||||
Disposition: no remaining test blocker in these reviewed bytes after correcting the evaluator's extra inventory-walk scratch demand. Final formatting or source/test changes require rebinding the hash before this becomes final.
|
||||
|
||||
## Concrete pre-execution correction
|
||||
|
||||
Initial test SHA256 `e134d5f162ae5036a1a76a4db6075aaad1324543169ecbf1e3786dd7c91f1b1b` called `project::text_producer_inventory(...).unwrap()` on syntax with fully occupied entry caps29,37 and103. That helper invokes `accounting::syntax`, whose `Walk::push` reserves its existing scratch entry (`mixed/project/accounting.rs:118–123`). It would refuse after C+U+M already equaled the cap, even though the intended syntax producer check succeeded. This was an evaluator phase conflation, not evidence against the authored syntax caps.
|
||||
|
||||
Implementer corrected the tests: exact29/37/103 syntax controls remain, asserting literal C+U+M; the independent existing inventory runs on a separate same-source roomy4096 fixture and still must equal29/37/103 after scratch release. The original cap-minus-one and prefix refusals were not weakened. E/H have no position/AST work and their exact-cap inventory checks remain valid.
|
||||
|
||||
## Oracle comparison
|
||||
|
||||
| Test family | Independent assessment |
|
||||
| --- | --- |
|
||||
| E and H syntax/resolve | C/U/M tuples1/1/11 and3/3/19, syntax13/12 and25/24, resolver17/16 and29/28 match the oracle. Syntax refusal pathsmain/part0..1 are distinguished from resolvermain11..73. Successful transfers retain C once and unchanged Usage/numeric work. |
|
||||
| Owner/value timing | Prefix4 at75..76 and7 at149..150 match literal grammar positions. Complete syntax positives29/37 are separate; next-integer prefix completion is not falsely claimed. Direct reserve/mutate helper tests check unchanged actual map/Vec on new-entry refusal. |
|
||||
| Nested syntax-only | Literal344-byte source matches the authored body: U13, M89,49tokens, three owners `[None,Some(0),None]`, three envelopes, element/node actual header lengths5/4 while both reserve7. Exact103/102 limits and six value spans145..221,153..218,154..156,158..201,203..217,210..214 match. No full Project admission is claimed for arbitrary payload/top-level node. |
|
||||
| Quota and helper controls |29 underflow/31 leftover surround authored projection30. They are explicitly injected invariants, not alternate valid source inventories. Existing-key replacement consumes no new M, new-key/owner refusals preserve collections. Overflow, sticky error, atomic initial install and syntax-work precedence are separately checked. |
|
||||
| OA/SA and compatibility | Supported oa_property/sa_property grammar provides complete resolution parity versus text-only for actual owner and explicit borrowed C0. Compares whole Project/warnings/storage, Usage/numeric/T/M and original source. Old legacy11 versus new C0 combined12 and old phase/text-only owner refusal locations remain distinct. |
|
||||
|
||||
Byte policy4096 avoids the previously observed grammar UUID/text peaks and source-byte prechecks; other policies remain the same inherited fixture profile. The nested fixture's arbitrary ordinary payload is correctly limited to syntax evidence. Calls to the existing inventory walk are independent reconciliation, not production-output-derived expected numbers; expected totals are literal authored constants. Whole-Project equality against text-only is a parity control, not an independently authored new semantic model oracle; existing prior complete-model tests retain that role.
|
||||
|
||||
Test access is within the carried descendant module, using ancestor-private state/helpers and existing language functions. I found no obvious privacy/type-shape blocker by inspection; that is not a compilation result.
|
||||
|
||||
## Source-adjacent qualification
|
||||
|
||||
Reported to parent: State::value_end initially calls reserve_metadata only for a new key. A replacement after an already latched failure could therefore bypass Budget.active and mutate/return Ok. The actual parser propagates the first Err immediately, so this is not a demonstrated successful-witness escape. Parent/source reviewer owns whether the accepted latch contract requires active checking before replacement; the initial tests follow a failed map reservation with an owner reservation and do not cover that replacement path. Any repair/test addition should be reviewed and hash-bound below.
|
||||
|
||||
No tests were edited by this reviewer. This review establishes consistency of finite evaluators, not execution success, complete storage-domain closure or accepted-output authority.
|
||||
|
||||
## Final frozen rebind
|
||||
|
||||
Final formatted test SHA256 `6d37e6976d9d164e70a9947de2d6655b57bd7ff6a5cf0fb5a0eb1dcbbb4417f7` supersedes the intermediate67839578 hash above. Independently reread the bounded delta: value_end now calls reserve_metadata with delta0 for an existing key before mutation, and the test attempts replacement10..99 after the earlier new-key20 refusal. It requires original offset20/message, unchanged map10→12 and unchanged M2. This resolves the source-adjacent qualification without changing real fixture caps or expected inventories. Parent/implementer source mixed.rs pin is `6db2e6cc414becd32d80868653651e31de3036a6d8bf63a2c7b0c055ca7cc314`.
|
||||
|
||||
No remaining pre-execution test blocker in the final frozen bytes; ready for parent's compiler/runtime gates. Earlier hashes and corrections remain recorded rather than being relabeled runtime failures.
|
||||
|
||||
## Actual first compile refusal and test-only repair
|
||||
|
||||
Parent's first focused build at a629ae01 failed before any test ran: E0277 at entry_producer.rs:241, because Result::unwrap_err requires Debug on its success value, and the projected EditDeclaration vector does not implement it. My preceding static review did not detect this trait-bound issue; it was not a compilation guarantee. Preserve the original log/receipt and do not report that candidate's focused tests as passed.
|
||||
|
||||
Independently reviewed the exact test delta at `29417130c71f70c4eaefe8ed4c879efba78eb72c`: replaces only this unwrap_err with explicit `Err(error) => error` and `Ok(_) => panic!("injected projection quota must refuse")`. Both quota29/31 refusal assertions and all expected diagnostics remain unchanged. Production code is unchanged; the other modified file is the implementation note. Final current test SHA256 is `ebdcd69eae66103a7ed596356e5f629099399d944b5659ace54edc9f558e7bc9`. No compiler or binary was executed by this reviewer; parent owns subsequent gates.
|
||||
Binary file not shown.
@@ -0,0 +1,203 @@
|
||||
"""Read-only entry producer gate reconciliation. Run only after the final five gates.
|
||||
|
||||
Usage: python -I -B inspect_runtime.py FULL_SOURCE_SHA PIN7 EXPECTED_NEW_COUNT
|
||||
Only Git read commands are executed; Cargo, launchers and binaries are never run.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
if sys.flags.optimize:
|
||||
raise SystemExit('Optimized Python forbidden: verification uses assertions')
|
||||
assert len(sys.argv) == 4
|
||||
source, stem, expected_added = sys.argv[1], sys.argv[2], int(sys.argv[3])
|
||||
assert re.fullmatch(r'[0-9a-f]{40}', source)
|
||||
assert stem == source[:7]
|
||||
assert 1 <= expected_added <= 100
|
||||
base = Path(__file__).resolve().parents[2]
|
||||
root = base / '.local/as3batch'
|
||||
directory = base / '.local/analysis-entry-producer-gates-20260925'
|
||||
prior = base / '.local/analysis-text-producer-gates-20260925'
|
||||
destination = Path(__file__).with_name('ENTRY-PRODUCER-RUNTIME-READBACK.json')
|
||||
assert not destination.exists(), 'Preserve prior readback; do not overwrite'
|
||||
BASELINE = '97a8703adc75467a7f8e75f5c6cb00ca542b707c'
|
||||
ARCHIVE_SHA = '252ea94e7c7f500a2afb3d0fa47c43a051f39d9c844328337289eea0c463becd'
|
||||
sha = lambda raw: hashlib.sha256(raw).hexdigest()
|
||||
|
||||
|
||||
def git(*args):
|
||||
return subprocess.check_output(['git', '--no-replace-objects', *args], cwd=root)
|
||||
|
||||
|
||||
def within(folder, relative):
|
||||
candidate = (folder / relative).resolve()
|
||||
assert candidate.is_relative_to(folder.resolve()), relative
|
||||
return candidate
|
||||
|
||||
|
||||
def receipt(folder, name):
|
||||
raw_receipt = (folder / (name + '.result.json')).read_bytes()
|
||||
data = json.loads(raw_receipt)
|
||||
raw = (folder / (name + '.log')).read_bytes()
|
||||
assert data['log_sha256'] == sha(raw)
|
||||
return data, raw, raw_receipt
|
||||
|
||||
|
||||
def outcomes(raw):
|
||||
rows = re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)\r?$', raw.decode(), re.M)
|
||||
assert len(rows) == len(dict(rows)), 'Duplicate runtime name'
|
||||
return rows
|
||||
|
||||
|
||||
def members(raw):
|
||||
names = re.findall(r'^([^\r\n]+): test\r?$', raw.decode(), re.M)
|
||||
assert len(names) == len(set(names)), 'Duplicate listing name'
|
||||
return names
|
||||
|
||||
|
||||
def failure_blocks(raw):
|
||||
# Preserve every byte of block whitespace/body except the numeric thread PID.
|
||||
rows = re.findall(rb'^---- ([^\r\n]+) stdout ----\r?\n(.*?)(?=^---- |^failures:|\Z)',
|
||||
raw, re.M | re.S)
|
||||
assert len(rows) == len(dict(rows)), 'Duplicate failure block'
|
||||
return {name.decode(): re.sub(rb"(?m)^(thread '[^\r\n]*') \(\d+\) panicked",
|
||||
rb'\1 (<PID>) panicked', body) for name, body in rows}
|
||||
|
||||
|
||||
# Anchor baseline local full/list/fmt logs AND receipts to the immutable locally committed ZIP (server publication is blocked).
|
||||
archive_raw = (base / 'harness/experiments/analysis-text-producer-20260925/evidence.zip').read_bytes()
|
||||
assert sha(archive_raw) == ARCHIVE_SHA
|
||||
baseline = {}
|
||||
with zipfile.ZipFile(io.BytesIO(archive_raw)) as archive:
|
||||
names = archive.namelist()
|
||||
assert len(names) == len(set(names))
|
||||
for mode in ('full', 'list', 'fmt'):
|
||||
name = f'text-producer-{mode}-97a8703-1'
|
||||
data, raw, raw_receipt = receipt(prior, name)
|
||||
assert data['source'] == data['head_after'] == BASELINE
|
||||
for suffix, content in [('.log', raw), ('.result.json', raw_receipt)]:
|
||||
matches = [n for n in names if n == name + suffix or n.endswith('/' + name + suffix)]
|
||||
assert len(matches) == 1, (name, suffix, matches)
|
||||
assert archive.read(matches[0]) == content
|
||||
baseline[mode] = (data, raw)
|
||||
old, old_raw = baseline['full']
|
||||
old_rows = outcomes(old_raw)
|
||||
assert old_rows == [tuple(x) for x in old['outcomes']]
|
||||
assert len(old_rows) == 275 and old['exit'] == 101
|
||||
assert sum(v == 'ok' for _, v in old_rows) == 259
|
||||
assert sum(v == 'FAILED' for _, v in old_rows) == 16
|
||||
old_out = dict(old_rows)
|
||||
old_listing = members(baseline['list'][1])
|
||||
assert old_listing == baseline['list'][0]['listing_members']
|
||||
assert baseline['list'][0]['exit'] == 0 and set(old_listing) == set(old_out)
|
||||
assert baseline['fmt'][0]['exit'] == 1
|
||||
|
||||
assert git('rev-parse', 'HEAD').decode().strip() == source
|
||||
assert not git('status', '--porcelain', '--untracked-files=no').strip()
|
||||
scope = ['Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', '.cargo', 'build', 'crates',
|
||||
'assets', 'docs', 'examples', 'harness/fixtures', 'vendor']
|
||||
paths = git('ls-tree', '-r', '--name-only', source, *scope).decode().splitlines()
|
||||
blobs = subprocess.check_output(['git', '--no-replace-objects', 'cat-file', '--batch'], cwd=root,
|
||||
input=''.join(f'{source}:{p}\n' for p in paths).encode())
|
||||
offset, expected_inputs = 0, []
|
||||
for path in paths:
|
||||
end = blobs.index(b'\n', offset)
|
||||
_, kind, count = blobs[offset:end].split()
|
||||
count = int(count)
|
||||
raw = blobs[end + 1:end + 1 + count]
|
||||
assert kind == b'blob' and within(root, path).read_bytes() == raw, path
|
||||
expected_inputs.append({'path': path, 'bytes': count, 'sha256': sha(raw)})
|
||||
offset = end + count + 2
|
||||
assert offset == len(blobs)
|
||||
|
||||
prefix = ['cargo', 'test', '--locked', '--offline', '-p', 'oa-core', '--lib']
|
||||
commands = {
|
||||
'focused': prefix + ['entry_producer', '--', '--test-threads=1'],
|
||||
'full': prefix + ['--', '--test-threads=1'],
|
||||
'list': prefix + ['--', '--list'],
|
||||
'clippy': ['cargo', 'clippy', '--locked', '--offline', '-p', 'oa-core', '--all-targets', '--', '-D', 'warnings'],
|
||||
'fmt': ['cargo', 'fmt', '--all', '--', '--check'],
|
||||
}
|
||||
expected_env = baseline['full'][0]['environment']
|
||||
assert expected_env['CARGO_BUILD_JOBS'] == '1' and expected_env['CARGO_INCREMENTAL'] == '0'
|
||||
for key in ('RUSTFLAGS', 'RUSTC', 'RUSTUP_TOOLCHAIN', 'ARCADIA_CODEC_LIFECYCLE_PHASE', 'RUST_MIN_STACK'):
|
||||
assert expected_env[key] is None
|
||||
verified, all_receipts, raw_logs = {}, {}, {}
|
||||
artifact_identity = launcher_identity = None
|
||||
for mode, command in commands.items():
|
||||
name = f'entry-{mode}-{stem}-1'
|
||||
data, raw, receipt_raw = receipt(directory, name)
|
||||
assert data['source'] == data['head_after'] == source
|
||||
assert data['mode'] == mode and data['command'] == command
|
||||
assert data['invocation'] == 'cargo' and data['test_target'] is None
|
||||
assert data['filter'] == ('entry_producer' if mode == 'focused' else '')
|
||||
assert not data['changed_inputs'] and not data['verification_failures']
|
||||
assert data['cwd'] == str(root) and data['environment'] == expected_env
|
||||
manifest_raw = within(directory, data['inputs']).read_bytes()
|
||||
assert sha(manifest_raw) == data['inputs_sha256']
|
||||
assert json.loads(manifest_raw) == {'source': source, 'inputs': expected_inputs}
|
||||
launcher = within(directory, data['launcher_copy']).read_bytes()
|
||||
assert sha(launcher) == data['launcher_sha256'] == data['launcher_sha256_after']
|
||||
assert source.encode() in launcher
|
||||
if launcher_identity is None:
|
||||
launcher_identity = sha(launcher)
|
||||
assert sha(launcher) == launcher_identity, 'Unexpected mixed launchers: review explicitly'
|
||||
rows = outcomes(raw)
|
||||
assert rows == [tuple(x) for x in data['outcomes']]
|
||||
listing = members(raw) if mode == 'list' else []
|
||||
assert listing == data['listing_members'] and len(listing) == data['listing_count']
|
||||
if mode in ('focused', 'full'):
|
||||
counts = tuple(sum(v == state for _, v in rows) for state in ('ok', 'FAILED', 'ignored'))
|
||||
summary = re.findall(r'^test result: (ok|FAILED)\. (\d+) passed; (\d+) failed; (\d+) ignored; 0 measured; (\d+) filtered out;', raw.decode(), re.M)
|
||||
assert len(summary) == 1 and tuple(map(int, summary[0][1:4])) == counts
|
||||
assert summary[0][0] == ('FAILED' if counts[1] else 'ok')
|
||||
assert int(summary[0][4]) == (275 if mode == 'focused' else 0)
|
||||
else:
|
||||
assert not rows
|
||||
assert data['exit'] == {'focused': 0, 'full': 101, 'list': 0, 'clippy': 0, 'fmt': 1}[mode]
|
||||
assert len(data['artifacts']) == (1 if mode in ('focused', 'full', 'list') else 0)
|
||||
for artifact in data['artifacts']:
|
||||
path = Path(artifact['path'])
|
||||
assert path.resolve().is_relative_to(Path(expected_env['CARGO_TARGET_DIR']).resolve())
|
||||
actual = path.read_bytes()
|
||||
assert len(actual) == artifact['bytes'] and sha(actual) == artifact['sha256']
|
||||
assert str(path).replace('\\', '/') in raw.decode().replace('\\', '/')
|
||||
if artifact_identity is None:
|
||||
artifact_identity = artifact
|
||||
assert artifact == artifact_identity, 'Test/list artifact mismatch'
|
||||
all_receipts[mode], raw_logs[mode] = data, raw
|
||||
verified[name] = {'source': source, 'exit': data['exit'], 'outcomes': len(rows),
|
||||
'listing': len(listing), 'log_sha256': sha(raw), 'result_sha256': sha(receipt_raw),
|
||||
'inputs_sha256': sha(manifest_raw), 'launcher_sha256': sha(launcher)}
|
||||
|
||||
new_out = dict(all_receipts['full']['outcomes'])
|
||||
assert len(new_out) == 275 + expected_added
|
||||
assert all(new_out.get(k) == v for k, v in old_out.items())
|
||||
added = set(new_out) - set(old_out)
|
||||
assert len(added) == expected_added
|
||||
assert all(new_out[k] == 'ok' and 'entry_producer' in k for k in added)
|
||||
assert set(dict(all_receipts['focused']['outcomes'])) == added
|
||||
assert all(status == 'ok' for _, status in all_receipts['focused']['outcomes'])
|
||||
assert set(all_receipts['list']['listing_members']) == set(new_out)
|
||||
old_blocks, new_blocks = failure_blocks(old_raw), failure_blocks(raw_logs['full'])
|
||||
assert len(old_blocks) == len(new_blocks) == 16
|
||||
assert set(old_blocks) == {k for k, v in old_out.items() if v == 'FAILED'}
|
||||
assert old_blocks == new_blocks, 'Failure bodies differ beyond thread PID'
|
||||
assert raw_logs['fmt'] == baseline['fmt'][1]
|
||||
|
||||
result = {'source': source, 'baseline': BASELINE, 'baseline_archive_sha256': ARCHIVE_SHA,
|
||||
'checker_sha256': sha(Path(__file__).read_bytes()), 'inputs': len(expected_inputs),
|
||||
'unchanged_old_outcomes': 275, 'added_passed': expected_added, 'added_names': sorted(added),
|
||||
'full_passed': sum(v == 'ok' for v in new_out.values()), 'full_failed': 16,
|
||||
'identical_failure_blocks_after_pid_only_normalization': 16,
|
||||
'identical_fmt_sha256': sha(raw_logs['fmt']), 'artifact': artifact_identity,
|
||||
'environment': expected_env, 'receipts': verified,
|
||||
'scope': 'Committed declared inputs, pinned baseline archive, raw logs and current artifact bytes; no Cargo/executable execution. Launcher semantics require independent source review.'}
|
||||
with destination.open('x', encoding='utf-8', newline='\n') as stream:
|
||||
stream.write(json.dumps(result, indent=2) + '\n')
|
||||
print(json.dumps(result, indent=2))
|
||||
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"source": "29417130c71f70c4eaefe8ed4c879efba78eb72c",
|
||||
"scope": "Private retained entry producer prerequisite; no accepted editing or universal parser allocation guarantee. Full library and formatter retain documented baseline failures.",
|
||||
"archive": {
|
||||
"file": "evidence.zip",
|
||||
"bytes": 434046,
|
||||
"sha256": "19a87583a8dc4c22f35999044de5cac2c2c97b04fb457d2c3df3f6d2c054c865"
|
||||
},
|
||||
"members": {
|
||||
"baseline/launchers/bcd83039653815c485ec18fb8d2a75dfa76a39c6e3debca6f525c35a6e474b3a.py": {
|
||||
"bytes": 7666,
|
||||
"sha256": "bcd83039653815c485ec18fb8d2a75dfa76a39c6e3debca6f525c35a6e474b3a"
|
||||
},
|
||||
"baseline/text-producer-fmt-97a8703-1.inputs.json": {
|
||||
"bytes": 104052,
|
||||
"sha256": "907d453bc94eada74a42e2a3c2056660515102273283cb4867f6ab82c887e52a"
|
||||
},
|
||||
"baseline/text-producer-fmt-97a8703-1.log": {
|
||||
"bytes": 6446,
|
||||
"sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d"
|
||||
},
|
||||
"baseline/text-producer-fmt-97a8703-1.result.json": {
|
||||
"bytes": 1876,
|
||||
"sha256": "f5e40697e7ba4305d4b2b800ac4dda0cd04867e739d127c7bc5469bed370c9ff"
|
||||
},
|
||||
"baseline/text-producer-full-97a8703-1.inputs.json": {
|
||||
"bytes": 104052,
|
||||
"sha256": "907d453bc94eada74a42e2a3c2056660515102273283cb4867f6ab82c887e52a"
|
||||
},
|
||||
"baseline/text-producer-full-97a8703-1.log": {
|
||||
"bytes": 45016,
|
||||
"sha256": "7cd8ac2de3b641e0421f48196be255c6b79706049e814e9f62ca2936794f8f71"
|
||||
},
|
||||
"baseline/text-producer-full-97a8703-1.result.json": {
|
||||
"bytes": 41033,
|
||||
"sha256": "b6c97b253e29e15ba476f10ffbd544906f54ca66ca5feedbab36ef6b68358ca3"
|
||||
},
|
||||
"baseline/text-producer-list-97a8703-1.inputs.json": {
|
||||
"bytes": 104052,
|
||||
"sha256": "907d453bc94eada74a42e2a3c2056660515102273283cb4867f6ab82c887e52a"
|
||||
},
|
||||
"baseline/text-producer-list-97a8703-1.log": {
|
||||
"bytes": 31556,
|
||||
"sha256": "25845198d079fa9f5eef5a6610816310a264fccec99e93aff0a865e03abbe612"
|
||||
},
|
||||
"baseline/text-producer-list-97a8703-1.result.json": {
|
||||
"bytes": 33812,
|
||||
"sha256": "fbafa99392bdedda02c91781f3dd5223a91fe5df38b80f88c186d9dd8066e5cc"
|
||||
},
|
||||
"contracts/ENTRY-CRITIQUE.md": {
|
||||
"bytes": 10271,
|
||||
"sha256": "908582a5e5a1e56bf3dacc9478a0db32a3d179c3aef8821b83f0b5f2927b4ce2"
|
||||
},
|
||||
"contracts/ENTRY-PROPOSAL.md": {
|
||||
"bytes": 12504,
|
||||
"sha256": "c53684331353f7f69b750baf0032361cadd0b591bc9ff1bbe1669ce9dd2b7d56"
|
||||
},
|
||||
"contracts/analysis-entry-producer-contract-20260925.md": {
|
||||
"bytes": 6457,
|
||||
"sha256": "0dd194e155f3ea3b6795601e199c2a63d7edff7644f3a75942801f7329a1751c"
|
||||
},
|
||||
"diagnostics/entry-focused-2941713-1.active-frames.json": {
|
||||
"bytes": 15060,
|
||||
"sha256": "920985da2a4d8f15fed04e8c5677d531c479e8679df0b063b2b12b2c1614317a"
|
||||
},
|
||||
"diagnostics/entry-focused-2941713-1.projector-frames.json": {
|
||||
"bytes": 37226,
|
||||
"sha256": "6580c158c71539e5a6d7299ea029b1fceb0a4a13e60ebb5dc555b7232d3332ee"
|
||||
},
|
||||
"diagnostics/entry-focused-2941713-1.stack-frames.json": {
|
||||
"bytes": 13197,
|
||||
"sha256": "aeb7a50375058828c9e61c12328b2b9ef1714286ec5ea623b6a499d2ec9920ad"
|
||||
},
|
||||
"diagnostics/inspect_projector_frames.py": {
|
||||
"bytes": 1929,
|
||||
"sha256": "ae54298c811294bfbf863ed6db54159c4b176b9115534ba057e461e2d70074f0"
|
||||
},
|
||||
"diagnostics/inspect_repaired_active_frames.py": {
|
||||
"bytes": 2236,
|
||||
"sha256": "684dfbbebe3cf3d5deeefd7792ef4a3c205c166390c171da48acefc8d1ee9428"
|
||||
},
|
||||
"diagnostics/inspect_stack_frames.py": {
|
||||
"bytes": 1889,
|
||||
"sha256": "80372b64f336b73570c1ee790c41646d0d7765e781d3489a4aa682b07515a1a6"
|
||||
},
|
||||
"diagnostics/prior-97a8703.active-frames.json": {
|
||||
"bytes": 15060,
|
||||
"sha256": "f767ef6788981d0198922c651504ef8cf8073c092555466b1cd8c517b9479535"
|
||||
},
|
||||
"diagnostics/prior-97a8703.projector-frames.json": {
|
||||
"bytes": 18345,
|
||||
"sha256": "0c6743aa5f308b98eef423f9bde3389d61e65033cc5ace5aa6db73cdd12770c7"
|
||||
},
|
||||
"diagnostics/prior-97a8703.stack-frames.json": {
|
||||
"bytes": 13087,
|
||||
"sha256": "499c3758551b5c935e69ed4f3447efd9bb35fb50b12cd8ee88a05357d40f33fc"
|
||||
},
|
||||
"diffs/97a8703-to-2941713.patch": {
|
||||
"bytes": 38255,
|
||||
"sha256": "a61fe872e0af041acf95058f2f62e001aeaf41f472f23340a4b6679d20f7b95c"
|
||||
},
|
||||
"diffs/97a8703-to-a629ae0.patch": {
|
||||
"bytes": 37780,
|
||||
"sha256": "c7675ecdb38f5a1053fb2b96bd2747bc9aa9ee3e79924d3524b2ec80b4587706"
|
||||
},
|
||||
"gates/entry-clippy-2941713-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c"
|
||||
},
|
||||
"gates/entry-clippy-2941713-1.log": {
|
||||
"bytes": 165,
|
||||
"sha256": "3f18ecfb5fac754c6660d217d1f87752ee99a321fff525a6113ff7deb6ee2baa"
|
||||
},
|
||||
"gates/entry-clippy-2941713-1.result.json": {
|
||||
"bytes": 1966,
|
||||
"sha256": "edb45b1706f09e89ab2f0584a9708ab7e808e7f1048bde2b1439c4f0d49d439d"
|
||||
},
|
||||
"gates/entry-fmt-2941713-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c"
|
||||
},
|
||||
"gates/entry-fmt-2941713-1.log": {
|
||||
"bytes": 6446,
|
||||
"sha256": "c1c6b12861c8117ce6ffc6d6742ebf92618aafb10160ec6f99d370ca72ebab2d"
|
||||
},
|
||||
"gates/entry-fmt-2941713-1.result.json": {
|
||||
"bytes": 1879,
|
||||
"sha256": "a7f1c7ec70ec4a6872dc8a387d1a8c5b3b424f125d21a59a6320b3c2ac17c772"
|
||||
},
|
||||
"gates/entry-focused-2941713-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c"
|
||||
},
|
||||
"gates/entry-focused-2941713-1.log": {
|
||||
"bytes": 1205,
|
||||
"sha256": "fb1cb5d33b724c54687c56439b01fcf4d1c7a393dd08d9cd789702625acdad06"
|
||||
},
|
||||
"gates/entry-focused-2941713-1.result.json": {
|
||||
"bytes": 3158,
|
||||
"sha256": "f8b1ad7859ae58f7b9cc618a22e603a922bb1d4ab4c73b84525c4267ea30a88b"
|
||||
},
|
||||
"gates/entry-focused-a629ae0-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "8b5b416955d7f79db3ee08edcbce69d1c96d688bfefcf6760b2ca2dabf2fd3d9"
|
||||
},
|
||||
"gates/entry-focused-a629ae0-1.log": {
|
||||
"bytes": 1371,
|
||||
"sha256": "cfd534fb67405666ba7a86aa3aa3164655d803b00d4e80f09893d1e312c2a58a"
|
||||
},
|
||||
"gates/entry-focused-a629ae0-1.result.json": {
|
||||
"bytes": 1994,
|
||||
"sha256": "0490608967cc91ac5e666453304a657a01743508d3d98aa9b3e469482b3629f0"
|
||||
},
|
||||
"gates/entry-full-2941713-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c"
|
||||
},
|
||||
"gates/entry-full-2941713-1.log": {
|
||||
"bytes": 45776,
|
||||
"sha256": "47fef6f46d136be0e53f48f8ff03a96be73635fc4c3f57350c1e641ad44b01c4"
|
||||
},
|
||||
"gates/entry-full-2941713-1.result.json": {
|
||||
"bytes": 41913,
|
||||
"sha256": "0bbf4cc28d8832e0cdc4e674296db0b71c7da38a0ac1e3c7ecf34e9d19ab6a62"
|
||||
},
|
||||
"gates/entry-list-2941713-1.inputs.json": {
|
||||
"bytes": 104264,
|
||||
"sha256": "3453c4b85aa27e79fa602e491e333ddeb42914228bb6e3dda8efbabbbe14f02c"
|
||||
},
|
||||
"gates/entry-list-2941713-1.log": {
|
||||
"bytes": 32280,
|
||||
"sha256": "4552e8512731a2fb3dbaba02b671c32837018298b5d8b52057af7fa372f2f50e"
|
||||
},
|
||||
"gates/entry-list-2941713-1.result.json": {
|
||||
"bytes": 34534,
|
||||
"sha256": "5374aea8aba0790bcfb6fa4dee179a4c5ddc0df2efd602e876acbc8c84ae59d1"
|
||||
},
|
||||
"gates/launchers/43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc.py": {
|
||||
"bytes": 7668,
|
||||
"sha256": "43a25f27b417cc66f81ec1714c57eb079a9923995bdadbe79440b00836ac73fc"
|
||||
},
|
||||
"gates/launchers/43b11fbe0074912211e9cc7b6741035912384ed333e7dfa0179e88dadf24f937.py": {
|
||||
"bytes": 7668,
|
||||
"sha256": "43b11fbe0074912211e9cc7b6741035912384ed333e7dfa0179e88dadf24f937"
|
||||
},
|
||||
"launchers/package_evidence.py": {
|
||||
"bytes": 4724,
|
||||
"sha256": "f87452e0d21298b5d45676fb0152183729f0738944955a848a41bc9bb97eb39b"
|
||||
},
|
||||
"notes/prior-toolchain.txt": {
|
||||
"bytes": 536,
|
||||
"sha256": "1f101518dd1f90bc2cba8d26570a762832aba6debebbbe6aa50f97a944590610"
|
||||
},
|
||||
"reviews/ENTRY-ORACLE.md": {
|
||||
"bytes": 8131,
|
||||
"sha256": "8b5d8193d3c63fe418834a90083abe05f43ed59567adcb1b149c1825231dc109"
|
||||
},
|
||||
"reviews/ENTRY-PRODUCER-RUNTIME-READBACK.json": {
|
||||
"bytes": 4939,
|
||||
"sha256": "f45c86d42a1d89c4cf2b22342f2c41dcd4514622f0bd2367101f219367d1c66c"
|
||||
},
|
||||
"reviews/RUNTIME-REVIEW.md": {
|
||||
"bytes": 6191,
|
||||
"sha256": "e200443119c92f3b6f04b19d07fc0fddaeab8cbe905841686b29e47aa374200a"
|
||||
},
|
||||
"reviews/SOURCE-REVIEW.md": {
|
||||
"bytes": 10097,
|
||||
"sha256": "1a6629537b2e916a2275101f4d307079bde80b9dded5a237f6b160ccdcacbc13"
|
||||
},
|
||||
"reviews/STACK-OBSERVATIONS.md": {
|
||||
"bytes": 3129,
|
||||
"sha256": "1d844aa9859f0b74a9bcb996a8268ba4587585faf6578058fccc0d6decd836a6"
|
||||
},
|
||||
"reviews/TEST-REVIEW.md": {
|
||||
"bytes": 6944,
|
||||
"sha256": "5f2ead8da18940e2378017800be4f88ec6f9beed0e0e885e6f14e49a89bee000"
|
||||
},
|
||||
"reviews/inspect_runtime.py": {
|
||||
"bytes": 10444,
|
||||
"sha256": "792b2eff0a9288a73bad9495b05ca06927ca0717a176dce5913206ffa9731080"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
*.md -text
|
||||
*.py -text
|
||||
*.txt -text
|
||||
*.json -text
|
||||
*.log -text
|
||||
@@ -0,0 +1,31 @@
|
||||
# Mixed CLI launcher review
|
||||
|
||||
Read-only review; neither launcher, Cargo nor an application was executed. Compared the new helpers directly with the previously audited public-read launchers and inspected the complete affected gate setup/receipt paths.
|
||||
|
||||
Reviewed unpinned gate `.local/run-analysis-mixed-cli-gate-20260925.py` SHA256 `512dcc82ecb57fa60104d7332ea1cb9798ce1f4919cac6a4e2568d674f3abf1a`; ordinary CLI helper `.local/run-analysis-mixed-cli-ordinary-20260925.py` SHA256 `a8ae7e9c4cb15a87720e364772c3239eef1fe6f4753b1f74b1f9e5482c7bcdad`.
|
||||
|
||||
No actionable orchestration issue found in these deltas. New `mixed_source_files` targets oa-core, while `mixed_cli` and `source_cli` target oa-cli. Integration list/run receipts retain exact same-source input/artifact/name-set comparisons and all-passed summary checks. Strict all-target Clippy selects both packages. Existing core, ordinary integration, doctest, format and CLI-build commands remain recognizable and scoped. Complete Git/raw input capture already includes both crates. Full pre/post nonignored cleanliness and raw artifact/log binding remain present.
|
||||
|
||||
The doctest reconciliation is deliberately restricted to the two existing exact CheckedMixed source paths/line36 and line50 with Rustdoc's ` - compile fail` suffix. Raw names remain in outcomes; the mapping is recorded separately. It cannot collapse duplicate mapped names, waive a failed status or accept a mismatched inventory. Source-line movement or a new differently spelled example will fail closed and require inspection. Successful group summaries still must account for the exact nonzero listed names. This is the previously established spelling repair, not a generic result normalization.
|
||||
|
||||
The ordinary CLI helper's only differences are output folder and receipt/stem names. Its actual literals, report/byte oracles, arguments, source/build/input/environment validation and subprocess behavior are unchanged. This review does not cover the forthcoming separate mixed executable fixture helper.
|
||||
|
||||
Before execution, replace the gate's `PENDING_REVIEWED_MIXED_CLI_SOURCE` with the independently reviewed committed source and bind that exact final helper hash. The current pending marker intentionally prevents a run against the worktree. Parent owns execution; final runtime reconciliation must inspect actual process exits, all expected gate records and raw outcomes rather than treating this source review as a pass.
|
||||
|
||||
## Actual mixed executable helper
|
||||
|
||||
Read `.local/run-analysis-mixed-cli-behavior-20260925.py`, SHA256 `78b612d631175032c7a7819105e03262e21630a1139be62ae78bbe9b5d387a7b`, without executing it. No blocker found. It validates the captured successful build receipt, log/input hashes, actual binary bytes and matching environment; then invokes actual `check-mixed` for valid JSON, unresolved JSON and valid human output. Three authored files form a real nested include chain with CRLF/Unicode, scoped repeated parameter UUIDs and a misleading commented include. It checks exact input file bytes and complete relative file/directory inventory around every command, while preserving raw streams and per-command receipts.
|
||||
|
||||
The expected unresolved report independently computes the byte span of the alias `missing`, excluding `@`, and source-character line/column. This agrees with the existing Cursor::name span and lower.rs unknown-global-reference branch. It compares the whole Report and exact exit/stderr, not only status; valid human output has an independently fixed complete byte string. Successful model equality and substantial OA/SA coverage are explicitly assigned to integration tests rather than invented report fields.
|
||||
|
||||
This helper covers its three declared commands, not every CLI failure or platform case. New argument/path/journal/UUID tests remain necessary elsewhere. Creation of fixture files is launcher setup, distinct from the command's no-write assertion. Its exclusive fixture/receipt creation intentionally refuses rerunning into existing evidence; any actual failure must be preserved before a revised attempt.
|
||||
|
||||
## Actual dependency omission and final recipe repair
|
||||
|
||||
While preparing runtime reconciliation, found an actual newly exercised source_cli dependency missing from the inherited declaration recipe: `include_str!` loads `harness/experiments/textual-authoring-20260911/alarm-response.arcadia`, outside `harness/fixtures`. The initial f232482 six receipts remain intact with566 declared inputs; do not retrospectively claim the launcher captured that file's raw bytes. Its immutable Git identity can be checked separately.
|
||||
|
||||
Parent added exactly that path and pinned final f10490b13bb3332ff60c2372d554e276f6f44959 before final runs. Reviewed final helper SHA256 `15d3bae6c4235f20a4b5ae523e9cde38842118397bf1accbf5837fb18de356b4`; replacing only the source pin yields template `0349a19e62b9c57231e6ef3abad30643f39d7ed2fa4ac1fcab4b314159a39d52`. Removing only the added path from that template reproduces the original reviewed512dcc82 hash exactly. Final declared inventory is567. No other recorder behavior changed. The independent checker recognizes these exact two recipes and preserves the omission caveat for historical receipts.
|
||||
|
||||
## Evidence packager source review
|
||||
|
||||
Read `.local/package-analysis-mixed-cli-20260925.py`, SHA256 `d98cbd11e29d44d1a9e68b5ddfe7971343766e7e7737adf47bab904d758a333b`, without executing it. No material bug found. It pins the completed readback and source, checks every selected receipt against the reader's receipt hash, requires six initial plus30 final Cargo records and five CLI records, and preserves complete raw gate contents. Human CLI stdout uses the recorded `stdout_file` (.stdout.txt) rather than a forced JSON suffix. Input/launcher/log hashes and566/567 distinction are retained; review mirrors, exact Git diffs/oracles and selected immutable baseline evidence are included. Destination creation is non-overwriting and occurs after required payload collection, followed by CRC/member-byte verification and a per-member manifest. This is a bounded pre-execution packaging review, not a claim that a packet or publication already exists.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
# Mixed CLI independent oracle and gate plan
|
||||
|
||||
Design/source review only; parent owns every compiler/application run. Baseline `bab6f96a5b05b37f2b5d67a430aed0f67d783e73`; selected root contract committed locally at `f810fb40`, SHA256 `69935281eadf9fa82bd8d4f606fed2df758cfe643ef88bd5168ee327453942e1`. No public mixed CLI acceptance is inferred from the preceding public library checkpoint.
|
||||
|
||||
## Independent observable oracles
|
||||
|
||||
- Success fixtures must bind real disk bytes to a complete independently constructed Project via `load_mixed_source` then `check_mixed_bundle`. The CLI report does not contain a model; do not pretend a status assertion establishes model equality. Prefer the same OA/SA literals for model and executable checks, with cross-file typed calls, scoped parameters, ordinary nested records, explicit identities, Unicode/CRLF and misleading include text in comments/strings.
|
||||
- Compare the complete meaningful Report: operation/status/exit, ordered warning/error diagnostics and original spans/line/column/path, changes empty, written false, migration null, identity count zero. Compare stable human output too. The executable must use actual new dispatch, not only a direct helper call.
|
||||
- Snapshot exact relative directory names and every file's raw bytes before/after success, warning, syntax/semantic/path/journal refusal and argument refusal. Diagnostic text should not grant missing-file or partial-bundle success. Explicitly distinguish schema/UUID rejection from ordinary check's existing migration/stabilization behavior.
|
||||
- Internal discovery tests should use real parsed units with test-only tightened caps. Two individually valid files must exceed one shared aggregate cap; repeated targets inspect once while repeated authored edges count. Check retained conservative charges after unit drop, zero temporary balance, unchanged actual policy capture and shared ModelCounts. Cover first latched refusal with an unparsed queued sibling and exact first-file location. No reset/refund or partial-result escape is accepted by these tests.
|
||||
- Exercise caller byte/file/depth/edge boundary and boundary-minus-one, including unlimited caller bytes clamped before read; missing/cyclic includes, invalid UTF-8, reserved/escaping paths, hard-link/case aliases, nonregular files and pending journals. Use positive controls. Windows and Unix-specific cases must be labelled by actual availability, not inferred from source-only test declarations.
|
||||
|
||||
## Proportionate final gates
|
||||
|
||||
1. Normal core integration list/run for the new mixed disk boundary, plus the ten existing `mixed_source8_read` external tests. Test compilation alone does not establish the non-test API path.
|
||||
2. Core full listing/run: preserve all 299 baseline named outcomes and enumerate exact additions. New focused discovery tests must be a declared subset of that list, with no ignored/filtered-away expected controls.
|
||||
3. Existing seven ordinary integration selections (65 Windows outcomes at baseline), particularly all eight Windows `source_files` tests because the shared discovery loop changes. The other three source-file tests are `cfg(unix)`, not missing Windows results. Retain the eleven exact core stack controls and the structural-writeback integration control named in the preceding public-read runtime plan; compare names/outcomes, not an approximate stack-name regex.
|
||||
4. Existing `oa-cli` `source_cli` integration suite (12 authored baseline tests) plus exact newly listed mixed CLI names. Run real built executable mixed success/refusal/usage paths and ordinary check/rename-preview regression. Preserve full commands, output streams, exit codes and directory bytes.
|
||||
5. Existing three public-read doctests, strict all-target core/CLI Clippy, and formatting disposition. Rustdoc's two exact `CheckedMixed ... - compile fail` runtime suffixes require the previously established narrow listing/runtime reconciliation if the recorder still compares literal names. Do not broadly strip arbitrary suffixes or conceal recorder failures. Compare inherited formatting bytes; any changed disposition needs inspection.
|
||||
|
||||
Bind each receipt to reviewed clean source, full declared Git/raw inputs, launcher/hash/argv/environment, raw log, actual artifact provenance and post-run clean state. Preserve initial compilation, test or recorder failures separately. Reuse already-valid evidence only for explicitly unchanged inputs/components; do not assume a new parser helper preserves stack reservations. Static frame observations, if collected, are supplemental to finite exercised worker tests.
|
||||
|
||||
The final source report will record settled file hashes and the actual commit after workers freeze their disjoint changes. Missing gates remain pending rather than inferred passes. No Linux, GUI/editor/save/history integration, atomic disk snapshot or universal stack/allocation guarantee is part of this milestone.
|
||||
|
||||
Frozen candidate readback: `f2324822936374c5b9092518b986375233dc7882`, clean. Exact authored additions are three core unit tests (expected full302), five `mixed_source_files` external tests and six `mixed_cli` integration tests. See SOURCE-REVIEW.md for complete file hashes and committed ancestry. No tests have been executed by this reviewer.
|
||||
@@ -0,0 +1,105 @@
|
||||
# Mixed CLI Windows evidence
|
||||
|
||||
Source `f10490b13bb3332ff60c2372d554e276f6f44959`; baseline `bab6f96a5b05b37f2b5d67a430aed0f67d783e73`.
|
||||
Source is published and ref-verified on `codex/analysis-mixed-cli-956atf-20260925`.
|
||||
The existing integrated Windows prerelease is unchanged.
|
||||
|
||||
`arcadia check-mixed ROOT [--json]` now loads and validates complete explicit-ID
|
||||
source8 projects with ordinary and typed analysis declarations. It preserves
|
||||
input files and original diagnostic locations. This is a developer CLI
|
||||
checkpoint; mixed editing and application integration remain unfinished.
|
||||
|
||||
At this source, Windows checks pass 302 core tests, 98 selected integration
|
||||
tests, three doctests, strict core/CLI Clippy and five direct executable trials.
|
||||
All eleven prior named core stack controls pass. Formatting reports only the
|
||||
same inherited eight differences in five untouched files.
|
||||
|
||||
## Build, run and verify
|
||||
|
||||
Use Rust/Cargo 1.98.1 and a working Windows gnullvm toolchain; this run used
|
||||
LLVM-MinGW 20260908. Set `CARGO_BUILD_JOBS=1` and `CARGO_INCREMENTAL=0`.
|
||||
With the dependencies available locally, run from the source checkout:
|
||||
|
||||
```sh
|
||||
cargo build --locked --offline -p oa-cli --bin arcadia
|
||||
cargo run --locked --offline -p oa-cli --bin arcadia -- check-mixed path/to/main.arcadia --json
|
||||
cargo test --locked --offline -p oa-core --lib -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-core --test mixed_source_files -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-cli --test mixed_cli -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-cli --test source_cli -- --test-threads=1
|
||||
cargo test --locked --offline -p oa-core --doc -- --test-threads=1
|
||||
cargo clippy --locked --offline -p oa-core -p oa-cli --all-targets -- -D warnings
|
||||
```
|
||||
|
||||
The packet's receipts preserve exact commands, filters and inputs for the other
|
||||
integration suites. Its `gates/` fixtures supply the three-file checked and
|
||||
unresolved-reference examples, and `launchers/` preserves the actual CLI byte
|
||||
oracles. See `docs/source-cli.md` at the source commit for report/exit semantics.
|
||||
|
||||
Archive: 1,448,804 bytes, 192 members, SHA256 `00a6cefedb5a921283c1e00c1e2564cda774ffc2c9723a47bd8c09e477240c03`.
|
||||
Runtime readback: [`MIXED-CLI-RUNTIME-READBACK.json`](MIXED-CLI-RUNTIME-READBACK.json), SHA256 `1b02b0eb3870cbc4074542467ef527acb7b13e9956674115484ebc82d3a5d97b`.
|
||||
Read [RUNTIME-REVIEW.md](RUNTIME-REVIEW.md) for reconciled outcomes and limitations; this packager only preserves data.
|
||||
|
||||
The packet retains all six initial f232482 Cargo receipts, thirty final Cargo receipts, and five actual CLI invocations (ordinary JSON check/rename, mixed valid/invalid JSON and human output).
|
||||
Initial source_cli completed ten passes and two stale schema-target expectation failures; mixed_cli passed six with an import-shadowing warning. Initial manifests omitted the alarm fixture. Those records are preserved unchanged; the final 567-input manifest includes that exact fixture.
|
||||
The final successor to f232482 corrects only those test expectations/import and records their history. Source patches and the original alarm fixture are included.
|
||||
The inherited formatting refusal remains raw evidence. The final doctest recorder
|
||||
passes with the two exact compile-fail name mappings documented by the prior
|
||||
public-read checkpoint; it does not apply generic name normalization.
|
||||
|
||||
No mixed editing/save/history, GUI, universal depth128, atomic filesystem snapshot or Linux qualification is claimed.
|
||||
Discovery and complete validation use separate bounded passes; logical producer accounting is not an all-heap bound.
|
||||
|
||||
## Cargo receipt index
|
||||
|
||||
| Receipt | Source | Exit | Recorded verification refusals |
|
||||
| --- | --- | ---: | ---: |
|
||||
| `mixed-cli-cli-build-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-clippy-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-doc-list-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-doc-suite-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-fmt-f10490b-1.result.json` | `f10490b` | 1 | 0 |
|
||||
| `mixed-cli-focused-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-full-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-mixed_cli-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-mixed_cli-f232482-1.result.json` | `f232482` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-mixed_source8_read-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-mixed_source_files-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-mixed_source_files-f232482-1.result.json` | `f232482` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-r3_migration-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-review_regressions-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source7_contract-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_cli-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_cli-f232482-1.result.json` | `f232482` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_files-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_identity_updates-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_nested_updates-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-list-source_project-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-mixed_cli-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-mixed_cli-f232482-1.result.json` | `f232482` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-mixed_source8_read-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-mixed_source_files-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-mixed_source_files-f232482-1.result.json` | `f232482` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-r3_migration-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-review_regressions-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source7_contract-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source_cli-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source_cli-f232482-1.result.json` | `f232482` | 101 | 2 |
|
||||
| `mixed-cli-integration-suite-source_files-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source_identity_updates-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source_nested_updates-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-integration-suite-source_project-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
| `mixed-cli-list-f10490b-1.result.json` | `f10490b` | 0 | 0 |
|
||||
|
||||
## Actual CLI receipt index
|
||||
|
||||
| Receipt | Source | Exit |
|
||||
| --- | --- | ---: |
|
||||
| `mixed-cli-actual-unresolved-json-f10490b-1.cli.json` | `f10490b` | 1 |
|
||||
| `mixed-cli-actual-valid-human-f10490b-1.cli.json` | `f10490b` | 0 |
|
||||
| `mixed-cli-actual-valid-json-f10490b-1.cli.json` | `f10490b` | 0 |
|
||||
| `mixed-cli-ordinary-check-f10490b-1.cli.json` | `f10490b` | 0 |
|
||||
| `mixed-cli-ordinary-rename-alias-f10490b-1.cli.json` | `f10490b` | 0 |
|
||||
|
||||
Exact member lengths, SHA256 values and local/Git origins are in [manifest.json](manifest.json). Review mirrors are byte-identical to archived `reviews/` members. No executables or prior archive copies are included.
|
||||
The baseline archive is referenced by SHA256 `1c20b7bffdaee9b1139b0e922d4366f6ac739f8567040e8f4723dc19e3974656`; selected logs/receipts and ordinary CLI fixture bytes are copied directly from it.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Mixed CLI runtime reconciliation plan
|
||||
|
||||
Parent owns Cargo, executable runs and the eventual checker invocation. `inspect_runtime.py` is data-only: raw JSON/log/ZIP/file reads plus read-only Git commands. It must not execute archived helpers, compiler or product binaries and refuses overwriting its final readback. Do not invoke before final gates are complete.
|
||||
|
||||
Baseline: public-read source bab6f96a5b05b37f2b5d67a430aed0f67d783e73, immutable archive SHA256 1c20b7bffdaee9b1139b0e922d4366f6ac739f8567040e8f4723dc19e3974656. It proves299 core outcomes,10 public-read external tests,65 selected ordinary integration results and three doctest passes (with the preserved narrow historical recorder spelling exception). Existing source_cli's12 names come from baseline source only: this checkpoint newly executes that suite, so no prior passing-runtime claim is made for it.
|
||||
|
||||
Require exact full302 names/outcomes: all299 baseline plus the three authored mixed_discovery names. Require focused mixed_discovery exactly3. Eleven integration list/run pairs: new mixed_source_files5, mixed_source8_read10, seven ordinary selections65, source_cli12 and mixed_cli6. Compare names, raw outcomes and artifacts, not totals alone. Require three docs and the exact two existing compile-fail name mappings; current recorder must succeed. Require core+CLI strict Clippy, inherited fmt bytes, actual CLI build, ordinary check/rename-preview2 and mixed validJSON/unresolvedJSON/validhuman3 against that same built binary.
|
||||
|
||||
The final checker verifies each declared input against immutable Git and current raw bytes, launcher template/source pin, environment, command/filter/package, receipt/raw log/hash, artifact origin/current bytes and source cleanliness. Preserve historical receipts separately without treating their overwritten binaries as current. The reviewed executable helpers are a8ae7e9c4cb15a87720e364772c3239eef1fe6f4753b1f74b1f9e5482c7bcdad (ordinary) and78b612d631175032c7a7819105e03262e21630a1139be62ae78bbe9b5d387a7b (mixed). The mixed helper's UTF-8 string literals may be read using AST literal evaluation; neither helper is imported or executed by the checker. Reconstruct expected whole reports from authored inputs and preserve exact files/directories/streams.
|
||||
|
||||
Initial f232482 source evidence must remain: six integration receipts, mixed_source_files5/5 and mixed_cli6/6, plus mixed_cli Command glob-shadow warning and source_cli10/12 with only complete_alarm_example_preview_then_write_and_fixed_point and rename_shows_missing_identity_and_separate_source_migration failing. The corrected tests retain full-text/model/fixed-point oracles and align only historical header expectations to current schema8. Record final exact repair/source hash; do not normalize the initial failures into passes.
|
||||
|
||||
The initial recorder recipe omitted source_cli's actual include_str dependency harness/experiments/textual-authoring-20260911/alarm-response.arcadia. Parent added exactly this input and pinned final f10490b13bb3332ff60c2372d554e276f6f44959. Final helper SHA25615d3bae6c4235f20a4b5ae523e9cde38842118397bf1accbf5837fb18de356b4, normalized template0349a19e62b9c57231e6ef3abad30643f39d7ed2fa4ac1fcab4b314159a39d52, declares567 inputs. Preserve original512dcc82-template receipts with566 declarations; any separate historical Git-blob confirmation is not a retroactive raw-input capture.
|
||||
|
||||
## Exact old stack controls
|
||||
|
||||
The baseline299 inventory contains eleven named core stack controls. Require each actual final outcome to pass:
|
||||
|
||||
- `language::analysis_source::index::tests::deep_parse_index_plan_and_failed_build_cleanup_on_128k_stack`
|
||||
- `language::analysis_source::index::tests::maximum_index_paths_compare_lookup_debug_and_drop_on_128k_stack`
|
||||
- `language::analysis_source::mixed::project::ordinary_index::rename::emission::acceptance::tests::scoped_small_stack_actual_deep_wide_verification_and_drop`
|
||||
- `language::analysis_source::mixed::project::ordinary_index::rename::emission::tests::scoped_small_stack_changed_unchanged_and_failure_drop`
|
||||
- `language::analysis_source::mixed::project::ordinary_index::rename::tests::deep_and_wide_equality_and_late_refusal_drop_on_small_stack`
|
||||
- `language::analysis_source::mixed::project::ordinary_index::tests::small_stack_success_and_late_header_failure_leave_no_partial_owner`
|
||||
- `language::analysis_source::mixed::project::tests::index_tests::success_and_late_failure_drop_on_small_stack`
|
||||
- `language::analysis_source::mixed::project::tests::inherited_storage_failure_and_success_drop_deep_syntax_on_128k_stack`
|
||||
- `language::analysis_source::mixed::tests::mixed_deep_typed_success_and_rejection_cleanup_on_128k_stack`
|
||||
- `language::analysis_source::tests::every_parent_shape_rejects_depth129_and_cleans_children_on_128k_stack`
|
||||
- `language::nesting_tests::deep_declaration_parsing_and_positions_use_a_bounded_rust_stack`
|
||||
|
||||
Also require `deep_structural_writeback_runs_on_a_small_thread_stack` in actual source_nested_updates integration results. These establish their finite exercised scopes; no universal stack headroom, setup-stack qualification or Linux/depth128 claim follows. Any parent-captured static frame evidence is supplemental and bound to its actual binary, not substituted for worker execution.
|
||||
|
||||
No Linux, GUI/edit/save/history adoption, atomic snapshot or universal stack/RSS claim follows. Missing records remain incomplete gates; preserve evaluator problems before correcting them. Parent decides acceptance after independent readback.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user