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
38 changes: 30 additions & 8 deletions docs/reference/protocols/goal-vision-replan-contract-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,14 +518,36 @@ For the same `agent_id`, a newer satisfied checkpoint with `patched` or
`unchanged_with_reason` supersedes older
`missing_required` checkpoints; `not_required` does not.

The ordinary CLI settlement plan now puts a compact material-closeout reminder
in its existing writeback step, before the first write. The shared authoring
example includes the acceptance claim, continuation path and evidence reference;
replace its illustrative claims and reference with observed facts. Explicit
`in_flight_continuation` plans retain their existing short writeback precondition.
This changes guidance in CLI/TurnEnvelope and the shared MCP/replan authoring
projection, not validation, admission or receipt authority. It does not establish
lower model token cost or eliminate all replanning; those require live measurement.
The ordinary Todo-bound CLI settlement plan carries `vision_authoring` in its
existing durable-writeback step, including in-flight plans. It reuses the same
TypeScript example and field limits as MCP and replan; it is authoring guidance,
not a requirement to patch vision on every in-flight step. Replace example claims
and references with observed facts and pass the packet via `--agent-vision-json`.
`checkpoint-context` is recovery **after** the original committed Turn writeback,
not a first-write preparation command. MCP removes the manual CLI settlement plan
and retains its own authoring projection. The default quota CLI also retains
autonomous replan's authoring schema. When an identical schema is already present
in its durable-writeback step, the replan contract uses a same-response
`vision_authoring_ref`; it never requires a diagnostic detail read for this input.
Different schemas remain separate, and progress-only replan does not acquire a
Vision requirement. TurnEnvelope preserves the ordinary plan's guidance.

Shared `todo plan` and guided-start authoring steps also provide a routed exact
readback command for each authored or reused Todo id. Inventory text is a bounded
excerpt. Verify `todo_detail_projection.source_complete=true`, compare `.todo.text`
with the intended requirements and check current status/claim before handoff;
missing, ambiguous or changed work requires reinspection. Readback does not replace
quota admission or lease authority. Lists remain compact and exact bodies lossless.

These default guidance changes preserve validation, admission, original-Turn
recovery and receipt authority. A larger self-contained packet can avoid discovery
calls, but lower model cost or better outcomes still require live measurement.

普通 Todo 结算包在写回步骤直接携带既有的 vision 示例和字段限制;示例须替换为实际
事实与证据,不要求每个 in-flight 步骤都修改 vision。`checkpoint-context` 仅用于原
Turn 写回后的恢复。规划与接续指引提供逐条精确读回命令,用完整 `.todo.text` 核对
需求和当前状态,不能拿列表摘要判断正文丢失。读取不授予执行权限;准入、租约、
恢复和单次记账规则保持不变。包体增量与模型效率、效果收益须分别测量。

A satisfied checkpoint is protocol-complete, but a material closeout also has
to qualify its relationship to the final outcome. A patched checkpoint must
Expand Down
16 changes: 10 additions & 6 deletions docs/reference/protocols/quota-cli-hot-path-compaction-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ projection. Candidate lists and peer action lists retain counts and point to
detail section.

When a replan action carries a complete `vision_authoring` schema, the default
`quota should-run` packet keeps its executable writeback summary (`required_fields`,
accepted path outcomes, and rule) and replaces only that nested schema with a
`vision_authoring_detail_ref`. `--include-detail vision` restores the schema.
`turn plan` is different: its TurnEnvelope preserves the complete schema because
the plan must be capable of authoring the exact input its validator accepts.
The crowded Turn budget therefore accounts for that fixed contract without
`quota should-run` packet now retains it, alongside its executable writeback
summary (`required_fields`, accepted path outcomes, and rule). Only when the
durable-writeback step already contains an identical schema does the replan action
replace its duplicate with `vision_authoring_ref`, an exact path within the same
response. Missing or different authoring stays inline. This replaces the former
`vision_authoring_detail_ref` cold read; diagnostic vision audits remain optional
detail. Progress-only replan does not gain a Vision input requirement.
`--include-detail vision` retains full explicit detail. `turn plan` preserves the
complete schema because it must author the exact input its validator accepts.
The crowded quota and Turn budgets account for that fixed contract without
relaxing Todo-count growth or the small and multi-Agent ceilings.

## Qualification Contract
Expand Down
1 change: 1 addition & 0 deletions examples/control_plane/cli-output-probe-runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def _receipt_row(
else []
),
"next_action_basis_count": semantics.next_action_basis_count(payload),
"authoring_inputs": semantics.authoring_input_observations(text),
}


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 @@ -614,6 +614,7 @@ class SettlementStep:
command_template: str | None = None
conditional: bool = False
command_condition: str | None = None
vision_authoring: Mapping[str, Any] | None = None

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


Expand Down
2 changes: 2 additions & 0 deletions loopx/control_plane/effect_program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export interface SettlementStep {
expected_receipt: string;
command_template?: string;
command_condition?: "todo_deliverable_complete";
vision_authoring?: JsonObject;
conditional?: true;
}

Expand Down Expand Up @@ -606,6 +607,7 @@ export function settlementStepPayload(step: SettlementStep): JsonObject {
if (step.command_template) payload.command_template = step.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;
return payload;
}

Expand Down
19 changes: 19 additions & 0 deletions loopx/control_plane/goals/start_goal_todo_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,23 @@ def todo_authoring_steps(
agent_id=agent_id,
registry_path=registry_path,
)
# This adapter already owns routed CLI templates for both planning entrypoints.
readback = {
"id": "read_back_authored_todos",
"kind": "operator_or_agent_actions",
"command_template": (
f"{render_cli_command_prefix(cli_bin=cli_bin, runtime_root=runtime_root)} "
+ (f"--registry {shell_arg(str(registry_path))} " if registry_path is not None else "")
+ f"--format json todo list --goal-id {shell_arg(str(goal_id))} "
+ (f"--agent-id {shell_arg(str(agent_id))} " if agent_id else "")
+ "--todo-id '<todo-id>'"
),
"purpose": (
"Read each authored/reused id: one match, todo_detail_projection.source_complete=true; "
"compare .todo.text, status/claim. Excerpts cannot verify writes. "
"Missing/ambiguous/changed: reinspect before handoff. Readback grants no guard/lease authority."
),
}
if not existing_runnable_frontier:
return [
{
Expand All @@ -173,6 +190,7 @@ def todo_authoring_steps(
"the admitted action_kind and target_key for later quota re-entry"
),
},
readback,
]
return [
{
Expand Down Expand Up @@ -205,6 +223,7 @@ def todo_authoring_steps(
"add_new_command_template": add_template,
"purpose": "takeover continues the frontier; authoring is a delta",
},
readback,
]


Expand Down
5 changes: 4 additions & 1 deletion loopx/control_plane/goals/vision_checkpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ export function visionAuthoringContract(): JsonObject {
evidence_refs: ["evidence:verified-result"],
},
},
authoring_hint: "Replace example claims/refs with evidence; obey the live contract and total limit.",
authoring_hint: "Replace example claims/refs with evidence; obey the live contract and total limit. " +
"For ordinary CLI writeback, pass the packet with --agent-vision-json <file>. " +
"checkpoint-context is only for recovery after the original committed Turn writeback; " +
"follow its returned same-Turn recovery action, not a fresh-turn preflight.",
total_text_limit: GOAL_VISION_TOTAL_LIMIT,
unchanged_reason_limit: VISION_UNCHANGED_REASON_LIMIT,
path_delta: {
Expand Down
32 changes: 27 additions & 5 deletions loopx/control_plane/quota/cli_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,24 +462,44 @@ def _compact_vision_continuation_audit(
return compact


def _compact_replan_action_packet(packet: dict[str, Any]) -> dict[str, Any]:
"""Keep the executable writeback summary hot and move its schema cold."""
def _reference_inline_replan_authoring(
packet: dict[str, Any], *, payload: dict[str, Any]
) -> dict[str, Any]:
"""Reference an identical executable input already present in this response."""

writeback = packet.get("writeback_contract")
if not isinstance(writeback, dict) or not isinstance(
writeback.get("vision_authoring"), dict
):
return packet
interaction = payload.get("interaction_contract")
cli = interaction.get("cli_channel") if isinstance(interaction, dict) else None
plan = cli.get("settlement_plan") if isinstance(cli, dict) else None
steps = plan.get("ordered_steps") if isinstance(plan, dict) else None
if not isinstance(steps, list):
return packet
index = next(
(index for index, step in enumerate(steps)
if isinstance(step, dict) and step.get("kind") == "durable_writeback"
and step.get("vision_authoring") == writeback["vision_authoring"]),
None,
)
if index is None:
return packet
reference = (
"$.interaction_contract.cli_channel.settlement_plan.ordered_steps"
f"[{index}].vision_authoring"
)
compact_writeback = dict(writeback)
compact_writeback.pop("vision_authoring")
compact_writeback["vision_authoring_detail_ref"] = QUOTA_CLI_VISION_DETAIL_COMMAND
compact_writeback["vision_authoring_ref"] = reference
compact = dict(packet)
compact["writeback_contract"] = compact_writeback
compact["payload_compaction"] = {
"schema_version": QUOTA_CLI_REPLAN_ACTION_COMPACTION_SCHEMA_VERSION,
"mode": "compact_hot_path",
"compacted_fields": ["writeback_contract.vision_authoring"],
"full_detail_cold_path": QUOTA_CLI_VISION_DETAIL_COMMAND,
"projection_ref": reference,
}
return compact

Expand Down Expand Up @@ -759,7 +779,9 @@ def compact_quota_should_run_cli_payload(
)
replan_action = payload.get("replan_action_packet")
if not include_vision_detail and isinstance(replan_action, dict):
compact_replan_action = _compact_replan_action_packet(replan_action)
compact_replan_action = _reference_inline_replan_authoring(
replan_action, payload=compact
)
if compact_replan_action is not replan_action:
compact = dict(compact)
compact["replan_action_packet"] = compact_replan_action
Expand Down
1 change: 1 addition & 0 deletions loopx/control_plane/quota/effect_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def build_turn_scoped_cli_settlement_plan(
precondition=row["precondition"], idempotency_key_ref=row["idempotency_key_ref"],
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"),
) for row in payload["ordered_steps"]
), _runtime_payload=payload)

Expand Down
4 changes: 3 additions & 1 deletion loopx/control_plane/quota/settlement_plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
settlementIdentity, type JsonObject, type SettlementIdentityInput,
type SettlementPlan, type SettlementStep,
} from "../effect_program.ts";
import {VISION_MATERIAL_CLOSEOUT_HINT} from "../goals/vision_checkpoint.ts";
import {VISION_MATERIAL_CLOSEOUT_HINT, visionAuthoringContract} from "../goals/vision_checkpoint.ts";
import {parseExactGoalRef} from "../goals/goal_instance_identity.ts";
import {requireJsonObject, requireNonEmptyString} from "../runtime_decode.ts";

Expand Down Expand Up @@ -56,6 +56,8 @@ export function turnScopedCliSettlementPlan(params: JsonObject): SettlementPlan
"outcome_gap: blocked + blocker/evidence IDs; continuation checks.",
idempotency_key_ref: "$.identity.effect_id", expected_receipt: "durable_writeback_receipt",
command_template: writeback,
// Autonomous replan already carries this owner in its writeback contract.
...(identity.binding_kind === "todo" ? {vision_authoring: visionAuthoringContract()} : {}),
},
{
kind: "quota_spend", owner: "agent",
Expand Down
17 changes: 11 additions & 6 deletions loopx/control_plane/testing/cli_output_budget.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,24 @@ class CliOutputCommandClassification:
# Fixed-path base/head emit 21,871 JSON / 8,690 Markdown chars.
# Keep the selected-Todo source, freshness, ordering and stop rules.
"small": {"json": 22_000, "markdown": 9_000},
# 36 Todos / 12 runs emit 35,710 chars; 36,000 leaves 290.
# Same 36-Todo / 12-run source: 35,383 -> 38,432 chars when
# required replan authoring is inline instead of a diagnostic read.
# Per-Todo growth and fixed semantic growth remain independent.
"crowded": {"json": 36_000, "markdown": 7_800},
"crowded": {"json": 39_000, "markdown": 7_800},
"multi_agent": {"json": 23_000, "markdown": 7_000},
},
max_lines={
"small": {"json": 600, "markdown": 140},
"crowded": {"json": 850, "markdown": 90},
"crowded": {"json": 950, "markdown": 90},
"multi_agent": {"json": 650, "markdown": 80},
},
scale_axis="todo_count",
max_json_growth_chars_per_unit=300,
# Required replan carries dense decision evidence from the full index.
# The unchanged fixture grows 21,871 -> 35,710 chars / 579 -> 836 lines.
# The required authoring adds 3,049 fixed chars / 94 lines; small and
# multi-agent cases stay identical. It does not grow with Todo count.
# This fixed decision packet must not relax per-Todo growth or other routes.
max_json_fixed_semantic_growth_chars=6_000,
max_json_fixed_semantic_growth_chars=9_000,
),
CliOutputBudgetSpec(
surface_id="loopx_turn_plan",
Expand Down Expand Up @@ -381,7 +383,10 @@ class CliOutputCommandClassification:
"packet_summary",
),
markdown_anchor="# Guided Start Goal",
max_chars={"json": 64_000, "markdown": 3_200},
# The real differential fixture grows from 2,781 to 3,217 Markdown
# characters with the complete Todo readback step and command. Keep
# that decision guidance; only the explicit detail-mode ceiling grows.
max_chars={"json": 64_000, "markdown": 3_600},
max_lines={"json": 650, "markdown": 55},
),
CliOutputModeVariantSpec(
Expand Down
Loading
Loading