Skip to content

docs: 60 秒上手的 README,其余进 GUIDE;CHANGELOG 自动生成 - #370

Merged
oratis merged 11 commits into
mainfrom
claude/opt-docs
Sep 7, 2026
Merged

oratis merged 11 commits into
mainfrom
claude/opt-docs

Conversation

@oratis

@oratis oratis commented Sep 7, 2026

Copy link
Copy Markdown
Owner

第 2 / 8 条,实现 UX-6 与 T-9 的文档部分。基于 #369。

做了什么

README 从 767 行降到 ~130 行。 安装命令现在在前 20 行内可达(之前在第 119 行)。密钥示例同时给出 Anthropic 和 DeepSeek,兑现官网宣传的多 provider。原有全部内容移入 docs/GUIDE.md(不是删除),按安装配置 / 各表面 / Soul / 知识库 / 邮件 / 渠道 / 心跳自治 / 工具与沙箱 / 配置文件 / REPL / 目录结构分组,所有站内链接同步更新。

中英结构对齐。 README.zh-CN.md 同样拆分为 docs/GUIDE.zh-CN.md,补译了此前只有英文版才有的章节。scripts/check-readme-drift.mjs 比较两种语言的标题树(层级与顺序),漂移即失败;scripts/check-md-links.mjs 检查全仓库相对链接可解析。两者都是零依赖、可离线运行,通过新增的 docs-check.yml 在相关路径变更时触发。

CHANGELOG 自动生成。 文件之前停在 0.12.0,之后 12 个版本只存在于 docs/RELEASE_*.md。scripts/gen-changelog.mjs 从这些发布说明生成 Keep-a-Changelog 格式条目,0.12.0 及更早的手写内容保留在标记注释之下。

docs 索引与归档。 新增 docs/README.md 索引;已完工的计划文档 git mv 进 docs/archive/plans/,全仓库(含 .ts/.swift 注释)对它们的引用同步修正。仍有未完成阶段的计划、路线图和运行手册留在原处。

harness 计划勾选。 只勾选代码可验证满足的验收项,每条附一行证据。

验证

链接检查与漂移检查均通过;README 与 GUIDE 的标题并集覆盖旧 README 的全部章节。

🤖 Generated with Claude Code

oratis and others added 11 commits September 7, 2026 22:34
The README had grown to 767 lines / 62 headings with the first install
command on line 119 — it read as a reference manual, not an entry point,
so a newcomer met 118 lines of positioning before learning how to install
anything (UX-6 in the v0.24.0 UX review; target: install command within
the first 20 lines).

README.md is now 85 lines: badges, one-line positioning, a quick start
whose first install command sits on line 19, the compact
SOUL / DESIRES / HEARTBEAT / REVE block, screenshot slots pointing at the
current session shell (assets/screenshots/shell-nebula.png and
shell-calm.png — the images themselves are regenerated separately), a
short "what's special" list, and links out.

Everything else MOVED — nothing deleted — into docs/GUIDE.md, grouped
under Install & configure / Surfaces / Soul / Knowledge base / Mail /
Channels / Heartbeat / Tools & sandbox / Configuration files / REPL /
Layout / Acknowledgements, with a table of contents and every intra-repo
link re-anchored for its new depth. Verified by diffing the old README's
content against the union of the new README and GUIDE: the only
differences are renamed headings and re-pathed links.

The quick start shows a non-Anthropic key (DeepSeek) next to the
Anthropic one, because the web onboarding advertises those providers to
Chinese users and the old README implied Anthropic was required.

`<a id="install">` is kept in the README so the existing
CONTRIBUTING.md#install link still resolves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 9e28ea5b05623bfe2345cfc41c3853ee1f2f8910)
The Chinese README had drifted: 59 headings against the English 62, last
touched twelve days behind it, and missing whole sections (AGENTS.md /
CLAUDE.md instruction layering, project skills, sandbox modes, the
open-source building blocks). Two documents evolving independently is how
a translation rots.

README.zh-CN.md now has exactly the same heading tree as README.md, and
docs/GUIDE.zh-CN.md exactly the same tree as docs/GUIDE.md — verified by
scripts/check-readme-drift.mjs (7 and 51 headings, same shape). Structure
being identical is the point: a section can no longer exist in one
language and silently not the other, and the drift check makes that a CI
failure rather than something a reader discovers.

The long content MOVED out of README.zh-CN.md into docs/GUIDE.zh-CN.md
with links re-pathed for docs/ — nothing deleted; verified the same way
as the English split. Sections that only existed in English were
translated (Providers, Birth ritual, sandbox modes, AGENTS.md / CLAUDE.md,
project skills, open-source building blocks). The `bash` row of the tool
table was stale in Chinese — it still described `LISA_SANDBOX=1` as the
whole story — and now points at the three-mode sandbox table.

Both READMEs keep the language toggle on line 10.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit d975efde9ab7e62f62052234c76333c2fa0f559e)
Two failure modes were only ever caught by a reader: a relative link that
no longer resolves, and a section that exists in one language and not the
other. The README split made both more likely, so make them CI failures.

check-md-links.mjs walks the Markdown roots and verifies every relative
link and every `#anchor` — the anchor half matters most, because moving a
section changes its slug and nothing else notices. It reimplements
GitHub's slug rules, and two of them are subtle:

  - a heading that is entirely a code span (`~/.lisa/config.env`) still
    has an anchor, so heading extraction must not blank inline code the
    way link extraction does;
  - `<slug>` inside a code span is literal text, not an HTML tag, so tag
    stripping has to skip code spans or `#…skillsslugtooljs` breaks.

Both were wrong in the first draft and are now the reason those helpers
are split apart. External URLs are deliberately not fetched: an offline
check is one that never fails for reasons unrelated to the change.

PENDING is an explicit, reasoned allowlist for targets referenced before
they exist — right now the regenerated session-shell screenshots. It
fails the build once the file appears, so an exemption cannot outlive its
cause.

check-readme-drift.mjs compares heading *trees* (level and order, text
ignored) for README.md ↔ README.zh-CN.md and docs/GUIDE.md ↔
docs/GUIDE.zh-CN.md. Wording is allowed to lag; structure is not.

Also fixed three links that were already broken before this change:
scripts/test/ never existed (tests are co-located `src/**/*.test.ts`);
reference/ is gitignored so the session-shell mockup can't be linked; and
a ROADMAP anchor had a dash where the heading has a quote.

The issue-template "Documentation" link pointed at the README for
"install, soul system, channels, all subcommands and the capability
matrix" — that is docs/GUIDE.md now, so it points there.

No package.json script: the workflow calls node directly, and neither
script needs node_modules or the network, so the job runs without npm ci.
Verified by running both checkers, and by pointing the drift checker at a
deliberately mismatched pair to confirm the diff output and exit 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 5f94ccee17e25114d72887c9040c5753f7599dd3)
CHANGELOG.md stopped at [0.12.0] — 2026-06-19 while thirteen more
releases shipped, each documented only in its own docs/RELEASE_v*.md.
That is the predictable outcome of keeping two hand-written accounts of
one release: the one nobody reads goes stale. So there is now one source
(the release note) and a generated summary.

scripts/gen-changelog.mjs emits, per release: the version and the date
of its vX.Y.Z tag (the day it actually shipped — falling back to the
note's commit date so an untagged note still lands in order), the note's
headline paragraph verbatim, its `##` section titles as bullets, and
links to the note and the GitHub release. This makes the headline
paragraph and section titles load-bearing, which is documented in
RELEASING.md so the next release writes them knowing that.

Two details worth naming. Links inside a release note are relative to
docs/, so they are re-pathed for a file that lives at the repo root —
otherwise every generated entry would fail the link check. And the
0.12.0-and-older entries predate the release-note convention: they sit
below a `gen-changelog:handwritten` marker and are copied through
untouched. Reading the tail back from that marker is also what makes
re-running idempotent, verified by running it twice and diffing.

The stale `[Unreleased]` block is dropped rather than preserved: it
described the knowledge-base v2.0 work, which shipped in 0.21.0 and is
covered by that release note. An "Unreleased" heading over shipped work
is worse than no heading.

`--check` exists for release time but is deliberately NOT a CI gate: it
needs full history and tags, and a shallow clone would fail it for
reasons unrelated to the change.

package.json gains exactly one line (`npm run changelog`).

Ran: node scripts/gen-changelog.mjs (twice, byte-identical),
node scripts/gen-changelog.mjs --check, node scripts/check-md-links.mjs
(only the docs index, which lands next, is still missing).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 64e549bc81103fa491b7a9a4f1e9331726366dea)
docs/ had grown to 88 files with no index — 31 PLAN_* among release notes,
reviews, runbooks and research, and no way to tell from a filename whether
a plan was a proposal, in flight, or finished two months ago. The v0.24.0
technical review flagged this (T-9).

docs/README.md is now the index: Start here, Current plans, Completed
plans (archive), Releases, Reviews, Runbooks, Research, Design notes —
each entry with a one-line gloss, because a list of filenames is not an
index. It states the rule it exists to enforce: a plan whose work has
shipped moves to docs/archive/plans/.

Seven documents moved, each on the evidence of its own status line —
never on my reading of the code:

  PLAN_AUTH_OTP_GOOGLE_v1.0    "Status: IMPLEMENTED(代码侧全部落地)"
  PLAN_KNOWLEDGE_BASE_v1.0     "✅ shipped (PRs #235 → #242)"
  HANDOFF_KNOWLEDGE_BASE_v2.0  a spent handoff; the K-series shipped in v0.21.0
  PLAN_UI_SESSION_SHELL_v1.0   "✅ Phase 1–3 已实现"; its remainder became v1.1
  PLAN_UI_SESSION_SHELL_v1.1   "✅ F1–F7 已实现" — F1–F7 is the whole scope
  PLAN_ROOM_v2.0               "✅ Phase A–E 均已落地、验证、部署"
  PLAN_DESIRE_DYNAMICS_v2.0    "PR A + PR B 已实现;PR C 已实现"

Everything else stayed, and the reasons are worth recording. ROADMAP_v1.0
is the map, not a plan. The four pillar plans (SENSE / DISPATCH / REVE /
MODEL / FOUNDATIONS) and their sub-plans expand it and have open phases.
PLAN_CLOUD_v1.0 says M0 is deployed but per-user isolation is not.
PLAN_IOS_REACHABILITY says R1–R4 landed and R5 waits on cloud accounts —
one open phase is enough to keep a plan current. PLAN_ROOM_v1.0 marks
only Phase 1 as landed, so it stays even though its successor is
archived. PLAN_KNOWLEDGE_BASE_v2.0 still says 提案(待评审): the marker is
stale (the K-series shipped) but overruling a document's own status on a
hunch is exactly how an archive stops being trustworthy — it needs its
status line updated first, by someone who knows. CODING_PLANS.md says
phases 1–5 shipped but is user documentation the README links to, not an
internal plan, so it belongs in "Start here". Runbooks were never
candidates. SPRINT_4_PLAN was never started, so it is not "completed"
either — it is filed under older plans with its reasoning intact.

Every relative link to a moved file was rewritten, in both directions:
docs/-level files gained archive/plans/, and the moved files' own links
to ../src/ became ../../../src/. Ten files outside docs/ cite a moved
plan by path in a comment and were updated too (comment text only, no
code): src/kb/paths.ts, src/tools/registry.ts, src/web/{server,
lisa-client,lisa-css,lisa-html-snapshot.test,googleAuth,mailer,otp,
email-deliverability}.ts and packaging/ios-companion/Sources/Theme.swift.
CHANGELOG.md was regenerated rather than hand-edited.

Ran: node scripts/check-md-links.mjs (green — 96 files, links resolve),
node scripts/check-readme-drift.mjs (green). No npm gate: the source
changes are comment text inside existing comments and cannot affect the
build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 440044a9c04e699d973205216974bb92b2ca5476)
The v0.24.0 technical review found 11 of 13 acceptance boxes in this plan
still unticked while H1 and most of H2 had shipped — the document
disagreed with the tree, which is the failure mode the 1.0 criterion
"叙事 = 代码" exists to prevent.

Six boxes are now ticked, each with a one-line evidence note naming the
file and line that satisfies it, so the next reader can re-verify in
seconds instead of re-deriving:

  H1 · ToolContext.caps            src/types.ts:43 (optional; unset = local)
  H1 · no direct node:fs imports   0 occurrences across the seven tools,
                                   with the regression assertion living in
                                   src/capabilities/seam.test.ts:35
  H1 · in-memory fs provider       src/capabilities/memory.ts, exercised by
                                   five tools in seam.test.ts:80–134
  H2 · bounded writes              sandboxed.ts realpath comparison, tested
                                   for ../, absolute and symlink escapes
  H2 · SANDBOX_UNAVAILABLE         sandbox/mode.ts:38 + mode.test.ts:108
  H2 · sandboxMode in the header   sessions/store.ts:51/65/72, v1 still read
                                   via replay.ts:40

Seven stay unticked, deliberately. The FOOTPRINT.md / README narrative
box is an AND and docs/FOOTPRINT.md still says nothing about sandbox
modes (the README half is done). The replay-script box says in the plan's
own words that it is not wired to the Reve drift metric yet. The three
dsh-dispatch boxes need a `backend: "dsh"` that does not exist in src/.

Ticking a box because the neighbouring work shipped is how an acceptance
list stops meaning anything; every tick here was checked against the tree.

Ran: node scripts/check-md-links.mjs (green).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 77f9b390bf5235594fc7b4092ca5ec4af4db5f8f)
A session that reads .codex/ first had no pointer to either of the two
documents that now carry the map: docs/README.md (what every file in
docs/ is, and whether its plan is open or archived) and docs/GUIDE.md
(the long-form user documentation the README no longer holds). Two lines
in the existing file index, so the next Codex session finds them where it
already looks.

Ran: node scripts/check-md-links.mjs (green — .codex/ is one of its roots).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 5ce5f7854ec8f9ceb06d30415e740d4870aab2d8)
Four of the doc-path references updated by the archive move turned out
not to be source comments at all: they sit in CSS and JS comments that
are *emitted into* MAIN_HTML (src/web/lisa-css.ts, src/web/lisa-client.ts),
so the byte-identity snapshot in lisa-html-snapshot.test.ts failed.

The delta is exactly +56 bytes = 4 × len("archive/plans/"), which is the
proof that nothing else moved: no markup, no styles, no behavior. The
constants are re-pinned and the reason recorded next to them, along with
the one-liner that re-derives them, because the next person to hit this
guard deserves better than a bare hex string.

Ran: npm run typecheck (clean), npm test (1645 tests, 1644 pass, 1
skipped, 0 fail), npm run build (clean), npm run check:api-contract
(clean).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 4415f254f58c615f0d1cc4be8b589c20a0cf9c0b)
The six screenshots in assets/screenshots/ were taken on 2026-05-12 and show
the pixel-art shell that the v0.23 session-shell rewrite replaced — a reader
comparing them against a fresh install would not recognise the product.

These two are captured from this branch's code at 1440×900: the three-column
session shell in both themes, with a synthesised soul and a brand-new session,
which is exactly what someone sees on their first run. Nothing is staged — the
conversation area shows the real empty state, including the starter card the
web-UI branch adds later in this chain.

The old 01–06 files stay on disk; nothing links to them any more, and deleting
images that external posts may still hotlink is a separate decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both are the checker doing its job on its first real run.

**A dead cross-reference.** The UX review links to the technical review's T-3
section as `#t-3`, but GitHub derives anchors from the heading text, and that
heading is `### T-3 · P1 · 可靠性:…` — so the real anchor is a long CJK slug
and `#t-3` silently landed at the top of the file. Rather than paste the
generated slug (which rots the moment the heading is reworded), the section
now carries an explicit `<a id="t-3">`, which the checker validates.

**A stale waiver.** PENDING carried the two shell screenshots because they did
not exist yet when the checker was written. They landed in the previous commit,
so the waiver is now a lie — and the checker fails on a stale waiver rather
than quietly ignoring it, which is why this showed up. Map emptied; it stays as
the mechanism for the next legitimately-pending target.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GUIDE.md and GUIDE.zh-CN.md were written from the pre-#365 README, so
moving the content into a new file silently reverted six corrections. Git
saw a pure file addition, not a conflict, so nothing flagged it.

Restored in both languages:

- "all five observers" → "all ten observers", naming the five coding-agent
  adapters plus git, shell, takoapi, managed and pty, and saying which three
  are enabled by default.
- "every adapter has a privacy test" → six of the ten, naming the four that
  have none. The wider claim is false for github-pr, takoapi, managed and
  pty; managed and pty have no test file at all.
- the `integrations/` tree line: "observers: … · managed · …" → the real
  ten, no ellipsis.
- the `advisor/` tree line: the category list was missing cost_spike, which
  src/advisor/types.ts now pins at runtime via SUGGESTION_CATEGORIES.

Checked the split itself while here: the union of README + GUIDE headings
covers every section of the old README (42 → 54), with only renames
unaccounted — "IM channels" → "Channels", "空闲模式(Idle)" →
"空闲模式(梦境 Reve)" — and the content present under the new names.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oratis
oratis changed the base branch from claude/opt-assets to main September 7, 2026 14:38
@oratis

oratis commented Sep 7, 2026

Copy link
Copy Markdown
Owner Author

评审 — 已 rebase;修掉一处 rebase 静默回滚的内容退化

已 rebase 到 main,base 改为 main

冲突三处,都不是选一边就完事的:

  • README.md / README.zh-CN.md —— 旧长 README vs 新短 README,取新版。
  • lisa-html-snapshot.test.ts —— 本 PR 的 +56 字节(归档路径出现在会随 MAIN_HTML 一起下发的 CSS/JS 注释里)撞上 perf(assets): lossless PNG diet — 39.1 MB → 32.2 MB, and real manifest icons #369 的 +21 字节(apple-touch-icon link)。这个不能选边,必须重算。重算结果 308278 = 308201 + 21 + 56,算术正好对上,说明两处改动都在、都没被吃掉。两段说明注释都保留了。

已修:README → GUIDE 的搬迁静默回滚了 #365 的六处修正

这是本轮最值得说的一处。docs/GUIDE.md 与 docs/GUIDE.zh-CN.md 是从 #365 之前的 README 抄的。因为内容搬进的是新文件,git 视作纯新增而非冲突,没有任何东西会报警——rebase 干干净净地通过,六处修正无声消失:

位置 被回滚成 应为
Observe 段(中英) "all five observers" "all ten observers",并列出 git/shell/takoapi/managed/pty 及默认开启的三个
Observe 段(中英) "every adapter has a privacy test" 十个里只有六个;github-pr、takoapi、managed、pty 没有,后两者连测试文件都没有
integrations/ 树行(中英) … · pty · managed · …(带省略号) 真实的十个
advisor/ 树行(中英) 缺 cost_spike 补上——src/advisor/types.ts 的 SUGGESTION_CATEGORIES 现在在运行时钉死了这个集合

那句隐私断言尤其不能放过:它是隐私优先产品对用户的承诺,而且对 managed/pty 从来就不成立。#365 刚把它改对,这次搬迁又原样搬回了错的版本。已全部按 main 的正确文本恢复(程序化取回,不手抄)。

这类风险会贯穿整条栈——凡是"把内容搬进新文件"的改动,rebase 都不会给冲突。后面几层我会继续按这个角度查。

核实过的承诺

"README 与 GUIDE 的标题并集覆盖旧 README 的全部章节" —— 这是本 PR 最该被验证的一条,因为 767 → 85 行的删减很容易顺手丢内容。逐节比对(忽略层级变化、跳过代码块内的 # 注释):

README.md      : 旧 42 节 → 新并集 54 节,未覆盖 2
README.zh-CN.md: 旧 39 节 → 新并集 54 节,未覆盖 4

未覆盖的都是重命名,内容都在:IM channels → Channels、空闲模式(Idle) → 空闲模式(梦境 Reve)、怎么用 并入快速上手、LISA = pi-mono + … 并入 What LISA is / credits。没有真正的内容丢失。

其余实测:

承诺 实测
README 大幅瘦身 767 → 85 行(比 PR 描述的 ~130 还短)
安装命令进前 20 行 第 19 行(旧版在第 140 行,PR 描述记的 119 略有出入)
CHANGELOG 生成器幂等 再跑一次 gen-changelog.mjs,输出零差异 ✓(26 条版本条目)
链接检查 ✓ relative links resolve in 99 Markdown file(s)
中英漂移检查 ✓ README 7 headings, same tree / ✓ GUIDE 51 headings, same tree

两个检查脚本零依赖、可离线跑,docs-check.yml 按路径触发——方向是对的,尤其是漂移检查:中英双 README 长期靠人肉对齐,这是第一次有机器盯着。

验证

npm run typecheck 通过;npm test 1710 个,1709 通过,0 失败,1 跳过(PTY,Node 26 已知);链接与漂移检查均通过。

🤖 Generated with Claude Code

@oratis
oratis merged commit f87198c into main Sep 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant