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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/09-reviews/2026-09-02-m5-2-real-effects-live-attempt.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,17 @@ brittle model obligation. The correction makes it a coordinator-bound schema
constant instead, while retaining exact path/counterexample comparison against
the detached checkout, bounded reason validation, wrong-content negative
coverage, and all downstream lifecycle/Git/verifier bindings.

## Attempts 14 and 15

Attempt 14 stopped before business execution with a bootstrap marker mismatch:
3 created roles were deleted and absence-confirmed, all business counts stayed
zero, and cleanup completed. One bounded retry was allowed because the reviewer
fix was not exercised and no business effect occurred.

Attempt 15 crossed bootstrap but again reported 5 selected and 4 completed
actions at the reviewer callback. This disproves the digest-copy hypothesis:
another exact finding condition is being rejected. The compound validator is
therefore split into fixed source, resource, counterexample, checkout, reason,
and digest branches. The public failure projection may expose only one matching
boundary enum; it still cannot expose model arguments or outputs.
7 changes: 7 additions & 0 deletions docs/09-reviews/2026-09-02-mainline-checkpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ coordinator-derivable digest from tool output with a coordinator-bound schema
constant. Exact path and counterexample matching against the detached checkout,
negative tamper coverage, and the downstream verifier chain remain mandatory.

Attempt 14 did not exercise the change because role bootstrap failed with zero
business records and exact cleanup. Attempt 15 reached the reviewer but retained
the 5-selected/4-completed result, disproving the digest-copy hypothesis. The
compound callback validator is now split into six fixed, publicly safe boundary
enums so the next failure identifies the exact rejected condition without
publishing any model argument or output.

## Ordered next gates

1. Run the merged real-effects Codex path once with the new partial-stage
Expand Down
37 changes: 28 additions & 9 deletions src/validation/coordinator-driven-no-plan-scenario.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ export const COORDINATOR_FAILURE_RECONCILIATION_REASONS = Object.freeze([
"codex-native-turn-still-in-progress",
"codex-native-turn-started-id-mismatch",
]);
export const COORDINATOR_FAILURE_BOUNDARIES = Object.freeze({
threadmesh_real_effect_review_source_invalid: "review-source",
threadmesh_real_effect_review_resource_invalid: "review-resource",
threadmesh_real_effect_review_counterexample_invalid: "review-counterexample",
threadmesh_real_effect_review_checkout_invalid: "review-checkout",
threadmesh_real_effect_review_reason_invalid: "review-reason",
threadmesh_real_effect_review_digest_invalid: "review-digest",
});

export function deriveCoordinatorDrivenFailureStage(counts) {
const durableStages = Math.min(
Expand Down Expand Up @@ -110,6 +118,7 @@ export function captureCoordinatorDrivenFailureProgress(database, error) {
? {
state: "ambiguous",
reasonCode,
boundary: COORDINATOR_FAILURE_BOUNDARIES[error?.originCode] ?? null,
}
: null;
return Object.freeze({
Expand Down Expand Up @@ -1349,15 +1358,25 @@ export async function runCoordinatorDrivenNoPlanScenario({
counterexample: value?.counterexample,
};
const candidateDigest = independentGitFindingDigest(candidate);
if (
value?.sourceEventId !== artifactEvent.messageId ||
candidate.resourcePath !== REAL_EFFECT_RESOURCE ||
candidate.counterexample !== content.trim() ||
!content.includes(candidate.counterexample) ||
checkout.subjectSha !== implementationSha ||
typeof value?.reason !== "string" || value.reason.length < 1 ||
value?.findingDigest !== candidateDigest
) throw scenarioError("threadmesh_real_effect_review_finding_not_reproduced");
if (value?.sourceEventId !== artifactEvent.messageId) {
throw scenarioError("threadmesh_real_effect_review_source_invalid");
}
if (candidate.resourcePath !== REAL_EFFECT_RESOURCE) {
throw scenarioError("threadmesh_real_effect_review_resource_invalid");
}
if (candidate.counterexample !== content.trim() ||
!content.includes(candidate.counterexample)) {
throw scenarioError("threadmesh_real_effect_review_counterexample_invalid");
}
if (checkout.subjectSha !== implementationSha) {
throw scenarioError("threadmesh_real_effect_review_checkout_invalid");
}
if (typeof value?.reason !== "string" || value.reason.length < 1) {
throw scenarioError("threadmesh_real_effect_review_reason_invalid");
}
if (value?.findingDigest !== candidateDigest) {
throw scenarioError("threadmesh_real_effect_review_digest_invalid");
}
finding = Object.freeze(candidate);
findingDigest = candidateDigest;
payloads["review-failed"].findingDigest = findingDigest;
Expand Down
8 changes: 6 additions & 2 deletions src/validation/m5-2-event-pump-codex-gate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from "node:path";

import { canonicalJson, sha256Digest } from "../canonical-json.mjs";
import {
COORDINATOR_FAILURE_BOUNDARIES,
COORDINATOR_FAILURE_RECONCILIATION_REASONS,
deriveCoordinatorDrivenFailureStage,
runCoordinatorDrivenNoPlanScenario,
Expand Down Expand Up @@ -203,17 +204,20 @@ export function projectM52EventPumpFailureProgress(value) {
let reconciliation = null;
if (value.reconciliation !== null) {
const source = value.reconciliation;
const reconciliationKeys = ["state", "reasonCode"];
const reconciliationKeys = ["state", "reasonCode", "boundary"];
if (!source || typeof source !== "object" || Array.isArray(source) ||
canonicalJson(Object.keys(source).sort()) !==
canonicalJson(reconciliationKeys.sort()) ||
source.state !== "ambiguous" ||
!COORDINATOR_FAILURE_RECONCILIATION_REASONS.includes(source.reasonCode)) {
!COORDINATOR_FAILURE_RECONCILIATION_REASONS.includes(source.reasonCode) ||
(source.boundary !== null &&
!Object.values(COORDINATOR_FAILURE_BOUNDARIES).includes(source.boundary))) {
return null;
}
reconciliation = Object.freeze({
state: source.state,
reasonCode: source.reasonCode,
boundary: source.boundary,
});
}
return Object.freeze({
Expand Down
2 changes: 1 addition & 1 deletion test/coordinator-driven-no-plan-scenario.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ test("real-effects path rejects a model-reported finding not present in checkout
(error) => {
assert.equal(error?.code, "threadmesh_codex_live_context_terminal_reconciled");
assert.equal(error?.originCode,
"threadmesh_real_effect_review_finding_not_reproduced");
"threadmesh_real_effect_review_counterexample_invalid");
assert.equal(error.cleanup?.complete, true);
assert.equal(error.cleanup?.roles.length, 5);
assert.equal(error.cleanup?.verifierServiceClosed, true);
Expand Down
2 changes: 2 additions & 0 deletions test/m5-2-event-pump-codex-gate.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ test("failure progress projection exposes only bounded SQLite-derived stage data
reconciliation: {
state: "ambiguous",
reasonCode: "codex-native-turn-completed-observation-only",
boundary: "review-counterexample",
},
};
assert.deepEqual(projectM52EventPumpFailureProgress(source), source);
Expand All @@ -447,6 +448,7 @@ test("failure progress projection exposes only bounded SQLite-derived stage data
(value) => { value.stage = "review-published"; },
(value) => { value.reconciliation.reasonCode = "/private/raw/path"; },
(value) => { value.reconciliation.reasonCode = "codex-native-turn-secret-id"; },
(value) => { value.reconciliation.boundary = "review-secret-id"; },
]) {
const tampered = structuredClone(source);
mutate(tampered);
Expand Down
Loading