Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/plans/live-read-witness-classification-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,19 @@ Phases are ordered; each closes at a named consumer tier.

---

## 13. Open sub-threads
## 14. Hand-Rust scaffold receipt (P1 G2 marshal)

**Authority:** `v2.std.fn_index::fn_arrow_skeleton_g2_marshal_host_scaffold_dissolution_trigger`

**Seed-retained site:** `src/v1/stage0/src/coproduct_reflection.rs` — `marshal_string_literal_atom`, `hoist_call_arg_string_literal_edges`, and callee/literal atoms on `marshal_generic` for `ExprCall` nodes. These expand the fn-arrow skeleton corpus-wide so G2 can stat string-literal path arguments and callee chains from `fn_arrow_decl_facts_live()`.

**Dissolution trigger:** fn-arrow body projection becomes a modeled substrate fold (the #5364 self-host corridor for `eval_fn_arrow_decl_facts_live`) emitting equivalent skeleton `Node` facts without hand-Rust marshal expansion in `coproduct_reflection.rs`.

**Witness:** `v2.test.claim.live_read_classification_test::g2_fn_arrow_marshal_host_scaffold_receipt_is_checkable` (Scaffold disposition row is checkable by execution).

---

## 15. Open sub-threads

- **Path pattern static analysis depth** — how many `filesystem_read` path arguments are literal at G2 vs require `Unknown` never-skip.
- **Namespace-only resolution terminal step** — import edges become `container.member` references; carrier registry and G2 must be edge-source-agnostic (same constraint as `dependency_edge_source_migration_note` in `module_graph.dag`).
Expand Down
51 changes: 51 additions & 0 deletions src/v1/stage0/src/coproduct_reflection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,45 @@ fn marshal_skeleton(
}
}

// SCAFFOLD (§7 hand-Rust shrink-to-zero): G2 live-read skeleton marshal expansion
// (`marshal_string_literal_atom`, `hoist_call_arg_string_literal_edges`, callee atoms on
// `ExprCall`) — see `v2.std.fn_index::fn_arrow_skeleton_g2_marshal_host_scaffold_dissolution_trigger`.
// Host SOURCE half for P1 G2 call-reachability (docs/plans/live-read-witness-classification-design.md §9 P1 / §14).
// Dissolves when fn-arrow body projection is a modeled substrate fold (same #5364 corridor as
// `eval_fn_arrow_decl_facts_live`) rather than hand-Rust marshal in this module.
fn marshal_string_literal_atom(
ctx: &InterpContext,
node: &Rc<Node>,
) -> Option<Value> {
match node.expr_data.as_ref() {
ExprData::ExprLiteral { value, .. } => match value.as_ref() {
crate::std_syntax::LiteralValue::LitStr { value: s, .. } => {
Some(edge_positional(ctx, atom_identity_node(ctx, s)))
}
_ => None,
},
_ => None,
}
}

fn hoist_call_arg_string_literal_edges(
ctx: &InterpContext,
node: &Rc<Node>,
edges: &mut Vec<Value>,
) {
if let Some(literal_edge) = marshal_string_literal_atom(ctx, node) {
edges.push(literal_edge);
return;
}
if let Some(child0) = node.children.first() {
if let Some(literal_edge) = marshal_string_literal_atom(ctx, child0) {
edges.push(literal_edge);
} else {
hoist_call_arg_string_literal_edges(ctx, child0, edges);
}
}
}

fn marshal_generic(
ctx: &InterpContext,
node: &Rc<Node>,
Expand All @@ -629,6 +668,13 @@ fn marshal_generic(
let mut refs: std::collections::BTreeSet<String> = std::collections::BTreeSet::new();
if node_references_param(node, &name, param_names) {
edges.push(edge_positional(ctx, atom_identity_node(ctx, &name)));
} else if matches!(node.expr_data.as_ref(), ExprData::ExprCall { .. }) && !name.is_empty() {
// G2 live-read call reachability: callee atoms make cross-fn carrier chains
// visible in the fn-arrow skeleton (docs/plans/live-read-witness-classification-design.md P1).
edges.push(edge_positional(ctx, atom_identity_node(ctx, &name)));
}
if let Some(literal_edge) = marshal_string_literal_atom(ctx, node) {
edges.push(literal_edge);
}
if let Some(ref_name) = node_local_reference_name(node, &name) {
refs.insert(ref_name);
Expand All @@ -638,6 +684,11 @@ fn marshal_generic(
edges.push(edge_positional(ctx, child_skel));
refs.extend(child_refs);
}
if matches!(node.expr_data.as_ref(), ExprData::ExprCall { .. }) {
for child in node.children.iter() {
hoist_call_arg_string_literal_edges(ctx, child, &mut edges);
}
}
if let Some(inner) = node.body.as_ref() {
let (inner_skel, inner_refs) = marshal_skeleton(ctx, inner, param_names, si);
edges.push(edge_positional(ctx, inner_skel));
Expand Down
Loading
Loading