From 42f978ecc44cf552ccd6cfc45e948cd3fc20b40d Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Fri, 6 Nov 2026 10:22:52 +0800 Subject: [PATCH 1/2] feat(goals): check Goal commitments without gating local Todos Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- .../smoke/goal-acceptance-contract-smoke.mjs | 3 ++ .../dashboard/src/data/delivery-review.ts | 8 ++-- .../src/data/goal-acceptance-actions.ts | 2 +- .../src/data/goal-acceptance-observation.ts | 1 + .../delivery-review-copy.ts | 4 +- .../goal-acceptance-contract.tsx | 6 +-- .../reference/goal-acceptance-observations.md | 19 +++++++- .../goals/acceptance_authority.ts | 2 +- .../goals/acceptance_contract.ts | 21 ++++++--- .../goals/outcome_requirements.ts | 2 +- .../control_plane/test_goal_acceptance_cli.py | 43 +++++++++++++++++++ .../goal_acceptance_authority.test.ts | 28 ++++++++++++ 12 files changed, 119 insertions(+), 20 deletions(-) diff --git a/apps/presentation/dashboard/smoke/goal-acceptance-contract-smoke.mjs b/apps/presentation/dashboard/smoke/goal-acceptance-contract-smoke.mjs index 9cd8ec23b1..f1a326f38e 100644 --- a/apps/presentation/dashboard/smoke/goal-acceptance-contract-smoke.mjs +++ b/apps/presentation/dashboard/smoke/goal-acceptance-contract-smoke.mjs @@ -31,6 +31,9 @@ for (const copy of Object.values(deliveryReviewCopy)) { scope: { kind: "selected_work", todo_ids: ["todo_confirmed"] } }), snapshot.goal_id); assert.ok(deliveryReviewMarkdown(selected, copy).includes(copy.contract.selectedWork)); assert.ok(deliveryReviewMarkdown(parseDeliveryReview(withContract(contract), snapshot.goal_id), copy).includes(copy.contract.allWork)); + const goalOnly = parseDeliveryReview(withContract({ ...contract, + scope: { kind: "goal" }, tasks: [], held_todo_ids: [] }), snapshot.goal_id); + assert.ok(deliveryReviewMarkdown(goalOnly, copy).includes(copy.contract.goalOnly)); const empty = parseDeliveryReview(withContract({ ...contract, criteria: [], tasks: [] }), snapshot.goal_id); assert.ok(deliveryReviewMarkdown(empty, copy).includes(copy.contract.noTasks)); assert.ok(deliveryReviewMarkdown(empty, copy).includes(copy.contract.noCriteria)); diff --git a/apps/presentation/dashboard/src/data/delivery-review.ts b/apps/presentation/dashboard/src/data/delivery-review.ts index ad2b7a2a92..4986e2f37a 100644 --- a/apps/presentation/dashboard/src/data/delivery-review.ts +++ b/apps/presentation/dashboard/src/data/delivery-review.ts @@ -138,7 +138,7 @@ export function reviewNodeColumn(node: ReviewNode) { } type ConfiguredContract = GoalAcceptanceChecks; -type ContractExportLabels = Record<"title" | "boundary" | "scope" | "selectedWork" | "allWork" | "source" | "revision" | "digest" | "objective" | "criteria" +type ContractExportLabels = Record<"title" | "boundary" | "scope" | "goalOnly" | "selectedWork" | "allWork" | "source" | "revision" | "digest" | "objective" | "criteria" | "nonGoals" | "tasks" | "verification" | "unknown" | "noTasks" | "noCriteria" | "notApplicable" | "heldTasks" | "receipt" | "receiptNote" | "operation" | "verificationScope" | "allCriteria" | "passed" | "failed" | "exitCode" | "oracleChecker" | "oracleSourceDigest" | "oracleCheckedAt" | "oracleInputVersions" | "oracleOutputVersions", string> & { @@ -236,7 +236,7 @@ export function deliveryReviewMarkdown(snapshot: DeliveryReviewSnapshot, labels: if (hasConfiguredGoalChecks(contract)) { const copy = labels.contract; rows.push("", `## ${copy.title}`, "", copy.boundary, - `${copy.scope}: ${contract.scope?.kind === "selected_work" ? copy.selectedWork : copy.allWork}`, + `${copy.scope}: ${contract.scope?.kind === "goal" ? copy.goalOnly : contract.scope?.kind === "selected_work" ? copy.selectedWork : copy.allWork}`, `${copy.source}: ${line(snapshot.goal_id)}`, `${copy.revision}: ${contract.revision}`, `${copy.digest}: ${line(contract.digest)}`, "", `### ${copy.objective}`, line(contract.objective || copy.unknown), "", `### ${copy.criteria}`); if (contract.non_goals.length) rows.push(`${copy.nonGoals}: ${line(contract.non_goals.join("; "))}`); @@ -246,8 +246,8 @@ export function deliveryReviewMarkdown(snapshot: DeliveryReviewSnapshot, labels: if (criterion.oracle) rows.push(` ${copy.oracleChecker}: ${line(criterion.oracle.source_id)} · ${copy.oracleState[criterion.oracle.state]}`, ` ${copy.oracleSourceDigest}: ${line(criterion.oracle.source_digest)}`); } - rows.push("", `### ${copy.tasks}`); - if (!contract.tasks.length) rows.push(copy.noTasks); + if (contract.tasks.length || contract.scope?.kind !== "goal") rows.push("", `### ${copy.tasks}`); + if (!contract.tasks.length && contract.scope?.kind !== "goal") rows.push(copy.noTasks); for (const task of contract.tasks) { rows.push(`- ${line(task.todo_id)}: ${copy.taskState[task.state]}`, ` ${copy.criteria}: ${line(task.criterion_ids.join(", ") || copy.unknown)}`); diff --git a/apps/presentation/dashboard/src/data/goal-acceptance-actions.ts b/apps/presentation/dashboard/src/data/goal-acceptance-actions.ts index 00ebe4c742..c956403af4 100644 --- a/apps/presentation/dashboard/src/data/goal-acceptance-actions.ts +++ b/apps/presentation/dashboard/src/data/goal-acceptance-actions.ts @@ -17,7 +17,7 @@ export async function acceptanceRequest(goalId: string, operation?: Record void operate("clear-checks")}>{zh ? "移除检查配置" : "Remove check configuration"}
{copy.source}
{goalId}
- {checksConfigured ? <>
{copy.scope}
{contract.scope?.kind === "selected_work" ? copy.selectedWork : copy.allWork}
+ {checksConfigured ? <>
{copy.scope}
{contract.scope?.kind === "goal" ? copy.goalOnly : contract.scope?.kind === "selected_work" ? copy.selectedWork : copy.allWork}
{copy.revision}
{contract.revision}
{copy.digest}
{contract.digest}
: null}
- {checksConfigured ? <>

{contract.non_goals.join(" · ")}

{copy.tasks}

+ {checksConfigured ? <>

{contract.non_goals.join(" · ")}

{contract.tasks.length ?

{copy.tasks}

: null}