feat(engine, cli): op-script doc slot -- the vocabulary grows the C29 meaning line

Iteration 3 completion (tasks 5-6): the construction vocabulary gains
the slot its own #125 scope-cut comment anticipated. Op::Doc { text }
is the op-script twin of the builder's .doc(...) -- a closed, typed
metadata construct (C25, no logic content); at most one per script, a
second refuses via OpError::DuplicateDoc (the existing duplicate-fault
family), rendered "a doc op may appear at most once". GraphSession
threads the text through Composite::with_doc at finish, so op-built
composites pass the C29 store gate like builder-built ones.

The op-script register test runs on the described variant
(SIGNAL_DOC_DESCRIBED) for both shapes; the doc-less script now pins
the C29 refusal, and the E2E phase added the RestatesName op-script
case. Full gates: cargo test --workspace green (98 suites, 0 failed);
clippy -D warnings clean.

refs #316
This commit is contained in:
2026-07-23 20:33:00 +02:00
parent 593e233e66
commit 7126886b81
3 changed files with 152 additions and 7 deletions
+6
View File
@@ -54,6 +54,9 @@ enum OpDoc {
as_name: String,
into: Vec<String>,
},
/// Declare the composite's one-line meaning (C29, #316) — the op-script
/// twin of the builder's `.doc(...)`.
Doc { text: String },
}
impl OpDoc {
@@ -68,6 +71,7 @@ impl OpDoc {
OpDoc::Expose { .. } => "expose",
OpDoc::Tap { .. } => "tap",
OpDoc::Gang { .. } => "gang",
OpDoc::Doc { .. } => "doc",
}
}
}
@@ -85,6 +89,7 @@ impl From<OpDoc> for Op {
OpDoc::Expose { from, as_name } => Op::Expose { from, as_name },
OpDoc::Tap { from, as_name } => Op::Tap { from, as_name },
OpDoc::Gang { as_name, into } => Op::Gang { as_name, into },
OpDoc::Doc { text } => Op::Doc { text },
}
}
}
@@ -129,6 +134,7 @@ fn format_op_error(e: &OpError) -> String {
}
OpError::GangArity { gang } => format!("gang `{gang}`: needs at least two members"),
OpError::Incomplete(ce) => format!("{ce:?}"),
OpError::DuplicateDoc => "a doc op may appear at most once".to_string(),
}
}