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
13 changes: 13 additions & 0 deletions docs/architecture/rfcs/goal-outcome-refinement-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,19 @@ review record. This is sequential composition: refinement commits before the
normal writeback. If writeback fails, its returned refinement receipt identifies
what committed; retry the identical operation rather than assuming rollback.

An enabled due Stride review also binds the delivered context, including these
outcome facts. For a changed milestone, refine first, re-enter the same Turn's
guard, read its current facts and author the complete decision before ordinary
writeback. Do not silently rebind a stale decision. Batched dry-run now uses the
acceptance owner's prospective contract, so it detects the same basis mismatch
as execution without committing a refinement, run or spend. Execution retains
its sequential contract and partial-effect receipt; recover an already applied
refinement by its original operation, then reassess against fresh context.
Ordinary batching, unchanged work and the exact-context gate remain unchanged.
Real File/SQLite CLI cases cover preview, stale refusal, fresh-context recovery,
retained requirements and single-debit replay. This is source qualification,
not installed adoption, general atomicity or a model-efficiency claim.

| Event | Default action | Existing mechanism |
| --- | --- | --- |
| Material direct-user deliverable/correction | Add to the matching outcome, retaining prior intent | Host context + native refinement or skill/CLI bridge |
Expand Down
9 changes: 9 additions & 0 deletions docs/architecture/rfcs/goal-outcome-refinement-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,15 @@ active 含义;显式非活动状态仍拒绝细化。
这里是顺序组合:先提交细化,再做普通写回。后续写回失败时,返回的细化回执
标明已提交部分;按原操作重试,不能假定全部回滚。

启用的到期 Stride 审查还绑定已交付上下文,其中包括这些成果事实。节点有变化时,
先细化,再以原 Turn 身份重入 guard、读取当前事实,完整重作决定后普通写回;
不能悄悄将旧决定绑定到新上下文。批量 dry-run 现使用验收 owner 的预期契约,
在不提交细化、运行或扣额的前提下,识别与实际执行相同的基线不匹配。
实际执行保持顺序组合和部分副作用回执;已应用细化按原操作恢复,再据新上下文
重新判断。普通批量写回、无变化工作及精确上下文门槛保持不变。
真实 File/SQLite CLI 覆盖预览、旧基线拒绝、新上下文恢复、要求保留与单次扣额
重放。此为源码资格,不代表已安装采用、通用原子性或模型效率收益。

| 节点 | 默认动作 | 联动机制 |
| --- | --- | --- |
| 直接用户消息带来重要成果/实质纠正 | 细化对应成果并保留旧意图 | 宿主上下文+原生细化或技能/CLI |
Expand Down
12 changes: 10 additions & 2 deletions loopx/cli_commands/project_lifecycle_refresh_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ def handle_refresh_state_command(
goal_ref: dict[str, str] | None = None
outcome_update = None
outcome_update_result = None
goal_acceptance_preview = None
try:
if getattr(args, "settle_turn", False) and not (
args.agent_id and args.turn_instance_id and bool(args.todo_id) != bool(args.replan_obligation_id)
Expand Down Expand Up @@ -569,9 +570,14 @@ def handle_refresh_state_command(
raise ValueError("--resume-external-sinks requires the original --turn-instance-id")
if outcome_update is not None:
from ..control_plane.goals.acceptance import refine_goal_outcome, public_goal_acceptance
outcome_update_result = public_goal_acceptance(refine_goal_outcome(
refinement_result = refine_goal_outcome(
registry_path=registry_path, runtime_root=args.runtime_root, goal_id=args.goal_id,
agent_id=args.agent_id, execute=not args.dry_run, **outcome_update), include_contract=False)
agent_id=args.agent_id, execute=not args.dry_run, **outcome_update)
outcome_update_result = public_goal_acceptance(refinement_result, include_contract=False)
if args.dry_run:
# Preview the same ordered composition as execution: the typed
# refinement owner supplies the prospective acceptance facts.
goal_acceptance_preview = refinement_result["goal_acceptance_contract"]
payload = refresh_state_run(
external_delivery={"suppress": bool(args.suppress_external_sinks),
"resume_key": getattr(args, "resume_external_sinks", None)},
Expand Down Expand Up @@ -619,6 +625,8 @@ def handle_refresh_state_command(
dry_run=bool(args.dry_run),
sync_global=not bool(args.no_global_sync),
goal_ref=goal_ref,
**({"goal_acceptance_preview": goal_acceptance_preview}
if goal_acceptance_preview is not None else {}),
)
except Exception as exc:
payload = {
Expand Down
12 changes: 12 additions & 0 deletions loopx/state_refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,10 +740,13 @@ def refresh_state_run(
sync_global: bool = True,
external_delivery: dict[str, Any] | None = None,
goal_ref: dict[str, str] | None = None,
goal_acceptance_preview: dict[str, Any] | None = None,
) -> dict[str, Any]:
from .control_plane.todos.provider_projection import recover_refresh_todo_projection

safe_goal_id = validate_goal_id_path_segment(goal_id)
if goal_acceptance_preview is not None and not dry_run:
raise ValueError("prospective acceptance facts are valid only for dry-run planning")
if next_action_basis and not next_action:
raise ValueError("--next-action-basis requires --next-action")
if checkpoint_read_context_id and not turn_instance_id:
Expand Down Expand Up @@ -967,6 +970,15 @@ def refresh_state_run(
state_text, planning_events, todo_fields = (
planning_source.state_text, planning_source.events, planning_source.todo_fields,
)
if goal_acceptance_preview is not None:
# Only the batched CLI dry-run supplies this owner-produced plan.
# Execution always reads committed canonical facts. In particular,
# do not qualify a due Stride decision against the pre-update basis.
if not isinstance(todo_fields, dict) or not isinstance(todo_fields.get("agent_todos"), dict):
raise ValueError("outcome preview requires a canonical planning snapshot")
todo_fields = {**todo_fields, "agent_todos": {
**todo_fields["agent_todos"], "goal_acceptance_contract": goal_acceptance_preview,
}}
expected_write_state_text = state_text
normalized_next_action = normalize_next_action_text(next_action) if next_action else None
if normalized_next_action and registry_goal is None:
Expand Down
16 changes: 16 additions & 0 deletions skills/loopx-project/references/outcome-refinement.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ For changed requirements or reviews, add this envelope to the **existing**
its ordinary routing, Turn, checkpoint and delivery arguments. This does not
replace them.

An enabled due Stride review binds the delivered context, which includes outcome
facts. When this milestone changes those facts, apply the refinement first with
the standalone command below, then re-enter the guard with the same Turn identity
and read its fresh context before authoring the complete Vision decision. Omit
the already applied update from that ordinary writeback. No extra refinement is
needed when the facts are unchanged. Do not copy a new context ID into an old
decision without reviewing the changed facts.

The batched response's `goal_outcome_update` acknowledges the operation with its
status and canonical revision; it does not echo the complete acceptance contract.
The same receipt remains present if the later ordinary writeback fails. Retry the
Expand All @@ -127,6 +135,14 @@ context; the compact receipt cannot substitute for reading that basis before a
new refinement. Standalone `goal-acceptance refine` and conversation outcome tools
retain their full readback.

Batching is sequential: refinement commits before ordinary writeback. A dry-run
uses the typed owner's prospective acceptance facts; `planned` commits nothing.
If execution returns `stride_review_basis_mismatch` with an `applied` or
`replayed` refinement receipt, preserve that effect and use the same-Turn fresh
context route above. Repeating the stale Vision alone cannot recover it. An
identical refinement operation recovers its receipt without applying it again;
never replace its operation ID to evade the existing receipt or CAS check.

Do not add an immediate inspection solely to acknowledge this receipt. Reuse the
complete admitted context while current; inspect only when that basis is absent
or stale. Reuse its revision when still current:
Expand Down
1 change: 1 addition & 0 deletions skills/loopx-self-repair/references/repair-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ teaches a reusable control-plane lesson.

| Pattern | Symptoms | Evidence To Read | Likely Root | Durable Repair |
| --- | --- | --- | --- | --- |
| `stride_inline_outcome_basis_ordering` | A batched milestone dry-run succeeds, but execution returns `stride_review_basis_mismatch` after an outcome refinement has committed. | Exact Turn/obligation/context, the returned `goal_outcome_update` status and operation, current acceptance and run/spend receipts; compare due Stride with ordinary batching. | Sequential refinement changes the context that the decision references; a preview using pre-update facts hides that change. | Feed the typed acceptance owner's prospective contract to dry-run planning. For a changed due-review milestone, refine before a fresh same-Turn guard, read the new facts and author the complete decision; unchanged work needs no update. On partial failure retain applied/replayed receipts and original IDs, reassess fresh context, then settle once. Never assume rollback, blindly replace a context token, lower the gate or replay work. Cover real File/SQLite preview/refusal/recovery, ordinary batching and single debit. |
| `native_code_cell_source_normalization` | An optional native context adapter always falls back to full after an output-budget pragma, despite complete retained input. | The same live model call, native cell source, child identity and complete model-visible capture bytes; compare the executable source separately from native framing. | Native removes the documented first-line execution pragma before recording the cell, while the adapter compares that body with the unprocessed model call. | Normalize only that first-line JSON-object pragma and retain exact remaining source, live call/cell ordering and complete-byte verification. Cover unchanged framing, altered bodies, malformed/extra headers and stale or partial input, plus real native resume and recovery. Preserve automatic same-capture full fallback; do not add an admission or owner question. |
| `native_history_output_budget` | A complete CLI or code-cell result becomes a clipped or missing page in the next model input despite a larger direct-result budget. | Compare the CLI result, completed native cell, actual inference input and effective model history-output policy at the same native version. | Direct-result and retained-history limits are separate; an unknown loopback model may use a smaller byte-based fallback than the intended host's token-based policy. | Keep the original low-budget failures. Qualify a distinct matched workload under the intended declared history budget without changing live host limits or frozen criteria. Size batches within both budgets, retain complete-byte checks and same-capture recovery, and never count incomplete trials as savings or runtime output as retention proof. |
| `archive_verification_byte_epoch_gap` | Backup preview or execution accepts compressed input rewritten after preflight; restoring it before the final hash conceals the change. | External manifest and preflight archive identity, the digest/count of bytes actually consumed by gzip/tar, copy observations and destination publication. | Separate mutable-file reads supply the hash and parser facts; a final hash cannot prove which bytes were parsed. | Keep early wrong-digest refusal. Generate a bounded compressed-byte witness in the parser's actual input stream, compare it with preflight before audit, and compare copy witnesses before publication. Preserve capacity checks, inert status and no execution authority. Cover preview, execute and ABA restoration with real producer archives and filesystem fault injection. |
Expand Down
Loading
Loading