Add typed Modeling request generations
This commit is contained in:
parent
e7d7f2961b
commit
abce2aaf0a
9 changed files with 629 additions and 43 deletions
|
|
@ -33,9 +33,11 @@ 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;
|
||||
use epiphany_core::RuntimeSpineInitOptions;
|
||||
use epiphany_core::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION;
|
||||
|
|
@ -44,8 +46,10 @@ use epiphany_core::SoulVerdictReceipt;
|
|||
use epiphany_core::SubstrateGateRepoAccessGrantReceipt;
|
||||
use epiphany_core::WeksaInterlinguaInput;
|
||||
use epiphany_core::WeksaSpeakerContext;
|
||||
use epiphany_core::advance_repo_work_modeling_route;
|
||||
use epiphany_core::build_weksa_interlingua_packet;
|
||||
use epiphany_core::build_weksa_target_lowering_request;
|
||||
use epiphany_core::commit_initial_repo_work_modeling_route;
|
||||
use epiphany_core::commit_repo_work_map_admission;
|
||||
use epiphany_core::default_launch_organ_contract;
|
||||
use epiphany_core::hands_action_review_for_intent;
|
||||
|
|
@ -74,7 +78,6 @@ use epiphany_core::put_hands_command_receipt;
|
|||
use epiphany_core::put_hands_commit_receipt;
|
||||
use epiphany_core::put_hands_patch_receipt;
|
||||
use epiphany_core::put_hands_pr_receipt;
|
||||
use epiphany_core::put_repo_work_modeling_request;
|
||||
use epiphany_core::put_soul_verdict_receipt;
|
||||
use epiphany_core::put_substrate_gate_repo_access_grant_receipt;
|
||||
use epiphany_core::record_weksa_target_lowering_receipt;
|
||||
|
|
@ -87,6 +90,7 @@ use epiphany_core::runtime_latest_hands_receipt_chain_after;
|
|||
use epiphany_core::runtime_repo_work_map_entry;
|
||||
use epiphany_core::runtime_repo_work_modeling_finding;
|
||||
use epiphany_core::runtime_repo_work_modeling_request;
|
||||
use epiphany_core::runtime_repo_work_modeling_route;
|
||||
use epiphany_core::write_epiphany_cultmesh_repo_work_map_entry;
|
||||
use epiphany_core::write_epiphany_cultmesh_repo_work_overview;
|
||||
use epiphany_core::write_epiphany_cultmesh_repo_work_public_proof;
|
||||
|
|
@ -125,6 +129,9 @@ fn main() -> Result<()> {
|
|||
"execute" | "exec" => run_execute(parse_execute_args(args)?),
|
||||
"verify" | "soul-verify" => run_verify(parse_close_args(args)?),
|
||||
"close" | "closure" | "verify-close" => run_close(parse_close_args(args)?),
|
||||
"revise-modeling" | "modeling-retry" => {
|
||||
run_revise_modeling(parse_revise_modeling_args(args)?)
|
||||
}
|
||||
"publish" => run_publish(parse_publish_args(args)?),
|
||||
"sync" | "sync-main" => run_sync(parse_sync_args(args)?),
|
||||
"overview" | "proof-bundle" | "status" => run_overview(parse_overview_args(args)?),
|
||||
|
|
@ -297,6 +304,15 @@ struct CloseArgs {
|
|||
state_revision: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ReviseModelingArgs {
|
||||
workspace: PathBuf,
|
||||
item: String,
|
||||
runtime_store: Option<PathBuf>,
|
||||
rationale: String,
|
||||
review_ref: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum ClosurePhase {
|
||||
SoulOnly,
|
||||
|
|
@ -958,6 +974,32 @@ fn parse_close_args(args: impl Iterator<Item = String>) -> Result<CloseArgs> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_revise_modeling_args(args: impl Iterator<Item = String>) -> Result<ReviseModelingArgs> {
|
||||
let mut workspace = None;
|
||||
let mut item = None;
|
||||
let mut runtime_store = None;
|
||||
let mut rationale = None;
|
||||
let mut review_ref = None;
|
||||
let mut args = args.peekable();
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"--workspace" => workspace = Some(take_path(&mut args, "--workspace")?),
|
||||
"--item" => item = Some(take_string(&mut args, "--item")?),
|
||||
"--runtime-store" => runtime_store = Some(take_path(&mut args, "--runtime-store")?),
|
||||
"--rationale" => rationale = Some(take_string(&mut args, "--rationale")?),
|
||||
"--review-ref" => review_ref = Some(take_string(&mut args, "--review-ref")?),
|
||||
other => return Err(anyhow!("unexpected revise-modeling argument {other:?}")),
|
||||
}
|
||||
}
|
||||
Ok(ReviseModelingArgs {
|
||||
workspace: workspace.context("missing --workspace")?,
|
||||
item: item.context("missing --item")?,
|
||||
runtime_store,
|
||||
rationale: rationale.context("missing --rationale")?,
|
||||
review_ref: review_ref.context("missing --review-ref")?,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_publish_args(args: impl Iterator<Item = String>) -> Result<PublishArgs> {
|
||||
let mut workspace = None;
|
||||
let mut epiphany_root = None;
|
||||
|
|
@ -11168,6 +11210,118 @@ fn run_verify(args: CloseArgs) -> Result<Value> {
|
|||
run_closure_pipeline(args, ClosurePhase::SoulOnly)
|
||||
}
|
||||
|
||||
fn run_revise_modeling(args: ReviseModelingArgs) -> Result<Value> {
|
||||
let workspace = args
|
||||
.workspace
|
||||
.canonicalize()
|
||||
.with_context(|| format!("failed to resolve {}", args.workspace.display()))?;
|
||||
ensure_git_repo(&workspace)?;
|
||||
let item_slug = sanitize(&args.item);
|
||||
let close_path = work_receipt_path(&workspace, "close", &args.item);
|
||||
let close = read_json(&close_path)?;
|
||||
if close.get("status").and_then(Value::as_str) != Some("awaiting-modeling") {
|
||||
return Err(anyhow!(
|
||||
"revise-modeling requires an awaiting-modeling closure projection"
|
||||
));
|
||||
}
|
||||
let runtime_store = args
|
||||
.runtime_store
|
||||
.or_else(|| path_from_json(&close, &["runtimeStore"]))
|
||||
.ok_or_else(|| anyhow!("awaiting-modeling closure has no runtime store"))?;
|
||||
let route_id = format!("repo-work-modeling-route-{item_slug}");
|
||||
let current = runtime_repo_work_modeling_route(&runtime_store, &route_id)?
|
||||
.ok_or_else(|| anyhow!("typed Modeling route {route_id:?} is missing"))?;
|
||||
let current_request = runtime_repo_work_modeling_request(&runtime_store, ¤t.request_id)?
|
||||
.ok_or_else(|| anyhow!("current Modeling request is missing"))?;
|
||||
let previous_finding_id = format!("{}-finding", current.request_id);
|
||||
let previous_finding =
|
||||
runtime_repo_work_modeling_finding(&runtime_store, &previous_finding_id)?
|
||||
.ok_or_else(|| anyhow!("revise-modeling requires the current typed finding"))?;
|
||||
if previous_finding
|
||||
.verdict
|
||||
.trim()
|
||||
.eq_ignore_ascii_case("passed")
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"passing Modeling truth cannot be revised into a retry"
|
||||
));
|
||||
}
|
||||
let generation = current.generation.saturating_add(1);
|
||||
let request_id = format!("repo-work-close-{item_slug}-modeling-request-g{generation}");
|
||||
let now = Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
|
||||
let request = RepoWorkModelingRequest {
|
||||
schema_version: REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION.to_string(),
|
||||
request_id: request_id.clone(),
|
||||
item: current.item.clone(),
|
||||
requester: "mind".to_string(),
|
||||
soul_verdict_receipt_id: current_request.soul_verdict_receipt_id.clone(),
|
||||
commit_sha: current_request.commit_sha.clone(),
|
||||
changed_paths: current_request.changed_paths.clone(),
|
||||
instruction: format!(
|
||||
"Re-model the same Soul-verified consequence after reviewed correction {}. Previous finding {} said: {}. Review rationale: {}",
|
||||
args.review_ref,
|
||||
previous_finding.receipt_id,
|
||||
compact_line(&previous_finding.finding),
|
||||
compact_line(&args.rationale)
|
||||
),
|
||||
requested_at: now.clone(),
|
||||
private_state_exposed: false,
|
||||
contract: "Mind-reviewed next generation of one immutable repo-work Modeling route; preserves the Soul-verified consequence and previous finding."
|
||||
.to_string(),
|
||||
};
|
||||
let gateway_id = format!("repo-work-modeling-route-{item_slug}-g{generation}-mind-review");
|
||||
let review = MindGatewayReview {
|
||||
schema_version: MIND_GATEWAY_REVIEW_SCHEMA_VERSION.to_string(),
|
||||
gateway_id: gateway_id.clone(),
|
||||
source_kind: "repo_work_modeling_revision".to_string(),
|
||||
source_role_id: "mind".to_string(),
|
||||
decision: MindGatewayDecision::Accept,
|
||||
allowed_effects: vec!["repoWork.modelingRoute".to_string()],
|
||||
refused_effects: vec![
|
||||
"repoWork.map".to_string(),
|
||||
"publication".to_string(),
|
||||
"merge".to_string(),
|
||||
"handsAction".to_string(),
|
||||
],
|
||||
reasons: vec![
|
||||
format!("Reviewed correction reference: {}.", args.review_ref),
|
||||
format!("Previous immutable verdict: {}.", previous_finding.verdict),
|
||||
args.rationale.clone(),
|
||||
],
|
||||
contract: "Mind review advances only the current Modeling request generation; it admits no map, publication, merge, or Hands effect."
|
||||
.to_string(),
|
||||
};
|
||||
let route = RepoWorkModelingRoute {
|
||||
schema_version: REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION.to_string(),
|
||||
route_id: current.route_id.clone(),
|
||||
item: current.item.clone(),
|
||||
generation,
|
||||
request_id: request.request_id.clone(),
|
||||
previous_finding_receipt_id: previous_finding.receipt_id.clone(),
|
||||
authority_owner: "mind".to_string(),
|
||||
authority_witness_id: review.gateway_id.clone(),
|
||||
updated_at: now,
|
||||
private_state_exposed: false,
|
||||
contract: "Sole current-generation pointer for repo-work Modeling; older requests and findings remain immutable evidence."
|
||||
.to_string(),
|
||||
};
|
||||
let route = advance_repo_work_modeling_route(&runtime_store, &request, &route, &review)?;
|
||||
Ok(json!({
|
||||
"schemaVersion": REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION,
|
||||
"status": "modeling-route-advanced",
|
||||
"workspace": workspace,
|
||||
"item": route.item,
|
||||
"routeId": route.route_id,
|
||||
"generation": route.generation,
|
||||
"requestId": route.request_id,
|
||||
"previousFindingReceiptId": route.previous_finding_receipt_id,
|
||||
"mindReviewId": route.authority_witness_id,
|
||||
"reviewRef": args.review_ref,
|
||||
"privateStateExposed": false,
|
||||
"nextSafeMove": "Pulse the scheduler to launch the reviewed Modeling generation through Idunn."
|
||||
}))
|
||||
}
|
||||
|
||||
fn run_close(args: CloseArgs) -> Result<Value> {
|
||||
run_closure_pipeline(args, ClosurePhase::Full)
|
||||
}
|
||||
|
|
@ -11490,33 +11644,61 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result<Value> {
|
|||
declared_changed_paths.join(", ")
|
||||
)
|
||||
});
|
||||
let modeling_request_id = format!("repo-work-close-{item_slug}-modeling-request");
|
||||
let mut modeling_request = RepoWorkModelingRequest {
|
||||
schema_version: REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION.to_string(),
|
||||
request_id: modeling_request_id.clone(),
|
||||
item: item.clone(),
|
||||
requester: "self".to_string(),
|
||||
soul_verdict_receipt_id: soul_verdict.receipt_id.clone(),
|
||||
commit_sha: commit_sha.clone(),
|
||||
changed_paths: declared_changed_paths.clone(),
|
||||
instruction: "Model the Soul-verified consequence and return a bounded repo-map finding; do not admit state or route the next action.".to_string(),
|
||||
requested_at: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
|
||||
private_state_exposed: false,
|
||||
contract: "Self-to-Modeling request over a passing Soul verdict; Self may route but cannot author the result.".to_string(),
|
||||
};
|
||||
if let Some(existing) =
|
||||
runtime_repo_work_modeling_request(&runtime_store, &modeling_request_id)?
|
||||
{
|
||||
modeling_request.requested_at = existing.requested_at.clone();
|
||||
if modeling_request != existing {
|
||||
return Err(anyhow!(
|
||||
"closure retry conflicts with immutable Modeling request"
|
||||
));
|
||||
}
|
||||
modeling_request = existing;
|
||||
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)?
|
||||
.ok_or_else(|| anyhow!("closure requires the typed Modeling route"))?;
|
||||
let request = runtime_repo_work_modeling_request(&runtime_store, &route.request_id)?
|
||||
.ok_or_else(|| anyhow!("closure requires the current typed Modeling request"))?;
|
||||
(request, route)
|
||||
} else {
|
||||
put_repo_work_modeling_request(&runtime_store, &modeling_request)?;
|
||||
}
|
||||
let modeling_request_id = format!("repo-work-close-{item_slug}-modeling-request");
|
||||
let mut request = RepoWorkModelingRequest {
|
||||
schema_version: REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION.to_string(),
|
||||
request_id: modeling_request_id.clone(),
|
||||
item: item.clone(),
|
||||
requester: "self".to_string(),
|
||||
soul_verdict_receipt_id: soul_verdict.receipt_id.clone(),
|
||||
commit_sha: commit_sha.clone(),
|
||||
changed_paths: declared_changed_paths.clone(),
|
||||
instruction: "Model the Soul-verified consequence and return a bounded repo-map finding; do not admit state or route the next action.".to_string(),
|
||||
requested_at: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
|
||||
private_state_exposed: false,
|
||||
contract: "Self-to-Modeling request over a passing Soul verdict; Self may route but cannot author the result.".to_string(),
|
||||
};
|
||||
if let Some(existing) =
|
||||
runtime_repo_work_modeling_request(&runtime_store, &modeling_request_id)?
|
||||
{
|
||||
request.requested_at = existing.requested_at.clone();
|
||||
if request != existing {
|
||||
return Err(anyhow!(
|
||||
"closure retry conflicts with immutable Modeling request"
|
||||
));
|
||||
}
|
||||
request = existing;
|
||||
}
|
||||
let mut route = RepoWorkModelingRoute {
|
||||
schema_version: REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION.to_string(),
|
||||
route_id: modeling_route_id.clone(),
|
||||
item: item.clone(),
|
||||
generation: 0,
|
||||
request_id: request.request_id.clone(),
|
||||
previous_finding_receipt_id: String::new(),
|
||||
authority_owner: "soul".to_string(),
|
||||
authority_witness_id: soul_verdict.receipt_id.clone(),
|
||||
updated_at: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
|
||||
private_state_exposed: false,
|
||||
contract: "Current repo-work Modeling generation; generation zero is established atomically with its Soul-backed request, and later movement requires Mind review."
|
||||
.to_string(),
|
||||
};
|
||||
if let Some(existing) =
|
||||
runtime_repo_work_modeling_route(&runtime_store, &modeling_route_id)?
|
||||
{
|
||||
route.updated_at = existing.updated_at.clone();
|
||||
}
|
||||
let route = commit_initial_repo_work_modeling_route(&runtime_store, &request, &route)?;
|
||||
(request, route)
|
||||
};
|
||||
if phase == ClosurePhase::SoulOnly || !model_closure_passed {
|
||||
let awaiting_receipt = json!({
|
||||
"schemaVersion": "epiphany.repo_work_closure_receipt.v0",
|
||||
|
|
@ -11536,6 +11718,8 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result<Value> {
|
|||
"closureReview": closure_review,
|
||||
"modeling": {
|
||||
"requestId": modeling_request.request_id,
|
||||
"routeId": modeling_route.route_id,
|
||||
"generation": modeling_route.generation,
|
||||
"requester": modeling_request.requester,
|
||||
"findingReceiptId": Value::Null
|
||||
},
|
||||
|
|
@ -14170,8 +14354,8 @@ fn run_queue(args: QueueArgs) -> Result<Value> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn repo_work_modeling_job_id(item_slug: &str) -> String {
|
||||
format!("repo-work-modeling-{item_slug}")
|
||||
fn repo_work_modeling_job_id(item_slug: &str, generation: u64) -> String {
|
||||
format!("repo-work-modeling-{item_slug}-g{generation}")
|
||||
}
|
||||
|
||||
fn resolve_repo_work_model_runtime(epiphany_root: &Path) -> Result<PathBuf> {
|
||||
|
|
@ -14239,8 +14423,9 @@ fn launch_repo_work_modeling_worker(
|
|||
local_verse_store: &Path,
|
||||
request: &RepoWorkModelingRequest,
|
||||
item_slug: &str,
|
||||
generation: u64,
|
||||
) -> Result<Value> {
|
||||
let job_id = repo_work_modeling_job_id(item_slug);
|
||||
let job_id = repo_work_modeling_job_id(item_slug, generation);
|
||||
let verified_diff = git_output(
|
||||
workspace,
|
||||
&[
|
||||
|
|
@ -14730,10 +14915,11 @@ fn run_tick(args: TickArgs) -> Result<Value> {
|
|||
.clone()
|
||||
.or_else(|| path_from_json(&partial_close, &["runtimeStore"]))
|
||||
.ok_or_else(|| anyhow!("awaiting-modeling closure has no runtime store"))?;
|
||||
let request_id = string_from_json(&partial_close, &["modeling", "requestId"])
|
||||
.ok_or_else(|| anyhow!("awaiting-modeling closure has no typed request id"))?;
|
||||
let request = runtime_repo_work_modeling_request(&runtime_store, &request_id)?
|
||||
.ok_or_else(|| anyhow!("typed Modeling request {request_id:?} is missing"))?;
|
||||
let route_id = format!("repo-work-modeling-route-{item_slug}");
|
||||
let route = runtime_repo_work_modeling_route(&runtime_store, &route_id)?
|
||||
.ok_or_else(|| anyhow!("typed Modeling route {route_id:?} is missing"))?;
|
||||
let request = runtime_repo_work_modeling_request(&runtime_store, &route.request_id)?
|
||||
.ok_or_else(|| anyhow!("current Modeling request {:?} is missing", route.request_id))?;
|
||||
let finding_id = format!("{}-finding", request.request_id);
|
||||
if let Some(finding) = runtime_repo_work_modeling_finding(&runtime_store, &finding_id)? {
|
||||
if finding.verdict.trim().eq_ignore_ascii_case("passed") {
|
||||
|
|
@ -14781,7 +14967,7 @@ fn run_tick(args: TickArgs) -> Result<Value> {
|
|||
.to_string();
|
||||
}
|
||||
} else {
|
||||
let job_id = repo_work_modeling_job_id(&item_slug);
|
||||
let job_id = repo_work_modeling_job_id(&item_slug, route.generation);
|
||||
match runtime_job_snapshot(&runtime_store, &job_id)? {
|
||||
Some(snapshot)
|
||||
if matches!(
|
||||
|
|
@ -14829,6 +15015,7 @@ fn run_tick(args: TickArgs) -> Result<Value> {
|
|||
&lifecycle_store,
|
||||
&request,
|
||||
&item_slug,
|
||||
route.generation,
|
||||
)?;
|
||||
status = "modeling-launched".to_string();
|
||||
reason =
|
||||
|
|
@ -16724,7 +16911,24 @@ mod authority_tests {
|
|||
private_state_exposed: false,
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
put_repo_work_modeling_request(&store, &request)?;
|
||||
let route = RepoWorkModelingRoute {
|
||||
schema_version: REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION.to_string(),
|
||||
route_id: "modeling-route-1".to_string(),
|
||||
item: request.item.clone(),
|
||||
generation: 0,
|
||||
request_id: request.request_id.clone(),
|
||||
previous_finding_receipt_id: String::new(),
|
||||
authority_owner: "soul".to_string(),
|
||||
authority_witness_id: request.soul_verdict_receipt_id.clone(),
|
||||
updated_at: "2026-07-12T00:00:01Z".to_string(),
|
||||
private_state_exposed: false,
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
commit_initial_repo_work_modeling_route(&store, &request, &route)?;
|
||||
assert_eq!(
|
||||
runtime_repo_work_modeling_route(&store, &route.route_id)?,
|
||||
Some(route.clone())
|
||||
);
|
||||
let mut finding = RepoWorkModelingFinding {
|
||||
schema_version: REPO_WORK_MODELING_FINDING_SCHEMA_VERSION.to_string(),
|
||||
receipt_id: "modeling-finding-1".to_string(),
|
||||
|
|
@ -16821,6 +17025,120 @@ mod authority_tests {
|
|||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modeling_route_generation_requires_mind_and_preserves_previous() -> Result<()> {
|
||||
let temp = tempfile::tempdir()?;
|
||||
let store = temp.path().join("runtime.cc");
|
||||
initialize_runtime_spine(
|
||||
&store,
|
||||
RuntimeSpineInitOptions {
|
||||
runtime_id: "modeling-route-test".to_string(),
|
||||
display_name: "Modeling Route Test".to_string(),
|
||||
created_at: "2026-07-12T00:00:00Z".to_string(),
|
||||
},
|
||||
)?;
|
||||
let soul = SoulVerdictReceipt {
|
||||
schema_version: SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.to_string(),
|
||||
receipt_id: "route-soul-1".to_string(),
|
||||
source_result_id: "result-1".to_string(),
|
||||
source_job_id: "job-1".to_string(),
|
||||
verdict: "passed".to_string(),
|
||||
summary: "verified".to_string(),
|
||||
evidence_ids: Vec::new(),
|
||||
risks: Vec::new(),
|
||||
emitted_at: "2026-07-12T00:00:00Z".to_string(),
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
put_soul_verdict_receipt(&store, &soul)?;
|
||||
let request0 = RepoWorkModelingRequest {
|
||||
schema_version: REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION.to_string(),
|
||||
request_id: "route-request-g0".to_string(),
|
||||
item: "route-item".to_string(),
|
||||
requester: "self".to_string(),
|
||||
soul_verdict_receipt_id: soul.receipt_id.clone(),
|
||||
commit_sha: "abc123".to_string(),
|
||||
changed_paths: vec!["README.md".to_string()],
|
||||
instruction: "Model consequence.".to_string(),
|
||||
requested_at: "2026-07-12T00:00:01Z".to_string(),
|
||||
private_state_exposed: false,
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
let route0 = RepoWorkModelingRoute {
|
||||
schema_version: REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION.to_string(),
|
||||
route_id: "route-item-current".to_string(),
|
||||
item: request0.item.clone(),
|
||||
generation: 0,
|
||||
request_id: request0.request_id.clone(),
|
||||
previous_finding_receipt_id: String::new(),
|
||||
authority_owner: "soul".to_string(),
|
||||
authority_witness_id: soul.receipt_id.clone(),
|
||||
updated_at: "2026-07-12T00:00:01Z".to_string(),
|
||||
private_state_exposed: false,
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
commit_initial_repo_work_modeling_route(&store, &request0, &route0)?;
|
||||
let finding0 = RepoWorkModelingFinding {
|
||||
schema_version: REPO_WORK_MODELING_FINDING_SCHEMA_VERSION.to_string(),
|
||||
receipt_id: "route-request-g0-finding".to_string(),
|
||||
item: request0.item.clone(),
|
||||
model_ref: "model-1".to_string(),
|
||||
soul_verdict_receipt_id: soul.receipt_id.clone(),
|
||||
verdict: "needs-work".to_string(),
|
||||
finding: "Need the verified diff.".to_string(),
|
||||
summary: "Context incomplete.".to_string(),
|
||||
changed_paths: request0.changed_paths.clone(),
|
||||
commit_sha: request0.commit_sha.clone(),
|
||||
emitted_at: "2026-07-12T00:00:02Z".to_string(),
|
||||
private_state_exposed: false,
|
||||
contract: "test".to_string(),
|
||||
request_id: request0.request_id.clone(),
|
||||
};
|
||||
put_repo_work_modeling_finding(&store, &finding0)?;
|
||||
let review = MindGatewayReview {
|
||||
schema_version: MIND_GATEWAY_REVIEW_SCHEMA_VERSION.to_string(),
|
||||
gateway_id: "route-g1-mind-review".to_string(),
|
||||
source_kind: "repo_work_modeling_revision".to_string(),
|
||||
source_role_id: "mind".to_string(),
|
||||
decision: MindGatewayDecision::Accept,
|
||||
allowed_effects: vec!["repoWork.modelingRoute".to_string()],
|
||||
refused_effects: vec!["repoWork.map".to_string()],
|
||||
reasons: vec!["Reviewed missing context.".to_string()],
|
||||
contract: "test".to_string(),
|
||||
};
|
||||
let request1 = RepoWorkModelingRequest {
|
||||
request_id: "route-request-g1".to_string(),
|
||||
requester: "mind".to_string(),
|
||||
instruction: "Re-model with reviewed context.".to_string(),
|
||||
requested_at: "2026-07-12T00:00:03Z".to_string(),
|
||||
..request0.clone()
|
||||
};
|
||||
let route1 = RepoWorkModelingRoute {
|
||||
generation: 1,
|
||||
request_id: request1.request_id.clone(),
|
||||
previous_finding_receipt_id: finding0.receipt_id.clone(),
|
||||
authority_owner: "mind".to_string(),
|
||||
authority_witness_id: review.gateway_id.clone(),
|
||||
updated_at: "2026-07-12T00:00:03Z".to_string(),
|
||||
contract: "test generation one".to_string(),
|
||||
..route0.clone()
|
||||
};
|
||||
advance_repo_work_modeling_route(&store, &request1, &route1, &review)?;
|
||||
assert_eq!(
|
||||
runtime_repo_work_modeling_route(&store, &route0.route_id)?,
|
||||
Some(route1.clone())
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_repo_work_modeling_request(&store, &request0.request_id)?,
|
||||
Some(request0)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_repo_work_modeling_finding(&store, &finding0.receipt_id)?,
|
||||
Some(finding0)
|
||||
);
|
||||
assert!(advance_repo_work_modeling_route(&store, &request1, &route1, &review).is_err());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn adopted_action_item_from_plan(plan: &Value) -> Value {
|
||||
|
|
|
|||
|
|
@ -659,9 +659,12 @@ pub use modeling_gateway::REPO_WORK_MODELING_FINDING_SCHEMA_VERSION;
|
|||
pub use modeling_gateway::REPO_WORK_MODELING_FINDING_TYPE;
|
||||
pub use modeling_gateway::REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION;
|
||||
pub use modeling_gateway::REPO_WORK_MODELING_REQUEST_TYPE;
|
||||
pub use modeling_gateway::REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION;
|
||||
pub use modeling_gateway::REPO_WORK_MODELING_ROUTE_TYPE;
|
||||
pub use modeling_gateway::RepoWorkMapEntry;
|
||||
pub use modeling_gateway::RepoWorkModelingFinding;
|
||||
pub use modeling_gateway::RepoWorkModelingRequest;
|
||||
pub use modeling_gateway::RepoWorkModelingRoute;
|
||||
pub use organ_dependencies::EPIPHANY_LAUNCH_ORGAN_CONTRACT_SCHEMA_VERSION;
|
||||
pub use organ_dependencies::EPIPHANY_ORGAN_DEPENDENCY_SCHEMA_VERSION;
|
||||
pub use organ_dependencies::EPIPHANY_STANDING_ORGANS;
|
||||
|
|
@ -770,8 +773,10 @@ pub use runtime_spine::RuntimeSpineInitOptions;
|
|||
pub use runtime_spine::RuntimeSpineJobOptions;
|
||||
pub use runtime_spine::RuntimeSpineJobResultOptions;
|
||||
pub use runtime_spine::RuntimeSpineSessionOptions;
|
||||
pub use runtime_spine::advance_repo_work_modeling_route;
|
||||
pub use runtime_spine::append_runtime_event;
|
||||
pub use runtime_spine::clear_epiphany_job_binding_backend;
|
||||
pub use runtime_spine::commit_initial_repo_work_modeling_route;
|
||||
pub use runtime_spine::commit_repo_work_map_admission;
|
||||
pub use runtime_spine::complete_runtime_job;
|
||||
pub use runtime_spine::create_runtime_job;
|
||||
|
|
@ -817,6 +822,7 @@ pub use runtime_spine::runtime_reorient_worker_result;
|
|||
pub use runtime_spine::runtime_repo_work_map_entry;
|
||||
pub use runtime_spine::runtime_repo_work_modeling_finding;
|
||||
pub use runtime_spine::runtime_repo_work_modeling_request;
|
||||
pub use runtime_spine::runtime_repo_work_modeling_route;
|
||||
pub use runtime_spine::runtime_role_worker_result;
|
||||
pub use runtime_spine::runtime_schema_catalog_response;
|
||||
pub use runtime_spine::runtime_soul_verdict_receipt;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ pub const REPO_WORK_MODELING_FINDING_SCHEMA_VERSION: &str =
|
|||
pub const REPO_WORK_MODELING_REQUEST_TYPE: &str = "epiphany.modeling.repo_work_request";
|
||||
pub const REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION: &str =
|
||||
"epiphany.modeling.repo_work_request.v0";
|
||||
pub const REPO_WORK_MODELING_ROUTE_TYPE: &str = "epiphany.modeling.repo_work_route";
|
||||
pub const REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION: &str = "epiphany.modeling.repo_work_route.v0";
|
||||
pub const REPO_WORK_MAP_ENTRY_TYPE: &str = "epiphany.repo_work.map_entry";
|
||||
pub const REPO_WORK_MAP_ENTRY_SCHEMA_VERSION: &str = "epiphany.repo_work.map_entry.v0";
|
||||
|
||||
|
|
@ -75,6 +77,36 @@ pub struct RepoWorkModelingRequest {
|
|||
pub contract: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
|
||||
#[cultcache(
|
||||
type = "epiphany.modeling.repo_work_route",
|
||||
schema = "RepoWorkModelingRoute"
|
||||
)]
|
||||
pub struct RepoWorkModelingRoute {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_version: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub route_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub item: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub generation: u64,
|
||||
#[cultcache(key = 4)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 5)]
|
||||
pub previous_finding_receipt_id: String,
|
||||
#[cultcache(key = 6)]
|
||||
pub authority_owner: String,
|
||||
#[cultcache(key = 7)]
|
||||
pub authority_witness_id: String,
|
||||
#[cultcache(key = 8)]
|
||||
pub updated_at: String,
|
||||
#[cultcache(key = 9)]
|
||||
pub private_state_exposed: bool,
|
||||
#[cultcache(key = 10)]
|
||||
pub contract: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
|
||||
#[cultcache(type = "epiphany.repo_work.map_entry", schema = "RepoWorkMapEntry")]
|
||||
pub struct RepoWorkMapEntry {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ use crate::mind_gateway::MIND_THOUGHT_SCHEMA_VERSION;
|
|||
use crate::mind_gateway::MIND_THOUGHT_TYPE;
|
||||
use crate::mind_gateway::MIND_VERSE_ADOPTION_RECEIPT_SCHEMA_VERSION;
|
||||
use crate::mind_gateway::MIND_VERSE_ADOPTION_RECEIPT_TYPE;
|
||||
use crate::mind_gateway::MindGatewayDecision;
|
||||
use crate::mind_gateway::MindGatewayReview;
|
||||
use crate::mind_gateway::MindStateCommitReceipt;
|
||||
use crate::modeling_gateway::REPO_WORK_MAP_ENTRY_SCHEMA_VERSION;
|
||||
|
|
@ -46,9 +47,12 @@ use crate::modeling_gateway::REPO_WORK_MODELING_FINDING_SCHEMA_VERSION;
|
|||
use crate::modeling_gateway::REPO_WORK_MODELING_FINDING_TYPE;
|
||||
use crate::modeling_gateway::REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION;
|
||||
use crate::modeling_gateway::REPO_WORK_MODELING_REQUEST_TYPE;
|
||||
use crate::modeling_gateway::REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION;
|
||||
use crate::modeling_gateway::REPO_WORK_MODELING_ROUTE_TYPE;
|
||||
use crate::modeling_gateway::RepoWorkMapEntry;
|
||||
use crate::modeling_gateway::RepoWorkModelingFinding;
|
||||
use crate::modeling_gateway::RepoWorkModelingRequest;
|
||||
use crate::modeling_gateway::RepoWorkModelingRoute;
|
||||
use crate::organ_dependencies::EpiphanyLaunchOrganContract;
|
||||
use crate::soul_gateway::SoulVerdictReceipt;
|
||||
use crate::soul_gateway::*;
|
||||
|
|
@ -734,6 +738,7 @@ pub fn runtime_spine_cache(store_path: impl AsRef<Path>) -> Result<CultCache> {
|
|||
cache.register_entry_type::<MindStateCommitReceipt>()?;
|
||||
cache.register_entry_type::<RepoWorkModelingFinding>()?;
|
||||
cache.register_entry_type::<RepoWorkModelingRequest>()?;
|
||||
cache.register_entry_type::<RepoWorkModelingRoute>()?;
|
||||
cache.register_entry_type::<RepoWorkMapEntry>()?;
|
||||
cache.register_entry_type::<EyesEvidencePacket>()?;
|
||||
cache.register_entry_type::<SubstrateGateRepoAccessGrantReceipt>()?;
|
||||
|
|
@ -1849,6 +1854,183 @@ pub fn runtime_repo_work_modeling_request(
|
|||
cache.get::<RepoWorkModelingRequest>(request_id)
|
||||
}
|
||||
|
||||
pub fn commit_initial_repo_work_modeling_route(
|
||||
store_path: impl AsRef<Path>,
|
||||
request: &RepoWorkModelingRequest,
|
||||
route: &RepoWorkModelingRoute,
|
||||
) -> Result<RepoWorkModelingRoute> {
|
||||
if request.schema_version != REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION {
|
||||
return Err(anyhow!("unsupported Modeling request schema"));
|
||||
}
|
||||
validate_non_empty(&request.request_id, "Modeling request id")?;
|
||||
validate_non_empty(&request.item, "Modeling request item")?;
|
||||
validate_non_empty(
|
||||
&request.soul_verdict_receipt_id,
|
||||
"Modeling request Soul verdict receipt id",
|
||||
)?;
|
||||
validate_non_empty(&request.commit_sha, "Modeling request commit sha")?;
|
||||
validate_non_empty(&request.instruction, "Modeling request instruction")?;
|
||||
validate_non_empty(&request.requested_at, "Modeling request timestamp")?;
|
||||
if request.requester != "self" || request.private_state_exposed {
|
||||
return Err(anyhow!(
|
||||
"initial Modeling request must be Self-routed and private-state sealed"
|
||||
));
|
||||
}
|
||||
if route.schema_version != REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION {
|
||||
return Err(anyhow!("unsupported Modeling route schema"));
|
||||
}
|
||||
validate_non_empty(&route.route_id, "Modeling route id")?;
|
||||
validate_non_empty(&route.item, "Modeling route item")?;
|
||||
validate_non_empty(&route.request_id, "Modeling route request id")?;
|
||||
validate_non_empty(&route.authority_owner, "Modeling route authority owner")?;
|
||||
validate_non_empty(
|
||||
&route.authority_witness_id,
|
||||
"Modeling route authority witness",
|
||||
)?;
|
||||
validate_non_empty(&route.updated_at, "Modeling route timestamp")?;
|
||||
if route.generation != 0
|
||||
|| !route.previous_finding_receipt_id.is_empty()
|
||||
|| route.authority_owner != "soul"
|
||||
|| route.authority_witness_id != request.soul_verdict_receipt_id
|
||||
|| route.item != request.item
|
||||
|| route.request_id != request.request_id
|
||||
|| route.private_state_exposed
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"initial Modeling route must be generation zero, Soul-backed, request-matched, and private-state sealed"
|
||||
));
|
||||
}
|
||||
let mut cache = runtime_spine_cache(store_path)?;
|
||||
cache.pull_all_backing_stores()?;
|
||||
require_identity(&cache)?;
|
||||
let soul = cache
|
||||
.get::<SoulVerdictReceipt>(&request.soul_verdict_receipt_id)?
|
||||
.ok_or_else(|| anyhow!("initial Modeling route requires its Soul verdict"))?;
|
||||
if soul.verdict.trim().to_ascii_lowercase() != "passed" {
|
||||
return Err(anyhow!(
|
||||
"initial Modeling route requires passing Soul truth"
|
||||
));
|
||||
}
|
||||
if let Some(existing) = cache.get::<RepoWorkModelingRoute>(&route.route_id)? {
|
||||
let stored_request = cache
|
||||
.get::<RepoWorkModelingRequest>(&existing.request_id)?
|
||||
.ok_or_else(|| anyhow!("existing Modeling route lost its request"))?;
|
||||
if existing == *route && stored_request == *request {
|
||||
return Ok(existing);
|
||||
}
|
||||
return Err(anyhow!(
|
||||
"initial Modeling route already belongs to different routing truth"
|
||||
));
|
||||
}
|
||||
if cache
|
||||
.get::<RepoWorkModelingRequest>(&request.request_id)?
|
||||
.is_some()
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"Modeling request exists without its atomic initial route"
|
||||
));
|
||||
}
|
||||
let (request_envelope, _) = cache.prepare_entry(&request.request_id, request)?;
|
||||
let (route_envelope, _) = cache.prepare_entry(&route.route_id, route)?;
|
||||
cache.put_prepared_batch(vec![request_envelope, route_envelope])?;
|
||||
Ok(route.clone())
|
||||
}
|
||||
|
||||
pub fn runtime_repo_work_modeling_route(
|
||||
store_path: impl AsRef<Path>,
|
||||
route_id: &str,
|
||||
) -> Result<Option<RepoWorkModelingRoute>> {
|
||||
validate_non_empty(route_id, "Modeling route id")?;
|
||||
let mut cache = runtime_spine_cache(store_path)?;
|
||||
cache.pull_all_backing_stores()?;
|
||||
cache.get::<RepoWorkModelingRoute>(route_id)
|
||||
}
|
||||
|
||||
pub fn advance_repo_work_modeling_route(
|
||||
store_path: impl AsRef<Path>,
|
||||
request: &RepoWorkModelingRequest,
|
||||
route: &RepoWorkModelingRoute,
|
||||
mind_review: &MindGatewayReview,
|
||||
) -> Result<RepoWorkModelingRoute> {
|
||||
if request.schema_version != REPO_WORK_MODELING_REQUEST_SCHEMA_VERSION
|
||||
|| route.schema_version != REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION
|
||||
{
|
||||
return Err(anyhow!("unsupported Modeling route generation schema"));
|
||||
}
|
||||
validate_non_empty(&request.request_id, "next Modeling request id")?;
|
||||
validate_non_empty(&request.item, "next Modeling request item")?;
|
||||
validate_non_empty(
|
||||
&request.soul_verdict_receipt_id,
|
||||
"next Modeling request Soul verdict",
|
||||
)?;
|
||||
validate_non_empty(&request.commit_sha, "next Modeling request commit")?;
|
||||
validate_non_empty(&request.instruction, "next Modeling request instruction")?;
|
||||
validate_non_empty(&request.requested_at, "next Modeling request timestamp")?;
|
||||
validate_non_empty(&route.route_id, "Modeling route id")?;
|
||||
validate_non_empty(
|
||||
&route.previous_finding_receipt_id,
|
||||
"previous Modeling finding receipt id",
|
||||
)?;
|
||||
validate_non_empty(&route.updated_at, "next Modeling route timestamp")?;
|
||||
if request.requester != "mind"
|
||||
|| request.private_state_exposed
|
||||
|| route.private_state_exposed
|
||||
|| route.authority_owner != "mind"
|
||||
|| route.authority_witness_id != mind_review.gateway_id
|
||||
|| route.request_id != request.request_id
|
||||
|| route.item != request.item
|
||||
|| mind_review.decision != MindGatewayDecision::Accept
|
||||
|| mind_review.source_kind != "repo_work_modeling_revision"
|
||||
|| !mind_review
|
||||
.allowed_effects
|
||||
.iter()
|
||||
.any(|effect| effect == "repoWork.modelingRoute")
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"next Modeling generation requires a private-state-sealed Mind acceptance that owns only the route transition"
|
||||
));
|
||||
}
|
||||
let mut cache = runtime_spine_cache(store_path)?;
|
||||
cache.pull_all_backing_stores()?;
|
||||
require_identity(&cache)?;
|
||||
let current = cache
|
||||
.get::<RepoWorkModelingRoute>(&route.route_id)?
|
||||
.ok_or_else(|| anyhow!("cannot advance a missing Modeling route"))?;
|
||||
let current_request = cache
|
||||
.get::<RepoWorkModelingRequest>(¤t.request_id)?
|
||||
.ok_or_else(|| anyhow!("current Modeling route lost its request"))?;
|
||||
let previous_finding = cache
|
||||
.get::<RepoWorkModelingFinding>(&route.previous_finding_receipt_id)?
|
||||
.ok_or_else(|| anyhow!("next Modeling generation requires the previous finding"))?;
|
||||
if route.generation != current.generation.saturating_add(1)
|
||||
|| previous_finding.request_id != current.request_id
|
||||
|| previous_finding.item != current.item
|
||||
|| previous_finding
|
||||
.verdict
|
||||
.trim()
|
||||
.eq_ignore_ascii_case("passed")
|
||||
|| request.item != current_request.item
|
||||
|| request.soul_verdict_receipt_id != current_request.soul_verdict_receipt_id
|
||||
|| request.commit_sha != current_request.commit_sha
|
||||
|| request.changed_paths != current_request.changed_paths
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"next Modeling generation must follow one non-passing current finding and preserve the Soul-verified consequence"
|
||||
));
|
||||
}
|
||||
if cache
|
||||
.get::<RepoWorkModelingRequest>(&request.request_id)?
|
||||
.is_some()
|
||||
{
|
||||
return Err(anyhow!("next Modeling request id already exists"));
|
||||
}
|
||||
let (request_envelope, _) = cache.prepare_entry(&request.request_id, request)?;
|
||||
let (review_envelope, _) = cache.prepare_entry(&mind_review.gateway_id, mind_review)?;
|
||||
let (route_envelope, _) = cache.prepare_entry(&route.route_id, route)?;
|
||||
cache.put_prepared_batch(vec![request_envelope, review_envelope, route_envelope])?;
|
||||
Ok(route.clone())
|
||||
}
|
||||
|
||||
pub fn runtime_repo_work_modeling_finding(
|
||||
store_path: impl AsRef<Path>,
|
||||
receipt_id: &str,
|
||||
|
|
@ -2560,6 +2742,23 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
|
|||
"Schedulers and raw CLI fields cannot substitute for this persisted receipt.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
REPO_WORK_MODELING_ROUTE_TYPE,
|
||||
REPO_WORK_MODELING_ROUTE_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::IntentSubmit,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::Coordinator,
|
||||
vec![REPO_WORK_MODELING_REQUEST_TYPE, MIND_GATEWAY_REVIEW_TYPE],
|
||||
vec![REPO_WORK_MODELING_ROUTE_TYPE],
|
||||
vec![
|
||||
"The route is the sole current-generation owner for repo-work Modeling requests.",
|
||||
"Generation zero is Soul-backed; later generations require a Mind review and preserve the previous finding.",
|
||||
"Filesystem closure artifacts and Self are projections/routers, not route writers.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
REPO_WORK_MAP_ENTRY_TYPE,
|
||||
REPO_WORK_MAP_ENTRY_SCHEMA_VERSION,
|
||||
|
|
|
|||
|
|
@ -152,6 +152,19 @@ artifacts, and publishes an
|
|||
process identity. Self receives that receipt ID as routing evidence only. Live
|
||||
item `idunn-owned-modeling` crossed this boundary and reached the Bifrost gate.
|
||||
|
||||
The current Modeling request is owned by
|
||||
`epiphany.modeling.repo_work_route.v0`, not the filesystem closure projection.
|
||||
Generation zero lands atomically with its Soul-backed request. A later
|
||||
generation can advance only through `advance_repo_work_modeling_route`: the
|
||||
current finding must exist and be non-passing, the new request must preserve
|
||||
item/Soul/commit/paths, and a Mind acceptance must grant only
|
||||
`repoWork.modelingRoute`. Request, Mind review, and stable route pointer commit
|
||||
in one CultCache batch; old request/finding documents remain immutable.
|
||||
`epiphany-work revise-modeling --review-ref ... --rationale ...` is the explicit
|
||||
review mouth. Scheduler job IDs include the route generation and derive the
|
||||
stable route key from the item, so neither close JSON nor an old completed job
|
||||
can select current work.
|
||||
|
||||
The
|
||||
accepted interpretation is persisted as
|
||||
`epiphany.modeling.repo_work_finding.v0`; it references the passing Soul verdict,
|
||||
|
|
|
|||
|
|
@ -204,9 +204,9 @@ Delete or demote:
|
|||
|
||||
## Immediate Next Action
|
||||
|
||||
Design and implement a typed Mind-reviewed request-generation pointer for
|
||||
non-passing immutable repo-work Modeling findings. Idunn now owns detached
|
||||
worker launch through its existing lifecycle receipt mouth. Preserve the old
|
||||
request/finding as immutable evidence, make one typed owner select the current
|
||||
generation, and keep filesystem closure artifacts and Self from becoming
|
||||
mutable routing authorities.
|
||||
Expose the launched worker executable's build/schema fingerprint in Idunn's
|
||||
lifecycle receipt and preflight required runtime document registration before
|
||||
launch. A stale `epiphany-openai-runtime` binary already proved it can otherwise
|
||||
impersonate a Modeling failure after the producer adds a schema. Keep the new
|
||||
typed route owner and reviewed generation transition intact; do not repair
|
||||
stale consumers by mutating requests or findings.
|
||||
|
|
|
|||
|
|
@ -2097,6 +2097,24 @@ admission, and overview gate `awaiting-publication` with
|
|||
`bifrost-publication-missing`. Next design the typed Mind-reviewed generation
|
||||
pointer for a non-passing immutable finding; do not mutate the old request or
|
||||
let a filesystem close artifact become the new routing authority.
|
||||
That typed owner is now implemented. `RepoWorkModelingRoute` is registered in
|
||||
runtime CultCache/CultNet. Generation zero is atomically committed with the
|
||||
Soul-backed request. `revise-modeling` requires explicit review reference and
|
||||
rationale, reads the current non-passing finding, creates a Mind acceptance
|
||||
whose only allowed effect is `repoWork.modelingRoute`, and atomically commits
|
||||
the next request, review, and stable route pointer. The transition preserves
|
||||
item, Soul receipt, commit, and changed paths; passing findings cannot retry;
|
||||
stale repeat advancement is refused; prior requests/findings remain readable.
|
||||
Scheduler job IDs are generation-scoped and scheduler reads the stable typed
|
||||
route rather than `work-close-*.json` request cargo. Authority tests pass 4/4,
|
||||
core library 248/248, and model runtime 8/8. Authenticated live item
|
||||
`typed-modeling-route-v2` proved generation zero through Idunn, model-authored
|
||||
finding, Mind/map admission, and closure. The preceding
|
||||
`typed-modeling-route` probe correctly failed because the already-built model
|
||||
runtime lacked the new route schema; rebuilding the consumer made v2 pass.
|
||||
Next expose executable build/schema fingerprint in the Idunn lifecycle receipt
|
||||
and refuse launch before work when the consumer cannot register required typed
|
||||
documents.
|
||||
|
||||
## Immediate Re-entry Instruction
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -659,4 +659,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`. Gjallar 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: Design and implement a typed Mind-reviewed request-generation pointer for non-passing immutable repo-work Modeling findings. Idunn now owns detached worker launch through the existing daemon service lifecycle receipt mouth. Preserve each prior request/finding as immutable evidence; filesystem closure artifacts and Self must not become mutable routing authorities.
|
||||
next_action: Expose the launched worker executable build/schema fingerprint in Idunn's lifecycle receipt and preflight required runtime document registration before launch. The first typed-route live probe found a stale epiphany-openai-runtime binary; after rebuild, generation-zero item typed-modeling-route-v2 closed successfully. Preserve the typed route owner and Mind-reviewed generation transition; do not mutate requests/findings to compensate for stale consumers.
|
||||
|
|
|
|||
Reference in a new issue