Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
28d4999
docs(book): add long-horizon spine chapters and align bilingual nav
songoow Sep 30, 2026
c1923db
docs(book): rewrite the developer book around long-horizon requirements
songoow Sep 30, 2026
c4eac92
docs(book): ground architecture explanations in current runtime contr…
songoow Sep 30, 2026
d3adac6
test(book): validate rendered chapter fragment links
songoow Sep 30, 2026
9a74c1d
Merge latest main for Developer Book supplement
songoow Sep 30, 2026
b642a78
feat(book-example): ship bounded text statistics provider and contrac…
songoow Sep 30, 2026
8e1976e
docs(book): connect design tradeoffs through one running task
songoow Sep 30, 2026
322be74
test(book): validate companion provider and architecture diagrams
songoow Sep 30, 2026
16dc9cf
docs(book): mark conceptual fields and state the harness scope
songoow Sep 30, 2026
4dcd1a5
docs(book): add evidence-backed reader checkpoints
songoow Sep 30, 2026
76b7583
docs(book): connect the learning path to accountable delivery
songoow Sep 30, 2026
aa026be
docs(book): consolidate evidence, recovery and collaboration chapters
songoow Oct 1, 2026
2e45356
Merge remote-tracking branch 'origin/main' into codex/book-unify-5354
songoow Oct 1, 2026
7a0046a
fix(runtime): remove duplicate worktree digest import
songoow Oct 1, 2026
9d9bc9c
docs(book): reconcile source scope after consolidating reader chapters
songoow Oct 1, 2026
ea30283
test(book): run reader checkpoint checks in Frontstage CI
songoow Oct 1, 2026
e3be56b
Merge remote-tracking branch 'origin/main' into codex/book-unify-5354
songoow Oct 1, 2026
a29b7e1
Merge remote-tracking branch 'fork/codex/dev-book-architecture-sample…
songoow Oct 1, 2026
0621a2f
test(ci): isolate disposable probe CLI from checkout coverage
songoow Oct 1, 2026
b46a3ef
Merge remote-tracking branch 'origin/main' into codex/pr-repair-5354-…
songoow Oct 1, 2026
e7ba528
test(workspace): stabilize time and confirmation-delivery fixtures
songoow Oct 1, 2026
421f35c
Merge commit 'eced3985d7abc39ad93eb773f87ba0adaeb5b066' into codex/pr…
songoow Oct 1, 2026
ca90b66
docs(book): derive cadence from the frontier, not from should_run=false
songoow Oct 2, 2026
b1a8ae7
Merge branch 'main' of https://github.com/loopx-project/loopx into co…
songoow Oct 2, 2026
f18be12
Merge branch 'main' of https://github.com/loopx-project/loopx into co…
songoow Oct 2, 2026
c89b54d
Merge origin/main into codex/pr-repair-5354-final
song Oct 2, 2026
d590219
Merge origin/main into codex/dev-book-architecture-sample
songoow Oct 2, 2026
09d0202
docs(book): keep the zero-lane fresh-registration branch in identity …
songoow Oct 2, 2026
a72fca5
Merge origin/main into codex/dev-book-architecture-sample
songoow Oct 2, 2026
b53c3ef
docs(book): run every monitor checkpoint selector as one pytest command
songoow Oct 2, 2026
896027d
Merge origin/main into codex/dev-book-architecture-sample
songoow Oct 2, 2026
0a31cda
Merge origin/main into codex/dev-book-architecture-sample
songoow Oct 2, 2026
240e05c
docs(book): align connection, App and CLI chapters with the identity …
songoow Oct 2, 2026
c8644cd
docs(book): stop charging gated waits to quota and scope identity def…
songoow Oct 2, 2026
904eabd
docs(book): describe what extension rollback and registry evidence ac…
songoow Oct 2, 2026
d910885
Merge origin/main into codex/dev-book-architecture-sample
songoow Oct 2, 2026
8643a7c
docs(book): stop listing the retired event contract as current state …
songoow Oct 2, 2026
171e8e5
docs(book): restore the connection acceptance checklist and stop citi…
songoow Oct 2, 2026
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: 10 additions & 0 deletions .github/workflows/frontstage-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ on:
- "examples/readme-star-history-smoke.py"
- "examples/frontstage-stargazer-fetch-smoke.py"
- "examples/dev-book-publication-smoke.py"
- "packages/loopx-text-stats/**"
- "tests/test_dev_book_reader_checkpoints.py"
- "examples/dev-book-welcome-wagon-smoke.py"
- "examples/goal-channel-frontstage-fixture.py"
- "examples/showcase-catalog-smoke.py"
Expand Down Expand Up @@ -73,6 +75,8 @@ on:
- "examples/readme-star-history-smoke.py"
- "examples/frontstage-stargazer-fetch-smoke.py"
- "examples/dev-book-publication-smoke.py"
- "packages/loopx-text-stats/**"
- "tests/test_dev_book_reader_checkpoints.py"
- "examples/dev-book-welcome-wagon-smoke.py"
- "examples/goal-channel-frontstage-fixture.py"
- "examples/showcase-catalog-smoke.py"
Expand Down Expand Up @@ -159,6 +163,12 @@ jobs:
- name: Validate Developer Book publication
run: python3 examples/dev-book-publication-smoke.py

- name: Validate Developer Book companion provider
run: python3 -m unittest discover -s packages/loopx-text-stats/tests -v

- name: Validate Developer Book reader checkpoints
run: python3 -m unittest discover -s tests -p test_dev_book_reader_checkpoints.py -v

- name: Validate bilingual Blog catalog
run: node examples/blog-bilingual-index-smoke.mjs

Expand Down
144 changes: 113 additions & 31 deletions docs/book/chapters/00-reading-guide.md

Large diffs are not rendered by default.

201 changes: 83 additions & 118 deletions docs/book/chapters/01-from-session-to-loop.md
Original file line number Diff line number Diff line change
@@ -1,148 +1,114 @@
# 从一次会话到长程任务

一个 Agent 能在当前会话里修改代码、运行测试并解释结果,不代表它能可靠地拥有一项持续数天的
工作。本章先区分 session context 与 project memory,再说明 control plane 为什么存在。
一个 Agent 能在当前会话里改代码、跑测试、解释结果,不代表它能可靠地拥有一项持续数天的工作。本章说明这个差别从哪里来,以及它为什么需要一个不在会话里的东西。

## 本章目标
## 一个看起来很顺利的开头

读完后,你应该能:
假设你要给已有 CLI 增加 `--format json`:

- 指出哪些状态不能只留在 transcript 中;
- 区分 execution plane 与 control plane;
- 为一个会跨 session 的任务列出最小外置状态;
- 区分 durable project fact 与必须重新探测的 environment fact;
- 判断一个任务是否仍适合只用普通 Agent 会话。

## 贯穿全书的任务

假设你要为已有 CLI 增加 `--format json`:
```text
10:02 你让 Agent 改输出层。
10:11 改完了,默认文本输出保持不变,加了测试。
10:14 本地测试全过,提交,推送,开 PR。
10:16 CI 开始跑。Agent 说:"等待 CI 结果,通过后请维护者确认 JSON contract。"
10:17 你关掉窗口去开会。
```

1. 修改输出层;
2. 保持默认文本输出兼容;
3. 添加测试;
4. 等待 CI;
5. 交给维护者确认 JSON contract;
6. 根据反馈修订并发布。
到 10:17 为止,一切正常。问题从这一刻开始:

如果所有步骤能在一次连续会话内完成,transcript 加 Git diff 通常已经够用。真实工作却经常在
第三步之后中断:上下文被压缩,CI 要等待,维护者隔天回复,另一个 Agent 接手,或者外部依赖
改变。此时“模型还记得什么”与“项目现在是什么状态”开始分离。
```text
次日 09:30 你重新打开。CI 昨天就绿了,但没人知道。
次日 09:30 维护者在 PR 里问了字段命名,没人回。
次日 09:31 Agent 不知道昨天做过什么,重新读了一遍代码,然后问:
"需要我实现 --format json 吗?"
```

## Session context 是工作内存,不是账本
这个情境中的代码和测试可能都正确,失败发生在工作衔接上:等待对象、验收责任和恢复入口没有被接手者可靠地读取。即使 Host 保存了聊天,也仍需要从当前 PR、CI 与工作状态重建下一步。

模型上下文适合承载:
## 为什么这是结构性的

- 当前问题的局部推理;
- 刚读取的代码;
- 本轮工具结果;
- 即将执行的短计划。
自然的反应是"那就别关窗口"。但这取决于一个不可能维持的前提:工作必须在一次连续会话内完成。真实工作会不断打破它:

它不适合成为以下事实的唯一存放位置:
- 上下文被压缩,早期步骤让位给近期内容;
- CI 要等,而等待的时间以小时计;
- 维护者隔天才回复;
- 另一个 Agent 接手,它的上下文从零开始;
- 外部依赖更新,昨天的判断今天不再成立。

- 当前目标及验收条件;
- 哪些工作已经完成并通过了什么验证;
- 哪个动作正在等待谁的决定;
- 哪个 Agent 拥有当前任务;
- 外部写操作是否真的发生;
- 何时应该重试或停止。
这些是长程工作需要准备处理的情形。关键控制信息如果只能靠当前上下文解释,跨会话接手就会依赖人工重建;持久记录与明确读取入口可以减少这种依赖。

原因不只是 token 有限。下面这些事件会分别破坏不同假设:
## 会话上下文是工作内存

| 事件 | 被破坏的假设 |
| --- | --- |
| session 结束 | 下一轮还能直接读取全部上下文 |
| context compaction | 原始细节仍以相同强度存在 |
| 模型或 Agent 切换 | 新执行者共享原 Agent 的隐含计划 |
| 人类插入决定 | 旧计划仍然合法 |
| CI、Issue 或服务状态变化 | 旧观察仍代表当前外部事实 |
| 工具超时 | “发起了动作”等于“动作已完成” |
模型上下文天然适合承载这些东西:

长程工作需要把恢复所需的最小事实外置。外置不等于保存整段对话,而是保存可供下一轮重新推导
行动的 durable project facts。恢复时还必须重新探测 checkout、Host capability 和外部服务,
因为环境事实可能在两轮之间改变:
- 当前问题的局部推理;
- 刚读取的代码;
- 本轮的工具有返回结果;
- 即将执行的短计划。

```text
next decision =
replay(durable project facts)
+ inspect(fresh environment)
```
它不适合作为这些事实的唯一存放位置:

Canonical state(规范状态)只拥有 LoopX 生命周期事实。Git commit、CI check 和外部资源状态仍由
对应系统拥有,LoopX 保存的是 bounded readback、revision 与 evidence pointer。
| 事实 | 为什么不能只放在上下文里 |
|---|---|
| 当前目标与验收条件 | 压缩后可能只剩最近的步骤,"为什么做"丢了 |
| 哪些工作已完成、通过了什么验证 | 下一位执行者无法区分"做过并验证"和"打算做" |
| 哪个动作在等谁的决定 | 等待是跨会话的,而上下文不跨会话 |
| 哪个 Agent 拥有当前任务 | 重启或交接后,所有权无法从记忆里恢复 |
| 外部世界的当前状态 | 昨天读到的 CI 状态今天可能已经变了 |

## Execution plane 与 control plane
Host 可以持久保存 transcript,但旧对话本身不提供当前权限、验收或恢复状态。判据是接手者能否从明确的事实源重新核对这些信息,而不依赖原会话的隐含理解。

**Execution plane(执行面)** 负责执行一个有界动作,例如:
## 执行面与控制面

- Agent 修改代码;
- shell 运行测试;
- provider 调用 GitHub;
- Host 启动下一次模型 Turn。
理解了"状态必须外置",接下来的问题是:外置之后,谁来用它?

**Control plane(控制面)** 负责决定什么动作现在合法、为什么继续、何时等待,以及结果如何进入
持久状态:
**Execution plane(执行面)** 负责执行一个有界动作:Agent 修改代码、shell 运行测试、provider 调用 GitHub、Host 启动下一次模型 Turn。

- 目标和验收是否仍然有效;
- 当前 frontier 中哪个 Todo 可以执行;
- 是否存在需要用户处理的 Gate;
- 当前 evidence 能否支持状态转换;
- quota 是否允许再启动一轮;
- 中断后从哪里恢复。
**Control plane(控制面)** 负责判断什么动作现在合法、为什么继续、何时等待,以及结果如何进入持久状态——目标与验收是否仍然有效、当前 frontier 里哪个 Todo 可以执行、是否存在需要用户处理的 Gate、当前 evidence 能否支持状态转换、quota 是否允许再启动一轮、中断后从哪里恢复。

```text
Control plane: 选择并约束下一步
|
v
↓
Execution plane: 执行一个有界动作
|
v
↓
Observation / receipt: 返回可验证结果
|
v
↓
Control plane: 接受、拒绝或重规划
```

控制面不替代执行面。LoopX 不写代码、不托管 Git,也不代替 CI;它使这些系统的结果可以被一个
跨 Turn 的工作生命周期消费。
**控制面不替代执行面。** LoopX 不写代码、不托管 Git、也不代替 CI。它让这些系统的结果能被一个跨 Turn 的工作生命周期消费——这正是 10:17 之后缺的那一环。

## 三类长程任务为什么能复用同一控制面
## 三类长程任务为什么能共用同一控制面

LoopX 的控制合同不绑定某一种业务流程。仓库中的 Control-Plane Course 用三类 Showcase
说明:领域事实和验收方式可以完全不同,Goal、Todo、Gate、Quota、Evidence 与恢复机制仍可复用。
LoopX 的控制合同不绑定某一种业务流程。仓库里的 Control-Plane Course 用三类 Showcase 说明:领域事实和验收方式完全不同,Goal、Todo、Gate、Quota、Evidence 与恢复机制仍然可以复用。

| Showcase | 领域事实与判断 | 复用的控制面 |
| --- | --- | --- |
|---|---|---|
| PR Issue Fix | issue feasibility、exact-head checks、review 与 merge state | Todo、claim、workspace guard、monitor、successor、terminal closeout |
| Single-Agent Auto ML | metric contract、matched baseline、实验 revision、外部 task 与 guardrail | Quota、Provider receipt、monitor、defer/resume、promotion Gate |
| Multi-Agent Auto Research | hypothesis、dev/holdout evidence、支持或反驳关系 | per-Agent frontier、handoff、Evidence lineage、promotion/retirement |

三条产品链都可以压成同一个长期闭环:
三条产品链都能压成同一个长期闭环:

```text
外部事实
-> Provider observation
-> Capability 的领域判断与 transition proposal
-> Kernel 检查 authority、frontier、quota 与 workspace
-> Agent / Host 执行一个 bounded Turn
-> 独立验证、evidence 与 receipt 写回
-> 重新计算 continue | wait | ask | replan | repair | terminal
→ Provider observation
→ Capability 的领域判断与 transition proposal
→ Kernel 检查 authority、frontier、quota 与 workspace
→ Agent / Host 执行一个 bounded Turn
→ 独立验证、evidence 与 receipt 写回
→ 重新计算 continue | wait | ask | replan | repair | terminal
```

复用的不是一段通用 prompt,而是生命周期不变量。Issue-Fix 可以理解
`CHANGES_REQUESTED`,Auto ML 可以理解 matched baseline,Auto Research 可以理解 holdout;
这些领域含义属于 Capability 与 Domain State。谁能 claim、是否可执行、何时再次唤醒、什么证据
允许 writeback,以及 Goal 能否终止,仍由同一 Kernel 合同决定。
复用的是**生命周期不变量**,而非一段通用 prompt。Issue-Fix 理解 `CHANGES_REQUESTED`,Auto ML 理解 matched baseline,Auto Research 理解 holdout——这些领域含义属于 Capability 与 Domain State。而谁能 claim、是否可执行、何时再次唤醒、什么证据允许 writeback、Goal 能否终止,由同一套 Kernel 合同决定。

这个边界也解释了为什么新增领域能力不应复制一套 runner、queue、retry 和 completion 状态机。
领域层提供可判定事实与 proposal,Provider 执行外部调用,Kernel 拥有跨领域生命周期。
这条边界也解释了为什么新增领域能力不该复制一套 runner、queue、retry 和 completion 状态机。领域层提供可判定事实与 proposal,Provider 执行外部调用,Kernel 拥有跨领域生命周期。

需要从三个 Showcase 进入架构、源码入口和完整 case 时,继续阅读
[Control-Plane Course 第 2 讲](/loopx/docs/development/control-plane-course/02-goal-control-plane-architecture/);
第一次接触术语时可先看[概念导读](/loopx/docs/development/control-plane-course/00-concept-primer/)。
需要从三个 Showcase 进入架构与源码入口时,继续读 [Control-Plane Course 第 2 讲](/loopx/docs/development/control-plane-course/02-goal-control-plane-architecture/);第一次接触术语可以先看[概念导读](/loopx/docs/development/control-plane-course/00-concept-primer/)。

## 哪些状态必须外置
## 最小外置状态长什么样

对贯穿任务,最小状态不是完整 transcript,而是一组可回答恢复问题的事实:
对上面的贯穿任务,最小状态不是完整 transcript,而是一组能回答恢复问题的事实:

```yaml
# 为解释而简化,不是 LoopX 文件格式
Expand All @@ -161,30 +127,29 @@ next_wake:
when: maintainer decision arrives
```

这些字段的价值在于:下一位执行者不必相信前一位 Agent 的自述,而能从目标、工作队列、Gate、
证据和 fresh environment 重新判断下一步。示例是解释模型,不是 LoopX 的存储格式;第三章会
说明这些信息分别属于哪些协议与状态表面。
这些字段的价值在于:**下一位执行者不必相信上一位 Agent 的自述**,而能从目标、工作队列、Gate、证据和 fresh environment 重新判断下一步。示例是解释模型,不是 LoopX 的存储格式。

## 代价与边界:什么被放弃了

外置状态有代价。说清楚代价,才能判断什么时候值得。

**代价一:多一份必须维护的状态。** 项目里多了一个不能随手改、需要理解其生命周期的目录。写错状态比不写状态更糟,因为下游会拿它当真。

**代价二:每一步都变慢。** 读取状态、判断合法性、验证、写回,都比"直接开干"慢。一次会话内能完成的小任务会被这些步骤拖累。

## 什么时候普通会话已经足够
**代价三:需要外部事实可见。** 如果 CI 结果、维护者回复、外部依赖状态无法被程序读取,控制面就只能等,而"等"需要有人重新触发。

不要把所有任务都升级成长程控制面。普通会话适合:
**边界一:本书只讲长程运行。** 范围封闭、能在当前上下文完成、不需要等待外部事件、没有跨 Agent 交接的工作,普通会话就够了——第 2 章的任务资格卡会给判据。

- 范围封闭;
- 能在当前上下文完成;
- 不需要等待外部事件;
- 没有跨 Agent 交接;
- 失败后可以低成本重做;
- Git diff 和测试结果足以恢复。
**边界二:控制面不拥有领域判断。** 它不判断一个 issue 值不值得修、一个实验指标是否显著;那是 Capability 的职责。

例如“解释这个函数”“修正一处 typo”“为纯函数补一个测试”,通常不需要项目级 Goal 和 Todo。
**边界三:恢复需要当前行动条件。** 详见[恢复与运行边界](04-runtime-boundaries.md)。

当任务出现以下任一条件时,再考虑持久 Goal 或 LoopX:
## 不变式

- 需要跨多个 Turn;
- 有依赖、并行 lane 或明确 handoff;
- 有权限边界或人类 Gate;
- 有外部 effect,需要 readback 与 receipt;
- 需要定时 monitor 或 backoff;
- 需要从另一个 Host 或 Agent 恢复。
1. **Prompt 内容不能独自证明持久写回。** 检查可寻址的记录、身份和版本,而不是窗口是否还开着。
2. **执行面与控制面不能互相替代。** 控制面不写代码,执行面不决定自己是否合法。
3. **复用的是生命周期不变量,不是 prompt。** 三个不同领域能共用一套控制面,靠的是这条。
4. **下一位执行者不需要相信前一位的自述。** 如果需要,说明外置得不够。

下一章会进一步区分:普通会话、Codex Goal 与 LoopX 分别把哪些控制信息移出了当前 prompt。
接下来用[会话、Host Goal 与 LoopX](02-session-goal-loopx.md)判断任务需要哪层状态,再读[四个要求](02b-long-horizon-requirements.md),把这些问题组织成完整的架构视角。
Loading
Loading