@gavin-hu/my-pi-agent 0.18.0 → 0.20.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 +66 -52
- package/README.zh-CN.md +56 -46
- package/docs/extensions/README.md +34 -0
- package/docs/extensions/board.md +507 -0
- package/{extensions/bytefly/README.md → docs/extensions/bytefly.md} +774 -574
- package/{extensions/check/README.md → docs/extensions/check.md} +83 -68
- package/{extensions/context/README.md → docs/extensions/context.md} +40 -23
- package/docs/extensions/file-browse.md +561 -0
- package/{extensions/file-open/README.md → docs/extensions/file-open.md} +31 -23
- package/{extensions/file-read/README.md → docs/extensions/file-read.md} +47 -55
- package/{extensions/goal/README.md → docs/extensions/goal.md} +115 -131
- package/{extensions/job/README.md → docs/extensions/job.md} +62 -52
- package/{extensions/memory/README.md → docs/extensions/memory.md} +71 -60
- package/{extensions/plan/README.md → docs/extensions/plan.md} +440 -322
- package/{extensions/question/README.md → docs/extensions/question.md} +54 -31
- package/{extensions/rewind/README.md → docs/extensions/rewind.md} +115 -122
- package/docs/extensions/session-bus.md +298 -0
- package/{extensions/subagent/README.md → docs/extensions/subagent.md} +165 -118
- package/docs/extensions/team.md +254 -0
- package/{extensions/todo/README.md → docs/extensions/todo.md} +85 -88
- package/{extensions/watch/README.md → docs/extensions/watch.md} +54 -36
- package/{extensions/web-access/README.md → docs/extensions/web-access.md} +93 -50
- package/{extensions/wechat/README.md → docs/extensions/wechat.md} +260 -163
- package/{extensions/worktree/README.md → docs/extensions/worktree.md} +137 -79
- package/extensions/board/commands.ts +105 -0
- package/extensions/board/config.ts +36 -0
- package/extensions/board/format.ts +170 -0
- package/extensions/board/index.ts +40 -0
- package/extensions/board/input.ts +54 -0
- package/extensions/board/join.ts +42 -0
- package/extensions/board/page.ts +388 -0
- package/extensions/board/result.ts +108 -0
- package/extensions/board/rows.ts +48 -0
- package/extensions/board/schema.ts +90 -0
- package/extensions/board/seat.ts +28 -0
- package/extensions/board/snapshot.ts +42 -0
- package/extensions/board/tools.ts +444 -0
- package/extensions/board/transport/router.ts +91 -0
- package/extensions/board/transport/server.ts +138 -0
- package/extensions/board/types.ts +121 -0
- package/extensions/board/view/client.ts +51 -0
- package/extensions/board/view/dialog.ts +43 -0
- package/extensions/board/view/keys.ts +125 -0
- package/extensions/board/view/live.ts +231 -0
- package/extensions/board/view/names.ts +91 -0
- package/extensions/board/view/page.ts +118 -0
- package/extensions/board/view/render.ts +519 -0
- package/extensions/board/view/styles.ts +228 -0
- package/extensions/board/view/team.ts +327 -0
- package/extensions/bytefly/footer/budget.ts +6 -5
- package/extensions/bytefly/footer/collect/entries.ts +12 -4
- package/extensions/bytefly/footer/collect/snapshot.ts +8 -17
- package/extensions/bytefly/footer/config.ts +19 -8
- package/extensions/bytefly/footer/price/price.ts +30 -8
- package/extensions/bytefly/footer/register.ts +5 -5
- package/extensions/bytefly/footer/render/format.ts +18 -0
- package/extensions/bytefly/footer/render/lines.ts +23 -7
- package/extensions/bytefly/footer/render/segments.ts +117 -31
- package/extensions/bytefly/footer/types.ts +29 -5
- package/extensions/bytefly/footer/unpriced.ts +42 -17
- package/extensions/bytefly/panel/commands.ts +67 -7
- package/extensions/bytefly/panel/filter.ts +68 -0
- package/extensions/bytefly/panel/format.ts +16 -15
- package/extensions/bytefly/panel/join.ts +56 -13
- package/extensions/bytefly/panel/prices.ts +43 -0
- package/extensions/bytefly/panel/settings-runtime.ts +0 -6
- package/extensions/bytefly/panel/settings.ts +75 -43
- package/extensions/bytefly/panel/tui/entries.ts +26 -8
- package/extensions/bytefly/panel/tui/frame.ts +130 -93
- package/extensions/bytefly/panel/tui/keys.ts +352 -0
- package/extensions/bytefly/panel/tui/list-view.ts +25 -46
- package/extensions/bytefly/panel/tui/panes.ts +76 -0
- package/extensions/bytefly/panel/tui/section-view.ts +126 -0
- package/extensions/bytefly/panel/tui/settings-section.ts +54 -125
- package/extensions/bytefly/panel/tui/settings-view.ts +30 -131
- package/extensions/bytefly/panel/tui/side-pane.ts +224 -0
- package/extensions/bytefly/panel/tui.ts +306 -259
- package/extensions/bytefly/picker/discovery.ts +0 -2
- package/extensions/bytefly/picker/types.ts +0 -2
- package/extensions/bytefly/update/check.ts +39 -0
- package/extensions/bytefly/update/format.ts +15 -0
- package/extensions/bytefly/update/register.ts +73 -34
- package/extensions/bytefly/update/state.ts +6 -3
- package/extensions/check/commands.ts +2 -1
- package/extensions/context/tui.ts +1 -1
- package/extensions/file-browse/{config.ts → config/config.ts} +1 -1
- package/extensions/file-browse/files/classify.ts +136 -0
- package/extensions/file-browse/files/files.ts +12 -0
- package/extensions/file-browse/files/index.ts +90 -0
- package/extensions/file-browse/files/list.ts +261 -0
- package/extensions/file-browse/{paths.ts → files/paths.ts} +1 -1
- package/extensions/file-browse/files/tree.ts +101 -0
- package/extensions/file-browse/{git.ts → git/git.ts} +10 -3
- package/extensions/file-browse/index.ts +4 -4
- package/extensions/file-browse/{live.ts → live/live.ts} +20 -69
- package/extensions/file-browse/{router.ts → transport/router.ts} +21 -17
- package/extensions/file-browse/transport/server.ts +110 -0
- package/extensions/file-browse/{chrome.ts → view/chrome.ts} +4 -4
- package/extensions/file-browse/{client.ts → view/client.ts} +1 -1
- package/extensions/file-browse/{diff-html.ts → view/diff-html.ts} +3 -3
- package/extensions/file-browse/view/emit.ts +51 -0
- package/extensions/file-browse/{html.ts → view/html.ts} +19 -18
- package/extensions/file-browse/{icons.ts → view/icons.ts} +1 -1
- package/extensions/file-browse/{markdown.ts → view/markdown.ts} +18 -20
- package/extensions/file-browse/{raw-html.ts → view/raw-html.ts} +19 -14
- package/extensions/file-browse/{styles.ts → view/styles.ts} +29 -5
- package/extensions/file-browse/{tree.ts → view/tree.ts} +1 -1
- package/extensions/file-browse/{urls.ts → view/urls.ts} +1 -1
- package/extensions/file-read/schema.ts +2 -1
- package/extensions/job/runtime.ts +4 -4
- package/extensions/memory/store.ts +12 -5
- package/extensions/plan/blocks.ts +23 -2
- package/extensions/plan/commands.ts +21 -16
- package/extensions/plan/feedback.ts +185 -52
- package/extensions/plan/format.ts +10 -3
- package/extensions/plan/index.ts +23 -5
- package/extensions/plan/plan-files.ts +88 -0
- package/extensions/plan/plan-index.ts +43 -9
- package/extensions/plan/plan-text.ts +33 -23
- package/extensions/plan/plans.ts +27 -34
- package/extensions/plan/policy.ts +30 -17
- package/extensions/plan/review.ts +3 -27
- package/extensions/plan/runtime.ts +52 -11
- package/extensions/plan/sections.ts +112 -0
- package/extensions/plan/steps.ts +3 -22
- package/extensions/plan/todos.ts +51 -3
- package/extensions/plan/tools/exit.ts +20 -95
- package/extensions/plan/tools/todo-seed.ts +4 -2
- package/extensions/plan/tools/write.ts +12 -1
- package/extensions/plan/tui.ts +5 -34
- package/extensions/plan/types.ts +15 -8
- package/extensions/plan/web-blocks.ts +89 -0
- package/extensions/plan/web-chrome.ts +3 -5
- package/extensions/plan/web-client.ts +179 -330
- package/extensions/plan/web-collab.ts +3 -3
- package/extensions/plan/web-comments.ts +18 -8
- package/extensions/plan/web-composer.ts +80 -0
- package/extensions/plan/web-draft.ts +40 -0
- package/extensions/plan/web-keys.ts +134 -0
- package/extensions/plan/web-outline.ts +192 -0
- package/extensions/plan/web-page.ts +4 -8
- package/extensions/plan/web-plan.ts +150 -0
- package/extensions/plan/web-router.ts +3 -58
- package/extensions/plan/web-settle.ts +194 -0
- package/extensions/plan/web-share-session.ts +24 -30
- package/extensions/plan/web-streams.ts +14 -14
- package/extensions/plan/web-tokens.ts +2 -2
- package/extensions/plan/web.ts +66 -120
- package/extensions/rewind/{commands.ts → commands/commands.ts} +5 -5
- package/extensions/rewind/{review.ts → commands/review.ts} +15 -14
- package/extensions/rewind/{rewind.ts → commands/rewind.ts} +6 -6
- package/extensions/rewind/{config.ts → config/config.ts} +1 -1
- package/extensions/rewind/index.ts +3 -3
- package/extensions/rewind/{policy.ts → state/policy.ts} +4 -4
- package/extensions/rewind/{runtime.ts → state/runtime.ts} +11 -11
- package/extensions/rewind/{snapshot-run.ts → state/snapshot-run.ts} +1 -1
- package/extensions/rewind/{timeline.ts → state/timeline.ts} +2 -2
- package/extensions/rewind/{format.ts → text/format.ts} +3 -3
- package/extensions/rewind/{git.ts → transport/git.ts} +2 -2
- package/extensions/rewind/{restore.ts → transport/restore.ts} +2 -2
- package/extensions/rewind/{snapshot.ts → transport/snapshot.ts} +1 -1
- package/extensions/rewind/{store.ts → transport/store.ts} +1 -1
- package/extensions/rewind/{checklist.ts → view/checklist.ts} +6 -6
- package/extensions/rewind/{hunk-picker.ts → view/hunk-picker.ts} +8 -8
- package/extensions/rewind/{path-picker.ts → view/path-picker.ts} +7 -7
- package/extensions/rewind/{review-tui.ts → view/review-tui.ts} +11 -11
- package/extensions/rewind/{rewind-tui.ts → view/rewind-tui.ts} +17 -11
- package/extensions/rewind/{status.ts → view/status.ts} +4 -4
- package/extensions/session-bus/commands.ts +17 -69
- package/extensions/session-bus/format.ts +22 -45
- package/extensions/session-bus/index.ts +13 -7
- package/extensions/session-bus/join-request.ts +40 -0
- package/extensions/session-bus/mail-watch.ts +134 -0
- package/extensions/session-bus/notice.ts +32 -4
- package/{lib/claims → extensions/session-bus}/overlap.ts +11 -18
- package/extensions/session-bus/protocol.ts +19 -49
- package/extensions/session-bus/resolve.ts +67 -0
- package/extensions/session-bus/result.ts +16 -51
- package/extensions/session-bus/rows.ts +11 -5
- package/extensions/session-bus/runtime.ts +220 -267
- package/extensions/session-bus/store.ts +55 -7
- package/extensions/session-bus/tools.ts +31 -66
- package/extensions/session-bus/tui.ts +5 -5
- package/extensions/session-bus/types.ts +23 -14
- package/extensions/subagent/agents.ts +9 -8
- package/extensions/subagent/commands.ts +2 -1
- package/extensions/subagent/invocation.ts +4 -2
- package/extensions/team/commands.ts +145 -0
- package/extensions/team/dispatch.ts +133 -0
- package/extensions/team/format.ts +119 -0
- package/extensions/team/index.ts +34 -0
- package/extensions/team/schema.ts +29 -0
- package/extensions/team/tools.ts +267 -0
- package/extensions/team/types.ts +65 -0
- package/extensions/todo/index.ts +4 -1
- package/extensions/todo/nudge.ts +8 -2
- package/extensions/web-access/fetch/page.ts +4 -1
- package/extensions/web-access/fetch/structured.ts +447 -0
- package/extensions/web-access/fetch/tool.ts +2 -1
- package/extensions/web-access/search/tool.ts +2 -1
- package/extensions/wechat/bridge.ts +106 -251
- package/extensions/wechat/{commands.ts → commands/commands.ts} +26 -18
- package/extensions/wechat/{doctor.ts → commands/doctor.ts} +5 -5
- package/extensions/wechat/{history.ts → commands/history.ts} +1 -1
- package/extensions/wechat/{login.ts → commands/login.ts} +3 -3
- package/extensions/wechat/{slash.ts → commands/slash.ts} +38 -2
- package/extensions/wechat/dialog/channels.ts +136 -0
- package/extensions/wechat/{interaction.ts → dialog/interaction.ts} +37 -37
- package/extensions/wechat/{prompt.ts → dialog/prompt.ts} +2 -2
- package/extensions/wechat/{remote-ui.ts → dialog/remote-ui.ts} +1 -1
- package/extensions/wechat/index.ts +10 -10
- package/extensions/wechat/intake.ts +245 -0
- package/extensions/wechat/{admission.ts → peer/admission.ts} +2 -2
- package/extensions/wechat/{peer-session.ts → peer/peer-session.ts} +2 -2
- package/extensions/wechat/{peer-worker.ts → peer/peer-worker.ts} +100 -22
- package/extensions/wechat/{presence.ts → peer/presence.ts} +8 -7
- package/extensions/wechat/{reply-pipeline.ts → peer/reply-pipeline.ts} +1 -1
- package/extensions/wechat/{credentials.ts → state/credentials.ts} +2 -2
- package/extensions/wechat/{state.ts → state/state.ts} +14 -2
- package/extensions/wechat/{format.ts → text/format.ts} +3 -3
- package/extensions/wechat/{notices.ts → text/notices.ts} +8 -0
- package/extensions/wechat/tools.ts +29 -12
- package/extensions/wechat/{client.ts → transport/client.ts} +26 -2
- package/extensions/wechat/{deliver.ts → transport/deliver.ts} +72 -28
- package/extensions/wechat/{inbound.ts → transport/inbound.ts} +5 -5
- package/extensions/wechat/{media.ts → transport/media.ts} +11 -5
- package/extensions/wechat/transport/outbound.ts +142 -0
- package/extensions/wechat/{poll.ts → transport/poll.ts} +3 -3
- package/extensions/wechat/types.ts +10 -1
- package/extensions/wechat/{login-screen.ts → view/login-screen.ts} +4 -4
- package/extensions/wechat/{status-screen.ts → view/status-screen.ts} +31 -26
- package/extensions/worktree/commands.ts +24 -17
- package/extensions/worktree/exit.ts +12 -6
- package/extensions/worktree/git.ts +22 -14
- package/extensions/worktree/guard.ts +18 -290
- package/extensions/worktree/handoff.ts +10 -2
- package/extensions/worktree/index.ts +2 -1
- package/extensions/worktree/lifecycle.ts +2 -0
- package/extensions/worktree/registry.ts +20 -11
- package/extensions/worktree/root-tools.ts +13 -3
- package/extensions/worktree/runtime.ts +8 -2
- package/extensions/worktree/screen.ts +15 -8
- package/extensions/worktree/shell.ts +303 -0
- package/extensions/worktree/state.ts +1 -1
- package/extensions/worktree/status.ts +42 -9
- package/extensions/worktree/tools.ts +19 -13
- package/lib/README.md +11 -8
- package/lib/board/card.ts +479 -0
- package/lib/board/links.ts +141 -0
- package/lib/board/page-pointer.ts +310 -0
- package/lib/board/round-text.ts +81 -0
- package/lib/board/round.ts +94 -0
- package/lib/board/rules.ts +437 -0
- package/lib/board/session.ts +105 -0
- package/lib/board/store.ts +497 -0
- package/lib/board/view.ts +234 -0
- package/lib/errors.ts +12 -4
- package/lib/format.ts +35 -0
- package/lib/http/guard.ts +112 -0
- package/lib/http/index.ts +16 -5
- package/lib/http/serve.ts +237 -0
- package/lib/http/server.ts +12 -10
- package/lib/http/sink.ts +135 -0
- package/lib/http/token.ts +38 -0
- package/lib/plan-entry.ts +11 -0
- package/lib/policy.ts +25 -2
- package/lib/requirements.ts +6 -7
- package/lib/session-label.ts +64 -0
- package/lib/session-roster.ts +201 -0
- package/lib/session-tool.ts +184 -0
- package/lib/spawn.ts +37 -3
- package/lib/stray-fields.ts +45 -0
- package/lib/tool-names.ts +38 -2
- package/lib/tui/glyphs.ts +3 -2
- package/lib/web/README.md +57 -4
- package/lib/web/client-runtime.ts +123 -0
- package/lib/web/components.ts +5 -0
- package/lib/web/index.ts +4 -2
- package/lib/web/markup.ts +88 -1
- package/lib/web/names.ts +42 -0
- package/lib/web/runtime.ts +7 -1
- package/lib/web/tokens.ts +25 -2
- package/package.json +26 -14
- package/skills/next/SKILL.md +4 -3
- package/skills/project-docs/SKILL.md +133 -0
- package/skills/project-docs/references/audit.md +131 -0
- package/skills/project-docs/references/changelog.md +105 -0
- package/skills/project-docs/references/discovery.md +127 -0
- package/skills/project-docs/references/readme.md +80 -0
- package/skills/project-docs/references/release.md +84 -0
- package/skills/project-docs/references/roadmap.md +93 -0
- package/skills/project-docs/scripts/state.ts +316 -0
- package/skills/refactor/SKILL.md +100 -125
- package/skills/refactor/references/handoff.md +35 -0
- package/skills/refactor/references/signals.md +54 -0
- package/skills/refactor/scripts/inventory.ts +587 -0
- package/extensions/bytefly/panel/tui/extensions-view.ts +0 -40
- package/extensions/bytefly/panel/tui/skills-view.ts +0 -50
- package/extensions/file-browse/README.md +0 -506
- package/extensions/file-browse/files.ts +0 -564
- package/extensions/file-browse/server.ts +0 -141
- package/extensions/job/process.ts +0 -35
- package/extensions/plan/split.ts +0 -87
- package/extensions/session-bus/README.md +0 -247
- package/extensions/session-bus/team.ts +0 -102
- package/extensions/wechat/outbound.ts +0 -100
- package/lib/plans/sections.ts +0 -172
- package/lib/plans/setting.ts +0 -52
- package/lib/plans/split.ts +0 -215
- package/lib/plans/store.ts +0 -19
- package/lib/plans/team.ts +0 -151
- package/skills/changelog/SKILL.md +0 -148
- package/skills/parallel-dev/SKILL.md +0 -150
- /package/extensions/file-browse/{rev.ts → live/rev.ts} +0 -0
- /package/extensions/file-browse/{diff.ts → text/diff.ts} +0 -0
- /package/extensions/file-browse/{fuzzy.ts → text/fuzzy.ts} +0 -0
- /package/extensions/file-browse/{live-client.ts → view/live-client.ts} +0 -0
- /package/extensions/file-browse/{palette.ts → view/palette.ts} +0 -0
- /package/extensions/rewind/{patch.ts → text/patch.ts} +0 -0
- /package/extensions/rewind/{paths.ts → text/paths.ts} +0 -0
- /package/extensions/rewind/{queue.ts → transport/queue.ts} +0 -0
- /package/extensions/rewind/{temp-index.ts → transport/temp-index.ts} +0 -0
- /package/extensions/wechat/{lock.ts → state/lock.ts} +0 -0
- /package/extensions/wechat/{channel.ts → text/channel.ts} +0 -0
package/lib/web/markup.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { escapeHtml } from "../escape.ts";
|
|
10
10
|
import { THEME_JS_PATH } from "./runtime.ts";
|
|
11
|
+
import { WEB_THEME_TOKENS } from "./tokens.ts";
|
|
11
12
|
|
|
12
13
|
/** Options for {@link docHead}. */
|
|
13
14
|
export interface DocHeadOptions {
|
|
@@ -17,6 +18,29 @@ export interface DocHeadOptions {
|
|
|
17
18
|
css: string;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* A page's browser-tab title: `<page> · <subject> · <count>`.
|
|
23
|
+
*
|
|
24
|
+
* One convention across the served pages, so a strip of tabs reads as one product. The
|
|
25
|
+
* page's name comes first, lowercase and the same word its header's `brandLockup`
|
|
26
|
+
* carries; then what the page is showing; then the count a reader opens the tab for. A
|
|
27
|
+
* part the page does not have is left out rather than drawn empty, so a board with
|
|
28
|
+
* nothing open reads `board · my-pi-agent` and a plan reads `plan review · <its title>`.
|
|
29
|
+
*/
|
|
30
|
+
export function tabTitle(product: string, subject?: string, count?: string): string {
|
|
31
|
+
const kept = [product, subject, count];
|
|
32
|
+
return kept.filter((part) => part !== undefined && part !== "").join(" · ");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The same body, as the browser receives it.
|
|
37
|
+
*
|
|
38
|
+
* The board's count is live, so its tab is repainted on every frame and this rule has to
|
|
39
|
+
* cross into the bundle. It is written as concatenation with no backtick and no
|
|
40
|
+
* interpolation, because the bundle is a template the source is spliced into.
|
|
41
|
+
*/
|
|
42
|
+
export const TAB_TITLE_JS = String(tabTitle);
|
|
43
|
+
|
|
20
44
|
/**
|
|
21
45
|
* The shared document head: charset, viewport, colour scheme, title, the page
|
|
22
46
|
* CSS, and the pre-paint theme bootstrap. The body and its scripts stay with
|
|
@@ -27,17 +51,80 @@ export function docHead(options: DocHeadOptions): string {
|
|
|
27
51
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
28
52
|
<meta name="color-scheme" content="dark light">
|
|
29
53
|
<title>${escapeHtml(options.title)}</title>
|
|
54
|
+
${markIcon()}
|
|
30
55
|
<style>${options.css}</style>
|
|
31
56
|
<script src="${THEME_JS_PATH}"></script>`;
|
|
32
57
|
}
|
|
33
58
|
|
|
59
|
+
/**
|
|
60
|
+
* The mark's blocks: `█▀█` over `█▀ █`, as `[x, height]` per row in a 4x2 grid.
|
|
61
|
+
*
|
|
62
|
+
* One shape, three places — the header lockup, the tab icon, and the TUI header's
|
|
63
|
+
* half-blocks — so it is written once. The rows differ: the top fills x=2, the bottom
|
|
64
|
+
* leaves it empty and fills x=3, which is what makes the mark read as two glyphs.
|
|
65
|
+
*/
|
|
66
|
+
const MARK_ROWS: ReadonlyArray<{ group: "top" | "bottom"; rects: ReadonlyArray<readonly [number, number]> }> = [
|
|
67
|
+
{
|
|
68
|
+
group: "top",
|
|
69
|
+
rects: [
|
|
70
|
+
[0, 1],
|
|
71
|
+
[1, 0.5],
|
|
72
|
+
[2, 1],
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
group: "bottom",
|
|
77
|
+
rects: [
|
|
78
|
+
[0, 1],
|
|
79
|
+
[1, 0.5],
|
|
80
|
+
[3, 1],
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/** One row of the mark, as `<rect>`s starting at `y`. */
|
|
86
|
+
function markRowRects(row: (typeof MARK_ROWS)[number], y: number): string {
|
|
87
|
+
return row.rects.map(([x, height]) => `<rect x="${x}" y="${y}" width="1" height="${height}"/>`).join("");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The mark as a standalone SVG, in one appearance's colours.
|
|
92
|
+
*
|
|
93
|
+
* A favicon is its own document: it cannot read the page's tokens, so the fills are
|
|
94
|
+
* resolved here from the same palette the page paints with, and each appearance gets
|
|
95
|
+
* its own icon.
|
|
96
|
+
*/
|
|
97
|
+
function markSvg(fills: { top: string; bottom: string }): string {
|
|
98
|
+
const rows = MARK_ROWS.map((row, index) => `<g fill="${fills[row.group]}">${markRowRects(row, index)}</g>`);
|
|
99
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 2">${rows.join("")}</svg>`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The tab icon: the mark, in the appearance the reader's system is in.
|
|
104
|
+
*
|
|
105
|
+
* The dark icon is the plain `rel="icon"` — the page paints dark at `:root`, and a
|
|
106
|
+
* browser that reads no `media` query on an icon keeps it. The light one is the
|
|
107
|
+
* override, so a light tab does not carry a mark tuned for a dark one.
|
|
108
|
+
*/
|
|
109
|
+
export function markIcon(): string {
|
|
110
|
+
const dark = encodeURIComponent(
|
|
111
|
+
markSvg({ top: WEB_THEME_TOKENS.dark["--accent"], bottom: WEB_THEME_TOKENS.dark["--warn"] }),
|
|
112
|
+
);
|
|
113
|
+
const light = encodeURIComponent(
|
|
114
|
+
markSvg({ top: WEB_THEME_TOKENS.light["--accent"], bottom: WEB_THEME_TOKENS.light["--warn"] }),
|
|
115
|
+
);
|
|
116
|
+
return `<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,${dark}">
|
|
117
|
+
<link rel="icon" type="image/svg+xml" media="(prefers-color-scheme: light)" href="data:image/svg+xml,${light}">`;
|
|
118
|
+
}
|
|
119
|
+
|
|
34
120
|
/**
|
|
35
121
|
* The Bytefly nameplate: the two-tone half-block mark, the `bytefly` wordmark,
|
|
36
122
|
* and the product name. The mark mirrors the TUI header (`█▀█` / `█▀ █`), drawn
|
|
37
123
|
* as a 4x2 grid so the accent and warning rows stay crisp at any zoom.
|
|
38
124
|
*/
|
|
39
125
|
export function brandLockup(product: string): string {
|
|
40
|
-
|
|
126
|
+
const rows = MARK_ROWS.map((row, index) => `<g class="bf-mark__${row.group}">${markRowRects(row, index)}</g>`);
|
|
127
|
+
return `<span class="bf-brand"><svg class="bf-mark" viewBox="0 0 4 2" aria-hidden="true">${rows.join("")}</svg><span class="bf-wordmark">bytefly</span><span class="bf-context">${escapeHtml(product)}</span></span>`;
|
|
41
128
|
}
|
|
42
129
|
|
|
43
130
|
/**
|
package/lib/web/names.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A page's class names, as a table a bundle can carry.
|
|
3
|
+
*
|
|
4
|
+
* A browser page in this package is a TypeScript document plus a client script held in
|
|
5
|
+
* a template literal, so the two halves cannot import from each other: a class name is a
|
|
6
|
+
* string in one and a string in the other, and a name built by concatenation
|
|
7
|
+
* (`"board-card__reason" + kind`) cannot be found by reading either. A table fixes both:
|
|
8
|
+
* the document and the bundle read the same values, and a test can compare the set the
|
|
9
|
+
* page wears with the set its stylesheet draws.
|
|
10
|
+
*
|
|
11
|
+
* The bundle carries the table as **source**, so every value must survive being spliced
|
|
12
|
+
* into a template literal: a backtick would end the string, and `${` would interpolate
|
|
13
|
+
* at build time. `KEBAB` is that contract, and {@link namesScript} throws rather than
|
|
14
|
+
* trusting a caller — a bad name is a build error here, not a mystery on the page.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** A page's vocabulary: a key per thing it dresses, and the class it wears. */
|
|
18
|
+
export type ClassNames = Readonly<Record<string, string>>;
|
|
19
|
+
|
|
20
|
+
/** What a class name may be: lowercase, hyphenated, and nothing a script could misread. */
|
|
21
|
+
export const KEBAB = /^[a-z][a-z0-9_-]*$/;
|
|
22
|
+
|
|
23
|
+
/** What the global the table is bound to may be: a JavaScript identifier, and nothing else. */
|
|
24
|
+
export const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
25
|
+
|
|
26
|
+
/** The declared global the table is bound to in a page's bundle. */
|
|
27
|
+
export const NAMES_GLOBAL = "N";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The table as one script statement, for a client bundle to start with.
|
|
31
|
+
*
|
|
32
|
+
* `JSON.stringify` is the serializer because the values are already strings that pass
|
|
33
|
+
* {@link KEBAB}; the check before it is what makes that true, and its message names the
|
|
34
|
+
* offending key and value so the fix is obvious.
|
|
35
|
+
*/
|
|
36
|
+
export function namesScript(table: ClassNames, global: string = NAMES_GLOBAL): string {
|
|
37
|
+
for (const [key, value] of Object.entries(table)) {
|
|
38
|
+
if (!KEBAB.test(value)) throw new Error(`the class name for "${key}" is not a kebab-case name: "${value}"`);
|
|
39
|
+
}
|
|
40
|
+
if (!IDENTIFIER.test(global)) throw new Error(`"${global}" is not a name a script can declare`);
|
|
41
|
+
return `var ${global} = ${JSON.stringify(table)};`;
|
|
42
|
+
}
|
package/lib/web/runtime.ts
CHANGED
|
@@ -123,9 +123,15 @@ export function dialogScript(options: DialogOptions): string {
|
|
|
123
123
|
// A button inside a closed dialog has no boxes, so the rects are the test that
|
|
124
124
|
// survives a hidden attribute, a collapsed panel, and a stylesheet swap alike.
|
|
125
125
|
function focusables() {
|
|
126
|
-
|
|
126
|
+
var nodes = Array.prototype.filter.call(dialog.querySelectorAll('${FOCUSABLE}'), function (node) {
|
|
127
127
|
return node.getClientRects && node.getClientRects().length > 0;
|
|
128
128
|
});
|
|
129
|
+
// A panel that names itself focusable is where focus lands on open, so the close
|
|
130
|
+
// button is not the first thing a dialog says with its ring. It stays first in the
|
|
131
|
+
// list, which is what keeps Shift+Tab wrapping inside instead of escaping the scrim.
|
|
132
|
+
var panel = dialog.querySelector('[role="dialog"][tabindex]');
|
|
133
|
+
if (panel && panel.getClientRects && panel.getClientRects().length > 0) nodes.unshift(panel);
|
|
134
|
+
return nodes;
|
|
129
135
|
}
|
|
130
136
|
function toggle(force) {
|
|
131
137
|
var open = force === undefined ? dialog.hidden : force;
|
package/lib/web/tokens.ts
CHANGED
|
@@ -21,8 +21,8 @@ interface ThemeJson {
|
|
|
21
21
|
const DARK = darkTheme as unknown as ThemeJson;
|
|
22
22
|
const LIGHT = lightTheme as unknown as ThemeJson;
|
|
23
23
|
|
|
24
|
-
/** Web custom property -> Bytefly theme var. `--accent-soft`, `--on-accent`,
|
|
25
|
-
* and `--shadow` are derived, so no appearance-only colour enters the kit. */
|
|
24
|
+
/** Web custom property -> Bytefly theme var. `--accent-soft`, `--raised`, `--on-accent`,
|
|
25
|
+
* `--scrim`, and `--shadow` are derived, so no appearance-only colour enters the kit. */
|
|
26
26
|
const VAR_TOKENS: ReadonlyArray<readonly [string, string]> = [
|
|
27
27
|
["--canvas", "canvas"],
|
|
28
28
|
["--surface", "canvasSubtle"],
|
|
@@ -73,6 +73,16 @@ function resolve(theme: ThemeJson, value: string | number): string {
|
|
|
73
73
|
return theme.vars[value] ?? value;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/** `#rrggbb` mixed toward another colour: `t` of the way from `a` to `b`. */
|
|
77
|
+
function mix(a: string, b: string, t: number): string {
|
|
78
|
+
const channel = (hex: string, at: number): number => Number.parseInt(hex.replace("#", "").slice(at, at + 2), 16);
|
|
79
|
+
const between = (x: number, y: number): number => Math.round(x + (y - x) * t);
|
|
80
|
+
const r = between(channel(a, 0), channel(b, 0));
|
|
81
|
+
const g = between(channel(a, 2), channel(b, 2));
|
|
82
|
+
const bl = between(channel(a, 4), channel(b, 4));
|
|
83
|
+
return `#${[r, g, bl].map((value) => value.toString(16).padStart(2, "0")).join("")}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
76
86
|
/** `#rrggbb` (or `#rgb`) plus alpha -> `rgba(r,g,b,a)`. */
|
|
77
87
|
function rgba(hex: string, alpha: number): string {
|
|
78
88
|
const raw = hex.replace("#", "");
|
|
@@ -94,6 +104,15 @@ function rgba(hex: string, alpha: number): string {
|
|
|
94
104
|
* lifts a panel off it, so each appearance needs its own alpha rather than the
|
|
95
105
|
* theme's colours.
|
|
96
106
|
*/
|
|
107
|
+
/**
|
|
108
|
+
* How far `--raised` sits above `--surface`: enough to see, not enough to shout.
|
|
109
|
+
*
|
|
110
|
+
* The light theme takes a smaller step because its accent is darker: at the dark
|
|
111
|
+
* step, `--accent` on `--raised` falls to 4.34:1 and the owner chips on a raised row
|
|
112
|
+
* stop being readable.
|
|
113
|
+
*/
|
|
114
|
+
const RAISED_STEP: Record<"dark" | "light", number> = { dark: 0.06, light: 0.03 };
|
|
115
|
+
|
|
97
116
|
const OVERLAYS: Record<"dark" | "light", { scrim: string; shadow: string }> = {
|
|
98
117
|
dark: { scrim: "rgba(0,0,0,.5)", shadow: "0 8px 24px rgba(0,0,0,.4)" },
|
|
99
118
|
light: { scrim: "rgba(15,23,42,.3)", shadow: "0 8px 24px rgba(15,23,42,.14)" },
|
|
@@ -104,6 +123,10 @@ function paletteOf(theme: ThemeJson, appearance: "dark" | "light", accentAlpha:
|
|
|
104
123
|
const palette: Record<string, string> = {};
|
|
105
124
|
for (const [token, name] of VAR_TOKENS) palette[token] = theme.vars[name];
|
|
106
125
|
palette["--accent-soft"] = rgba(palette["--accent"] ?? "#000000", accentAlpha);
|
|
126
|
+
// One step above `--surface`, for a block that must read as a plane rather than an
|
|
127
|
+
// outline: the theme offers only two neutral fills, and a surface one hairline
|
|
128
|
+
// lighter than the page is what made a dashboard look like a wireframe.
|
|
129
|
+
palette["--raised"] = mix(palette["--surface"] ?? "#000000", palette["--text"] ?? "#ffffff", RAISED_STEP[appearance]);
|
|
107
130
|
// A label on the accent fill is the canvas colour: a light blue button takes dark
|
|
108
131
|
// text, and the same derivation gives white on the light theme's darker blue.
|
|
109
132
|
palette["--on-accent"] = palette["--canvas"];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gavin-hu/my-pi-agent",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Personal Pi customizations, packaged as a Pi package: worktree isolation and rewind snapshots, question, todo, goal, plan, subagent, job, watch, web-access, file-browse, file-open, file-read, check, memory, context, session-bus, wechat, and bytefly.",
|
|
3
|
+
"version": "0.20.0",
|
|
4
|
+
"description": "Personal Pi customizations, packaged as a Pi package: worktree isolation and rewind snapshots, question, todo, goal, plan, subagent, job, watch, web-access, file-browse, file-open, file-read, check, memory, context, session-bus, board, team, wechat, and bytefly.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
7
7
|
"pi",
|
|
@@ -49,6 +49,12 @@
|
|
|
49
49
|
"excel",
|
|
50
50
|
"read_doc",
|
|
51
51
|
"memory",
|
|
52
|
+
"board",
|
|
53
|
+
"cards",
|
|
54
|
+
"backlog",
|
|
55
|
+
"team",
|
|
56
|
+
"handoff",
|
|
57
|
+
"assign",
|
|
52
58
|
"cross-session",
|
|
53
59
|
"context",
|
|
54
60
|
"compaction",
|
|
@@ -74,6 +80,7 @@
|
|
|
74
80
|
},
|
|
75
81
|
"files": [
|
|
76
82
|
"extensions/**",
|
|
83
|
+
"docs/extensions/**",
|
|
77
84
|
"lib/**",
|
|
78
85
|
"skills/**",
|
|
79
86
|
"themes/**",
|
|
@@ -101,6 +108,8 @@
|
|
|
101
108
|
"./extensions/file-open/index.ts",
|
|
102
109
|
"./extensions/memory/index.ts",
|
|
103
110
|
"./extensions/context/index.ts",
|
|
111
|
+
"./extensions/board/index.ts",
|
|
112
|
+
"./extensions/team/index.ts",
|
|
104
113
|
"./extensions/session-bus/index.ts",
|
|
105
114
|
"./extensions/wechat/index.ts",
|
|
106
115
|
"./extensions/bytefly/index.ts"
|
|
@@ -111,7 +120,7 @@
|
|
|
111
120
|
"themes": [
|
|
112
121
|
"./themes/*.json"
|
|
113
122
|
],
|
|
114
|
-
"image": "https://raw.githubusercontent.com/gavin-hu/my-pi-agent/main/assets/chrome.png"
|
|
123
|
+
"image": "https://raw.githubusercontent.com/gavin-hu/my-pi-agent/main/assets/screens/chrome.png"
|
|
115
124
|
},
|
|
116
125
|
"scripts": {
|
|
117
126
|
"test": "bun test --parallel=4 --timeout 30000",
|
|
@@ -127,12 +136,15 @@
|
|
|
127
136
|
"config:migrate": "bun run scripts/migrate-config.ts",
|
|
128
137
|
"compat:versions": "bun run scripts/peer-versions.ts",
|
|
129
138
|
"bench:render": "bun run scripts/render-bench.ts",
|
|
130
|
-
"screenshot:
|
|
131
|
-
"screenshot:
|
|
132
|
-
"screenshot:
|
|
133
|
-
"screenshot:
|
|
134
|
-
"screenshot:
|
|
135
|
-
"
|
|
139
|
+
"screenshot:board": "bun run scripts/shots/board.ts",
|
|
140
|
+
"screenshot:cards": "bun run scripts/shots/cards.ts",
|
|
141
|
+
"screenshot:file-browse": "bun run scripts/shots/file-browse.ts",
|
|
142
|
+
"screenshot:plan": "bun run scripts/shots/plan-review.ts",
|
|
143
|
+
"screenshot:tools": "bun run tools:render gallery assets/screens/tool-renderings.png",
|
|
144
|
+
"screenshot:tool-pngs": "bun run tools:render tools assets/tools",
|
|
145
|
+
"probe:wechat": "bun run scripts/wechat-poll.ts",
|
|
146
|
+
"screenshots": "bun run scripts/screenshots.ts",
|
|
147
|
+
"tools:render": "bun run scripts/tools/index.ts"
|
|
136
148
|
},
|
|
137
149
|
"dependencies": {
|
|
138
150
|
"exceljs": "^4.4.0",
|
|
@@ -153,15 +165,15 @@
|
|
|
153
165
|
},
|
|
154
166
|
"devDependencies": {
|
|
155
167
|
"@biomejs/biome": "^2.5.15",
|
|
156
|
-
"@earendil-works/pi-agent-core": "^1.0
|
|
157
|
-
"@earendil-works/pi-ai": "^1.0
|
|
158
|
-
"@earendil-works/pi-coding-agent": "^1.0
|
|
159
|
-
"@earendil-works/pi-tui": "^1.0
|
|
168
|
+
"@earendil-works/pi-agent-core": "^1.4.0",
|
|
169
|
+
"@earendil-works/pi-ai": "^1.4.0",
|
|
170
|
+
"@earendil-works/pi-coding-agent": "^1.4.0",
|
|
171
|
+
"@earendil-works/pi-tui": "^1.4.0",
|
|
160
172
|
"@types/bun": "latest",
|
|
161
173
|
"@types/qrcode": "^1.5.5",
|
|
162
174
|
"get-east-asian-width": "^1.6.0",
|
|
163
175
|
"playwright-core": "^1.64.1",
|
|
164
|
-
"typebox": "^1.3
|
|
176
|
+
"typebox": "^1.4.3",
|
|
165
177
|
"typescript": "^5.6.0"
|
|
166
178
|
}
|
|
167
179
|
}
|
package/skills/next/SKILL.md
CHANGED
|
@@ -16,9 +16,10 @@ The conversation decides where the candidates come from (section 3); the request
|
|
|
16
16
|
decides only what to ask and where to look.
|
|
17
17
|
|
|
18
18
|
Two sibling skills, where they are installed, own a narrower question: an audit
|
|
19
|
-
of *where to refactor* is `refactor`, and *
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
of *where to refactor* is `refactor`, and *whether a document still tells the
|
|
20
|
+
truth* — the changelog, the roadmap, the front door — is `project-docs`. When the
|
|
21
|
+
request is already scoped to one of those, name the skill that answers it and
|
|
22
|
+
hand over, instead of returning a generic list.
|
|
22
23
|
|
|
23
24
|
A next-steps block that the host draws itself is not this skill's output: that is
|
|
24
25
|
the reply's suggested follow-up, a turn-level hint. This skill inspects state, so
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-docs
|
|
3
|
+
description: "Keep a project's documents true to its tree: a read-only audit of the front door, the roadmap, the contributor path, and the changelog against the code and against each other, then one mode per act that writes — record a changelog bullet in the same commit as the change, curate a release section from the project's own rules, delete a shipped roadmap item and renumber, and sync the README front door. Use when a doc claim looks stale, before a release, or when a change lands owing an entry; prioritisation stays with `next` and structure with `refactor`."
|
|
4
|
+
compatibility: "Bun for scripts/state.ts; git for the roadmap and the audit."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Keep the docs true to the tree
|
|
8
|
+
|
|
9
|
+
Goal: the documents a reader trusts — the front door, the plan of record, the record
|
|
10
|
+
of what shipped, and the contributor path — so a claim the tree no longer meets is
|
|
11
|
+
found, and each act that needs writing has one owner. This is a procedure, not a
|
|
12
|
+
second policy: the project's instructions and release document win, and where they
|
|
13
|
+
are silent this file says ask.
|
|
14
|
+
|
|
15
|
+
A bare `/skill:project-docs` reads and reports. Nothing is written until a mode is
|
|
16
|
+
named.
|
|
17
|
+
|
|
18
|
+
## Pick the mode
|
|
19
|
+
|
|
20
|
+
| The words after `/skill:project-docs` | Mode | Owns | Writes | Follow |
|
|
21
|
+
|---|---|---|---|---|
|
|
22
|
+
| nothing | audit | every document, read-only | no | [`references/audit.md`](./references/audit.md) |
|
|
23
|
+
| `changelog` | changelog | the unreleased window of the changelog | yes | [`references/changelog.md`](./references/changelog.md) |
|
|
24
|
+
| `release <version>` | release | one version's section and link refs | yes | [`references/release.md`](./references/release.md) |
|
|
25
|
+
| `roadmap` | roadmap | items, ids, and buckets | yes | [`references/roadmap.md`](./references/roadmap.md) |
|
|
26
|
+
| `readme` | readme | the front door and its mirror | yes | [`references/readme.md`](./references/readme.md) |
|
|
27
|
+
| anything else | refuse, and name the five | — | no | — |
|
|
28
|
+
|
|
29
|
+
Audit is the default because the skill spans four documents: a bare invocation that
|
|
30
|
+
writes would edit a document nobody asked about.
|
|
31
|
+
|
|
32
|
+
## Start here
|
|
33
|
+
|
|
34
|
+
Read [`references/discovery.md`](./references/discovery.md) first, in every mode. It
|
|
35
|
+
finds the project's documents, the version's single source, the changelog's local
|
|
36
|
+
conventions, the roadmap's rules, the check command, and the guards by name. State
|
|
37
|
+
that profile in one paragraph before writing anything; it is how a misread is caught
|
|
38
|
+
in a line instead of in a diff.
|
|
39
|
+
|
|
40
|
+
For the changelog's mechanical half, run the state script, resolved against this
|
|
41
|
+
skill's own directory:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bun <skill>/scripts/state.ts <project-root>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
It prints the changelog file it found, the last tag and the commits since it, the
|
|
48
|
+
`[Unreleased]` categories with counts and line numbers, the empty and duplicate
|
|
49
|
+
headings, the scope prefixes in use, and the link refs. That is the state; read the
|
|
50
|
+
diffs for judgement, not for counting. When it finds no changelog, no repository, or no
|
|
51
|
+
Bun to run it with, say so and fall back to discovery by hand. The git commands these
|
|
52
|
+
references give are git's; use the project's VCS where it differs.
|
|
53
|
+
|
|
54
|
+
## Non-negotiables
|
|
55
|
+
|
|
56
|
+
1. **Discover, don't impose.** The project's document set, category spelling, scope
|
|
57
|
+
prefix, bullet shape, item ids, bucket caps, and release procedure are the rules.
|
|
58
|
+
State the profile in one paragraph, and ask when two sources disagree.
|
|
59
|
+
2. **One bullet per user-visible outcome**, in the same commit as the change. A
|
|
60
|
+
feature and the bug it fixed before release are one bullet; two observable
|
|
61
|
+
changes are two.
|
|
62
|
+
3. **A shipped item is deleted here, with its reason, never ticked.** A roadmap that
|
|
63
|
+
keeps what already landed describes a tree that no longer exists.
|
|
64
|
+
4. **One id per thing, across every document.** A README row, a roadmap item, and a
|
|
65
|
+
changelog entry that name the same feature use the same name. A mismatch is
|
|
66
|
+
reported, never renamed.
|
|
67
|
+
5. **A judgement is not a finding.** Positioning, priority, dates, non-goals, and
|
|
68
|
+
contribution policy are the maintainer's: list them and ask.
|
|
69
|
+
6. **One owner per artefact.** The changelog belongs here; what to do next belongs to
|
|
70
|
+
the `next` skill; structure belongs to `refactor`.
|
|
71
|
+
|
|
72
|
+
## Modes
|
|
73
|
+
|
|
74
|
+
- **Audit** — read-only, five faces: the tree against the docs, the docs against each
|
|
75
|
+
other, the changelog's commit window, the roadmap's own ids and caps, and the front
|
|
76
|
+
door's examples. Every finding names the mode that fixes it.
|
|
77
|
+
- **Changelog** — one bullet under the project's category for one user-visible
|
|
78
|
+
outcome, re-reading the file first. It never decides whether something has already
|
|
79
|
+
shipped.
|
|
80
|
+
- **Release** — only for a version the user named, and only after the project's
|
|
81
|
+
release document has been read; everything after moving the entries follows it.
|
|
82
|
+
- **Roadmap** — re-derived from the commits since the last tag rather than from the
|
|
83
|
+
last tag: shipped items deleted, ids renumbered, every citation and link fixed.
|
|
84
|
+
- **Readme** — the front door's catalog rows, counts, examples, and mirror, kept equal
|
|
85
|
+
to the tree; deep detail stays in the project's own guides.
|
|
86
|
+
|
|
87
|
+
## Handover
|
|
88
|
+
|
|
89
|
+
- **A changelog entry, an audit, or a release** is this skill: do not look for
|
|
90
|
+
another one.
|
|
91
|
+
- **What to do next** is `next`, where it is installed: it triages loose work and
|
|
92
|
+
broken promises across the project, and its candidates are not a doc audit's findings.
|
|
93
|
+
- **A structural change to the docs or the code** is `refactor`, where it is installed.
|
|
94
|
+
- **Who may contribute, and how** is a decision for the maintainer: ask, and edit
|
|
95
|
+
nothing until it is answered.
|
|
96
|
+
|
|
97
|
+
## Report
|
|
98
|
+
|
|
99
|
+
Open with the profile in one paragraph, then:
|
|
100
|
+
|
|
101
|
+
- **Stale** — the claim, `path:line`, the evidence in the tree, and the mode that
|
|
102
|
+
fixes it.
|
|
103
|
+
- **Missing** — a document, a row, an entry, or an item the project's own rules call
|
|
104
|
+
for and the tree does not have.
|
|
105
|
+
- **Suggested edit** — the diff or the exact replacement, for the mechanical items
|
|
106
|
+
only, and never applied until the user says so.
|
|
107
|
+
- **Needs a decision** — one line each: the question, and what it changes.
|
|
108
|
+
|
|
109
|
+
Nothing found is a valid result, and the whole report may be empty. Say what was
|
|
110
|
+
checked and stop; an audit that invents four entries to look thorough is worse than
|
|
111
|
+
one that finds nothing.
|
|
112
|
+
|
|
113
|
+
## Quality gate
|
|
114
|
+
|
|
115
|
+
- The project's own check passes, including any guard on the release window, the
|
|
116
|
+
documentation's parity, or the roadmap's ids.
|
|
117
|
+
- Every edit names the document and the line, and every bullet names a scope in the
|
|
118
|
+
project's spelling and a user outcome.
|
|
119
|
+
- No judgement is smuggled into a diff, and the changelog entry is in the change's
|
|
120
|
+
own commit.
|
|
121
|
+
|
|
122
|
+
## Stop conditions
|
|
123
|
+
|
|
124
|
+
- The project has only a README, no roadmap, and no changelog: say so. Whether to
|
|
125
|
+
adopt one is the maintainer's decision, not an edit.
|
|
126
|
+
- The changelog is generated — by `semantic-release`, `changesets`, `git-cliff`, or a
|
|
127
|
+
step in the release workflow: the entry lands upstream, in the commit message, a
|
|
128
|
+
changeset fragment, or the generator's config. Never hand-edit the file.
|
|
129
|
+
- Two sources disagree — two changelogs, a version in two places, a roadmap item the
|
|
130
|
+
changelog contradicts: ask instead of averaging them.
|
|
131
|
+
- The change would reverse a documented non-goal: it is a decision, and the item is
|
|
132
|
+
listed rather than written.
|
|
133
|
+
- The request is really triage or a refactor: name the sibling skill and stop.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Audit
|
|
2
|
+
|
|
3
|
+
Read-only. The audit answers one question per claim: is this still true, and if not,
|
|
4
|
+
which mode fixes it? It never edits — not even a typo, not even "while we are here".
|
|
5
|
+
If the user asks for the fixes, finish the report first, then enter the mode it names.
|
|
6
|
+
|
|
7
|
+
Read [`discovery.md`](./discovery.md) first and open the report with the profile. The
|
|
8
|
+
five faces below are a reading order, not a checklist: a face with no evidence
|
|
9
|
+
produces no findings.
|
|
10
|
+
|
|
11
|
+
## 1. The tree against the docs
|
|
12
|
+
|
|
13
|
+
The claims a reader acts on: a catalog row, a limit stated in a package README, a
|
|
14
|
+
default in a configuration table, a roadmap item, a non-goal, a "supported format"
|
|
15
|
+
list. For each, find the code that does it — the registration, the branch, the config
|
|
16
|
+
default — and name where it disagrees.
|
|
17
|
+
|
|
18
|
+
| Where the claim lives | What falsifies it |
|
|
19
|
+
|---|---|
|
|
20
|
+
| A catalog row or feature bullet | The tool, command, flag, or route no longer registers |
|
|
21
|
+
| A limitations section | The gap was closed, or widened, and the text did not move |
|
|
22
|
+
| A configuration default | The loader's default differs from the table |
|
|
23
|
+
| A roadmap item | The tree already does it (see face 4) |
|
|
24
|
+
| A non-goal | The changelog records the thing being shipped anyway |
|
|
25
|
+
|
|
26
|
+
## 2. The docs against each other
|
|
27
|
+
|
|
28
|
+
- **Counts** — a number a doc states about the code (modules, tools, extensions,
|
|
29
|
+
screens) belongs to the tree. A project that derives it in a test has the count; one
|
|
30
|
+
that does not is a finding, and the fix is a guard, not a number.
|
|
31
|
+
- **Catalog rows** — every row names a thing that exists; every existing thing the
|
|
32
|
+
catalog claims to cover has a row. Both directions.
|
|
33
|
+
- **Cross-reference ids** — the same feature named in a front-door row, a roadmap item,
|
|
34
|
+
and a changelog entry. Report a mismatch; never rename one side to match.
|
|
35
|
+
- **The version** — the source of truth, the newest dated changelog heading, the tag,
|
|
36
|
+
and any badge, badge-adjacent prose, or install instruction that repeats it.
|
|
37
|
+
- **The mirror** — a translated README carries the original's sections, table rows, and
|
|
38
|
+
links. A row that exists in one and not the other is a finding even when the prose is
|
|
39
|
+
deliberately translated.
|
|
40
|
+
- **The contributor path** — the commands `CONTRIBUTING.md` tells a newcomer to run,
|
|
41
|
+
against the manifest's `scripts` and the CI workflow's steps. A command the docs promise
|
|
42
|
+
and the manifest does not define is the one stale claim a new contributor hits first,
|
|
43
|
+
and a step CI runs that the docs never mention is the one they skip.
|
|
44
|
+
|
|
45
|
+
## 3. The changelog's commit window
|
|
46
|
+
|
|
47
|
+
Run `scripts/state.ts` (see the skill's *Start here*). It gives the file, the last tag,
|
|
48
|
+
the commits since it, the `[Unreleased]` categories, and the scopes in use.
|
|
49
|
+
|
|
50
|
+
When discovery says a tool generates the file, the window's entries live in that tool's
|
|
51
|
+
input — the changeset queue, the commit-message convention — so audit those, and report
|
|
52
|
+
a missing fragment rather than a missing bullet.
|
|
53
|
+
|
|
54
|
+
Read every commit it lists: `git show <sha>` for the diff, or the pull request when the
|
|
55
|
+
repository squashes. A subject line is not enough — `fix bug` and `wip` hide
|
|
56
|
+
user-visible changes, and `feat: rewrite the config loader` is often invisible to users.
|
|
57
|
+
For each commit, decide whether a user can observe it, which bullet covers it, whether
|
|
58
|
+
that bullet's scope is right, and whether a reader of the bullet alone would know what
|
|
59
|
+
changed for them.
|
|
60
|
+
|
|
61
|
+
| Commit | User-visible | Evidence | Existing entry | Action |
|
|
62
|
+
|---|---|---|---|---|
|
|
63
|
+
| `3f19a02` | yes | `src/load.ts:42` now rejects an unknown key | — | add |
|
|
64
|
+
| `b81c4de` | no | test-only | — | leave |
|
|
65
|
+
| `0ad9f12` | yes | retry limit 3 → 5 | `Changed`: "`api`: retries are now bounded" | update: the bullet never names the limit |
|
|
66
|
+
| `77e0a1e` | unclear | touches the public `--json` shape | — | ask |
|
|
67
|
+
|
|
68
|
+
`Action` is one of **add** (user-visible, no bullet), **update** (a bullet exists and is
|
|
69
|
+
wrong, unscopeable, or too vague to act on), **leave** (covered, internal, or recorded
|
|
70
|
+
under an older release), or **ask** (the outcome depends on intent the diff cannot show).
|
|
71
|
+
|
|
72
|
+
Report separately:
|
|
73
|
+
|
|
74
|
+
- Duplicate `##` or `###` headings — some tools render the second as its own section,
|
|
75
|
+
and a reader sees half the entries.
|
|
76
|
+
- An empty category heading, or a heading a release guard rejects.
|
|
77
|
+
- An `[Unreleased]` section that is missing or empty while the window contains
|
|
78
|
+
user-visible changes.
|
|
79
|
+
- An entry for something already shipped under a dated heading: the same outcome twice,
|
|
80
|
+
which reads as a second change.
|
|
81
|
+
- A stale link reference pointing at an older tag than the newest dated heading — where
|
|
82
|
+
the file uses link references at all. A generated or non-Keep-a-Changelog file may have
|
|
83
|
+
none, and the state script reports that absence as a missing reference without it being
|
|
84
|
+
a defect.
|
|
85
|
+
|
|
86
|
+
## 4. The roadmap's own ids and caps
|
|
87
|
+
|
|
88
|
+
Re-derive the window before judging an item: `git log --oneline <last-tag>..HEAD` plus
|
|
89
|
+
the changelog's newest dated heading. A roadmap describes the tree, so work that landed
|
|
90
|
+
but has not shipped is already part of what it should describe.
|
|
91
|
+
|
|
92
|
+
- An item the tree already does is a deletion, with its reason recorded where the item
|
|
93
|
+
was.
|
|
94
|
+
- An id used twice, skipped in a sequence, or cited from nowhere the file defines.
|
|
95
|
+
- A bucket over the cap the file states; a bucket that keeps growing stops being a
|
|
96
|
+
priority.
|
|
97
|
+
- A ledger row whose items all closed, or an open item with no ledger row.
|
|
98
|
+
- A relative link or a `path:line` citation that no longer resolves.
|
|
99
|
+
|
|
100
|
+
## 5. The front door's examples
|
|
101
|
+
|
|
102
|
+
- The quickstart command, run as written. A command that no longer exists is a stale
|
|
103
|
+
promise, and it is the most expensive one because it is the reader's first step.
|
|
104
|
+
- An example that imports, configures, or calls something the code no longer accepts.
|
|
105
|
+
- A screenshot or a recording that shows a surface that has since changed.
|
|
106
|
+
- A link to a guide that moved, a section anchor that was renamed, or a badge whose
|
|
107
|
+
target is gone.
|
|
108
|
+
|
|
109
|
+
## Report
|
|
110
|
+
|
|
111
|
+
Open with the profile, then the four sections from the skill: **Stale**, **Missing**,
|
|
112
|
+
**Suggested edit**, **Needs a decision**. Every stale finding carries the document,
|
|
113
|
+
`path:line`, the evidence in the tree, and the mode that fixes it. Group by the mode
|
|
114
|
+
when there are more than a handful, so the user can act one mode at a time.
|
|
115
|
+
|
|
116
|
+
Nothing found is a valid result for the whole audit or for any face. Say what was
|
|
117
|
+
checked — the files read, the commands run, the commits examined — and stop. An audit
|
|
118
|
+
that invents findings to look thorough is worse than one that reports none.
|
|
119
|
+
|
|
120
|
+
## What the audit cannot see
|
|
121
|
+
|
|
122
|
+
Name these in a closing line instead of guessing:
|
|
123
|
+
|
|
124
|
+
- Whether a change is user-visible to someone the diff does not show — a default that
|
|
125
|
+
only matters on one platform, a behavior the docs promised and the tests never
|
|
126
|
+
covered.
|
|
127
|
+
- Whether a commit message describes what the code does; only the diff does.
|
|
128
|
+
- Whether an item shipped: a merged change to a document is not a release, and only the
|
|
129
|
+
maintainer knows whether the front door's promise is meant to hold today or next
|
|
130
|
+
version.
|
|
131
|
+
- Whether a roadmap priority is still right, and whether a non-goal still stands.
|