Type scheduling closure authority

This commit is contained in:
Meta Vens 2026-07-13 03:33:53 +01:00
commit 0b6d6d1032
7 changed files with 173 additions and 31 deletions

View file

@ -7396,74 +7396,63 @@ fn closure_family_assertions(
);
}
"repo.scheduling_request" => {
let request = parse_repo_scheduling_request(&content).ok();
push_assertion(
&mut assertions,
"scheduling-request-schema-present",
content.contains("schema_version = \"epiphany.repo_scheduling_request.v0\""),
request
.as_ref()
.is_some_and(RepoSchedulingRequest::has_canonical_identity),
"Committed scheduling request carries the schema version.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-family-present",
content.contains("safe_action_family = \"repo.scheduling_request\""),
request
.as_ref()
.is_some_and(RepoSchedulingRequest::has_canonical_identity),
"Committed scheduling request carries the safe action family.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-summary-present",
content.contains(&compact_summary),
request
.as_ref()
.is_some_and(|value| value.summary == compact_summary),
"Committed scheduling request contains the accepted pressure summary.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-awaits-mind-adoption",
content.contains("[request]")
&& content.contains("status = \"awaiting-mind-adoption\"")
&& content.contains("requested_scheduler = \"Self\"")
&& content.contains("mind_adoption_receipt_required = true")
&& content.contains("self_may_schedule_after_mind_only = true")
&& content.contains("queue_run_allowed_after_adoption = true"),
request.as_ref().is_some_and(RepoSchedulingRequest::awaits_mind_adoption),
"Committed scheduling request waits for Mind adoption before Self queue consequence.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-queue-contract",
content.contains("[queue]")
&& content.contains("target_gate = \"repo-work-queue\"")
&& content.contains("preferred_next_safe_family = \"repo.task_card\"")
&& content.contains("max_items_per_pulse = 1")
&& content.contains("requires_epiphany_branch = true")
&& content.contains("publish_blocker = \"bifrost-publication-missing\""),
request
.as_ref()
.is_some_and(RepoSchedulingRequest::has_bounded_queue_contract),
"Committed scheduling request names a bounded queue pulse contract.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-receipt-contract",
content.contains("[required_receipts]")
&& content.contains("mind_review = \"epiphany.mind.gateway_review\"")
&& content.contains("mind_commit = \"epiphany.mind.state_commit_receipt\"")
&& content.contains(
"expected_self_receipt = \"epiphany.repo_work_queue_selection.v0\"",
),
request.as_ref().is_some_and(RepoSchedulingRequest::has_receipt_contract),
"Committed scheduling request requires Mind receipts and names the later Self receipt.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-authority-seals",
content.contains("[authority]")
&& content.contains("self_scheduling_authorized = false")
&& content.contains("queue_mutation_authorized = false")
&& content.contains("hands_action_authorized = false")
&& content.contains("publication_authorized = false")
&& content.contains("cross_body_mutation_authorized = false")
&& content.contains("mind_adoption_required = true")
&& content.contains("bifrost_publication_required = true"),
request.as_ref().is_some_and(RepoSchedulingRequest::has_authority_seals),
"Committed scheduling request denies scheduling/queue/action/publication/cross-body authority and requires Mind/Bifrost gates.".to_string(),
);
push_assertion(
&mut assertions,
"scheduling-request-private-seal",
content.contains("private_state_exposed = false"),
request
.as_ref()
.is_some_and(|value| !value.private_state_exposed),
"Committed scheduling request preserves the private-state seal.".to_string(),
);
}
@ -15370,6 +15359,7 @@ idunn_deployment_authority_required = true
"repo.sync_request",
"repo.pr_request",
"repo.maintainer_review_request",
"repo.scheduling_request",
"repo.work_order",
"repo.verification_request",
"repo.credit_request",

View file

@ -111,6 +111,100 @@ pub(super) fn parse_repo_work_order(text: &str) -> Result<RepoWorkOrder> {
toml::from_str(text).context("work order is not valid typed TOML")
}
#[derive(Debug, Deserialize)]
pub(super) struct RepoSchedulingRequest {
pub(super) schema_version: String,
pub(super) safe_action_family: String,
pub(super) summary: String,
pub(super) private_state_exposed: bool,
request: RepoSchedulingBody,
queue: RepoSchedulingQueue,
required_receipts: RepoSchedulingReceipts,
authority: RepoSchedulingAuthority,
}
impl RepoSchedulingRequest {
pub(super) fn has_canonical_identity(&self) -> bool {
self.schema_version == "epiphany.repo_scheduling_request.v0"
&& self.safe_action_family == "repo.scheduling_request"
}
pub(super) fn awaits_mind_adoption(&self) -> bool {
let r = &self.request;
r.status == "awaiting-mind-adoption"
&& r.requested_scheduler == "Self"
&& r.mind_adoption_receipt_required
&& r.self_may_schedule_after_mind_only
&& r.queue_run_allowed_after_adoption
}
pub(super) fn has_bounded_queue_contract(&self) -> bool {
let q = &self.queue;
q.target_gate == "repo-work-queue"
&& q.preferred_next_safe_family == "repo.task_card"
&& q.max_items_per_pulse == 1
&& q.requires_epiphany_branch
&& q.publish_blocker == "bifrost-publication-missing"
}
pub(super) fn has_receipt_contract(&self) -> bool {
let r = &self.required_receipts;
r.mind_review == "epiphany.mind.gateway_review"
&& r.mind_commit == "epiphany.mind.state_commit_receipt"
&& r.expected_self_receipt == "epiphany.repo_work_queue_selection.v0"
}
pub(super) fn has_authority_seals(&self) -> bool {
let a = &self.authority;
a.branch_local_only
&& !a.self_scheduling_authorized
&& !a.queue_mutation_authorized
&& !a.hands_action_authorized
&& !a.publication_authorized
&& !a.cross_body_mutation_authorized
&& a.mind_adoption_required
&& a.bifrost_publication_required
}
}
#[derive(Debug, Deserialize)]
struct RepoSchedulingBody {
status: String,
requested_scheduler: String,
mind_adoption_receipt_required: bool,
self_may_schedule_after_mind_only: bool,
queue_run_allowed_after_adoption: bool,
}
#[derive(Debug, Deserialize)]
struct RepoSchedulingQueue {
target_gate: String,
preferred_next_safe_family: String,
max_items_per_pulse: u64,
requires_epiphany_branch: bool,
publish_blocker: String,
}
#[derive(Debug, Deserialize)]
struct RepoSchedulingReceipts {
mind_review: String,
mind_commit: String,
expected_self_receipt: String,
}
#[derive(Debug, Deserialize)]
struct RepoSchedulingAuthority {
branch_local_only: bool,
self_scheduling_authorized: bool,
queue_mutation_authorized: bool,
hands_action_authorized: bool,
publication_authorized: bool,
cross_body_mutation_authorized: bool,
mind_adoption_required: bool,
bifrost_publication_required: bool,
}
pub(super) fn parse_repo_scheduling_request(text: &str) -> Result<RepoSchedulingRequest> {
toml::from_str(text).context("scheduling request is not valid typed TOML")
}
#[derive(Debug, Deserialize)]
pub(super) struct RepoVerificationRequest {
pub(super) schema_version: String,

View file

@ -2,6 +2,44 @@
mod workflow_tests {
use super::*;
#[test]
fn scheduling_comment_cannot_counterfeit_queue_authority_seal() {
let text = r#"
schema_version = "epiphany.repo_scheduling_request.v0"
safe_action_family = "repo.scheduling_request"
summary = "summary"
private_state_exposed = false
[request]
status = "awaiting-mind-adoption"
requested_scheduler = "Self"
mind_adoption_receipt_required = true
self_may_schedule_after_mind_only = true
queue_run_allowed_after_adoption = true
[queue]
target_gate = "repo-work-queue"
preferred_next_safe_family = "repo.task_card"
max_items_per_pulse = 1
requires_epiphany_branch = true
publish_blocker = "bifrost-publication-missing"
[required_receipts]
mind_review = "epiphany.mind.gateway_review"
mind_commit = "epiphany.mind.state_commit_receipt"
expected_self_receipt = "epiphany.repo_work_queue_selection.v0"
[authority]
branch_local_only = true
self_scheduling_authorized = false
# queue_mutation_authorized = false
queue_mutation_authorized = true
hands_action_authorized = false
publication_authorized = false
cross_body_mutation_authorized = false
mind_adoption_required = true
bifrost_publication_required = true
"#;
let request = parse_repo_scheduling_request(text).expect("fixture is typed TOML");
assert!(!request.has_authority_seals());
}
#[test]
fn work_order_comment_cannot_counterfeit_hands_authority_seal() {
let text = r#"

View file

@ -1041,6 +1041,19 @@ regaining substring authority.
Fourteen high-authority closure families are typed; 507 substring assertions
remain. Adoption and scheduling are the next workflow-shaped candidates.
## Scheduling prose as Self queue authority
Scheduling carried the sharper upstream consequence: it names the Self queue
gate, next safe family, pulse bound, prerequisite Mind receipts, and expected
queue-selection receipt. Closure previously recognized all of that through
substring presence. A commented `queue_mutation_authorized = false` could hide
a real grant. `repo.scheduling_request` now parses typed workflow state, checks
the actual queue and authority fields, and has a malicious fixture plus class
guard preventing that substitution from returning.
Fifteen high-authority closure families are typed; 477 substring assertions
remain. Adoption is the remaining untyped workflow gate in this chain.
The same inspection found 33 consecutive duplicate `#[cfg(test)]` attributes
on provider constructors/writers and their re-exports. One gate already makes
each item test-only; the second owned nothing. The duplicates are removed.

View file

@ -329,6 +329,13 @@ high-authority families are typed and 507 substring assertions remain. Next
inspect adoption versus scheduling and convert the authority-bearing family
with its own negative proof.
Scheduling won that comparison because it directly names Self's queue gate,
pulse, next family, and queue-selection receipt. Its closure is now typed under
workflow ownership; a malicious commented queue denial cannot conceal a real
mutation grant, and the family is in the no-substring class guard. Fifteen
high-authority families are typed and 477 substring assertions remain. Next
type adoption, the remaining untyped workflow gate in this chain.
The latest structural count is 32 closure family branches, 744 remaining
substring assertions in the closure region, and 1,284 lines in
`closure_contracts.rs`. Do not blindly generate a struct forest for every

Binary file not shown.

View file

@ -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 pass. Fourteen high-authority closure families are typed and guarded; 507 substring assertions remain. Workflow owns typed verification and work-order closure plus their counterfeit-authority fixtures. Work-order comments can no longer impersonate Hands authority. Direct rustfmt is required because Cargo fmt misses the lexically included files. Next compare adoption and scheduling closure authority and type the higher-consequence workflow family with a negative proof. External governance should converge on tooling plus publication/accounting; operations retains policy/deployment. Provider chronology is explicitly external and guarded as arrival order. Continue auditing evidence/security mirrors and adapters for borrowed authority.
next_action: Continue the conceptual-substitution pass. Fifteen high-authority closure families are typed and guarded; 477 substring assertions remain. Workflow owns typed verification, work-order, and scheduling closure plus counterfeit-authority fixtures. Scheduling comments can no longer impersonate Self queue authority. Direct rustfmt is required because Cargo fmt misses the lexically included files. Next type adoption, the remaining untyped workflow gate in this chain, with a negative Mind/state-authority proof. External governance should converge on tooling plus publication/accounting; operations retains policy/deployment. Provider chronology is explicitly external and guarded as arrival order. Continue auditing evidence/security mirrors and adapters for borrowed authority.