From 8efd931a0bdb97a1bc15fb12eccda28ac5e5e9e6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 12 Jul 2026 23:28:45 +0100 Subject: [PATCH] Make typed Modeling finding closure authority --- epiphany-core/src/bin/epiphany-work.rs | 244 +++--------------- ...onceptual-substitution-audit-2026-07-12.md | 11 + notes/fresh-workspace-handoff.md | 3 + state/ledgers.msgpack | Bin 445205 -> 445596 bytes state/map.yaml | 2 +- 5 files changed, 56 insertions(+), 204 deletions(-) diff --git a/epiphany-core/src/bin/epiphany-work.rs b/epiphany-core/src/bin/epiphany-work.rs index b524a770..bb9beb54 100644 --- a/epiphany-core/src/bin/epiphany-work.rs +++ b/epiphany-core/src/bin/epiphany-work.rs @@ -27,12 +27,10 @@ use epiphany_core::MindGatewayDecision; use epiphany_core::MindGatewayReview; use epiphany_core::PersonaMemoryCacheConfig; use epiphany_core::REPO_WORK_MAP_ENTRY_SCHEMA_VERSION; -use epiphany_core::REPO_WORK_MODELING_FINDING_SCHEMA_VERSION; use epiphany_core::REPO_WORK_MODELING_OUTPUT_CONTRACT_ID; use epiphany_core::REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION; use epiphany_core::REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION; use epiphany_core::RepoWorkMapEntry; -use epiphany_core::RepoWorkModelingFinding; use epiphany_core::RepoWorkModelingRequest; use epiphany_core::RepoWorkModelingRoute; use epiphany_core::RuntimeSpineHeartbeatJobOptions; @@ -281,12 +279,7 @@ struct CloseArgs { artifact_dir: Option, verification_command: Option, verification_summary: Option, - modeling_summary: Option, - closure_model_ref: Option, - closure_model_verdict: Option, - closure_model_finding: Option, require_source_grounding: bool, - model_authored: bool, state_revision: u64, } @@ -850,12 +843,7 @@ fn parse_close_args(args: impl Iterator) -> Result { let mut artifact_dir = None; let mut verification_command = None; let mut verification_summary = None; - let mut modeling_summary = None; - let mut closure_model_ref = None; - let mut closure_model_verdict = None; - let mut closure_model_finding = None; let mut require_source_grounding = false; - let mut model_authored = false; let mut state_revision = 0_u64; let mut args = args.peekable(); @@ -874,20 +862,7 @@ fn parse_close_args(args: impl Iterator) -> Result { "--verification-summary" => { verification_summary = Some(take_string(&mut args, "--verification-summary")?); } - "--modeling-summary" => { - modeling_summary = Some(take_string(&mut args, "--modeling-summary")?); - } - "--closure-model-ref" | "--model-ref" => { - closure_model_ref = Some(take_string(&mut args, "--closure-model-ref")?); - } - "--closure-model-verdict" | "--model-verdict" => { - closure_model_verdict = Some(take_string(&mut args, "--closure-model-verdict")?); - } - "--closure-model-finding" | "--model-finding" => { - closure_model_finding = Some(take_string(&mut args, "--closure-model-finding")?); - } "--require-source-grounding" => require_source_grounding = true, - "--model-authored" => model_authored = true, "--state-revision" => state_revision = take_u64(&mut args, "--state-revision")?, other => return Err(anyhow!("unexpected close argument {other:?}")), } @@ -900,12 +875,7 @@ fn parse_close_args(args: impl Iterator) -> Result { artifact_dir, verification_command, verification_summary, - modeling_summary, - closure_model_ref, - closure_model_verdict, - closure_model_finding, require_source_grounding, - model_authored, state_revision, }) } @@ -9772,82 +9742,6 @@ fn short_commit(commit_sha: &str) -> String { commit_sha.chars().take(12).collect::() } -fn closure_model_review( - model_authored: bool, - model_ref: Option<&str>, - verdict: Option<&str>, - finding: Option<&str>, -) -> Result<(Value, bool)> { - let normalized_verdict = verdict - .map(|value| value.trim().to_ascii_lowercase()) - .filter(|value| !value.is_empty()); - if let Some(verdict) = normalized_verdict.as_deref() { - match verdict { - "passed" | "failed" | "needs-work" | "blocked" => {} - other => { - return Err(anyhow!( - "unsupported closure model verdict {other:?}; expected passed, failed, needs-work, or blocked" - )); - } - } - } - - let has_typed_modeling_finding = model_authored - && model_ref.is_some_and(|value| !value.trim().is_empty()) - && finding.is_some_and(|value| !value.trim().is_empty()); - let gate_enforced = true; - let passed = match normalized_verdict.as_deref() { - Some("passed") => has_typed_modeling_finding, - Some("failed" | "needs-work" | "blocked") => false, - Some(_) => unreachable!(), - None => false, - }; - let status = match normalized_verdict.as_deref() { - Some("passed") if has_typed_modeling_finding => "passed", - Some("passed") => "missing-modeling-finding", - Some("failed" | "needs-work" | "blocked") => "failed", - Some(_) => unreachable!(), - None => "missing-required-verdict", - }; - let reason = match status { - "passed" => "model-authored closure verdict passed", - "failed" => "model-authored closure verdict refused closure", - "missing-required-verdict" => { - "closure required a model-authored verdict but none was supplied" - } - "missing-modeling-finding" => { - "a passing verdict lacked explicit model authorship, model reference, or finding" - } - _ => "model-authored Modeling finding refused closure", - }; - - Ok(( - json!({ - "schemaVersion": "epiphany.repo_work_model_closure_review.v0", - "status": status, - "passed": passed, - "required": true, - "gateEnforced": gate_enforced, - "modelAuthored": model_authored, - "typedFindingPresent": has_typed_modeling_finding, - "modelRef": model_ref, - "verdict": normalized_verdict, - "finding": finding.map(compact_line), - "reason": reason, - "reviewedInputs": [ - "Hands commit receipt matched execute receipt", - "Verification command result", - "Declared versus actual git changed paths", - "Safe-family committed-content assertions", - "Authority seal and private-state exposure flag" - ], - "operatorAuthoredShellDetails": false, - "privateStateExposed": false - }), - passed, - )) -} - fn closure_verification_source_grounding_review( declared_changed_paths: &[String], verification_stdout: &[u8], @@ -11140,13 +11034,15 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { closure_family_assertions(&workspace, &commit_sha, &execute_receipt, &item)?; let (mind_adoption_review, mind_adoption_passed) = closure_mind_adoption_review(&execute_receipt)?; - let closure_model_authored = args.model_authored || args.closure_model_ref.is_some(); - let (model_closure_review, model_closure_passed) = closure_model_review( - closure_model_authored, - args.closure_model_ref.as_deref(), - args.closure_model_verdict.as_deref(), - args.closure_model_finding.as_deref(), - )?; + let model_closure_review = json!({ + "schemaVersion": "epiphany.repo_work_model_closure_review.v0", + "status": "deferred-to-typed-modeling", + "passed": false, + "required": true, + "source": "runtime-spine Modeling finding", + "callerEchoAccepted": false, + "privateStateExposed": false + }); let closure_review_id = format!("repo-work-close-{item_slug}-closure-review"); let closure_review_path = artifact_dir.join(format!("work-close-{item_slug}-review.json")); let closure_review = json!({ @@ -11182,17 +11078,19 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { "sourceGroundingRequired": args.require_source_grounding, "mindAdoptionPassed": mind_adoption_passed, "familyAssertionsPassed": family_assertions_passed, - "modelClosurePassed": model_closure_passed + "modelClosurePassed": false }, "verificationSourceGrounding": verification_source_grounding, "mindAdoptionReview": mind_adoption_review, "familyAssertions": family_assertions, "modelingReview": { - "modelAuthored": closure_model_authored, - "modelRef": args.closure_model_ref.clone(), - "deterministicFallback": !closure_model_authored, + "modelAuthored": false, + "modelRef": Value::Null, + "deterministicFallback": false, + "source": "runtime-spine Modeling finding", + "callerEchoAccepted": false, "operatorAuthoredShellDetails": false, - "summary": args.modeling_summary.clone(), + "summary": "Modeling truth is resolved from the runtime-spine finding, not caller text.", "closureReview": model_closure_review }, "authoritySeal": { @@ -11343,12 +11241,6 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { })); } - let modeling_summary = args.modeling_summary.unwrap_or_else(|| { - format!( - "Modeling records repo work item {item} changed [{}] at commit {commit_sha}; scheduler should stop implementation until publication review.", - declared_changed_paths.join(", ") - ) - }); let modeling_route_id = format!("repo-work-modeling-route-{item_slug}"); let (modeling_request, modeling_route) = if phase == ClosurePhase::Full { let route = runtime_repo_work_modeling_route(&runtime_store, &modeling_route_id)? @@ -11404,7 +11296,7 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { let route = commit_initial_repo_work_modeling_route(&runtime_store, &request, &route)?; (request, route) }; - if phase == ClosurePhase::SoulOnly || !model_closure_passed { + if phase == ClosurePhase::SoulOnly { let awaiting_receipt = json!({ "schemaVersion": "epiphany.repo_work_closure_receipt.v0", "createdAt": now, @@ -11443,54 +11335,14 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { return Ok(awaiting_receipt); } let modeling_finding_receipt_id = format!("{}-finding", modeling_request.request_id); - let mut modeling_finding = RepoWorkModelingFinding { - schema_version: REPO_WORK_MODELING_FINDING_SCHEMA_VERSION.to_string(), - receipt_id: modeling_finding_receipt_id.clone(), - item: item.clone(), - model_ref: args - .closure_model_ref - .clone() - .expect("passed Modeling gate requires model ref"), - soul_verdict_receipt_id: soul_verdict.receipt_id.clone(), - verdict: args - .closure_model_verdict - .clone() - .expect("passed Modeling gate requires verdict"), - finding: args - .closure_model_finding - .clone() - .expect("passed Modeling gate requires finding"), - summary: modeling_summary, - changed_paths: declared_changed_paths.clone(), - commit_sha: commit_sha.clone(), - emitted_at: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true), - private_state_exposed: false, - contract: "Modeling interpretation of Soul-verified repo consequence; Mind must reread this typed receipt before map admission.".to_string(), - request_id: modeling_request.request_id.clone(), - }; - if let Some(existing) = + let modeling_finding = runtime_repo_work_modeling_finding(&runtime_store, &modeling_finding_receipt_id)? - { - if existing.item != modeling_finding.item - || existing.model_ref != modeling_finding.model_ref - || existing.soul_verdict_receipt_id != modeling_finding.soul_verdict_receipt_id - || existing.verdict != modeling_finding.verdict - || existing.finding != modeling_finding.finding - || existing.summary != modeling_finding.summary - || existing.changed_paths != modeling_finding.changed_paths - || existing.commit_sha != modeling_finding.commit_sha - || existing.request_id != modeling_finding.request_id - { - return Err(anyhow!( - "closure retry conflicts with immutable Modeling finding" - )); - } - modeling_finding = existing; - } else { - return Err(anyhow!( - "closure cannot author a Modeling finding; route the typed request through the Modeling runtime first" - )); - } + .ok_or_else(|| { + anyhow!( + "closure requires the persisted Modeling finding {}; caller-authored echoes are not accepted", + modeling_finding_receipt_id + ) + })?; if modeling_finding.soul_verdict_receipt_id != soul_verdict.receipt_id || modeling_finding.commit_sha != commit_sha || modeling_finding.changed_paths != declared_changed_paths @@ -11615,8 +11467,8 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { "summary": modeling_finding.summary, "changedPaths": execute_receipt["changedPaths"], "commitSha": execute_receipt["handsReceipts"]["commitSha"], - "source": "epiphany.repo_work_closure_review.v0", - "modelAuthored": closure_model_authored + "source": "runtime-spine Modeling finding", + "modelAuthored": true }, "mind": { "gatewayReviewId": mind_review.gateway_id, @@ -14016,12 +13868,7 @@ fn run_tick(args: TickArgs) -> Result { artifact_dir: Some(artifact_dir.clone()), verification_command: None, verification_summary: None, - modeling_summary: Some(finding.summary.clone()), - closure_model_ref: Some(finding.model_ref.clone()), - closure_model_verdict: Some(finding.verdict.clone()), - closure_model_finding: Some(finding.finding.clone()), require_source_grounding: false, - model_authored: true, state_revision: 0, })?; status = advanced_result["status"] @@ -14129,12 +13976,7 @@ fn run_tick(args: TickArgs) -> Result { artifact_dir: Some(artifact_dir.clone()), verification_command: None, verification_summary: None, - modeling_summary: None, - closure_model_ref: None, - closure_model_verdict: None, - closure_model_finding: None, require_source_grounding: false, - model_authored: false, state_revision: 0, })?; status = advanced_result @@ -15514,27 +15356,23 @@ fn default_if_empty(values: Vec, defaults: Vec) -> Vec { #[cfg(test)] mod authority_tests { use super::*; + use epiphany_core::REPO_WORK_MODELING_FINDING_SCHEMA_VERSION; + use epiphany_core::RepoWorkModelingFinding; use epiphany_core::put_repo_work_modeling_finding; #[test] - fn modeling_finding_is_mandatory_for_closure_admission() -> Result<()> { - let (_, missing) = closure_model_review(false, None, None, None)?; - assert!(!missing); - - let (counterfeit, passed) = - closure_model_review(true, Some("modeling-job-1"), Some("passed"), None)?; - assert!(!passed); - assert_eq!(counterfeit["status"], "missing-modeling-finding"); - - let (review, passed) = closure_model_review( - true, - Some("modeling-job-1"), - Some("passed"), - Some("Modeling grounded the map update in Soul-verified consequence."), - )?; - assert!(passed); - assert_eq!(review["status"], "passed"); - assert_eq!(review["typedFindingPresent"], true); + fn close_rejects_caller_authored_modeling_echoes() -> Result<()> { + for flag in [ + "--closure-model-ref", + "--closure-model-verdict", + "--closure-model-finding", + "--model-authored", + "--modeling-summary", + ] { + let error = parse_close_args([flag.to_string(), "counterfeit".to_string()].into_iter()) + .expect_err("legacy Modeling echo must be refused"); + assert!(error.to_string().contains("unexpected close argument")); + } Ok(()) } @@ -16370,7 +16208,7 @@ fn print_usage() { run --workspace [--item ] [--accept-receipt ] [--runtime-store ] [--requested-path ]\n\ adopt --workspace [--item ] [--run-receipt ] [--from-plan ] [--plan-summary ] [--adoption-evidence-ref ] [--mind-adoption-rationale ]\n\ execute --workspace [--item ] [--from-plan ] [--command ] [--changed-path ] [--commit-message ]\n\ - close --workspace [--item ] [--execute-receipt ] [--verification-command ] --closure-model-ref --model-authored --closure-model-verdict passed|failed|needs-work|blocked --closure-model-finding [--require-source-grounding]\n\ + close --workspace [--item ] [--execute-receipt ] [--verification-command ] [--require-source-grounding]\n\ overview --workspace [--item ] [--accept-receipt ] [--no-write]\n\ readiness --workspace [--item ] [--accept-receipt ] [--public-proof ] [--idunn-lifecycle-receipt ] [--deployment-aftercare-audit-receipt |--deployment-aftercare-audit-receipt-ref ] [--tool-directory-receipt ] [--no-write]\n\ deployment-config-audit --workspace [--artifact-dir ] [--no-write]\n\ diff --git a/notes/conceptual-substitution-audit-2026-07-12.md b/notes/conceptual-substitution-audit-2026-07-12.md index 07e2b9e6..fddd544a 100644 --- a/notes/conceptual-substitution-audit-2026-07-12.md +++ b/notes/conceptual-substitution-audit-2026-07-12.md @@ -370,3 +370,14 @@ acceptance and metrics closure, and Imagination consensus. No production owner called them; their remaining uses were unit fixtures. All sixteen constructor/ writer exports are now `cfg(test)`. Types, validation exercised by tests, and production readers remain available for genuine provider-authored ingest. + +## Caller echo as Modeling truth + +Repo closure already had a typed Modeling request/finding route, but the +`close` CLI also required callers to repeat model ref, verdict, finding prose, +authorship, and summary flags. Closure reviewed that echo before rereading the +persisted finding, while the scheduler quietly copied the real finding into +the caller fields. The echo fields, review helper, scheduler transcription, +and usage surface are deleted. Full closure now loads the current immutable +Modeling finding directly and refuses absence; caller text cannot stand in for +the Modeling organ even temporarily. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index a5170e27..f84a38df 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -91,6 +91,9 @@ The confirmed conceptual substitutions have been cut: Eve/daemon-tool acceptance, Bifrost publication/GitHub/public-proof/artifact/ metrics results, and Imagination consensus constructors/writers are `cfg(test)`; production retains their typed readers for real ingest. +- repo closure no longer accepts caller echoes of Modeling model ref, verdict, + finding, authorship, or summary. The scheduler no longer transcribes them. + Full closure reads the immutable runtime-spine Modeling finding directly. The presentation boundary is now plain: `swarm overview` is a generic compact read-only projection. Gjallar is a downstream TUI application on Nightwing and is not an Epiphany organ, provider, owner, runtime, or architectural dependency. Eve/CultUI graphs may be lowered or composited downstream without Epiphany caring which presentation client does it. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index fa59d7ec56fec82e96b91dbb75770c569cc30ee9..26f0553ef9ec5dd0ed3311829da7ec534f4da0c7 100644 GIT binary patch delta 417 zcmXv~OG*Pl6ttse;m)OG^Th2;6iFcH8Qh2TPxdGNZ&b|xpI(bd;R|F?ZVU^B+{@0Y!YWsecMbCa+| z*#21d`gh+?w?F+|HhFscWP`;YyF5qZ<|sjMtw64EHUR znpfcz%B1yr0_AcUAl3-Vm=t-T5qz>y8O%eYEUsgrq@+$KlJ{sM#I~VQ9%l(d1a3QC zra(P-5zq?y{RO}F6-JU_qneuAHotLx3S)@m2^k!Zk3g$peWeBEg|a{!5>x82$_z>- R%nO&S>`JWOpy445{{jD+m7f3r delta 56 zcmbO;Q+nz&=?#*MTt-%=W>Lo&*iL@htjt)*$f(dfm8pFy6C)6VXl5X00bNr GP5=M})e-0b diff --git a/state/map.yaml b/state/map.yaml index d8da073a..54af5d07 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -660,4 +660,4 @@ current_status: - Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass. - `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure. last_completed_repo_swarm_cut: Huginn live-fire has crossed the first real repo Body from Persona pressure to branch-local Hands commit and Soul/Mind closure, and now has repeatable closure and redacted-public-proof mouths. On `E:\Projects\Huginn` branch `epiphany/huginn/first-awakening`, `tools/epiphany_local_run.ps1 -Mode repo-persona-intake` accepted item `huginn-inspection-readback-livefire`, Weksa/Persona intake remained sealed, and `epiphany-work derive-plan` lowered it to model-authored safe family `repo.status_section` for `README.md` only. `tools/epiphany_local_run.ps1 -Mode repo-swarm-run` advanced four bounded pulses: run-from-plan, adopt-from-plan, execute-from-plan, and close-from-execute. Huginn commit `e9b07c38fceabbdc89ea35c2156326c80c0393a2` updated only `README.md`; closure receipt `.epiphany\work\work-close-huginn-inspection-readback-livefire.json` records status `closed`, Soul verdict `passed`, Mind state commit `repo-work-close-huginn-inspection-readback-livefire-mind-commit`, safe family `repo.status_section`, path scope `README.md`, Bifrost publication gate, and `privateStateExposed=false`. Verification also ran Huginn's TypeScript compiler through concrete Node path: `C:\Program Files\nodejs\node.exe E:\Projects\Huginn\node_modules\typescript\bin\tsc -p tsconfig.json` passed. Native verifier `epiphany-repo-livefire-closure-smoke --workspace E:\Projects\Huginn --item huginn-inspection-readback-livefire --expected-path README.md --expected-family repo.status_section --expected-gate awaiting-publication --expected-blocker bifrost-publication-missing` checks closure receipt, Mind map entry, overview gate/blocker, authority seals, and `git show` changed paths, returning `status=ok`, `soulVerdict=passed`, `publicationGate=Bifrost`, and `privateStateExposed=false`. Wrapper `tools/epiphany_local_run.ps1 -Mode repo-livefire-closure -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exposes the same read-only proof through the local operator mouth; artifact `local-20260621-190156-803-2f85ba15` printed commit, path, gate, blocker, Soul verdict, Mind commit receipt, and `privateStateExposed=False` without push, merge, publication, or target mutation. New wrapper `tools/epiphany_local_run.ps1 -Mode repo-work-public-proof -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exports the redacted proof bundle and repo-local Verse index without publishing; artifact `local-20260621-190645-345-4555b1dc` wrote `.epiphany\public\proof-bundles\repo-work-public-proof-huginn-inspection-readback-livefire.json`, proof id `repo-work-public-proof-huginn-inspection-readback-livefire`, SHA-256 `857545b199f3e37eb06c2e757e5cfc201958e46667bb1f8403fd333a22620f63`, nine artifact rows, zero publication rows, and `privateStateExposed=False`. swarm overview readback `local-20260621-190701-140-b9519ec6` sees the `REPO-WORK-PUBLIC-PROOF` row and action row from Huginn's repo-local Verse with the same SHA-256 while Bifrost publication remains missing. Launcher compact modes are now named compact operator-context modes instead of read-only modes, and `bifrost-public-proof` summaries print item, target public Verse, room, proof SHA-256, review receipts, and credit receipts so publication receipts are auditable without claiming upstream sync. - next_action: Continue the conceptual-substitution modeling pass beyond receipt writers. Fresh-repo proof, publication/sync commands and readers, caller-transcribed Hands PR proof, and sixteen ownerless provider-result library actuators are removed from production authority; typed readers remain for genuine ingest. Audit remaining public receipt writers by named owner, especially Mind/Soul/Substrate/Hands runtime writers and daemon lifecycle paths, then inventory projections, caches, adapters, schedulers, coordinators, and compatibility surfaces that assert facts owned elsewhere. + next_action: Continue the conceptual-substitution modeling pass beyond receipt writers. Publication/PR/provider result authority is sealed, and repo closure now reads immutable Modeling findings directly instead of caller/scheduler echoes. Audit remaining public receipt writers by named owner, especially Mind/Soul/Substrate/Hands runtime writers and daemon lifecycle paths, then inventory projections, caches, adapters, schedulers, coordinators, and compatibility surfaces that assert facts owned elsewhere.