@gavin-hu/my-pi-agent 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/README.zh-CN.md +3 -2
- package/docs/extensions/README.md +1 -0
- package/docs/extensions/board.md +57 -42
- package/docs/extensions/bytefly.md +85 -89
- package/docs/extensions/file-browse.md +36 -41
- package/docs/extensions/plan.md +31 -14
- package/docs/extensions/serve.md +129 -0
- package/docs/extensions/session-bus.md +1 -1
- package/docs/extensions/team.md +11 -11
- package/extensions/board/commands.ts +27 -14
- package/extensions/board/index.ts +14 -2
- package/extensions/board/join.ts +31 -10
- package/extensions/board/page.ts +53 -83
- package/extensions/board/result.ts +1 -24
- package/extensions/board/rows.ts +1 -1
- package/extensions/board/schema.ts +9 -3
- package/extensions/board/snapshot.ts +7 -6
- package/extensions/board/tools.ts +27 -15
- package/extensions/board/transport/router.ts +3 -5
- package/extensions/board/transport/server.ts +59 -28
- package/extensions/board/types.ts +0 -10
- package/extensions/board/view/client.ts +3 -2
- package/extensions/board/view/live.ts +1 -7
- package/extensions/board/view/page.ts +16 -5
- package/extensions/board/view/render.ts +22 -17
- package/extensions/board/view/styles.ts +7 -1
- package/extensions/bytefly/footer/config.ts +3 -6
- package/extensions/bytefly/footer/render/footer.ts +18 -4
- package/extensions/bytefly/footer/render/key.ts +46 -0
- package/extensions/bytefly/footer/render/layout.ts +13 -3
- package/extensions/bytefly/footer/render/lines.ts +4 -4
- package/extensions/bytefly/footer/render/segments.ts +10 -34
- package/extensions/bytefly/header/component.ts +4 -20
- package/extensions/check/render.ts +10 -1
- package/extensions/file-browse/config/config.ts +4 -19
- package/extensions/file-browse/index.ts +27 -48
- package/extensions/file-browse/live/live.ts +1 -1
- package/extensions/file-browse/transport/router.ts +12 -4
- package/extensions/file-browse/transport/server.ts +61 -28
- package/extensions/file-browse/view/chrome.ts +4 -4
- package/extensions/file-browse/view/client.ts +3 -1
- package/extensions/file-browse/view/html.ts +73 -40
- package/extensions/file-browse/view/live-client.ts +2 -2
- package/extensions/file-browse/view/markdown.ts +13 -14
- package/extensions/file-browse/view/palette.ts +2 -2
- package/extensions/file-browse/view/raw-html.ts +9 -9
- package/extensions/file-browse/view/tree.ts +1 -1
- package/extensions/file-browse/view/urls.ts +20 -6
- package/extensions/goal/tui.ts +12 -2
- package/extensions/job/tools.ts +19 -7
- package/extensions/job/tui.ts +2 -28
- package/extensions/plan/commands.ts +2 -2
- package/extensions/plan/feedback.ts +62 -16
- package/extensions/plan/index.ts +7 -1
- package/extensions/plan/plan-text.ts +114 -0
- package/extensions/plan/runtime.ts +12 -2
- package/extensions/plan/tools.ts +2 -2
- package/extensions/plan/web-blocks.ts +76 -5
- package/extensions/plan/web-chrome.ts +4 -0
- package/extensions/plan/web-client.ts +99 -2
- package/extensions/plan/web-collab.ts +4 -4
- package/extensions/plan/web-comments.ts +39 -8
- package/extensions/plan/web-composer.ts +14 -3
- package/extensions/plan/web-keys.ts +149 -25
- package/extensions/plan/web-markdown.ts +1 -1
- package/extensions/plan/web-outline.ts +22 -2
- package/extensions/plan/web-page.ts +56 -86
- package/extensions/plan/web-payload.ts +188 -0
- package/extensions/plan/web-plan.ts +23 -13
- package/extensions/plan/web-settle.ts +14 -7
- package/extensions/plan/web-share-session.ts +24 -55
- package/extensions/plan/web-share.ts +19 -37
- package/extensions/plan/web-write.ts +112 -0
- package/extensions/plan/web.ts +77 -130
- package/extensions/serve/config.ts +37 -0
- package/extensions/serve/index.ts +71 -0
- package/extensions/serve/registry.ts +251 -0
- package/extensions/session-bus/join-request.ts +16 -9
- package/extensions/session-bus/result.ts +1 -27
- package/extensions/session-bus/tools.ts +5 -4
- package/extensions/team/commands.ts +3 -1
- package/extensions/todo/tui.ts +21 -3
- package/lib/README.md +5 -4
- package/lib/board/page-pointer.ts +29 -4
- package/lib/board/session.ts +84 -18
- package/lib/board/store.ts +34 -8
- package/lib/board/view.ts +20 -14
- package/lib/bus-request.ts +83 -0
- package/lib/http/index.ts +11 -7
- package/lib/http/mount.ts +142 -0
- package/lib/http/port.ts +25 -0
- package/lib/http/serve.ts +170 -46
- package/lib/http/server.ts +3 -3
- package/lib/plan-entry.ts +9 -13
- package/lib/requirements.ts +2 -2
- package/lib/session-label.ts +23 -7
- package/lib/session-tool.ts +37 -21
- package/lib/tui/README.md +6 -3
- package/lib/tui/glyphs.ts +2 -4
- package/lib/tui/render-cache.ts +29 -0
- package/lib/tui/tool.ts +30 -1
- package/lib/web/client-runtime.ts +27 -1
- package/lib/web/markup.ts +18 -1
- package/package.json +3 -2
- package/extensions/board/config.ts +0 -36
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ document. `PI_OFFLINE` skips the check;
|
|
|
108
108
|
|
|
109
109
|
## What you get
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
22 extensions, 4 packaged skills, and 2 themes, grouped by the promises the
|
|
112
112
|
[roadmap](./ROADMAP.md) tracks; the [guide](./docs/user-guide/) covers the same
|
|
113
113
|
ground chapter by chapter. Each extension's own page in `docs/extensions/` has
|
|
114
114
|
the full tool and command surface, opening with its capabilities.
|
|
@@ -126,7 +126,8 @@ the full tool and command surface, opening with its capabilities.
|
|
|
126
126
|
| [`job`](./docs/extensions/job.md) | `job`, `/jobs` | Run long-lived shell commands in the background; inspect logs, wait, or kill them. |
|
|
127
127
|
| [`watch`](./docs/extensions/watch.md) | `watch`, `/watch` | Tail a file or command output, match lines against patterns, and alert you or hand matching lines to the agent. |
|
|
128
128
|
| [`session-bus`](./docs/extensions/session-bus.md) | `session`, `/sessions` (screen) | Coordinate parallel Pi sessions on one repository: discover peers, exchange short messages/events, consume an inbox, or claim paths before editing, with `/sessions` as a live board of peers, unread mail, and claims. Local, pull-based by default, with an opt-in inbox watch that raises this session's turn once it is idle; it never spawns an agent. |
|
|
129
|
-
| [`
|
|
129
|
+
| [`serve`](./docs/extensions/serve.md) | — | The session's one loopback server. `/board`, `/browse`, and a browser plan review mount path prefixes on it instead of binding their own listeners, so a session has one port, one chip, and one close path — and a second session (a peer conversation, another worktree, another Pi) still gets its own. `serve.port` in `bytefly.json` pins that port, so a bookmarked URL survives a restart, and a shared review borrows exactly one LAN address for the one page that asked. |
|
|
130
|
+
| [`board`](./docs/extensions/board.md) | `board`, `/board` | One shared feature board per repository: a card per feature, which any session claims, moves, edits, notes, finishes, and archives — a finished card leaves the board for an `archive/` pile with its notes and landed commit still readable, so a long history stops costing every read — and one loopback page that shows the same cards live in a **Board** and a **Team** tab. The page is a read view — the tools are the only writers — served as the seat `team-lead`, so a second session opens the same page instead of starting a rival one, and handing a card to a teammate is `team`'s job because only it can message them. A card can carry a priority and name the cards it waits on. Steps stay in the owner's plan and `todo`; a card is the feature, its owner, and the history that explains it. The page answers at `/board` on the session's one port, so `serve.port` is the address to bookmark. |
|
|
130
131
|
| [`team`](./docs/extensions/team.md) | `team`, `/team` | The lead's round over the same board. `/team join <label>` puts a session on the team, and `/board` does it for the lead as `team-lead`; then `assign` hands a feature to a running session, `offer` hands one to whoever is free — a broadcast that writes nothing, claimed by the first taker — and `reclaim` takes a card back to To do. A result says who will be woken for it and who will read it at their next turn, `/team` prints the round in the terminal without a browser, and nothing is spawned. |
|
|
131
132
|
| [`context`](./docs/extensions/context.md) | `/context` | Show where the context window goes — system prompt, tool definitions, conversation by role, injected notes — and compact from the report with the before and after numbers. |
|
|
132
133
|
|
package/README.zh-CN.md
CHANGED
|
@@ -92,7 +92,7 @@ Pi 自己的版本请求只是被重新绘制,本包的最新版本则来自
|
|
|
92
92
|
|
|
93
93
|
## 包含内容
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
22 个扩展、4 个随包技能,以及 2 个主题,按 [路线图](./ROADMAP.md) 追踪的承诺分组;
|
|
96
96
|
[用户指南](./docs/user-guide/) 按章节讲述同样的内容。每个扩展在 `docs/extensions/`
|
|
97
97
|
下的页面提供完整的工具与命令说明,并以能力表开头。
|
|
98
98
|
|
|
@@ -109,7 +109,8 @@ Pi 自己的版本请求只是被重新绘制,本包的最新版本则来自
|
|
|
109
109
|
| [`job`](./docs/extensions/job.md) | `job`, `/jobs` | 在后台运行长时 shell 命令;查看日志、等待或结束它们。 |
|
|
110
110
|
| [`watch`](./docs/extensions/watch.md) | `watch`, `/watch` | 跟踪文件或命令输出,按模式匹配行,并提醒你或把匹配的行交给智能体。 |
|
|
111
111
|
| [`session-bus`](./docs/extensions/session-bus.md) | `session`, `/sessions`(屏幕) | 在同一仓库的多个 Pi 会话之间协调:发现彼此、交换简短消息/事件、读取收件箱、编辑前声明路径;`/sessions` 是显示对等会话、未读邮件和路径声明的实时面板。本地、默认拉取式;收件箱监视需会话自行开启,空闲时会唤起本会话的一轮,从不创建智能体。 |
|
|
112
|
-
| [`
|
|
112
|
+
| [`serve`](./docs/extensions/serve.md) | — | 每个 session 一个 loopback 服务。`/board`、`/browse` 和浏览器里的 plan review 都在它上面挂载路径前缀,而不是各自监听端口,因此一个 session 只有一个端口、一个 chip、一条关闭路径——而第二个 session(peer 会话、另一个 worktree、另一个 Pi)依然有自己的端口。`bytefly.json` 里的 `serve.port` 可以固定该端口,收藏的地址在重启后依然有效;共享 review 只为发起共享的那一个页面借用同一个网段上的一个地址。 |
|
|
113
|
+
| [`board`](./docs/extensions/board.md) | `board`、`/board` | 每个仓库一块共享看板:一张卡片代表一个 feature,任何 session 都可以认领、移动、编辑、加注、完成、归档——已完成的卡片会离开看板进入 `archive/`,其注记与落地 commit 仍可读,长历史不再拖累每次读取——同一个看板在浏览器里以 **Board** 和 **Team** 两个 tab 实时显示。页面只读——写入只走工具——并以固定席位 `team-lead` 对外服务,因此第二个 session 打开的是同一张页面,而不是另起一个;把卡片交给队友由 `team` 负责,因为只有它能给对端发消息。卡片可以带上优先级、声明自己在等待哪几张卡片。步骤留在 owner 的 plan 和 `todo` 里,卡片就是 feature、它的 owner,以及解释它的历史。页面以 `/board` 挂在该 session 唯一的端口上,所以收藏时用 `serve.port`。 |
|
|
113
114
|
| [`team`](./docs/extensions/team.md) | `team`、`/team` | 同一块看板上的 lead 轮次。`/team join <label>` 让一个 session 加入团队,lead 打开 `/board` 时则以 `team-lead` 自动加入;随后 `assign` 把一个 feature 交给运行中的 session,`offer` 交给谁有空谁接——广播而不写卡片,由第一个认领的人拿走——`reclaim` 把卡片收回 To do。结果会说明谁会因此被叫醒、谁会在下一轮才读到;`/team` 在终端里打印同一份轮次,不用开浏览器,也不启动任何进程。 |
|
|
114
115
|
| [`context`](./docs/extensions/context.md) | `/context` | 显示上下文窗口的去向 —— 系统提示、工具定义、按角色拆分的对话、注入的笔记 —— 并从报告中触发压缩,给出压缩前后的数字。 |
|
|
115
116
|
|
|
@@ -17,6 +17,7 @@ sections behind them.
|
|
|
17
17
|
| `job` | Long-lived shell commands in the background, with logs and a wait | [`job.md`](./job.md) |
|
|
18
18
|
| `watch` | Tailing a file or command and matching new lines | [`watch.md`](./watch.md) |
|
|
19
19
|
| `session-bus` | Coordination between parallel Pi sessions on one repository | [`session-bus.md`](./session-bus.md) |
|
|
20
|
+
| `serve` | The session's one loopback server: every page mounts a path prefix on it | [`serve.md`](./serve.md) |
|
|
20
21
|
| `board` | One shared feature board per repository, written by the tools and shown by one page a lead serves | [`board.md`](./board.md) |
|
|
21
22
|
| `team` | The lead's round: hand a card to a running session, take one back, or print it with `/team` | [`team.md`](./team.md) |
|
|
22
23
|
| `context` | Where the context window went, and compacting from the report | [`context.md`](./context.md) |
|
package/docs/extensions/board.md
CHANGED
|
@@ -27,11 +27,11 @@ decision.
|
|
|
27
27
|
|---|---|---|
|
|
28
28
|
| A shared feature list for one repository | `board` action `list` | Every open card in lane order — `todo`, `doing`, `blocked` — or one card, or one lane; the `done` cards are left out with a count of how many, and `status: "done"` reads them |
|
|
29
29
|
| The lead's rollup | `board` action `list` with `round: true` | Every owner with its live cards and, beside the count, what it has finished — an owner whose last card is done stays listed — then unassigned, unplanned, blocked, idle, and done |
|
|
30
|
-
| Publish a feature | `board` action `add` | A `todo` card with path hints and a first note |
|
|
30
|
+
| Publish a feature | `board` action `add` | A `todo` card with path hints and a first note (one line, at most 1000 characters) |
|
|
31
31
|
| Take a feature | `board` action `claim` | The card is `doing` and owned by this session |
|
|
32
32
|
| Hand it back | `board` action `release` | The card is `todo` again, with no owner |
|
|
33
33
|
| Change lane | `board` action `move` | Wherever the owner moves it: `doing`, `blocked`, `done` |
|
|
34
|
-
| Record what happened | `board` action `note` | A note appended to the card's history, attributed and stamped |
|
|
34
|
+
| Record what happened | `board` action `note` | A note appended to the card's history, attributed and stamped — one line, at most 1000 characters |
|
|
35
35
|
| Record the plan | `board` action `plan` | The plan file the card is executing, so "unplanned" work is visible |
|
|
36
36
|
| Fix what a card says | `board` action `edit` | A new title, path hints, priority, or the cards it waits for — by its holder, or by anyone while nobody holds it |
|
|
37
37
|
| Say how urgent it is | `board` action `add` or `edit` with `priority` | `high` sorts first inside its lane, and the card says so |
|
|
@@ -43,11 +43,11 @@ decision.
|
|
|
43
43
|
| Set a finished card aside | `board` action `archive` | A `done` card's file moves into an `archive/` pile beside the board with its notes, plan, owner, and landed commit still readable, and the board stops reading it: the card named by `card`, or every finished card when none is named. It is a decision a person makes, never a threshold in the background, and nothing un-archives |
|
|
44
44
|
| Delete a card | `board` action `drop` | The card and its notes are gone, and its id is spent: a record of the title, the lane, who ended it, and when stays in `ended/`, so a note or a handoff that names that id cannot come to mean a different feature. A `todo` or `done` card is anyone's to drop, an archived one included, one in flight only its holder's, and one that a card waits on cannot leave at all |
|
|
45
45
|
| One page per repository | `/board` | Serves a loopback page as `team-lead` with a **Board** and a **Team** tab, following the store live; a page already served is opened instead |
|
|
46
|
-
| Watch somebody else's page | `/board` on a session that is not serving | The same page, because there is one: every page is a read view, so a second session gets exactly what the first one sees instead of a writable rival. It joins the team under its own
|
|
46
|
+
| Watch somebody else's page | `/board` on a session that is not serving | The same page, because there is one: every page is a read view, so a second session gets exactly what the first one sees instead of a writable rival. It joins the team under its own name, so a handoff can still reach it |
|
|
47
47
|
| Read a board at its real size | the `Done` fold, an empty lane's rail | `Done` starts folded at six cards or more, its count in the head, and a reader's toggle decides from then on. A lane holding no cards narrows to its head, word, and count, so the lanes carrying work keep the width |
|
|
48
48
|
| Open a card | the card's title, or `Enter` on a focused one | The title is the only door, because it is the only one needed: it opens the dialog holding the card whole — its lane, its owner, its paths, what it waits for, its plan, and every note |
|
|
49
49
|
| See the lead's round at a glance | `/board team`, or `/team` with no browser | A queue of cards that need a decision, each with the reason and its way out, then who is on the team and what they hold |
|
|
50
|
-
| Join the team | `/board`, or
|
|
50
|
+
| Join the team | `/board`, or the first card you claim | Opening the page joins this session to the team — as `team-lead` when it serves the page, under its own `team-agent-…` name when it opens one somebody else serves — and so does the first card it claims, so nothing has to be armed by hand. Joining never renames Pi's session: the footer keeps the name you gave it. `/board status` reports the team this session is on, whichever door it used |
|
|
51
51
|
| See who is around | `/board team` | The Teammates list: every session this repository's bus has recorded, plus every owner a card names, each stating `live`, `quiet`, `no record`, or `—` when no bus is loaded |
|
|
52
52
|
|
|
53
53
|
## Quickstart
|
|
@@ -69,9 +69,9 @@ lead: board list round: true
|
|
|
69
69
|
|
|
70
70
|
| Command | Who | Effect |
|
|
71
71
|
|---|---|---|
|
|
72
|
-
| `/board` | lead | Serves the page as `team-lead`, or opens the one another session already serves — and opens it again when it is already up, so a closed tab is one command away. The line it prints names the address |
|
|
72
|
+
| `/board` | lead | Serves the page as `team-lead`, or opens the one another session already serves — and opens it again when it is already up, so a closed tab is one command away. The line it prints names the repository and the address |
|
|
73
73
|
| `/board team` | lead | The same, opened on the Team tab |
|
|
74
|
-
| `/board status` | both | One line: the seat, the port, how many tabs are watching, the store, and the team the last `/board` joined — or the page being watched, and whether the note behind it still answers |
|
|
74
|
+
| `/board status` | both | One line: the seat, the repository, the port, how many tabs are watching, the store's path, and the team the last `/board` joined — or the page being watched, and whether the note behind it still answers |
|
|
75
75
|
| `/board stop` | lead | Stops the page this session serves; a watched page that has stopped answering is dropped instead, and a watched page that is alive is its owner's to stop |
|
|
76
76
|
| `/team` | both | The round in the terminal: the rollup, the work a dead owner left behind, then who is live, who has gone quiet, and who is gone |
|
|
77
77
|
|
|
@@ -89,11 +89,19 @@ keeps its own note) instead of waiting for the next `/board` to trip over it.
|
|
|
89
89
|
|
|
90
90
|
**Joining.** One thing, done for you: `/board` puts this session on the team — as
|
|
91
91
|
`team-lead` when it serves the page, under its own name when it watches one — and so does
|
|
92
|
-
the first card
|
|
93
|
-
|
|
94
|
-
session
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
the first card it claims. A read, a new card, a note, a plan, or an edit enlists nobody: a
|
|
93
|
+
teammate is a session that holds work. The join is also the listening: mail is reported at
|
|
94
|
+
that session's next turn, and no turn is raised, so being on the team never spends a turn.
|
|
95
|
+
A session that has neither opened the board nor claimed a card is not on it.
|
|
96
|
+
|
|
97
|
+
**The two names.** A session's team name is the seat — `team-lead` — while it serves the
|
|
98
|
+
page, and `team-agent-` plus the last six characters of its session id otherwise, so
|
|
99
|
+
`billing-core` on this machine is `team-agent-9f21ac` to the team. The name is derived from
|
|
100
|
+
the id and not from Pi's session name, which means a rename cannot strand a card, two
|
|
101
|
+
sessions cannot settle on one name, and nothing here ever renames your session: `/team join
|
|
102
|
+
<label>` is the one door that does. A card records that name as its owner, so the chip, the
|
|
103
|
+
roster, and the bus record are one word — and `/board status` says it whichever door put
|
|
104
|
+
this session on the team, including a claim made with no page open.
|
|
97
105
|
|
|
98
106
|
The page still serves as a seat: `/board status` names `team-lead`, the toolbar chip says
|
|
99
107
|
so, and a card a browser claimed **before** the page stopped writing still names
|
|
@@ -154,7 +162,7 @@ path the board does not serve.
|
|
|
154
162
|
GET /theme.js the theme script — no token
|
|
155
163
|
GET /app.js the client script — no token
|
|
156
164
|
GET / the document (?view=board|team), whose tab reads
|
|
157
|
-
board · <
|
|
165
|
+
board · <repo> · <N> open
|
|
158
166
|
GET /index.html the same document, for a link that names it
|
|
159
167
|
GET /api/ping whether the page answers, and nothing else: a session
|
|
160
168
|
deciding whether to attach reads this, not the snapshot
|
|
@@ -169,13 +177,18 @@ answering its browser would otherwise be declared dead and taken over.
|
|
|
169
177
|
## Layout
|
|
170
178
|
|
|
171
179
|
One page, two tabs, one lifecycle. The kit shell keeps the toolbar and the footer
|
|
172
|
-
pinned and makes the main pane the only scroll box; the page adds no second one.
|
|
180
|
+
pinned and makes the main pane the only scroll box; the page adds no second one. The
|
|
181
|
+
footer is one line about the board itself: the repository's name, the store's path, the
|
|
182
|
+
count of cards, and the size they occupy — plus the files this build could not read —
|
|
183
|
+
with the repository root's whole path on the hover title, which is what tells two
|
|
184
|
+
clones of one repository apart. The tab carries the repository's name for the same
|
|
185
|
+
reason: a store key is a hash, and no reader can say it out loud.
|
|
173
186
|
|
|
174
187
|
| Band | What it holds |
|
|
175
188
|
|---|---|
|
|
176
189
|
| Toolbar | the mark, the seat the page is served as, as a chip, a live badge (`connecting…`, `live` or `live · 3m`, `reconnecting…`), then one group: the Board\|Team switch, done-of-total progress, a filter, the keys button, and the theme toggle |
|
|
177
190
|
| Lanes | trays, not a bare list: one column per lane, sized by the work it holds — a lane with two cards is wider than one with a single card, and a lane showing nothing, because it holds no cards or because it is folded, narrows to a rail of dot, word, and count — so the lanes carrying work keep the width. Three or four across above 1180px, two at 1180px or narrower, one lane plus the lane switch at 860px or narrower — where it opens on the first lane that holds a card. Each head sticks while the pane scrolls, carries its count as a pill, and folds its cards away: `Done` starts folded at six cards or more, since finished work is history, and a reader's toggle decides from then on |
|
|
178
|
-
| Cards | the id and a two-line title (the page's loudest text and its only door), an owner chip and an age, a muted priority chip when it is not `normal`, path chips, and one reason line in one voice — what a card waits for, a blocked card's recorded reason or else its last note (or `blocked, with nothing recorded`), `no plan recorded`, `planned`, `✓ done by <owner>` with the commit it landed as, and the last note of a card that is none of those — up to two lines at the Team tab's size, with the whole sentence as its tooltip, because the reason is the reason to act on the card. A card draws **no button**: claiming, moving, editing, and annotating are the tools' work, and a face that offered them would be offering a refusal. A hovered card lifts a pixel; a finished one recedes, title and owner chip muted |
|
|
191
|
+
| Cards | the id and a two-line title (the page's loudest text and its only door), an owner chip and an age, a muted priority chip when it is not `normal`, path chips, and one reason line in one voice — what a card waits for, a blocked card's recorded reason or else its last note (or `blocked, with nothing recorded`), `no plan recorded`, `planned`, `✓ done by <owner>` with the commit it landed as, and the last note of a card that is none of those — up to two lines at the Team tab's size, with the whole sentence as its tooltip, because the reason is the reason to act on the card. A title and a path chip elide **inside** the card: a chip is one line by design, so a path or a label longer than the card is clipped rather than crossing into the lane beside it, and its whole value is the hover title. A card draws **no button**: claiming, moving, editing, and annotating are the tools' work, and a face that offered them would be offering a refusal. A hovered card lifts a pixel; a finished one recedes, title and owner chip muted |
|
|
179
192
|
| Team | two panels and a strip. **Needs a decision** is one row per card — a card that is both idle and unplanned arrives once, keeping its strongest reason — laid out as two lines: the id, title and owner chip on the first, the reason on the second — a blocked card's recorded `blockedBy`, else its last note, and `offered 2h ago — nobody took it` for a card whose offer went unanswered — with the whole sentence as its tooltip, and its kind as a left edge (`--danger` blocked, `--warn` idle, `--dim` unplanned or waiting, the same `--dim` dashed for nobody's). The row is a reason to pick the card up in the terminal, and it draws no button: claiming and reclaiming are the tools' work. An unassigned card that waits on unfinished work is a row of its own kind, ranked just under a blocker. Above 1180px the queue stops at one screen's height and scrolls inside its panel, so the roster and the Done strip stay on the same page as its top. **Teammates** is one row per person — a state dot, the label, a `you` chip, a `not listening` chip on a live peer whose inbox watch is off, a mail badge, then `live · 3 held · 1 done · oldest 21m` (a quiet session reads `quiet for 2h`, because a word without an age is no reason to reclaim) — sorted you, live, quiet, no record, and an owner whose label nothing answers to keeps its row. Done is one quiet strip whose ids open their cards. Both panels honour the toolbar's filter, and their headings read `shown/total` the way a lane head does. Below 1180px the queue comes first and the roster follows |
|
|
180
193
|
| Card dialog | the record of one card, in two named sections. The head carries the id, the title, and the lane as a dot and a word. **The card** is a ladder — one fact per row, labels sized to the longest of them so the values line up: owner, priority when it is not `normal`, updated, in lane, last edited, landed, waits on, waited on by, plan, paths. `in lane` is the lane the card is in and how long it has held it, read from the card's transitions rather than from `updatedAt`, which a note or an edit moves; a card whose history does not say omits the row. The plan and each path are one line that elides, with the whole value on the hover title; what it waits for reads `#2 (doing)`, the lanes that make the id a decision. Empty rows take their labels with them. **Notes · N** is the cargo at body size on a 68ch measure, each sentence with its attribution under it and a rule between notes, and `M earlier notes dropped` when the store capped them. The body is the only scroll, so the head and `Close` stay put. Nothing in it writes, every field is a set as `textContent`, and the title underneath every card is the way in. `j`/`k` walk to the next or previous card without closing it, and an `sr-only` live region announces `card 2 of 3: <title>` — a title that changes inside an open modal is not announced on its own |
|
|
181
194
|
(feat(team): an offer leaves a record, so its age can be read)
|
|
@@ -292,17 +305,14 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
292
305
|
- **The page stops a minute after its last tab leaves, or two minutes after it starts
|
|
293
306
|
with no tab at all.** Closing the tab to run a command and coming back is fine, and a
|
|
294
307
|
teammate's watching tab counts as one. The second grace covers the page a browser never
|
|
295
|
-
opened — `openInBrowser` swallows a failure, and a
|
|
296
|
-
|
|
297
|
-
prints the address it reopened.
|
|
298
|
-
- **The
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
answers on it` — because a quiet fallback would move the page out from under the
|
|
304
|
-
bookmark. A live note still wins: one repository has one page, so this session attaches to
|
|
305
|
-
the port that note names rather than serving a second one.
|
|
308
|
+
opened — `openInBrowser` swallows a failure, and a prefix held by a page nobody saw is a
|
|
309
|
+
prefix held for the session. Either way `/board` starts it again, on the session's port,
|
|
310
|
+
and prints the address it reopened.
|
|
311
|
+
- **The prefix is `/board` on the session's one server.** The port belongs to `serve`, so
|
|
312
|
+
`/board`, `/browse`, and a browser plan review answer on one origin; `serve.port` in
|
|
313
|
+
`bytefly.json` pins that origin, so a bookmarked URL survives a restart. A live note still
|
|
314
|
+
wins: one repository has one page, so this session attaches to the page that note names
|
|
315
|
+
rather than serving a second one — and a session that attaches binds nothing at all.
|
|
306
316
|
- **The note is believed only while it answers.** A page that crashed leaves its note
|
|
307
317
|
behind; the next `/board` probes it, takes it over when nothing replies, and attaches to
|
|
308
318
|
the page that won when two sessions start in the same instant. A clean exit — `/board
|
|
@@ -310,16 +320,22 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
310
320
|
is the one a crash left. A note it cannot read at
|
|
311
321
|
all is named with its path — "another session is serving" is only said of a page that was
|
|
312
322
|
seen answering.
|
|
323
|
+
- **A page that cannot read the board says so once.** A snapshot is built on every tick, and
|
|
324
|
+
a read can fail under a running page — the board's directory removed, or replaced by
|
|
325
|
+
something that is not one. The frame is dropped rather than raised, the session is told
|
|
326
|
+
once, and the next tick tries again, so a board that comes back is followed again without
|
|
327
|
+
a second `/board`; a notice per tick would be a transcript nobody reads.
|
|
313
328
|
|
|
314
329
|
## Pi integration
|
|
315
330
|
|
|
316
|
-
- **`session-bus`**: a card's owner is the
|
|
331
|
+
- **`session-bus`**: a card's owner is the session's team name, so a card names a session a
|
|
317
332
|
peer can be addressed by. The board calls one thing on it — the join, through
|
|
318
333
|
`lib/session-tool.ts`, because a command context cannot call a tool and the request
|
|
319
334
|
therefore travels on `pi.events` — and reads its records otherwise, which is why the
|
|
320
|
-
page works with the bus disabled.
|
|
321
|
-
|
|
322
|
-
|
|
335
|
+
page works with the bus disabled. The join asks for the name the board already writes
|
|
336
|
+
and never renames the session, so the footer stays the user's. A failed join is a clause
|
|
337
|
+
on the `/board` line, not a failed page. The seat is the name the page is served and
|
|
338
|
+
reported under, and `/board status` says which session is on the team through it.
|
|
323
339
|
- **`plan`**: `board plan` records a plan file's path; the plan extension owns the
|
|
324
340
|
file. The board stays available while planning, and only `list` works: the same tool
|
|
325
341
|
writes, so its read-only hint cannot say that, and plan mode reads the action in the
|
|
@@ -330,9 +346,9 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
330
346
|
forces a todo update, while `add` or `claim` counts as work like any other write.
|
|
331
347
|
- **`worktree`**: the store is keyed by the repository's common git directory, so
|
|
332
348
|
every worktree shares one board.
|
|
333
|
-
- **`
|
|
334
|
-
|
|
335
|
-
|
|
349
|
+
- **`serve`**: the page mounts `/board` on the session's one server, which draws the
|
|
350
|
+
single `◉ <port>` chip. **`bytefly`**: the bar shows that chip, and `doctor` reports
|
|
351
|
+
nothing new — the board needs no binary and no per-machine setup.
|
|
336
352
|
|
|
337
353
|
## Design notes
|
|
338
354
|
|
|
@@ -417,8 +433,7 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
417
433
|
seat, and the token; it is created exclusively, so two sessions starting at
|
|
418
434
|
once cannot both serve, and the loser attaches to the winner. The alternative —
|
|
419
435
|
a setting that names the lead — was rejected: the role moves, the seat's name does
|
|
420
|
-
not. The port is the
|
|
421
|
-
listens, never who serves it.
|
|
436
|
+
not. The port in the note is the session's, never a number this page chose.
|
|
422
437
|
- **The page is a view because a browser is not an identity.** Every page write was made
|
|
423
438
|
as the seat, so a page `assign` had to write down that nobody had been told, and the
|
|
424
439
|
client's copy of the card rules drifted from `lib/board/rules.ts` — it offered a drop
|
|
@@ -464,7 +479,6 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
464
479
|
| File | Responsibility |
|
|
465
480
|
|---|---|
|
|
466
481
|
| `index.ts` | The factory: gate on `PI_DISABLED_EXTENSIONS`, build the runtime and the page, register both, close on shutdown |
|
|
467
|
-
| `config.ts` | The board's one setting: the port its page is pinned to, clamped, from the `bytefly.json` `board` section |
|
|
468
482
|
| `schema.ts` | The tool's parameters |
|
|
469
483
|
| `types.ts` | The shapes the tool registers and reports — the actions and the fields each acts on, the card an action produced, the cards a list read, the rollup when it was asked for, and the card a refusal carries |
|
|
470
484
|
| `tools.ts` | Action dispatch and the refusal shape |
|
|
@@ -472,13 +486,13 @@ it always meant: when the card was last touched, which is not when it last chang
|
|
|
472
486
|
| `format.ts` | The model-facing text |
|
|
473
487
|
| `rows.ts` | The transcript row grammar |
|
|
474
488
|
| `result.ts` | The transcript block |
|
|
475
|
-
| `page.ts` | The page's lifecycle: the
|
|
476
|
-
| `snapshot.ts` | The page's snapshot: the cards, the bus's records,
|
|
489
|
+
| `page.ts` | The page's lifecycle: the `/board` prefix it holds on the session's server, the three closes (`/board stop`, the idle grace, and shutdown — each taking the note with it), and the probe behind `/board status` |
|
|
490
|
+
| `snapshot.ts` | The page's snapshot: the cards, the bus's records, the store's size and path, and the repository's own name, handed to `buildView` |
|
|
477
491
|
| `commands.ts` | `/board`, its three words and their refusals, and the one line `/board status` prints |
|
|
478
492
|
| `seat.ts` | The seat the page is served as: one name, and an id derived from it. The page cannot write, so it is a label now — but the id is still what a card claimed from an older page names |
|
|
479
|
-
| `join.ts` | The board's side of the team:
|
|
493
|
+
| `join.ts` | The board's side of the team: when it asks (the page, or the first claimed card), the name it asks for, and how the outcome reads on a `/board` line |
|
|
480
494
|
| `transport/router.ts` | The five reads — the document, the client script, the theme script, the snapshot, and the frame stream — with the token gate and the guards in front of them |
|
|
481
|
-
| `transport/server.ts` | The loopback listener, the frame push, and the close |
|
|
495
|
+
| `transport/server.ts` | The loopback listener, the frame push — one read of the board per frame, and a failed read reported rather than thrown — and the close |
|
|
482
496
|
| `view/page.ts` | The document: an inert shell the client fills, with no form on it |
|
|
483
497
|
| `view/styles.ts` | The page's `board-*` layout rules |
|
|
484
498
|
| `view/render.ts` | The client's snapshot → DOM renderer: toolbar, lanes, cards, the dialog's contents |
|
|
@@ -499,9 +513,10 @@ The store, the rules, the rollup, and the snapshot are `lib/board/` — see
|
|
|
499
513
|
record, the dependency graph, the note a page leaves, the rollup and its text, the card's
|
|
500
514
|
transitions, the store a call opens and the identity it writes as, the files that store
|
|
501
515
|
keeps, and the snapshot, and
|
|
502
|
-
`extensions/board/{input,seat,tools,page,commands,
|
|
516
|
+
`extensions/board/{input,seat,tools,page,commands,extension,transport/router,view/pages,view/behaviour}`
|
|
503
517
|
for the card body, the seat, every action, the page's lifecycle over a real socket (a page
|
|
504
|
-
served, attached to, and taken over,
|
|
505
|
-
|
|
518
|
+
served, attached to, and taken over, a board that stops being readable, and a write refused
|
|
519
|
+
on the wire), the command, the
|
|
520
|
+
factory, the routes, the document and client bundle, and the
|
|
506
521
|
page driven in a browser — a card opened from its title, the filter, the fold, a live
|
|
507
522
|
frame, and the dialog's ladder.
|
|
@@ -263,9 +263,8 @@ Two lines, each with a left and right zone:
|
|
|
263
263
|
|
|
264
264
|
- **Line 1 — identity:** `pwd` and the session name on the left; on the right the
|
|
265
265
|
alert, then the mode chips (`≡ plan`), then `⎇ branch · ⑂ worktree`, then the
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
segment, so they share a weight, a position, and a floor.
|
|
266
|
+
session's page port (`◉ 4780`) while anything is served on it. One server serves
|
|
267
|
+
every page of a session, so it is one number from one status key.
|
|
269
268
|
- **Line 2 — resources:** the context gauge and usage meters on the left, the
|
|
270
269
|
child-run roll-up (`↳ 3 · ¥0.12`, present only once a subagent has finished),
|
|
271
270
|
and the model and thinking level on the right. The gauge is anchored at column
|
|
@@ -293,11 +292,10 @@ With no plan mode the mode slot is simply absent:
|
|
|
293
292
|
▰▰▰▰▰▰▱▱▱▱ 62%/200k · ¥0.31 · ↑42k ↓8.0k · R96k CH 87% opus-4.5 · high
|
|
294
293
|
```
|
|
295
294
|
|
|
296
|
-
While a page is served,
|
|
297
|
-
one cluster, in a fixed order, so the pair reads as a pair:
|
|
295
|
+
While a page is served, the session's port joins the run beside the worktree:
|
|
298
296
|
|
|
299
297
|
```
|
|
300
|
-
~/repo/my-pi-agent
|
|
298
|
+
~/repo/my-pi-agent ⎇ main · ◉ 4780
|
|
301
299
|
▰▰▰▰▰▰▱▱▱▱ 62%/200k · ¥0.31 · ↑42k ↓8.0k · R96k CH 87% opus-4.5 · high
|
|
302
300
|
```
|
|
303
301
|
|
|
@@ -315,12 +313,12 @@ fits, rather than collapsing to a bare glyph:
|
|
|
315
313
|
▰▰▰▰▰▰▱▱▱▱ 62% opus-4.5
|
|
316
314
|
```
|
|
317
315
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
316
|
+
The port drops the digits before the page they name: it compacts to `◉` once
|
|
317
|
+
the number no longer fits, so the narrowest bar that fits the location chips still
|
|
318
|
+
says a page is up.
|
|
321
319
|
|
|
322
320
|
```
|
|
323
|
-
~/repo/my-pi-agent
|
|
321
|
+
~/repo/my-pi-agent ⎇ main · ◉
|
|
324
322
|
▰▰▰▰▰▰▱▱▱▱ 62% · ¥0.31 opus-4.5 · high
|
|
325
323
|
```
|
|
326
324
|
|
|
@@ -346,7 +344,7 @@ Each segment reads a theme role and carries its own drop order:
|
|
|
346
344
|
| session | 1 left | muted, bracketed | after worktree |
|
|
347
345
|
| branch | 1 right | muted (warning when detached) | last |
|
|
348
346
|
| worktree | 1 right | success | first |
|
|
349
|
-
|
|
|
347
|
+
| port `◉ 4780` | 1 right | success glyph + accent port | first |
|
|
350
348
|
| context gauge + `%` | 2 left | muted ≤70 · warning 71–90 · error >90 | never |
|
|
351
349
|
| `/window` | 2 left | dim | before cost |
|
|
352
350
|
| cost | 2 left | muted | after tokens |
|
|
@@ -357,15 +355,12 @@ Each segment reads a theme role and carries its own drop order:
|
|
|
357
355
|
| thinking level | 2 right | thinking token | before cost |
|
|
358
356
|
|
|
359
357
|
The worktree status is read from the `worktree` status key, so the
|
|
360
|
-
[worktree](./worktree.md) extension and the bar agree. The
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
`⊞ 5043 · ◉ 4909` to `⊞ 5043 ◉ 4909` to `⊞ ◉`, and it drops as a unit, where
|
|
367
|
-
separate chips once let the board port outlive the browse one by four columns
|
|
368
|
-
for no reason a reader could see.
|
|
358
|
+
[worktree](./worktree.md) extension and the bar agree. The port is the `http`
|
|
359
|
+
status key, published by [serve](./serve.md) while anything is mounted on the
|
|
360
|
+
session's server — one number, because one socket serves every page a session
|
|
361
|
+
opens. It is a two-tone `<glyph> <port>` with a green glyph and an accent port,
|
|
362
|
+
and it compacts from `◉ 4780` to `◉` before it drops, so a bar too narrow for
|
|
363
|
+
the number still says a page is up.
|
|
369
364
|
|
|
370
365
|
The mode slot holds everything else an extension publishes: a plan chip, a
|
|
371
366
|
job count, a rewind timeline, the `✆` bridge, and an alert's front position. A
|
|
@@ -1474,11 +1469,10 @@ rather than showing a wrong value.
|
|
|
1474
1469
|
segment, so the percentage cannot move at all.
|
|
1475
1470
|
- **Statuses are routed, not repeated.** The built-in footer renders every
|
|
1476
1471
|
`setStatus` value on its own line, so the bar sorts them by meaning instead:
|
|
1477
|
-
`worktree`
|
|
1478
|
-
branch and `⑂` worktree
|
|
1479
|
-
|
|
1480
|
-
a
|
|
1481
|
-
alert, so it is its own segment ahead of both. The
|
|
1472
|
+
`worktree` is location, so the `◉ <port>` chip sits behind `⎇`
|
|
1473
|
+
branch and `⑂` worktree, and it is the session's one page port, so it keeps a
|
|
1474
|
+
weight and a floor of its own; a plan is a mode, so it leads the state line
|
|
1475
|
+
beside them; a failed job is an alert, so it is its own segment ahead of both. The
|
|
1482
1476
|
[wechat](./wechat.md) extension publishes `✆ wechat` while its bridge runs,
|
|
1483
1477
|
which is why the bar has to render `getExtensionStatuses()` at all.
|
|
1484
1478
|
- **A state chip leads its zone, so the zone does not move under it.** The right
|
|
@@ -1661,6 +1655,8 @@ columns, gauge), so the look follows the active theme.
|
|
|
1661
1655
|
| `footer/register.ts` | Installs/restores the footer and owns its session lifecycle. |
|
|
1662
1656
|
| `footer/config.ts` | Bar tuning (`CONFIG`): thresholds, gauge, separators, icons, alert and plan status keys, labels. |
|
|
1663
1657
|
| `footer/types.ts` | `StatusSnapshot`, `Segment`, `LineSpec`, `UsageRecord`, and footer/TUI shapes. |
|
|
1658
|
+
| `footer/budget.ts` | The session spend guardrail: whether the configured ceiling has been crossed and the one notice that says so — an alert, never a limit. |
|
|
1659
|
+
| `footer/delegation.ts` | The child-run ledger: the pricing inputs of the last delegated runs, versioned so the footer re-prices when a subagent finishes. |
|
|
1664
1660
|
| `footer/collect/entries.ts` | Session entries → usage records, each resolved to the model in effect. |
|
|
1665
1661
|
| `footer/collect/snapshot.ts` | Snapshot assembly; memoized pricing scan, context estimate, and session name per branch leaf. |
|
|
1666
1662
|
| `footer/price/types.ts` | `Currency`, `ModelRates`, `PeakWindow`/`PeakSchedule`, `ByteflyConfig`. |
|
|
@@ -1675,6 +1671,7 @@ columns, gauge), so the look follows the active theme.
|
|
|
1675
1671
|
| `footer/render/lines.ts` | Snapshot → two `LineSpec`s; status routing. |
|
|
1676
1672
|
| `footer/render/layout.ts` | Width reduction and right-zone folding. |
|
|
1677
1673
|
| `footer/render/footer.ts` | `StatusBar` component and footer factory. |
|
|
1674
|
+
| `footer/render/key.ts` | `snapshotKey`: the bar's repaint key, derived from the snapshot's own shape — sorted object keys, a map as sorted entries, a primitive by value — so a field added to `StatusSnapshot` is in the key the day it is added. |
|
|
1678
1675
|
| `message/config.ts` | Nameplate tuning (`MESSAGE_CONFIG`): the label and the rule. |
|
|
1679
1676
|
| `message/format.ts` | Pure `nameplate` and `styleUserMessage`: the two-row nameplate (label over a full-width rule) and its placement above the message. |
|
|
1680
1677
|
| `message/register.ts` | Registers the Markdown transformer (the nameplate). |
|
|
@@ -1744,67 +1741,66 @@ columns, gauge), so the look follows the active theme.
|
|
|
1744
1741
|
|
|
1745
1742
|
## Testing
|
|
1746
1743
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
the
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
and its
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
`panel/
|
|
1784
|
-
|
|
1785
|
-
the
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
(`
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
self-shell carve-out, and fallback framing (`block/register`).
|
|
1744
|
+
Every suite sits beside the code it covers, so a slash-prefixed stem below
|
|
1745
|
+
resolves to `extensions/bytefly/<stem>.test.ts`.
|
|
1746
|
+
|
|
1747
|
+
`extension` covers the registration, the interactive surfaces, and the command
|
|
1748
|
+
wiring through the factory.
|
|
1749
|
+
|
|
1750
|
+
`chrome` covers the chrome that frames a session: the config and its pad store;
|
|
1751
|
+
the header's frames, width shedding, identity ladder, update marker, live theme,
|
|
1752
|
+
quiet-startup lifecycle, and terminal-height shapes; the transcript notice's rows
|
|
1753
|
+
and registration; the turn separator's formatting (including the receipt's width
|
|
1754
|
+
ladder), component, and register/append/render/disable lifecycle with the run
|
|
1755
|
+
stats it records; and the user-message nameplate's transform — through pi-tui's
|
|
1756
|
+
real `Markdown` — and its registration.
|
|
1757
|
+
|
|
1758
|
+
`footer/footer` covers the bar end to end: the price config, its schema, clamping,
|
|
1759
|
+
and defaults; rate matching, window parsing and peak evaluation in two zones, the
|
|
1760
|
+
pricing formula with its off-peak multiplier, the built-in DeepSeek table and the
|
|
1761
|
+
fallback, the usage records, and the delegation ledger; the snapshot reader and its
|
|
1762
|
+
memo, the unpriced notice, and the budget; the formatters, the status-chip
|
|
1763
|
+
transforms, the segment builders, line composition, and the repaint key that
|
|
1764
|
+
spares an unchanged frame a rebuild; the reduction, separator collapse, and
|
|
1765
|
+
right-zone folding across a width sweep from 6 to 120 plus wide characters; and the
|
|
1766
|
+
component with its install/skip/restore/toggle lifecycle and a config-driven price.
|
|
1767
|
+
|
|
1768
|
+
`block/block` covers the tool-block frame: `toolBlockLines`, the call-headline
|
|
1769
|
+
rewrites, `ToolBlock`'s memo, the generic and call fallbacks, and the resolver's
|
|
1770
|
+
shell override and self-shell carve-out.
|
|
1771
|
+
|
|
1772
|
+
`picker/picker` covers discovery with an injected factory, the resolver and its
|
|
1773
|
+
entries, the pattern helpers, and the runtime's toggling, scope, and project
|
|
1774
|
+
override across the four list operations.
|
|
1775
|
+
|
|
1776
|
+
`panel/…` covers the control centre, one suite per capability: `panel/model` (the
|
|
1777
|
+
two panes' merged model and the text formatter), `panel/filter` and its chips, the settings
|
|
1778
|
+
catalogue and its cycling (`panel/settings`), the scope-aware runtime
|
|
1779
|
+
(`panel/settings-runtime`, including a nested leaf write that keeps its siblings),
|
|
1780
|
+
the skill metadata join and loader (`panel/skills`, on real `SKILL.md` files), the
|
|
1781
|
+
key table whose hints and help it holds to one source (`panel/keys`), the frame and
|
|
1782
|
+
the one height all three sections agree on (`panel/layout`), the row grammar and the
|
|
1783
|
+
focused-row block beside and under the list (`panel/views`), the two-pane split and
|
|
1784
|
+
its `… N more lines` clip (`panel/panes`), the editing key map (`panel/editing`),
|
|
1785
|
+
the update section's view (`panel/update`), the discovery probe (`panel/probe`), the
|
|
1786
|
+
component's frames, keys, sections, settings, and probe lifecycle
|
|
1787
|
+
(`panel/component`, `panel/component-input`, `panel/component-sections`,
|
|
1788
|
+
`panel/component-settings`, `panel/component-probing`), and the command through the
|
|
1789
|
+
bytefly factory (`panel/commands`) — eighteen suites in all.
|
|
1790
|
+
|
|
1791
|
+
`doctor/doctor` covers the report counts and text, the config loader, the notify
|
|
1792
|
+
seam, the published search provider, the proactive probe, the session state,
|
|
1793
|
+
`run_doctor`, and the tool wiring.
|
|
1794
|
+
|
|
1795
|
+
`notify/notify` covers its config loader, method selection, delivery over recording
|
|
1796
|
+
seams, the text builders, and its four triggers plus the handle.
|
|
1797
|
+
|
|
1798
|
+
`update/update` covers the cache path and key, the cache read and write with its
|
|
1799
|
+
window, the check and the injected registry read, the version ordering, the
|
|
1800
|
+
formatters and the release notice, the prototype suppression with its idempotent
|
|
1801
|
+
restore, the per-load state, the lifecycle — a fresh matching entry reused without
|
|
1802
|
+
a package-manager call, a stale one re-read and rewritten, silent on failure or an
|
|
1803
|
+
empty list, cache-only offline, skipped outside `tui`, a `recheck()` that ignores
|
|
1804
|
+
the window, and a reply that lands after shutdown — and the `update` action.
|
|
1805
|
+
|
|
1806
|
+
`working/working` covers the elapsed format, the counter, and the timer registration.
|