Skip to content

Goal acceptance observations

Open a local Goal, then Overview → Delivery & evidence → Acceptance observations. The read-only card shows each observed acceptance requirement with its Agent and observation time, pending gates with their target Agent and decision scope, and the next action already projected by status. A missing human decision owner is shown as unknown; the blocked Agent is not assumed to be the approver.

The same projection is available as run_history.goals[].acceptance_observation in loopx status --format json; status Markdown includes a compact summary. The observation card requires no activation or new permission. It changes presentation only; Todo, gate, quota, settlement, and Goal completion authority are unchanged.

Acceptance requirements reuse the frontier's existing per-Agent vision rules from already-collected history before display trimming. It does not collect a complete frontier or audit all Agent lanes. History is bounded, so every result is partial: no gaps is not successful acceptance. Missing sources and truncated observations stay visible. Historical lifecycle markers have source references when available and never override current open gates.

This bounded slice uses goal_acceptance_observation_projection_v0. It is not the broader goal_artifact_lifecycle_projection_v0 contract proposed by the Goal artifact lifecycle RFC, whose phases, declared milestones and legal transitions remain unchanged. No alias accepts that broader schema as this observation payload. It does not introduce declared milestone authoring, a universal phase sequence, an exhaustive evidence audit, new legal transitions, or a completion decision. Legacy sources without the projection display unavailable, not success. The proposed Goal direction baseline material declarations and revision-bound usage receipts are not implemented here; historical progress does not establish that current direction materials were read.

Status also exposes a separate run_history.goals[].artifact_lifecycle readout and Markdown summary: observed phase, evidence milestones, guards and next steps. It consumes the current Goal's session-runtime work observation before display trimming. Outstanding required work keeps the phase qualifying even when Todos are complete and historical progress is reached. An absent work observation does not invent a work requirement. This v0 readout never recommends a terminal transition: closing stays a verification step with the machine-readable next_transitions[].reason_codes value acceptance_unverified, both when sources are missing and when all bounded sources were observed. Consumers use that code, not English precondition text. A Goal already recorded as terminal still displays lifecycle_phase: closed with no next transitions. Adding acceptance-driven terminal advice requires a separate contract change and producer-side validation. This readout grants no execution or completion authority; the Dashboard card above keeps its separate acceptance-observation contract.

Work observation coverage follows the supplied projection, not adapter.kind:

Source delivered to status Work observation coverage
Session-runtime adapter, or another adapter emitting the same session-runtime projection Available only with session_runtime_readonly_projection_v0, a matching Goal id, and work facts
Adapter without that projection, or a projection with a mismatched schema/Goal id Unavailable; this readout does not query quota or other lane owners

Without that source a Goal may read closing from Todo/history even when a lane outside the observation still requires work. Neither closing nor absence of work_lane_selected proves all work is complete; the lane and completion owners retain their decisions.

Validation: python -m pytest tests/control_plane/test_goal_acceptance_observation.py and python -m pytest tests/control_plane/test_goal_artifact_work_observation.py, plus node examples/dashboard-goal-acceptance-browser-smoke.mjs. The browser check consumes real status collection over a disposable synthetic Goal; set LOOPX_GOAL_ACCEPTANCE_PACKAGED=1 after the Dashboard build to check shipped assets.

Owner-authorized contract (v0)

An owner can opt an existing registered Goal into a versioned acceptance contract. The Goal must already use promoted canonical authority. These commands never promote a provider or fall back to legacy Markdown when canonical reads fail. The owner makes three explicit decisions: the objective and its acceptance criteria, which existing advancement tasks serve those criteria, and whether to enable this governance. The existing Goal authority owns the contract; the Dashboard only reads it. No new capability editor or provider is introduced.

From the Goal's delivery workspace, inspect the current provider revision:

loopx --format json goal-acceptance inspect --goal-id example-goal
loopx --format json todo list --goal-id example-goal

Prepare an owner-reviewed acceptance.json, replacing the illustrative file check and task ID with the actual artifact checks and existing advancement task:

{
  "objective": "Deliver a checked artifact",
  "non_goals": ["Publish the artifact"],
  "criteria": [{
    "id": "artifact-present",
    "description": "The delivered text artifact exists and is nonempty.",
    "validation_argv": ["python3", "-c", "from pathlib import Path; assert Path('deliverable.txt').read_text().strip()"],
    "validation_timeout_seconds": 5
  }],
  "bindings": [{"todo_id": "todo_deliver", "criterion_ids": ["artifact-present"]}]
}

Keep executable declarations in the owner's local file; public readback omits command arguments and output. The configured checks run as bounded argv commands without a shell, using the existing delivery-workspace validation rules. Each criterion allows 1–25 seconds and defaults to 5 seconds. The sum of all criterion timeouts must not exceed 25 seconds. Run longer evaluations outside the completion wrapper and configure a bounded check of their resulting artifact.

The inline Python example binds its code text in the versioned document. For a script validator, optionally run sha256sum verify.py and add "validation_files": [{"path": "verify.py", "sha256": "<64-hex-digest>"}] to that criterion, using a delivery-workspace-relative path. The host checks the declared file bytes before and after the real run to detect changes. This bounded check does not prove all transitive imports or interpreter/external-tool identity.

Configure without --agent-id: registered Agent-role invocations can inspect and verify, but cannot configure or disable the contract. This is a trusted local invocation role, not an authentication boundary. The CLI relies on existing local-process and private-runtime filesystem permissions; omitting --agent-id is not authentication. Processes with the same private-runtime permissions are not isolated from owner operations.

Substitute the exact provider_revision from the preceding inspect, not the acceptance revision:

loopx goal-acceptance configure --goal-id example-goal --document acceptance.json --expected-provider-revision '<provider_revision>'
loopx goal-acceptance configure --goal-id example-goal --document acceptance.json --expected-provider-revision '<provider_revision>' --execute
loopx --format json goal-acceptance inspect --goal-id example-goal

Omitting --execute previews configuration. A revision conflict requires a new inspect and review of the changed basis before retrying. After enablement, the existing task claim and completion paths enforce the contract: applicable work with an unbound or stale association is held; the owner must confirm its current association by reconfiguring. Completion executes fresh bound artifact checks and retains the existing claim, lease/fence, permission and continuation gates. A prior verification receipt or a confirmed association cannot complete a task. Use loopx todo claim --help and loopx todo complete --help for the existing task arguments; this contract adds no bypass flags.

Terminal observations, including no_followup, do not change the work digest: finishing a task must not stale the binding that just admitted its completion. Text, validation requirements and unknown future work fields still invalidate the association. Existing enabled contracts configured with a persisted no_followup field under the earlier digest rule require owner inspection and reconfiguration; no historical receipt is rewritten or automatically accepted. Disabled/absent acceptance retains its existing behavior.

For an already authorized delegation, turn plan --todo-id todo_example and turn run-once --todo-id todo_example select that exact currently eligible work through the existing quota owner. Omitting the option retains controller selection. An unavailable task cannot silently select a different one. The option does not retarget resumed Turns or host sessions and is not exposed by turn managed-step; it grants no new task, lease, budget or completion authority.

Run all configured Goal checks and read back their recorded basis:

loopx goal-acceptance verify --goal-id example-goal
loopx goal-acceptance verify --goal-id example-goal --execute
loopx --format json goal-acceptance inspect --goal-id example-goal

Verification without --execute is a preview. In Overview → Delivery & evidence, refresh the snapshot and expand Goal acceptance contract below the delivery chain. It shows the Goal ID, contract revision/digest, criteria, task associations, and verification results with their own revision/digest. The section exists only when the server's acceptance.goal_acceptance_contract.enabled is true. Missing or disabled contracts retain the baseline UI and export. The existing snapshot export and status Markdown include the enabled readback without command bodies or raw logs.

Server state Readback meaning
Task ready Owner confirmed the current task association; artifact checks are separate
Task unbound / stale Association is missing / no longer current; applicable: false identifies tasks outside the current gate
Contract unverified Artifact checks have not been verified
Contract failed / stale Checks failed / their recorded basis is no longer current
Contract partial Task-scoped checks passed; Goal-wide verification remains unknown
Contract held Applicable task associations require confirmation; historical results remain inspectable
Contract accepted All configured artifact checks passed on the current basis; this does not approve or complete the Goal

Disabling is an explicit owner operation against a freshly inspected provider revision. It hides the contextual readback and removes this opt-in gate; existing task authority, permissions, and lifecycle rules still apply:

loopx --format json goal-acceptance inspect --goal-id example-goal
loopx goal-acceptance disable --goal-id example-goal --expected-provider-revision '<current_provider_revision>' --execute
loopx --format json goal-acceptance inspect --goal-id example-goal

Activation grants no publication, external effect, provider-promotion or Goal completion authority. Keep objective, criterion descriptions and reasons safe for their status audience. Lark rendering, remote contract editing, semantic intent-preservation proofs and general shared amendments remain outside this local-owner slice. Follow-up belongs to #3836 and #2831; it does not close either RFC.

Readback validation: Dashboard npm run smoke:delivery-review, node smoke/goal-acceptance-contract-smoke.mjs, npm run smoke:goal-acceptance-contract-browser, and uv run --extra test python -m pytest tests/test_goal_acceptance_contract_rendering.py. After the integrated Dashboard build, npm run smoke:goal-acceptance-contract-packaged runs the same contract browser check against the shipped assets.

中文

打开本机 Goal,选择 概览 → 交付与依据 → 验收观察。 只读卡片展示已有验收要求、对应 Agent、观测时间、待处理门禁的目标 Agent 和决策范围, 以及 status 已给出的下一步。人类决策责任人未提供时显示未知,不把被阻塞的 Agent 当作审批人。loopx status --format json 中的 run_history.goals[].acceptance_observation 提供相同投影,Markdown 提供简要摘要。

原有观察卡片无需启用或增加权限。仅改变展示,不改变 Todo、gate、quota、settlement 或 Goal 完成权威。 验收要求复用执行前沿已有的 Agent vision 规则,并消费展示截断前已读取的历史,不额外读取文件。 不收集完整执行前沿,也不审计所有 Agent 通道。历史是有界输入,因此始终显示部分观测: 没有缺口不等于通过验收。 缺少来源及观测截断会明确提示;历史生命周期记录不能覆盖当前未关闭的门禁。

此有界切片使用 goal_acceptance_observation_projection_v0,不是 RFC 中的完整 goal_artifact_lifecycle_projection_v0;后者的阶段、声明式里程碑和合法迁移设计保持不变。 不保留把完整协议误认作该观察结构的别名。此切片不增加里程碑声明入口、统一阶段序列、完整证据审计、 新的合法迁移或完成判定。Goal direction baseline 提案中的材料声明和绑定版本的阅读回执 不在此次实现范围;历史进展不能证明已阅读当前方向材料。旧来源不提供投影时显示不可用。 status 同时在独立的 run_history.goals[].artifact_lifecycle 和 Markdown 摘要中展示 观测阶段、证据里程碑、门禁和下一步。它在展示截断前读取当前 Goal 的 session-runtime 工作观察:即使 Todo 全部完成且历史进展已达成,只要仍有必须执行的工作,阶段就保持 qualifying。缺少工作观察不会凭空产生执行要求。此 v0 读出始终不建议终态迁移closing 保持为验收核验步骤,无论是否缺少来源,均通过 next_transitions[].reason_codes 中的 acceptance_unverified 表达本读出未验证验收。 机器消费者读取该 code,无需匹配英文 precondition。已记录为终态的 Goal 仍展示 lifecycle_phase: closed,下一步列表为空。未来若增加基于验收的终态建议,必须另行变更合同并验证产出侧。 此读出不授予执行或完成权威,Dashboard 卡片仍使用独立的验收观察合同。

工作观察覆盖取决于实际提供的投影,不按 adapter.kind 名称判断:

status 接收的来源 工作观察覆盖
session-runtime adapter,或提供相同 session-runtime 投影的其它 adapter schema 为 session_runtime_readonly_projection_v0、Goal id 匹配且包含工作事实时可用
不提供该投影的 adapter,或 schema/Goal id 不匹配的投影 不可用;此读出不会额外查询 quota 或其它工作通道权威

缺少该来源时,即使观察范围外仍有必须执行的工作,Todo/历史也可能让 Goal 显示 closingclosing 或缺少 work_lane_selected 均不证明所有工作完成,工作通道与完成权威仍保留各自的判断。 上面的测试命令覆盖合成 Goal 的生产 refresh-state 写入、 真实 status 收集和浏览器入口;打包验证使用 LOOPX_GOAL_ACCEPTANCE_PACKAGED=1

所有者授权的验收合同(v0)

所有者可为已注册且已提升到 canonical authority 的 Goal 显式启用版本化验收合同。 命令不会自动提升 provider,canonical 读取失败也不回退到旧 Markdown。 三个明确决定是:目标与验收条件、现有推进任务与条件的关联、是否启用这项治理。 合同归既有 Goal authority 所有,Dashboard 只读,不新增配置编辑器或 provider。

在 Goal 的交付工作区先运行 loopx --format json goal-acceptance inspect --goal-id example-goal, 并用 loopx --format json todo list --goal-id example-goal 查看任务。 按上方 JSON 示例准备所有者审阅过的 acceptance.json,将文件检查与任务 ID 替换为实际产物 检查和已有推进任务。argv 检查不经过 shell,沿用既有交付工作区验证规则;命令声明保留在本地, 公开读回不含参数、输出或原始日志。每个条件允许 1–25 秒,默认 5 秒;所有条件的 超时总和不得超过 25 秒。较长评估在完成包装器之外运行,再配置有界的产物检查。

上方内联 Python 示例的代码文本绑定在版本化文档中。脚本型验证器可选地运行 sha256sum verify.py,并在该条件中加入 "validation_files": [{"path": "verify.py", "sha256": "<64-hex-digest>"}], 路径相对于交付工作区。host 在真实运行前后检查声明文件的字节以发现变更; 这项有界检查不证明全部传递导入或解释器/外部工具身份。

所有者使用 goal-acceptance configure --goal-id example-goal --document acceptance.json --expected-provider-revision '<provider_revision>' 预览,再加 --execute 启用; 这里填写最近 inspect 返回的 provider revision,不是合同版本。配置时不传 --agent-id: 已注册 Agent 角色调用可 inspect/verify,但不能配置或停用合同。 所有者角色依赖受信任的本地调用,不是身份认证边界。 CLI 沿用本地进程与私有 runtime 文件系统权限;省略 --agent-id 不构成身份认证,具有相同私有 runtime 权限的进程 不会与所有者操作隔离。发生版本冲突时重新 inspect, 审阅变化后再重试,配置后再次 inspect 确认。

启用后,现有任务 claim/complete 路径执行真实门禁:适用任务缺少关联或关联过期时受阻, 所有者通过重新配置确认当前关联;完成任务必须执行当前绑定的产物检查,并继续满足原有 claim、lease/fence、权限和后续工作要求。既有验证回执或已确认的关联不能代替本次任务完成验证。 任务参数沿用 loopx todo claim --helploopx todo complete --help,没有绕过门禁的新参数。

loopx goal-acceptance verify --goal-id example-goal 仅预览;加 --execute 执行全部配置条件, 再运行 inspect 读回。进入 概览 → 交付与依据,刷新并展开交付链下方的 Goal 验收合同。 区块仅在服务端 acceptance.goal_acceptance_contract.enabled=true 时显示,缺失或停用保持原界面与导出。 区块及导出展示 Goal ID、合同版本/摘要、条件、任务关联,以及带独立版本/摘要的历史验证结果。

任务 ready 只表示所有者确认关联;unbound / stale 表示缺失 / 过期; applicable=false 表示不属于当前任务门禁范围。合同 unverified 表示未验证, failed / stale 表示检查失败 / 检查基线过期,partial 表示任务检查通过但 Goal 整体验证未知, held 表示适用任务关联需要确认。accepted 仅表示当前基线上的全部配置产物检查通过, 不代表自动批准或完成 Goal。

停用前重新 inspect,随后执行 loopx goal-acceptance disable --goal-id example-goal --expected-provider-revision '<current_provider_revision>' --execute, 并再次 inspect。停用隐藏此区块并移除此项显式启用的门禁,原有任务权威、权限和生命周期规则仍生效。 启用不会授予发布、外部副作用、provider 提升或 Goal 完成权威;目标、条件描述与原因必须适合其 status 受众。 Lark 呈现、远端合同编辑、语义意图保持证明与通用共享 amendment 留给 #3836 / #2831 后续切片, 不宣称任一 RFC 已完成。合同浏览器检查用 npm run smoke:goal-acceptance-contract-browser; 前端集成打包后,npm run smoke:goal-acceptance-contract-packaged 对已发布资源跑同一项检查。 Python renderer 测试和 API/export smoke 覆盖缺失、停用、过期、失败及通过的区别。