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
10 changes: 9 additions & 1 deletion docs/architecture/rfcs/loopx-overall-roadmap-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ visibility limits, ordinary notices, current cadence floors and unchanged
canonical waits/monitor clocks. Installed adoption and live host readback remain
separate from this source repair.

**S3/S7 administrative closeout proposal.** [#7117](https://github.com/loopx-project/loopx/pull/7117)
**S3/S7 administrative closeout checkpoint.** [#7117](https://github.com/loopx-project/loopx/pull/7117)
also separates an accepted blocked replan from the preceding real outcome
checkpoint. File/SQLite CLI readback and long/compacted history regressions retain
the previous milestone or genuine gap without creating a new outcome obligation
Expand All @@ -150,6 +150,14 @@ packet, preserving all clauses and standalone reads.
Full-repository qualification, comparable full caller cost, installed adoption
and measured long-horizon benefit remain distinct and incomplete.

The follow-on timer repair retains readiness at positive CLI work admission.
File/SQLite reentry distinguishes an unchanged timer already due at admission
from a later-authored wait, including one already due when read. Both preserve
the original binding and exactly-once result settlement. The shared TypeScript
owner checks microseconds; missing legacy facts retain conservative recovery.
This source qualification adds no scheduler, historical receipt rewrite or
installed/live-host qualification.

**S5/S11 long-horizon progress design.** The [research measurement refinement](long-horizon-harness-benchmark-research-program-v0.md#evidence-based-episode-evaluation-proposed-refinement)
and [product reading journey](../../product/use-cases/auto-research/long-horizon-progress-design.md)
connect native outcomes to research episodes, evidence and actual adoption.
Expand Down
8 changes: 7 additions & 1 deletion docs/architecture/rfcs/loopx-overall-roadmap-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ managed 与 attached 的工作对话都应能持续在 LoopX 中进行:沿用
| **S12 发布、开发体验与社区治理 · P0 卫生/P1** | 安装、源码验证、扩展注册、DCO/PR、测试层级、contributor route 与双语文档已存在 | 从干净机器/发布包验一条首次工作和一次升级/回滚;host/OS 支持以 release contract 为准。缩短合理改动的定位、测试和 review 成本;公开精确 head、可重复 fixture、兼容窗口、维护者路由和贡献归属,退休重复协议及过时证据 |
| **S13 采用、生态与商业可持续性 · P1 发现/P2 试点** | 公开 adoption loop、showcase、license/governance、observer-first 产品合同已存在;付费 PMF 未证明 | 先收集真实独立首次使用/重复使用/退出原因,做可复现案例和有固定预算/验收/回滚的试点;沉淀 reusable adapter 与交付手册。核算模型/计算/存储/支持成本及维护负担;满足重复需求后再决策商业托管边界、支持等级和分发,不承诺 SLA 或擅改开源条款 |

**S3/S7 行政收尾提案。** [#7117](https://github.com/loopx-project/loopx/pull/7117)
**S3/S7 行政收尾检查点。** [#7117](https://github.com/loopx-project/loopx/pull/7117)
进一步区分已验收的阻塞重规划与前一个真实成果 checkpoint。File/SQLite CLI 回读和
长期/压缩历史回归保留原里程碑或真实缺口,避免行政收尾制造新的成果义务。源码
覆盖已包括通知/真门禁叠加、原截止恢复,以及各自持有 Vision 和时钟时的原生取消
Expand All @@ -117,6 +117,12 @@ managed 与 attached 的工作对话都应能持续在 LoopX 中进行:沿用
完全相同的 Explore 指引改为同一 CLI 包内引用,保留全部条款及独立读取。整仓
资格、可比完整调用成本、安装采用与长程实测收益仍是分别验证的未完成项。

后续定时等待修复保留 CLI 正向工作准入时的就绪事实。File/SQLite 重入区分准入时
已经到期且未改变的等待与后来设置的等待,后者即使在回读时已到期也保留原结果
收尾义务。两条路径均保留原绑定及单次结果结算;共享 TypeScript owner 核对微秒,
旧回执缺失事实时保守进入恢复。这一源码资格不新增调度器、不改写历史回执,也不
证明安装或真实 Host 采用。

**S5/S11 长程进展设计。** [研究计量细化](long-horizon-harness-benchmark-research-program-v0.zh-CN.md#基于证据的研究片段评估拟议细化)
与[产品阅读旅程](../../product/use-cases/auto-research/long-horizon-progress-design.zh-CN.md)
把原生结果关联到研究片段、证据与实际采用。研究侧牵头方法、基线/窗口/成本口径及独立
Expand Down
15 changes: 15 additions & 0 deletions docs/quota-allocation.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,21 @@ become progress through recovery. Promoted authority's existing typed blocked
closeout can use a Turn-owned retry for an open Todo without a resume condition,
without inventing an external dependency or restarting the trial's budget.

Positive CLI work admission retains the selected Todo's `resume_when` and
`resume_ready` as scalar receipt facts. On same-Turn reentry, an unchanged
`resume_at` already satisfied at that admission can continue under the original
binding. The typed recovery owner checks the original receipt timestamp with
microsecond precision and current readiness. A newly authored or changed wait,
even one already due, still requires the original result's closeout. Missing or
malformed historical admission facts retain conservative recovery. No receipt,
wait, deadline or debit is rewritten; these facts grant no new work authority.

CLI 正向工作准入将所选 Todo 的 `resume_when` 和 `resume_ready` 作为标量事实保留
在回执中。同 Turn 重入时,若仍为准入时已经满足的同一个 `resume_at`,可沿原绑定
继续;typed recovery owner 用微秒精度核对原回执时间及当前就绪状态。后来新设或
改变的等待,即使已经到期,仍须结清原结果。历史准入事实缺失或畸形时保守进入恢复,
不改写回执、等待、期限或扣额,也不产生新的执行权限。

A Todo-bound path replan can be qualified during execution even when the
initial guard selected no replan obligation. Its exact durable writeback must
carry a recorded `autonomous_replan_ack_v0` with an accepted semantic delta or
Expand Down
27 changes: 26 additions & 1 deletion loopx/control_plane/quota/blocked_wait.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {settlementIdentity, type JsonObject} from "../effect_program.ts";
import { EffectRuntimeRequestError } from "../effect_runtime_errors.ts";
import { jsonObject, requireJsonObject } from "../runtime_decode.ts";
import {parseTodoTimestampMicros} from "../runtime_timestamp.ts";
import {nativeChildReportAdmission} from "../capabilities/native_child_admission.ts";
import {heartbeatReceiptBinding, heartbeatReceiptDetails, heartbeatReceiptFactFromEvent} from "./heartbeat_receipt_identity.ts";
import {
Expand Down Expand Up @@ -231,6 +232,29 @@ function admittedBusinessResult(request: JsonObject): boolean {
.report_permission === "new_operation";
}

/** A timer that was already satisfied at the original positive admission has
* not removed executable work. Missing historical facts retain recovery; the
* deadline alone cannot prove when a wait was authored. */
function runnableTimerAtAdmission(request: JsonObject, todo: JsonObject, resumeWhen: string): boolean {
const receipt = jsonObject(request.heartbeat_receipt);
const admitted = receipt && heartbeatReceiptDetails(receipt);
const condition = jsonObject(todo.resume_condition);
if (!receipt || !admitted || admitted.admission_resume_ready !== true ||
todo.status !== "open" || todo.resume_ready !== true ||
condition?.satisfied !== true || !resumeWhen.startsWith("resume_at:") ||
typeof receipt.recorded_at !== "string") return false;
try {
const original = normalizeTodoResumeWhen({schema_version: TODO_RESUME_NORMALIZE_REQUEST_SCHEMA_VERSION,
resume_when: admitted.admission_resume_when});
if (original !== resumeWhen) return false;
const due = parseTodoTimestampMicros(resumeWhen.slice("resume_at:".length), true);
const recorded = parseTodoTimestampMicros(receipt.recorded_at, true);
return due !== null && recorded !== null && due <= recorded;
} catch {
return false;
}
}

/** A pending dependency changes executable work, never the Turn's receipts.
* settlement_progress is the existing settlement owner's exact-Turn readback,
* transported by the live guard, not an author-declared progress observation.
Expand Down Expand Up @@ -295,7 +319,8 @@ export function projectReceiptBoundWait(value: unknown): JsonObject {
if (["open", "deferred"].includes(String(todo.status)) &&
todo.task_class === "advancement_task" &&
writebackRequired && request.replay_phase === "open" &&
admittedBusinessResult(request) && externalWait) {
admittedBusinessResult(request) && externalWait &&
!runnableTimerAtAdmission(request, todo, resumeWhen!)) {
const reason = "The original admitted Turn still owes durable writeback. Its later external wait cannot discard that identity. Inspect existing effects and record only the validated original result, then settle once under the original identity. Keep the wait unchanged; do not repeat business work, select a successor, or invent a retry clock.";
return boundRecovery(request, "durable_writeback", reason);
}
Expand Down
8 changes: 6 additions & 2 deletions loopx/control_plane/quota/heartbeat_receipt_identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,12 @@ export function heartbeatWorkRequalification(
throw receiptIdentityConflict("work requalification cannot replace the original semantic replan guard");
}
const qualified = {...oldDetails};
for (const field of ["ok", "should_run", "must_attempt_work", "delivery_allowed", "quiet_noop_allowed"]) {
qualified[field] = currentDetails[field]!;
// The first positive work admission owns these facts. A repair-only
// receipt's earlier selection cannot describe the newly admitted work.
for (const field of ["ok", "should_run", "must_attempt_work", "delivery_allowed", "quiet_noop_allowed",
"admission_resume_when", "admission_resume_ready"]) {
if (currentDetails[field] !== undefined) qualified[field] = currentDetails[field]!;
else delete qualified[field];
}
// Preserve workspace causality, semantic guards, pending selection and all
// original identities. Work admission makes this same Todo owe closeout.
Expand Down
7 changes: 7 additions & 0 deletions loopx/control_plane/quota/settlement_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ def quota_rollout_details(
"quiet_noop_allowed": bool(agent_channel.get("quiet_noop_allowed")),
"closeout_required": closeout_required,
}
if closeout_required and selected_todo and selected_todo.get("todo_id") == todo_id:
# Freeze canonical selection facts at positive admission. Reentry must
# not mistake this already-runnable timer for a newly authored wait.
# The TypeScript recovery owner validates the comparison; unknown
# readiness and an absent timer remain explicit null facts here.
details["admission_resume_when"] = selected_todo.get("resume_when")
details["admission_resume_ready"] = selected_todo.get("resume_ready")
replan_packet = payload.get("replan_action_packet")
receipt = payload.get("heartbeat_receipt")
capability_guard = (replan_packet.get("capability_guard") if isinstance(replan_packet, Mapping) else None) or (
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 @@ -59,6 +59,7 @@ teaches a reusable control-plane lesson.
| `pending_capability_intent_projection_gap` | A durable post-writeback sidecar says `intent_recorded`, but quota remains `monitor_quiet_skip` or `terminal_no_followup`; no governed executor wakes, so no local artifact or exact approval Todo appears. | Exact Goal/Agent sidecar, intent schema and authority, consumption receipt, quota interaction contract, generated-artifact count, approval-Todo count, and external-effect count. | The producer journal was durable but no read model projected unconsumed capability intents into quota arbitration. Terminal or quiet lifecycle state therefore hid required capability work forever. | Add a provider-neutral TypeScript-validated pending-intent interaction slot, let the opted-in capability read only exact eligible sidecars, and give the pending action precedence over quiet/terminal routes. Consume it through an idempotent local executor that freezes checked artifacts and one digest-bound user gate; keep external delivery unauthorized and suppress consumed intents on replay. |
| `approved_capability_delivery_successor_gap` | A governed report or other capability payload is frozen and its exact user gate is approved, but quota returns quiet terminal/monitor state and no provider action runs. A later caller may also improvise a destination or default sender because the approval receipt contains no executable route. | Frozen generation/consumption receipt, completed gate decision and scope, linked agent Todo, required decision scopes before/after approval, Goal Channel binding, selected Todo, provider effect and exact sender/destination readback. | The consumer created only a user gate. Approval recorded authority but had no explicitly linked, typed agent successor for Todo/quota selection, so the external effect existed only in chat memory or caller convention. | Before the gate, create one blocked agent successor bound to the frozen generation, exact decision scope, provider capability, and safe write scope; link the gate with `unblocks_todo_id`. Approval must atomically consume only that scope and resume the successor. The provider then resolves route and sender from the durable project binding, rejects caller overrides/default fallbacks, and records success only after native effect readback. |
| `host_closeout_presentation_lookup_gap` | A prior heartbeat remains in closeout recovery after a successful blocked/deferred/completed Todo writeback; adding unrelated Todos changes recovery. | Receipt-bound Todo id, exact `todo list --todo-id` readback, compact quota visibility lanes, same-Turn retry and quota-spend count. | Recovery treated absence from a bounded presentation list as absence of a durable lifecycle transition. | Resolve the exact receipt-bound Todo through the existing provider-aware read path before evaluating closeout; preserve provider errors, identity binding and no-spend recovery. Cover crowded versus small inventories and real legacy/File/SQLite CLI writes; never raise display limits or fabricate settlement receipts. |
| `admission_timer_reentry_gap` | A positively admitted Todo with an unchanged, already-due timer immediately becomes writeback-only on same-Turn reentry before producing a result. | The original positive admission receipt, its retained resume/readiness facts and timestamp, current canonical Todo, exact binding, and File/SQLite replay. | Recovery classified every external wait as introduced after admission; today's due flag alone cannot establish when a wait was authored. | Freeze scalar resume/readiness facts at the first positive admission and compare them in the existing typed wait owner with microsecond timestamps. Continue only the unchanged runnable timer; later waits and missing/malformed legacy facts retain original closeout. Preserve identity, clocks, gates and one debit. Never clear a legitimate wait, rewrite receipts, fabricate progress or reset a retry clock to escape recovery. |
| `blocked_turn_retry_history_gap` | An exact blocked Turn can close without spending, but its open Todo is immediately selected again or loses its wait when other runs crowd the status display; a peer hard lease prevents the blocked agent from updating the Todo. | Exact Goal/Agent/Todo/Turn receipt, peer lease, canonical Todo validator, persisted retry due time, full run index versus compact recent runs and cached index digest, next-Turn selection and spend count. | The settlement had no bounded retry authority, or quota selection reconstructed it from truncated or stale status projection and tried to mutate a peer-gated Todo. | Persist one bounded retry on the blocked Turn receipt, retain it in the full-index semantic projection, and fence cached scheduler status against the current Run index before projecting it for the same agent. Keep the canonical Todo and terminal validator intact; prove replay, no spend, crowded history, stale cache, and real File/SQLite hard-lease readback. |
| `host_closeout_history_scan_amplification` | Quota entry approaches or exceeds its runtime timeout only on a long-lived Goal, especially when many prior Turns already have valid closeouts. | Turn and receipt counts, rollout-log and runs-index sizes, candidate count, per-stage elapsed time, declared runtime budget, and the same synthetic settled history before and after repair. | Preflight rebuilt append-order recency with repeated list searches, then each candidate reread, reparsed, and rescanned the complete event and run history. A larger timeout hid the multiplicative work without bounding it. | Parse each persisted source once, retain strict-versus-tolerant read semantics in the shared snapshot, build append-order and exact Turn/effect indexes, and reduce every candidate from that snapshot. Restore the ordinary runtime budget and cover a sufficiently large all-settled history that must traverse every candidate; never truncate history, skip identity validation, or raise the timeout as the repair. |
| `turn_replay_recovery_semantic_gap` | A real Turn resumes from a safe Journal prefix, but `inspect-journal` presents `replay_legal=false` as if recovery were forbidden; scheduler-only or saved-Host-result recovery is especially misleading. | Journal integrity fields, replay decision, executor-adopted recovery decision, completed phase prefix, complete typed settlement identity, authoritative selected-Todo lineage, conditional Host Session Binding check, prepared-effect presence, and bounded recovery outcome. | Effect-free terminal replay and effectful executor recovery were collapsed into one user-facing decision even though the executor used separate status/phase rules; initial repairs also omitted either the settlement identity or its binding-to-Turn cross-check, allowing a drifted goal, agent, or canonical Todo to reach a later effect. | Keep replay legality and Journal consistency distinct. Make one typed recovery decision the source used by both executor and inspection; validate and cross-bind the canonical settlement goal, agent, Turn instance, binding, and effect id before authorization, including the selected Todo or adaptive primary Todo; project continue/resume phase/Host reinvocation/reason plus only participating checks, and persist a bounded planned-versus-actual audit. Cover identity and binding drift with zero-provider-call regressions. Preserve the existing prepared-effect readback owner and do not claim general exactly-once semantics. |
Expand Down
Loading
Loading