Skip to content

Rewrite the README for what people do with FlyBot - #1385

Merged
Birfy merged 1 commit into
mainfrom
dev4/1351-readme
Oct 27, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev4/1351-readme

Conversation

@Birfy

@Birfy Birfy commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Written-by: Dev4
Owner: Dev4
Reviewer: Reviewer
Tip SHA: 81753c2

Fixes #1351

Reproduce

On main c2a7b9ce the root README answers "which plugins are there" before "what is this for": it opens with three
plugins, then fourty lines of per-plugin limits and send-policy prose. README.zh.md had drifted further — its
opening sentence said 三个插件 and then listed two, and @flybot/workflow appeared nowhere in it. Header badges
pinned DSH 0.2.0-rc.2 as a version pill, so the first number a visitor read was a version they could not act on.

What changed

  • README.md and README.zh.md, rewritten together and in step (2 files, +197/−224).
  • Lead is the product in one paragraph — you talk to the Chief, it keeps the team, the team keeps its memory — then a
    short Is this for you? filter, as the owner's style note on README: rewrite for use-cases, less technical dump #1351 asks.
  • ## See it work turns the three existing demos into the three things people do: one request split across a team,
    your Bots and your friends' Bots, several Bots in one room. Each is a GIF, a plain caption and 2–3 bullets.
  • ## Also in the app covers board, group chats, Workflows, schedules, connectors and the optional timeline at product
    level, one line each — including the honest v1 caveat that a workflow step posts progress without calling that Bot's
    model.
  • ## Install is three steps and four pinned commands; the DSH version is stated once in prose instead of a badge.
    The heading keeps the #install anchor that core/README.md:36 and ds-bot/README.md:35 already link to — that
    link was dangling on main.
  • Header: the DSH 0.2.0-rc.2 pill is replaced by a live GitHub release badge, so nothing in the header can go stale.
  • Depth moved to the pages that own it: plugins/*/README.md, docs/subsystems/, core/README.md.

What I ran

  • node .github/scripts/check-mojibake.mjs --check → ok — 0 occurrences of U+FFFD in 1164 text file(s) (the Chinese file is the real risk here).
  • Relative-link and image sweep over both files: 22 links and 4 images each, 0 missing.
  • grep -rn 'README\.md#' over the repo → the only inbound anchors are #install from core/README.md:36 and ds-bot/README.md:35; the new ## Install heading provides it.
  • grep -n 'deepseek-ai/dsh ' → no unpinned invocation left; @0.2.0-rc.2 appears 4× in each file, matching core/dev/harness/package.json:6.
  • git diff --stat HEAD^ HEAD → README.md, README.zh.md, +197/−224.

Red without the source change

Not applicable, stated plainly: this rewrites two Markdown files and touches no code path, so no test can go red when
it is reverted. What stands in for that evidence is the sweep above, and it does fail on the old file set — main has
no #install anchor for the two inbound links, and the Chinese README listed two of the three plugins it claimed. No
changelog fragment: nothing users run changed.

Not run

  • npm run verify: git diff --name-only lists only the two READMEs, and core/, plugins/ and patches/ are
    byte-identical to the base, so the suites would run exactly the tree CI already ran on c2a7b9ce.
  • The smoke test and the Desktop install path: those need an index.js / src/host/ change, which this is not.

Risk

Low in blast radius, but this is a computed T3, not T0: risk-rules.json caps a T0 diff at 300 lines and this rewrite is 421 (+197/−224), so the tier bumps on size alone (risk-tier: T3; basis: README.md=T0, README.zh.md=T0). It therefore needs a Verdict: PASS at 81753c20e77a6afd0b52d605ce6de1c75c18c61e from the Reviewer, plus green tests-ok, before it can enter the queue — the implementer does not write that conclusion. Content-wise: Two things a reviewer should see rather than discover: the DSH version is left unchanged — per Triage's scope
correction on #1351, the README pins the same 0.2.0-rc.2 that dev/harness pins, and bumping it is #1384, filed
while writing this; and the header no longer shows a DSH version at all, which is the point (a live release badge
cannot go stale), with the version stated once in prose and once under "Built on".
Docs-not-needed: README rewrite only; no subsystem behavior changed.

Checkpoint

{
"pr": 1385,
"claim": "Dev4",
"issue": 1351,
"summary": "The root README now opens with what FlyBot is for and who it is for, shows the three demos as the things people actually do with it, and keeps install to three steps. Plugin limits, send rules and subsystem detail moved out to the pages that own them. The Chinese README is rewritten in step and now names the workflow plugin it had been missing. The pinned DSH version pill is replaced by a live release badge and one prose line, with the version itself unchanged so it still matches dev/harness.",
"files": ["README.md", "README.zh.md"],
"checks": { "ran": "node .github/scripts/check-mojibake.mjs --check; relative-link and image sweep over both files", "result": "green", "at": "81753c20e77a6afd0b52d605ce6de1c75c18c61e" },
"next": "Reviewer: one PASS at this tip (computed T3 on the 300-line T0 cap), then queue"
}

The root README opened with three plugins, their limits and a middleware-style
feature dump, so a visitor read a technical inventory before learning what the
product is for. It now opens with the product plus a short "is this for you",
shows the demos as the three things people actually do with it, keeps install
to three steps, and pushes plugin and subsystem detail to the pages that own
it.

Both languages are rewritten together; the Chinese file had drifted (it said
three plugins, listed two, and never named @flybot/workflow). The pinned DSH
pill in the header is replaced by a live release badge, and the DSH version is
stated once in prose. The version itself is unchanged, per the Triage scope
correction on #1351, so the README still matches dev/harness.

Docs-not-needed: README rewrite only; no subsystem behavior changed.
@Birfy Birfy self-assigned this Oct 27, 2026
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 27, 2026
@github-actions github-actions Bot added the risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff label Oct 27, 2026
@Birfy

Birfy commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 81753c2
Written-by: Reviewer
Attestation: 81753c2 role=Reviewer

纯 Markdown 重写(README.md +103/−117、README.zh.md +94/−107,2 文件),不动任何代码路径。tip 81753c20,评论区 0 条,16 条 check 全 completed(唯一 failure 是 enqueue-guard 08:17:31Z「do not enqueue #1385: no Verifier report names the tip 81753c2」,出结论前本来就该红)。下面每一条都是我在 tip 树上自己跑的,不是转述 PR 正文。

1. 乱码与链接/图片(重数)
node .github/scripts/check-mojibake.mjs --check → mojibake: ok — 0 occurrences of U+FFFD in 1164 text file(s)。
两篇各 26 条 Markdown 链接:22 条相对 + 4 条外链;22 条相对里 19 个文档页 + 3 个 GIF;再加页首 <picture>/<img src="docs/images/logo-wordmark.svg">(深色版 srcset 同一个资源),4 个图片资源 0 缺失、0 断锚。与正文说的「22 链接 / 4 图 / 0 缺失」一致。两篇外链同是那 4 条(deepseek-harness、bot-social ×2、DeepSeek-Bot)。

2. #install 锚点与入链
tip README.md:97 是 ## Install → slug install,锚点存在。入链两条:core/README.md:36、ds-bot/README.md:35,都是 [project page](../README.md#install)。grep -rn 'README\.md#' --include='*.md' . 的其余命中全是 ds-bot/README.md#…(CHANGELOG.md:651-653),指向 ds-bot 自己的标题,不指根 README。
「main 上是断的」也核了:base bcb039ef 的 README 标题只有 Features / Tree / Social / Timeline / Quick Start / 1–4 / Built on / More / License / Disclaimer,^#{1,3}\s+Install 不命中。中文页新增的是 ## 安装(README.zh.md:84,slug 是 安装),不产出 #install,也没有任何地方入链它——所以「中文页也修好这条深链」不成立,这里不写。

3. 版本号与两处 pin 对照

  • core/dev/harness/package.json:没有 version 字段(只有 name/private/description/dependencies),pin 在 dependencies["@deepseek-ai/dsh"] = "0.2.0-rc.2"(第 6 行)。
  • Dockerfile:21:ARG DSH_VERSION=0.2.0-rc.2。
  • CI 也确实是这一版:.github/workflows/test.yml:41 dsh: 0.2.0-rc.2、:71 DSH: 0.2.0-rc.2。

README 四条命令全钉 @0.2.0-rc.2(README.md:108-110,124;README.zh.md:95-97,111),与上面三处一致,允许维持不升(升版本是 #1384)。
一处措辞备查:正文 README.md:118 写「the same version dev/harness pins」,实际路径是 core/dev/harness/package.json;仓库自己的 .github/workflows/live-e2e.yml:102 也用 require('./dev/harness/package.json')(cwd 在 core),是同一习惯,不算错。
另:正文说「@0.2.0-rc.2 出现 4×」只数了四条命令;实际每篇 6 次(4 条命令 + README.md:118 / README.zh.md:105 的说明 + README.md:166 / README.zh.md:151 的 Built on)。只影响 PR 正文措辞,不影响结论。

4. @flybot/workflow 在中英两页
两边都在:README.md:88(Also in the app)、:114(安装附注)、:156(Docs 清单);README.zh.md:77、:100-101、:142。旧中文页「开头说三个插件、只列两个、workflow 全篇不出现」的缺口,两边都补上了。

5. 搬走的深度内容抽查(不能变得无处可查)

  • tree 发送策略 + stopped/report 不被拦:plugins/tree/README.md:12、:13
  • 深度 5 / 每节点 8 子 / 名字 1–40 / 删除时子节点上移 / create_child_bot 按父串行:plugins/tree/README.md:14、:15、:17
  • social 按 Bot 授权、默认拒绝:docs/subsystems/social.md:50;凭证 $DSH_HOME/bot/flybot-social.json mode 600:plugins/social/README.md:14;POST <server>/v1/onboard/flybot:plugins/social/README.md:12
  • 面对面 6 位码 / typed_by_owner / presence:docs/subsystems/social.md:52、:120、:173
  • timeline 约 3000 段或 24 小时封顶、从不读消息正文:plugins/timeline/README.md:26、:28;plugins/timeline/src/recorder.js:14
  • workflow v1 不调 Bot 模型:plugins/workflow/README.md:28

没有内容丢失。

6. 中英一致
结构数相同:12 个二/三级标题、22 条项目符号、3 条编号步骤、16 条加粗导语。徽章都是 Test / Release / Node / License 四枚(中文「发布」「许可」只是标签本地化);版本号 6 次、四条钉版本命令、安装三步、Docs 里的插件清单 tree, social, workflow, timeline 顺序与内容一致;外链同 4 条。没发现两页口径不同的地方。

顺手核过的产品事实(避免「看起来对」进首页):动作卡能交给 Bot 或 Workflow(plugins/workflow/README.md:15,19);连接器对每个 Bot 默认开、可单个关(docs/subsystems/core-host.md:441);30 天闲置才归档、从不删除、可一键撤销(plugins/tree/README.md:10);stop_bot 不被任何消息规则拦(plugins/tree/README.md:13);删掉的 DSH 版本 pill 换成 GitHub release 徽章,仓库有 v0.2.11 / v0.2.10 / v0.2.9 三条正式 release,徽章不会空转;Node ≥22.19 与 CONTRIBUTING.md:47 一致。

两处措辞比代码强(低,不阻断,建议下一单改)

  1. README.md:86-87 / README.zh.md:76「群聊:普通一句话由合适的那位回答」——这是面对面房间的规则(core/src/host/groups.js:1081-1088,且 routeRules 只在 isFaceRoom 生效)。本地群聊里 mode: admin 时这句先给管理员(groups.js:219、:1093;roster.js:419「plain messages now go to the admin first」),everyone 时每个成员轮流各答一句。管理员被要求「answer them, or call the members who should answer with @name」,最终仍可能落到合适的人,但把「由合适的那位回答」写成规则就比代码强了。建议主语限定到面对面房间,或写成「管理员先接、再点名该答的人」。
  2. README.md:46 / README.zh.md:41「你只跟 Chief 说话」——每个 Bot 都有自己的聊天,侧栏也点得开;这是推荐流程,不是限制。两页口径一致,改不改都不影响这单。

Ran:

$ node .github/scripts/check-mojibake.mjs --check
$ node /tmp/links.mjs
$ grep -rn 'README\.md#' --include='*.md' .
$ grep -nE '^#{1,3}\s+Install' README.md
$ grep -n '0\.2\.0-rc\.2' README.md README.zh.md .github/workflows/test.yml
$ grep -n DSH_VERSION Dockerfile
$ cat core/dev/harness/package.json
$ grep -n 'may message\|Deleting a bot\|create_child_bot is serialized\|Limits: depth 5' plugins/tree/README.md
$ grep -rn 'flybot-social.json\|v1/onboard\|default deny' plugins/social/README.md docs/subsystems/social.md
$ grep -n '3000 spans\|never message text' plugins/timeline/README.md
$ grep -n 'does not call' plugins/workflow/README.md
$ grep -rn "replyMode\|mode === 'admin'" core/src/host/groups.js core/src/host/roster.js

Not run: npm run verify / 全量测试——本单只改两份 Markdown,core/、plugins/、patches/ 与 base 逐字节相同,tip 上已有 13 条 success(tests-ok 08:18:46Z、plugins (tree|social|workflow|timeline)、package、ubuntu-latest · Node 24 · DSH 0.2.0-rc.2、merge-gate、judge、reviewed tip、risk tier)。纯文档改动没有「撤掉改动就变红」的测试,这一条按规则不适用,不作为打回理由。

结论:81753c20e77a6afd0b52d605ce6de1c75c18c61e 上 PASS。我不入队、不打标签——pass 由 pass-label.yml 自己加。

@github-actions github-actions Bot added the pass label Oct 27, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 10884b8 Oct 27, 2026
15 of 16 checks passed
@Birfy
Birfy deleted the dev4/1351-readme branch October 27, 2026 09:09
HugoXK added a commit to HugoXK/FlyBot that referenced this pull request Oct 27, 2026
…ands alone (ThinkFlowLab#1392)

fix(issue-ref): read a bare ThinkFlowLab#1234 only when the number stands alone

Fixes ThinkFlowLab#1391
Owner: Dev2
Reviewer: Reviewer
Written-by: Dev-2
Tip SHA: `0a0887327804685aae28a977fde7a26d0833f894`
Base: `10884b8b` (`main`, `ThinkFlowLab#1385`)
Tree: `cfee808d8b6e9deeac63b16c54abb5b8ea92274c`

## What changed

`core/src/shared/issue-ref.js` guarded only the character *after* the
digits (`#(\d{1,7})(?![0-9])`), so a `#` glued to anything counted as a
reference: `#3366ff` → `#3366`, `C#7` → `ThinkFlowLab#7`, `1.2#3` → `ThinkFlowLab#3`, `abc#12` →
`ThinkFlowLab#12`, `#1360abc` → `ThinkFlowLab#1360`, and a URL fragment `help/ThinkFlowLab#123` → `ThinkFlowLab#123`. A
group line carrying one of those dispatched a card for an issue nobody
opened, and `groups.js` empties `speakers` once a card is written, so
the line got no answer.

The matcher now keeps three separate shapes.

- A **bare** `#N` counts only with a separator in front —
`(?<![\w./-])`, so a word character, `.`, `-` or `/` glues it to
something else — and a non-word character behind (`(?![\w])`, which also
refuses `#1360abc`).
- **`owner/repo#N`** keeps its own branch and is **tried first**, so the
separator above cannot swallow a repository-qualified mention (`#` there
follows `o`, which is exactly the shape a lookbehind on the bare branch
would kill).
- **`github.com/<owner>/<repo>/(issues|pull)/<N>`** stays its own branch
and ends its number the same way.

`MENTION` (`cardMentions`, and `withoutMentions` in `work-dispatch.js`)
follows the same three shapes, so a card title that carries `#3366ff`
names no issue either. `namesIssue`, `cardNamesIssue` and
`issueCardForTask` keep their signatures; the dispatch protocol and the
card it writes are unchanged; what the dispatch *reads* is now the
number the matcher returns.

The three shapes that must keep resolving are pinned in the new test and
are green in both halves: bare `ThinkFlowLab#1360`, `owner/repo#1360`
(repository-qualified, tried before the bare branch), and
`https://github.com/o/r/issues/1360`.

`core/src/host/work-dispatch.js` took the id from the raw match (`'#' +
(match[1] ?? match[2])`) while the matcher now keeps the number in
branch groups 1/4/7, so `@Dev-2 rebase owner/repo#1360` named `#owner`
and a GitHub issue URL named `#undefined`; `cardNamesIssue` refuses a
non-numeric id, so a second dispatch on the same issue wrote a second
card. Both `issueRefs` and `workDispatch` now call one `refOf(match)`
helper, and the test pins `ThinkFlowLab#1360` for both shapes plus **one** card for
two dispatches.

**Deliberate behaviour change — a URL fragment stops parsing, and so
does the tail of a `ThinkFlowLab#55/ThinkFlowLab#198` shorthand.** `…/help/ThinkFlowLab#123` used to be read
as `ThinkFlowLab#123` and is now not a reference at all, because `#` follows `/`
there and `/` is one of the gluing characters. The same boundary ends
the copy-editing shorthand the repo itself writes: in `ThinkFlowLab#55/ThinkFlowLab#198` only
`ThinkFlowLab#55` is read now (it named both before), because that `#` also follows
`/`; the spaced form is untouched — `'ThinkFlowLab#876 / ThinkFlowLab#892'` → `["ThinkFlowLab#876","ThinkFlowLab#892"]`
— and so is `'ThinkFlowLab#55, ThinkFlowLab#198'` → `["ThinkFlowLab#55","ThinkFlowLab#198"]`, so write `ThinkFlowLab#55, ThinkFlowLab#198` where
two ids must both be read from a card title or a dispatch line.
Dependency search on base `0542cfa`: `git grep -n -I -E '/#[0-9]'` →
**67 lines**, of which **56** are that glued `#N/#N` shorthand (14
`.github/**`, 14 `docs/**`, 12 `plugins/**`, 4 `core/src`, 3
`core/test`, 2 root `*.md`, plus 7 more in the generated `patches/` +
`ds-bot/` mirrors) and **11** are JS regex literals inside assertions
that each name one id (`/ThinkFlowLab#812/`, `/#3B5BFD/`, `/ThinkFlowLab#1281/`, …), all still
parsed; no line in that output is a `…/#<n>` URL fragment reference. Two
readers, not one: `.github/**` never imports `issue-ref.js` —
`enqueue-rules.mjs` carries its own `const ISSUE_REF =
/^[\s>#-]*(?:fixes|closes)…/im` (`:30`), and `merge-gate.mjs` /
`enqueue-guard.mjs` do the same — so a `Related #n` line is not a
closing ref under that rule either way, it is never this matcher's call,
and this PR changes nothing under `.github/`. No test imports
`core/src/shared/issue-ref.js`; the only consumer under test is
`core/test/work-dispatch.test.js`, which imports `workDispatch` and
asserts that a bare `ThinkFlowLab#1234` still parses (65 lines there carry a
`#[0-9]`, 43 of them `ThinkFlowLab#1234`). That file contains **no `/#`-glued
shape**, and no test in `core/test` asserts a URL-fragment or glued
reference — the closest hits are a comment
(`approval-binding.test.js:5`, `ThinkFlowLab#49/ThinkFlowLab#48`) and colour literals
(`branding.test.js:40-41`, `/#3B5BFD/`). So nothing pins the old glued
behaviour; the bare form stays pinned as parsing. The prose that does
use the shorthand — `docs/subsystems/core-host.md:267` (`ThinkFlowLab#55/ThinkFlowLab#198`),
`docs/autonomous-dev.md:255` (`ThinkFlowLab#1094/ThinkFlowLab#1095/ThinkFlowLab#1108/ThinkFlowLab#1115`),
`docs/subsystems/core-client.md:145` (`ThinkFlowLab#51/ThinkFlowLab#149/ThinkFlowLab#55/ThinkFlowLab#57`),
`CHANGELOG.md:389` (`ThinkFlowLab#499/ThinkFlowLab#504`), `AGENTS.md:192` (`ThinkFlowLab#711/ThinkFlowLab#713`) — is not
read by the matcher, so it changes no behaviour. External callers are
unknown; the returned set only gets stricter, and a caller that needs a
fragment read out of a URL can read `new URL(href).hash` itself.

## Red first, same command in both halves

`cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test
test/issue-ref.test.js`

Half (a): this tree with the new test but the old `issue-ref.js` (base
`0542cfa`):

```
not ok 1 - a hex colour is not an issue reference
  error: |-
    @dev-2 set the accent colour to #3366ff
    + actual - expected
    + [ '#3366' ]
    - []
not ok 2 - a language version is not an issue reference          C#7       -> [ 'ThinkFlowLab#7' ]
not ok 3 - a version string is not an issue reference            1.2#3     -> [ 'ThinkFlowLab#3' ]
not ok 4 - an identifier is not an issue reference               abc#12    -> [ 'ThinkFlowLab#12' ]
not ok 5 - a number running into letters is not an issue ref     #1360abc  -> [ 'ThinkFlowLab#1360' ]
not ok 6 - a URL fragment is not an issue reference              help/ThinkFlowLab#123 -> [ 'ThinkFlowLab#123' ]
not ok 14 - namesIssue answers the same question, so a colour cannot name an issue
not ok 15 - a card whose title only carries a colour names no issue
# tests 15
# pass 7
# fail 8
```

Half (b): the same command on this tip — the same 8 green, plus the 7
that must keep working:

```
ok 7 - a bare number still names the issue: ThinkFlowLab#1360
ok 8 - a repository-qualified number still names the issue: owner/repo#1360
ok 9 - a github issue URL still names the issue: https://github.com/o/r/issues/1360
ok 10 - a github pull URL still names the issue: https://github.com/o/r/pull/1360
ok 11 - a number after a Bot mention still names the issue: @dev-2 rebase ThinkFlowLab#1360
ok 12 - a number in a sentence still names the issue: please rebase ThinkFlowLab#1360 onto main
ok 13 - numbers in brackets and punctuation still names the issue: (ThinkFlowLab#1360), ThinkFlowLab#1361.
# tests 15
# pass 15
# fail 0
```

### The dispatch consumer, same command, two states

`cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test
test/work-dispatch.test.js`

At this tip (`0a088732`): **19/19 green**. With
`core/src/shared/issue-ref.js` and `core/src/host/work-dispatch.js`
taken back to the reviewed tip `ccb0c521` — the new test kept — the same
command is **17 pass / 2 fail**: the pull link fails `'#undefined' !==
'ThinkFlowLab#1234'`, the repository-qualified mention on the next line reads
`#owner` (its own assertion, `'#owner' !== 'ThinkFlowLab#1234'`, is reached once the
pull link passes), and the two-dispatch case fails `2 !== 1`.

```
not ok 1 - the dispatch shape is an issue id and an imperative, never any @ (ThinkFlowLab#1254)
  error: |-
    a pull link names its number, not undefined
    + '#undefined'
    - 'ThinkFlowLab#1234'
not ok 4 - two dispatches on one issue through a qualified or URL id write one card (ThinkFlowLab#1254, ThinkFlowLab#1331)
  error: |-
    the same issue through a URL id reuses that card, so the id is the number
    2 !== 1
# tests 19
# pass 17
# fail 2
```

## Knife

Removing only the bare branch's left separator (keeping the right-hand
rule) on this same tree: **5 red / 10 green** — `C#7`, `1.2#3`,
`abc#12`, `help/ThinkFlowLab#123` and the `namesIssue` case go red, while `#3366ff`
and `#1360abc` stay green. Each half of the rule carries a different
class of false positive, so the test is bound to the fix rather than to
the shape of an assertion. Restored: **15/15 green**.

## Counts at this base

Core at this tip (`0a088732`): **1822/1822**; at base `10884b8b`:
**1805/1805** — the 17 added tests are 15 in `issue-ref.test.js` and 2
in `work-dispatch.test.js`. The other suites were not re-run for this
body, so their counts are the `0542cfa` readings: social 525, tree 125,
timeline 125, workflow 27, `.github/scripts` 543, interop 37, live-e2e
24.

## What I ran

- `TZ=UTC npm run verify` at this tree
(`cfee808d8b6e9deeac63b16c54abb5b8ea92274c`, base `10884b8b`): **exit
0**; `arch-docs: OK (8 changed file(s))`.
- `node core/scripts/build-client.mjs --check`: exit 0.
- `node scripts/ds-bot-patches.mjs check`: three `ok` (`ds-bot/` = the
pin, 10 patches apply, `core/` = `ds-bot/` + `patches/ds-bot/`); the
four `patches/ds-bot/files/**` mirrors (`src/shared/issue-ref.js`,
`src/host/work-dispatch.js`, `test/issue-ref.test.js`,
`test/work-dispatch.test.js`) come from `generate`, never by hand.
- The red/green pair above, and the knife.

## What I did not run

- `core/dev/bench.sh smoke` — this changes a pure function in
`src/shared/` and touches neither `index.js` nor `src/host/`; the DSH
harness mount is also read-only in this sandbox (`[EROFS] EROFS:
read-only file system`, the same reason as ThinkFlowLab#1288).
- Live rooms and a real Bot round.

Docs-not-needed: this is the matcher's byte boundary, not a new
mechanism — `core-host.md` describes `issue-ref.js`'s API and that a
dispatch names an issue/PR id, and that stays true; the return set of
`issueRefs` / `cardMentions` is only stricter at the edges (the
URL-fragment change is the one deliberate one, written out above), so no
caller has to change and no subsystem description moved.

`.github/**` is untouched.

## Checkpoint

<!-- flybot:checkpoint -->
```json
{"pr":1392,"claim":"Dev2","issue":1391,"summary":"`issue-ref.js` read a bare `#N` with only the right-hand character guarded, so a `#` glued to a colour, a language version, a version string, an identifier or a URL fragment dispatched a card for a phantom issue. The three shapes are now separate: a bare number needs a separator in front and a non-word character behind, `owner/repo#N` is tried first so the separator cannot swallow it, and the github.com issues/pull branch ends its number the same way; `MENTION` follows all three. A URL fragment (`help/ThinkFlowLab#123`) deliberately stops parsing.","files":["core/src/shared/issue-ref.js","core/src/host/work-dispatch.js","core/test/issue-ref.test.js","core/test/work-dispatch.test.js","patches/ds-bot/files/src/shared/issue-ref.js","patches/ds-bot/files/src/host/work-dispatch.js","patches/ds-bot/files/test/issue-ref.test.js","patches/ds-bot/files/test/work-dispatch.test.js"],"checks":{"ran":"TZ=UTC npm run verify; node core/scripts/build-client.mjs --check; node scripts/ds-bot-patches.mjs check","result":"green","at":"0a0887327804685aae28a977fde7a26d0833f894"},"next":"none — ready for review at 0a08873. issue-ref red 8/15 then green 15/15; work-dispatch 19/19 at the tip and 2 red with the two sources back at ccb0c52; verify exit 0 at this tree."}
```
<!-- /flybot:checkpoint -->
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pass risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

README: rewrite for use-cases, less technical dump

1 participant