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
31 changes: 31 additions & 0 deletions benchmark/runtime/EXECUTION_OBSERVATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ merely to produce an attachment. Configuration and readback invoke neither a
probe nor a model. Runtime receipts record the selected producer, which does
not attest execution, adoption or improvement.

Choose the settlement plan's ordinary `command_template` for in-flight progress
without new decision evidence. Use `semantic_closeout_command_template` for new
evidence from this admitted work, a route change or Todo completion; bind the
evaluated artifact/input and actual decision in a fresh Vision/path_delta,
including `continue`/`no_change` when retaining the route. Keep the original
Goal/Todo/Turn, follow the remaining writeback/spend steps and yield for freshly
guarded Host continuation; an unfinished Todo stays open. Prior-feedback
readback, bookkeeping and deterministic rechecks without new information are
context, not new progress: use them to advance the task first. Unchanged polls
alone need no checkpoint; neither feedback counts nor this command enables Stride.

For explicitly continuing optimization, candidate usability alone is not completion: before
stopping, weigh acceptance gaps, plausible headroom and feasible next work's full marginal
cost against accepted stops, recording evidence in path_delta. Continue/replan
useful authorized work; preserve Stop, budget/permission limits and genuine waits,
and never infer completion or invent work, pivots or successors from submission
or unused budget alone. This is Agent guidance, not automatic tool-result classification;
native-model adoption, long-Turn supervision and outcome benefit remain unqualified.

## Retiring the bundled research treatment

`research_loop` and `LOOPX_RESEARCH_LOOP` have been removed. Any presence of
Expand Down Expand Up @@ -170,6 +189,18 @@ Stop、原预算和真实阻塞继续有效,不为填满时长制造任务。
变化拒绝归因;文件清单哈希不是原生归档哈希,只覆盖明确选择的文件及探针
边界,不覆盖传递依赖或独立写入者,结果仍须证明对应实际评测快照和输入版本。

当前授权工作实际产生或取得新的决策证据后,才进入相应工作段的检查点。旧反馈读回、
记账和没有新增信息的确定性重复验证只是上下文,应先用于推进原任务。使用当前
settlement plan 的 `durable_writeback.semantic_closeout_command_template`,
保留原 Turn、Todo、Goal 身份,填写实际结果和 Vision,再按同一 plan 的剩余
步骤结算并让宿主接续;未完成的 Todo 保持 open。即使路线不变,也在既有
Vision/path delta 中记录被评估版本、输入和决策。下一次 guard 继续同一 Goal/session
或执行已有到期复核;反馈数量与这个命令都不启用 Stride。未变化轮询、记账本身
无需新 checkpoint。明确持续优化的目标不能因已有可用候选就自动收尾;结束前
评估剩余验收、改进空间、可行实验、完整边际成本和原停止条件。合理时可停止,
不强制换路或用满时间。这是 Agent 执行指导,不是自动分类工具结果或模型已采用的证明。
原生模型采用、自动长轮次监督和结果收益仍未取得资格,脚本路径通过不能替代这些证据。

观测通过既有 Explore 写回、replan 和研究历程保留,输入版本与引用必须属于
该 finding,计划/实际方法不同须记录理由。finding 引用及观测的 `evidence_refs`、
`result_ref` 共用既有语法,可保留 `validation:run/1`;方法 ID 仍使用独立规则。
Expand Down
61 changes: 52 additions & 9 deletions docs/reference/protocols/goal-vision-replan-contract-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -917,14 +917,57 @@ receipts retain their checkpoint semantics:
}
```

CLI in-flight settlement omits the material-closeout Vision authoring schema.
Use the projected continuation command and its original boundary/identity flags;
this does not waive validation, writeback or debit rules. Material CLI closeout
and MCP `complete_task` retain their evidence-linked Vision authoring contract.

CLI 进行中结算不附带实质收尾的 Vision 编写结构。沿用投影命令及原边界、身份
参数,仍须验证、写回与原 debit;实质 CLI 收尾和 MCP `complete_task` 保留
证据关联的 Vision 编写契约。
Ordinary CLI Todo settlement includes the existing Vision authoring schema even
when its default boundary is in-flight. The durable-writeback step also exposes
`semantic_closeout_command_template`: the same admitted Goal, Todo and Turn,
with `--delivery-boundary semantic_closeout --agent-vision-json <file>` selected.
It is an alternative for that step, not another plan, claim, debit or admission.
Material CLI closeout and MCP `complete_task` retain their existing evidence gates.

Choose `command_template` for ordinary in-flight progress without new decision
evidence; use `semantic_closeout_command_template` for new evidence from this
admitted work, a route change or Todo completion. Bind the evaluated artifact/input
and actual decision in fresh Vision/path_delta, including `continue`/`no_change`
when retaining the route. Keep the original Goal/Todo/Turn, follow the remaining
writeback/spend steps and yield for freshly guarded Host continuation; an unfinished
Todo stays open. Prior-feedback readback, bookkeeping and deterministic rechecks
without new information are context, not progress: advance the task first.
Unchanged polls alone need no checkpoint. This is Agent guidance, not automatic
tool-text classification, a Stride trigger or proof of adoption/benefit.

An open Todo with controller-declared completion validation can use this
semantic checkpoint for `outcome_progress` with a fresh, open Vision and an
evidence-linked `continue` or `no_change` path. The shared settlement owner
qualifies the admitted writeback and its exact receipted spend through the same
rule. This closes only the original Turn: the Todo remains open and its final
completion validator remains pending. Primary-outcome, closed-Vision and
terminal declarations retain that validator gate.

For explicitly continuing/optimization objectives, candidate usability alone is not completion:
before stop/no_followup, weigh acceptance gaps, plausible headroom and feasible next work's
full marginal cost against accepted stops in an evidence-linked path_delta.
Continue/replan useful authorized work; preserve Stop, budget/permission limits
and genuine waits. Neither submission nor unused budget alone establishes completion
or requires invented work, pivots or successors.

普通 CLI Todo 的默认 in-flight 结算也提供 Vision 编写结构。无新决策证据的普通
推进选 `command_template`;本次准入工作产生或取得新证据、改变路线或完成 Todo,
选 `semantic_closeout_command_template`,以 fresh Vision/path_delta 关联评估产物、
输入版本和实际决策,保留路线也可用 `continue` / `no_change`。沿用原 Goal、Todo、
Turn,按原计划继续写回和扣额,再由宿主以新 guard 接续;未完成 Todo 保持 open,
不另建 plan、认领、扣额或准入。旧反馈读回、记账、无新信息的确定性重验只是上下文,
应先用于推进任务;未变化轮询不要求新 checkpoint。它是 Agent 指导,不自动分类
工具文本、不触发 Stride,也不证明模型采用或收益。

持续优化目标不能仅因候选可用就完成:停止前在 path_delta 中用证据对照剩余验收、
改进空间、可行后续工作的完整边际成本和原停止条件;继续或重规划有用且获授权的工作,
保留 Stop、预算/权限限制与真实等待。提交或剩余额度均不证明完成,也不要求制造工作、
换路或后继 Todo。

声明完成验证器的开放 Todo,可以用 fresh、open 的 Vision 和有证据关联的
`continue` / `no_change` 路径记录 `outcome_progress`;准入写回与精确回执的扣额
复用同一 TS 资格规则。它只结算原 Turn,不完成 Todo,也不满足最终完成验证器。
primary outcome、已闭合 Vision 与终态声明仍须通过原完成验证门。

One explicit exception exists for in-flight delivery. When quota admits an
open advancement Todo for normal delivery, its settlement guidance may add the
Expand Down Expand Up @@ -954,7 +997,7 @@ decision merely because the scheduler woke up. Agents must start from
projected boundary and identity flags; reconstructing a generic
`semantic_closeout` command discards that continuity contract.

If the work actually replanned or completed the Todo, explicitly choose
If this admitted work obtains new decision evidence, actually replans or completes the Todo, explicitly choose
`semantic_closeout` and provide its required vision checkpoint. Do not simply
remove the replan ACK to make a real replan pass as in-flight work. Conversely,
ordinary within-Todo progress must not add `--autonomous-replan-recorded`.
Expand Down
3 changes: 3 additions & 0 deletions loopx/control_plane/effect_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ class SettlementStep:
conditional: bool = False
command_condition: str | None = None
vision_authoring: Mapping[str, Any] | None = None
semantic_closeout_command_template: str | None = None

def as_dict(self) -> dict[str, Any]:
step: dict[str, Any] = {
Expand All @@ -653,6 +654,8 @@ def as_dict(self) -> dict[str, Any]:
step["command_condition"] = self.command_condition
if self.vision_authoring is not None:
step["vision_authoring"] = dict(self.vision_authoring)
if self.semantic_closeout_command_template is not None:
step["semantic_closeout_command_template"] = self.semantic_closeout_command_template
return step


Expand Down
3 changes: 3 additions & 0 deletions loopx/control_plane/effect_program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ export interface SettlementStep {
idempotency_key_ref: string;
expected_receipt: string;
command_template?: string;
/** Same admitted writeback, with the existing semantic boundary selected. */
semantic_closeout_command_template?: string;
command_condition?: "todo_deliverable_complete";
vision_authoring?: JsonObject;
conditional?: true;
Expand Down Expand Up @@ -658,6 +660,7 @@ export function settlementStepPayload(step: SettlementStep): JsonObject {
expected_receipt: step.expected_receipt,
};
if (step.command_template) payload.command_template = step.command_template;
if (step.semantic_closeout_command_template) payload.semantic_closeout_command_template = step.semantic_closeout_command_template;
if (step.command_condition) payload.command_condition = step.command_condition;
if (step.conditional) payload.conditional = true;
if (step.vision_authoring) payload.vision_authoring = step.vision_authoring;
Expand Down
5 changes: 5 additions & 0 deletions loopx/control_plane/effect_runtime_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,11 @@ export function createEffectRuntimeHandlers(
requiredString(params.expected_effect_id, "expected_effect_id"),
),
],
[
"settlement.open_todo_semantic_checkpoint",
lazyHandler(() => import("./goals/vision_checkpoint.ts"), ({qualifiesOpenTodoSemanticCheckpoint}) => (params) =>
qualifiesOpenTodoSemanticCheckpoint(params.writeback, settlementIdentity(settlementIdentityInput(params.identity)))),
],
[
"settlement.receipt_bound_monitor_phase",
lazyHandler(() => import("./quota/settlement_phase.ts"), ({receiptBoundMonitorPhase}) => (params) => receiptBoundMonitorPhase({
Expand Down
3 changes: 3 additions & 0 deletions loopx/control_plane/goal_vision_lifecycle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"closed_states": ["vision_closed", "retired", "retired_or_superseded", "superseded", "no_followup"]
}
14 changes: 5 additions & 9 deletions loopx/control_plane/goals/goal_vision_state.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
from __future__ import annotations

from importlib.resources import files
import json
import re
from typing import Any


GOAL_VISION_DEFAULT_STATE = "vision_patch_proposed"
GOAL_VISION_CLOSED_STATES = frozenset(
{
"vision_closed",
"retired",
"retired_or_superseded",
"superseded",
"no_followup",
}
)
GOAL_VISION_CLOSED_STATES = frozenset(json.loads(
files("loopx.control_plane").joinpath("goal_vision_lifecycle.json").read_text(encoding="utf-8")
)["closed_states"])
GOAL_VISION_SUCCESSOR_REQUIRED_STATES = frozenset({"vision_closed"})
GOAL_VISION_STATE_ALIASES = {
"closed": "vision_closed",
Expand Down
45 changes: 43 additions & 2 deletions loopx/control_plane/goals/vision_checkpoint.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { JsonObject } from "../effect_program.ts";
import {settlementIdentityPayload, type JsonObject, type SettlementIdentity} from "../effect_program.ts";
import { EffectRuntimeRequestError } from "../effect_runtime_errors.ts";
import { isBoundedBlockedRetry } from "../quota/settlement_phase.ts";
import {jsonObject} from "../runtime_decode.ts";
import { isAcceptedProgressWriteback, isBoundedBlockedRetry } from "../quota/settlement_phase.ts";
import {
DELIVERY_BOUNDARIES,
type DeliveryBoundary,
Expand All @@ -12,6 +13,7 @@ import {
} from "../work_items/delivery_outcome.ts";

import {normalizeStrideDecision, STRIDE_DECISION_SCHEMA, RECORDED_STRIDE_SCHEMA, STRIDE_PROBE_LIMITS, STRIDE_AXIS_NAMES, STRIDE_PLAN_LIMIT, STRIDE_REASON_LIMIT, STRIDE_REVIEW_LIMIT} from "../work_items/stride_policy.ts";
import lifecycle from "../goal_vision_lifecycle.json" with {type: "json"};

export const VISION_REFRESH_REQUEST_SCHEMA = "loopx_vision_refresh_request_v0";
export const VISION_REFRESH_PREPARED_SCHEMA_VERSION =
Expand Down Expand Up @@ -126,6 +128,14 @@ export function visionAuthoringContract(autonomousReplan = false): JsonObject {
? `Autonomous review: changing ${GOAL_VISION_DURABLE_FIELDS.join(", ")} requires outcome=replan, even when the Goal objective stays unchanged. Retaining these fields permits continue/no_change. `
: "Changed mainline: outcome=replan. ") +
"vision_closed closes a stage, not Goal; no_followup: no scoped work.",
// Autonomous planning/Stride and settlement-only recovery carry their own
// decision guidance. Keep this reminder at the ordinary checkpoint entry.
...(autonomousReplan ? {} : {
continuation_review: "For explicitly continuing/optimization objectives, candidate usability alone is not completion: before stop/no_followup, " +
"weigh acceptance gaps, plausible headroom and feasible next work's full marginal cost against accepted stops in an evidence-linked path_delta; " +
"continue/replan useful authorized work, preserve Stop, budget/permission limits and genuine waits, " +
"and never infer completion or invent work/pivots/successors from submission or unused budget alone.",
}),
};
}
// Bounded typed fallback declarations survive prepare unchanged so the
Expand Down Expand Up @@ -408,6 +418,37 @@ function normalizeGoalVisionState(value: unknown): string {
return GOAL_VISION_STATE_ALIASES[state] ?? state;
}

/** The existing lifecycle vocabulary is shared with the Python read model. */
export function goalVisionStateIsOpen(value: unknown): boolean {
try { return !lifecycle.closed_states.includes(normalizeGoalVisionState(value)); }
catch { return false; }
}

/** Qualify an open Todo's evidence checkpoint without accepting its deliverable.
* Write-time callers supply the admitted identity and prepared Vision; spend
* callers first verify the exact durable receipt. Terminal validation remains
* with Todo completion. An unchanged reason alone is not new decision evidence. */
export function qualifiesOpenTodoSemanticCheckpoint(value: unknown, identity: SettlementIdentity): boolean {
const run = jsonObject(value), checkpoint = jsonObject(run?.vision_checkpoint);
const persisted = jsonObject(run?.settlement_identity), vision = jsonObject(run?.agent_vision);
if (!isAcceptedProgressWriteback(run, identity) || run?.completion_todo_id != null ||
checkpoint?.delivery_boundary !== "semantic_closeout" || checkpoint.required !== true ||
checkpoint.decision !== "patched" || !persisted ||
Object.entries(settlementIdentityPayload(identity)).some(([key, value]) => persisted[key] !== value) ||
vision?.schema_version !== "goal_vision_replan_contract_v0" ||
// Compact run history omits this redundant Goal field; the exact run
// and settlement identity above still bind it. Present conflicts fail.
(vision.goal_id != null && vision.goal_id !== identity.goal_id) ||
vision.agent_id !== identity.agent_id || typeof vision.state !== "string" || !vision.state.trim() ||
!goalVisionStateIsOpen(vision.state)) return false;
const acceptance = jsonObject(vision.vision_patch)?.acceptance_summary;
let path;
try { [path] = normalizeGoalPathDelta(vision.path_delta); } catch { return false; }
return typeof acceptance === "string" && !!acceptance.trim() && !!path &&
(path.outcome === "continue" || path.outcome === "no_change") &&
Array.isArray(path.evidence_refs) && path.evidence_refs.length > 0;
}

function normalizeAdvancementPolicy(value: unknown): string {
const candidate = compactText(value).toLowerCase().replaceAll("-", "_");
if (!GOAL_VISION_ADVANCEMENT_POLICIES.some(policy => policy === candidate)) {
Expand Down
20 changes: 15 additions & 5 deletions loopx/control_plane/quota/effect_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,19 @@ def build_turn_scoped_cli_settlement_plan(
f"{lifecycle_actor_args}{turn_arg}{goal_ref_arg} --evidence '<validated evidence>'"
)
terminal_closeout = ordinary_completion + " --no-follow-up"
writeback = (
f"{cli_prefix} refresh-state --goal-id {shlex.quote(goal_id)} "
"--classification <validated_progress> --delivery-batch-scale <scale> "
f"--delivery-outcome <outcome>{boundary_arg}{binding_arg}{turn_arg}{goal_ref_arg}"
f"{scoped_cli_args}{writeback_path_args}"

def writeback_command(boundary: str) -> str:
return (
f"{cli_prefix} refresh-state --goal-id {shlex.quote(goal_id)} "
"--classification <validated_progress> --delivery-batch-scale <scale> "
f"--delivery-outcome <outcome>{boundary}{binding_arg}{turn_arg}{goal_ref_arg}"
f"{scoped_cli_args}{writeback_path_args}"
)

writeback = writeback_command(boundary_arg)
semantic_writeback = (
writeback_command(" --delivery-boundary semantic_closeout")
+ " --agent-vision-json <file>"
)
spend = (
f"{cli_prefix} quota spend-slot --goal-id {shlex.quote(goal_id)} --slots 1 "
Expand All @@ -255,6 +263,7 @@ def build_turn_scoped_cli_settlement_plan(
"command_templates": {
**({"todo_claim": task_claim} if todo_id else {}),
"todo_completion": ordinary_completion, "durable_writeback": writeback,
"semantic_closeout": semantic_writeback,
"quota_spend": spend, "terminal_closeout": terminal_closeout,
},
})
Expand All @@ -267,6 +276,7 @@ def build_turn_scoped_cli_settlement_plan(
expected_receipt=row["expected_receipt"], command_template=row.get("command_template"),
conditional=row.get("conditional", False), command_condition=row.get("command_condition"),
vision_authoring=row.get("vision_authoring"),
semantic_closeout_command_template=row.get("semantic_closeout_command_template"),
) for row in payload["ordered_steps"]
), _runtime_payload=payload)

Expand Down
Loading
Loading