@dfosco/storyboard 0.5.0-alpha.3 → 0.5.0-alpha.4
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/dist/storyboard-ui.js +1 -1
- package/package.json +1 -1
- package/scaffold/manifest.json +17 -1
- package/scaffold/{agents/prompt-agent.agent.md → prompt-agent.agent.md} +2 -0
- package/scaffold/roles/cluster-token.md +25 -0
- package/scaffold/roles/leader.role.md +38 -0
- package/scaffold/roles/member.role.md +32 -0
- package/scaffold/roles/starter.role.md +79 -0
- package/scaffold/skills/architecture-scanner/SKILL.md +237 -0
- package/scaffold/skills/architecture-scanner/files.json +202 -0
- package/scaffold/skills/architecture-scanner/scan.sh +434 -0
- package/scaffold/skills/canvas/SKILL.md +700 -106
- package/scaffold/skills/changelog/SKILL.md +164 -0
- package/scaffold/skills/changeset/SKILL.md +169 -0
- package/scaffold/skills/clips/SKILL.md +352 -0
- package/scaffold/skills/create/SKILL.md +234 -40
- package/scaffold/skills/create-hub/SKILL.md +131 -0
- package/scaffold/skills/migrate/SKILL.md +232 -0
- package/scaffold/skills/migrate-0.5.0/SKILL.md +325 -0
- package/scaffold/skills/release/SKILL.md +219 -0
- package/scaffold/skills/storyboard-core/SKILL.md +249 -0
- package/scaffold/skills/tools/SKILL.md +932 -0
- package/scaffold/skills/web-perf/SKILL.md +201 -0
- package/scaffold/skills/worktree/SKILL.md +44 -35
- package/scaffold/{agents/terminal-agent.agent.md → terminal-agent.agent.md} +83 -16
- package/src/internals/CommandPalette/CommandPalette.jsx +0 -6
- package/toolbar.config.json +1 -0
- package/scaffold/skills/update-storyboard/SKILL.md +0 -16
- package/scaffold/skills/update-storyboard/update-storyboard-packages.sh +0 -26
package/dist/storyboard-ui.js
CHANGED
|
@@ -11573,7 +11573,7 @@ function At() {
|
|
|
11573
11573
|
console.error("[storyboard] Error in tool state subscriber:", t);
|
|
11574
11574
|
}
|
|
11575
11575
|
}
|
|
11576
|
-
const Fr = { "command-toolbar": { position: "bottom-right", layout: "row" }, "canvas-toolbar": { position: "bottom-left", layout: "row" }, "command-palette": { position: "command-menu", layout: "list" } }, Wr = { dark: "github-dark-dimmed", light: "github" }, Ur = { "hide-chrome": { ariaLabel: "Hide toolbars", icon: "primer/light-bulb", render: "button", surface: "command-toolbar", handler: "core:hide-chrome", modes: ["*"], prod: !0, shortcut: { key: ".", label: "cmd ." }, hideInCommandPalette: [".*"], alwaysVisible: !0 }, flows: { label: "Flows", ariaLabel: "Switch flow", icon: "feather/fast-forward", render: "menu", surface: "command-toolbar", modes: ["*"], prod: !0, menuWidth: "280px", handler: "core:flows", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"] }, theme: { label: "Theme", ariaLabel: "Switch theme", icon: "primer/sun", meta: { strokeWeight: 2 }, render: "menu", surface: "command-toolbar", handler: "core:theme", modes: ["*"], prod: !0, menuWidth: "260px", hideInCommandPalette: [".*"], options: [{ label: "System", value: "system" }, { label: "Light", value: "light" }, { label: "Light colorblind", value: "light_colorblind" }, { label: "Dark", value: "dark" }, { label: "Dark colorblind", value: "dark_colorblind" }, { label: "Dark high contrast", value: "dark_high_contrast" }, { label: "Dark Dimmed", value: "dark_dimmed" }] }, comments: { ariaLabel: "Comments", icon: "primer/comment", render: "button", surface: "*", handler: "core:comments", modes: ["*"], prod: !0, excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder"] }, inspector: { ariaLabel: "Inspect components", icon: "iconoir/square-dashed", render: "sidepanel", surface: "command-toolbar", sidepanel: "inspector", handler: "core:inspector", modes: ["*"], prod: !0, excludeRoutes: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], meta: { strokeWeight: 2, scale: 1.1 }, shortcut: { key: "i", label: "cmd + i" } }, create: { disabled: !0, label: "Create", ariaLabel: "Create", icon: "iconoir/plus-circle", meta: { strokeWeight: 2, scale: 1.1 }, render: "menu", surface: "command-toolbar", handler: "core:create", modes: ["*"], menuWidth: "290px", actions: [{ type: "header", label: "Create" }, { id: "workshop/create-prototype", label: "New prototype", type: "default", modes: ["*"], feature: "createPrototype" }, { id: "workshop/create-flow", label: "New flow", type: "default", modes: ["*"], feature: "createFlow", excludeRoutes: ["/canvas/", "/components/"] }, { id: "workshop/create-page", label: "New page", type: "default", modes: ["*"], feature: "createPage", excludeRoutes: ["/canvas/", "/components/"] }, { id: "workshop/create-canvas", label: "New canvas", type: "default", modes: ["*"], feature: "createCanvas" }, { type: "footer", label: "Only available in dev environment" }] }, autosync: { ariaLabel: "Auto sync", icon: "primer/sync", render: "menu", surface: "command-toolbar", handler: "core:autosync", modes: ["*"], menuWidth: "400px" }, "canvas-add-widget": { ariaLabel: "Add widget", icon: "iconoir/grid-plus", render: "menu", surface: "canvas-toolbar", handler: "core:canvas-add-widget", modes: ["*"], meta: { strokeWeight: 2, scale: 1.2 }, menuWidth: "300px", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: [".*"] }, "canvas-agents": { ariaLabel: "Add agent", label: "Add agent", icon: "agents", render: "menu", surface: "canvas-toolbar", handler: "core:canvas-agents", modes: ["*"], menuWidth: "220px", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: [".*"] }, "canvas-zoom": { ariaLabel: "Zoom controls", render: "canvas-zoom", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], prod: !0, hideInCommandPalette: [".*"] }, "canvas-zoom-to-fit": { ariaLabel: "Zoom to objects", label: "Zoom to objects", icon: "iconoir/square-3d-three-points", meta: { strokeWeight: 2, scale: 1.2 }, render: "canvas-zoom-to-fit", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], prod: !0, hideInCommandPalette: ["^(?!/canvas)"] }, "canvas-snap": { ariaLabel: "Snap to grid", label: "Snap to grid", labelOn: "Snap to grid (on)", labelOff: "Snap to grid (off)", icon: "primer/apps", meta: { strokeWeight: 1.5, scale: 1.2 }, render: "canvas-snap", surface: "canvas-toolbar", handler: "core:canvas-toolbar", gridSize: 40, modes: ["*"], hideInCommandPalette: ["^(?!/canvas)"] }, "canvas-undo-redo": { ariaLabel: "Undo and redo", render: "canvas-undo-redo", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], hideInCommandPalette: [".*"] }, workspace: { label: "Go to workspace", icon: "primer/home-fill", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "/" }, repository: { label: "Go to repository", icon: "primer/mark-github", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "" }, docs: { label: "Storyboard Docs", ariaLabel: "Storyboard Docs", icon: "primer/book", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "https://github.com/dfosco/storyboard/blob/main/DOCS.md" }, "submit-feedback": { label: "Submit feedback", icon: "primer/megaphone", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "https://github.com/dfosco/storyboard/issues/new?template=feedback.yml" }, devtools: { label: "Devtools", icon: "iconoir/wrench", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, handler: "core:devtools", hideFromCommandPaletteSearch: !0 }, "palette-theme": { label: "Switch theme", icon: "primer/sun", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, handler: "core:palette-theme" }, "feature-flags": { label: "Feature Flags", icon: "iconoir/white-flag", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, hideFromCommandPaletteSearch: !0, handler: "core:feature-flags" }, "hide-toolbars": { label: "Hide toolbars", icon: "primer/light-bulb", render: "button", surface: "command-palette", modes: ["*"], prod: !0, inlineAction: "toggle-chrome", shortcut: { key: ".", label: "cmd + ." } }, "command-palette": { ariaLabel: "Command palette", icon: "iconoir/key-command", meta: { strokeWeight: 2 }, render: "button", surface: "command-toolbar", size: "icon-2xl", handler: "core:command-palette", modes: ["*"], prod: !0, shortcut: { key: "k", label: "cmd + K" }, hideInCommandPalette: [".*"] } }, Gr = {
|
|
11576
|
+
const Fr = { "command-toolbar": { position: "bottom-right", layout: "row" }, "canvas-toolbar": { position: "bottom-left", layout: "row" }, "command-palette": { position: "command-menu", layout: "list" } }, Wr = { dark: "github-dark-dimmed", light: "github" }, Ur = { "hide-chrome": { ariaLabel: "Hide toolbars", icon: "primer/light-bulb", render: "button", surface: "command-toolbar", handler: "core:hide-chrome", modes: ["*"], prod: !0, shortcut: { key: ".", label: "cmd ." }, hideInCommandPalette: [".*"], alwaysVisible: !0 }, flows: { label: "Flows", ariaLabel: "Switch flow", icon: "feather/fast-forward", render: "menu", surface: "command-toolbar", modes: ["*"], prod: !0, menuWidth: "280px", handler: "core:flows", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"] }, theme: { label: "Theme", ariaLabel: "Switch theme", icon: "primer/sun", meta: { strokeWeight: 2 }, render: "menu", surface: "command-toolbar", handler: "core:theme", modes: ["*"], prod: !0, menuWidth: "260px", hideInCommandPalette: [".*"], options: [{ label: "System", value: "system" }, { label: "Light", value: "light" }, { label: "Light colorblind", value: "light_colorblind" }, { label: "Dark", value: "dark" }, { label: "Dark colorblind", value: "dark_colorblind" }, { label: "Dark high contrast", value: "dark_high_contrast" }, { label: "Dark Dimmed", value: "dark_dimmed" }] }, comments: { ariaLabel: "Comments", icon: "primer/comment", render: "button", surface: "*", handler: "core:comments", modes: ["*"], prod: !0, excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder"] }, inspector: { ariaLabel: "Inspect components", icon: "iconoir/square-dashed", render: "sidepanel", surface: "command-toolbar", sidepanel: "inspector", handler: "core:inspector", modes: ["*"], prod: !0, excludeRoutes: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], hideInCommandPalette: ["^/$", "^/workspace", "^/viewfinder", "/canvas/", "/components/", "/notebook/"], meta: { strokeWeight: 2, scale: 1.1 }, shortcut: { key: "i", label: "cmd + i" } }, create: { disabled: !0, label: "Create", ariaLabel: "Create", icon: "iconoir/plus-circle", meta: { strokeWeight: 2, scale: 1.1 }, render: "menu", surface: "command-toolbar", handler: "core:create", modes: ["*"], menuWidth: "290px", actions: [{ type: "header", label: "Create" }, { id: "workshop/create-prototype", label: "New prototype", type: "default", modes: ["*"], feature: "createPrototype" }, { id: "workshop/create-flow", label: "New flow", type: "default", modes: ["*"], feature: "createFlow", excludeRoutes: ["/canvas/", "/components/"] }, { id: "workshop/create-page", label: "New page", type: "default", modes: ["*"], feature: "createPage", excludeRoutes: ["/canvas/", "/components/"] }, { id: "workshop/create-canvas", label: "New canvas", type: "default", modes: ["*"], feature: "createCanvas" }, { type: "footer", label: "Only available in dev environment" }] }, autosync: { ariaLabel: "Auto sync", icon: "primer/sync", render: "menu", surface: "command-toolbar", handler: "core:autosync", modes: ["*"], menuWidth: "400px" }, "canvas-add-widget": { ariaLabel: "Add widget", icon: "iconoir/grid-plus", render: "menu", surface: "canvas-toolbar", handler: "core:canvas-add-widget", modes: ["*"], meta: { strokeWeight: 2, scale: 1.2 }, menuWidth: "300px", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: [".*"] }, "canvas-agents": { ariaLabel: "Add agent", label: "Add agent", icon: "agents", render: "menu", surface: "canvas-toolbar", handler: "core:canvas-agents", modes: ["*"], prod: !0, menuWidth: "220px", excludeRoutes: ["^/$", "^/workspace", "^/viewfinder"], hideInCommandPalette: [".*"] }, "canvas-zoom": { ariaLabel: "Zoom controls", render: "canvas-zoom", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], prod: !0, hideInCommandPalette: [".*"] }, "canvas-zoom-to-fit": { ariaLabel: "Zoom to objects", label: "Zoom to objects", icon: "iconoir/square-3d-three-points", meta: { strokeWeight: 2, scale: 1.2 }, render: "canvas-zoom-to-fit", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], prod: !0, hideInCommandPalette: ["^(?!/canvas)"] }, "canvas-snap": { ariaLabel: "Snap to grid", label: "Snap to grid", labelOn: "Snap to grid (on)", labelOff: "Snap to grid (off)", icon: "primer/apps", meta: { strokeWeight: 1.5, scale: 1.2 }, render: "canvas-snap", surface: "canvas-toolbar", handler: "core:canvas-toolbar", gridSize: 40, modes: ["*"], hideInCommandPalette: ["^(?!/canvas)"] }, "canvas-undo-redo": { ariaLabel: "Undo and redo", render: "canvas-undo-redo", surface: "canvas-toolbar", handler: "core:canvas-toolbar", modes: ["*"], hideInCommandPalette: [".*"] }, workspace: { label: "Go to workspace", icon: "primer/home-fill", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "/" }, repository: { label: "Go to repository", icon: "primer/mark-github", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "" }, docs: { label: "Storyboard Docs", ariaLabel: "Storyboard Docs", icon: "primer/book", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "https://github.com/dfosco/storyboard/blob/main/DOCS.md" }, "submit-feedback": { label: "Submit feedback", icon: "primer/megaphone", render: "link", surface: "command-palette", modes: ["*"], prod: !0, url: "https://github.com/dfosco/storyboard/issues/new?template=feedback.yml" }, devtools: { label: "Devtools", icon: "iconoir/wrench", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, handler: "core:devtools", hideFromCommandPaletteSearch: !0 }, "palette-theme": { label: "Switch theme", icon: "primer/sun", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, handler: "core:palette-theme" }, "feature-flags": { label: "Feature Flags", icon: "iconoir/white-flag", render: "submenu", surface: "command-palette", modes: ["*"], prod: !0, hideFromCommandPaletteSearch: !0, handler: "core:feature-flags" }, "hide-toolbars": { label: "Hide toolbars", icon: "primer/light-bulb", render: "button", surface: "command-palette", modes: ["*"], prod: !0, inlineAction: "toggle-chrome", shortcut: { key: ".", label: "cmd + ." } }, "command-palette": { ariaLabel: "Command palette", icon: "iconoir/key-command", meta: { strokeWeight: 2 }, render: "button", surface: "command-toolbar", size: "icon-2xl", handler: "core:command-palette", modes: ["*"], prod: !0, shortcut: { key: "k", label: "cmd + K" }, hideInCommandPalette: [".*"] } }, Gr = {
|
|
11577
11577
|
surfaces: Fr,
|
|
11578
11578
|
highlighting: Wr,
|
|
11579
11579
|
tools: Ur
|
package/package.json
CHANGED
package/scaffold/manifest.json
CHANGED
|
@@ -27,10 +27,26 @@
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"source": "scaffold/skills/",
|
|
30
|
-
"target": ".
|
|
30
|
+
"target": ".agents/skills/",
|
|
31
31
|
"mode": "updateable",
|
|
32
32
|
"directory": true
|
|
33
33
|
},
|
|
34
|
+
{
|
|
35
|
+
"source": "scaffold/roles/",
|
|
36
|
+
"target": ".agents/roles/",
|
|
37
|
+
"mode": "updateable",
|
|
38
|
+
"directory": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"source": "scaffold/prompt-agent.agent.md",
|
|
42
|
+
"target": ".agents/prompt-agent.agent.md",
|
|
43
|
+
"mode": "updateable"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"source": "scaffold/terminal-agent.agent.md",
|
|
47
|
+
"target": ".agents/terminal-agent.agent.md",
|
|
48
|
+
"mode": "updateable"
|
|
49
|
+
},
|
|
34
50
|
{
|
|
35
51
|
"source": "scaffold/deploy.yml",
|
|
36
52
|
"target": ".github/workflows/deploy.yml",
|
|
@@ -16,6 +16,8 @@ You are a **single-shot task agent** spawned by a prompt widget on a Storyboard
|
|
|
16
16
|
|
|
17
17
|
**You CANNOT signal completion unless the user can see your result on the canvas.** This is non-negotiable. If you did work but the canvas looks the same as before, you failed.
|
|
18
18
|
|
|
19
|
+
**Exception — messaging actions:** When your task is sending a message to a peer (via `storyboard terminal send` or the messaging bus), the message itself IS the deliverable. **Do NOT create a widget on the canvas to echo or summarize the message.** Just send the message, save your output, and signal done. Canvas widgets are for task results, not for reflecting conversational messages back onto the board. Only create a canvas widget for a messaging action if the message content explicitly calls for it (e.g., "send this result and post it on the canvas too") or if you're outputting a completed task result that happens to also be sent as a message.
|
|
20
|
+
|
|
19
21
|
Before signaling done, you must have done **at least one** of:
|
|
20
22
|
|
|
21
23
|
1. **Created a new widget** on the canvas (sticky note, markdown, story, etc.) connected to your prompt widget — showing the output, summary, or deliverable
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cluster Token Holder
|
|
3
|
+
type: transient
|
|
4
|
+
default: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Cluster Token
|
|
8
|
+
|
|
9
|
+
You currently **hold the cluster token** — you have speaking rights in the hub.
|
|
10
|
+
|
|
11
|
+
## What this means
|
|
12
|
+
|
|
13
|
+
- You can broadcast messages to the hub channel via `POST /_storyboard/messages/hub/send`.
|
|
14
|
+
- You can transfer the token to a peer via `POST /_storyboard/messages/hub/token` when you want them to act autonomously.
|
|
15
|
+
- Other hub members cannot broadcast until they hold the token or receive a message token for a specific request.
|
|
16
|
+
|
|
17
|
+
## What this does NOT mean
|
|
18
|
+
|
|
19
|
+
- Holding the cluster token does **not** make you the leader. You **cannot** set the hub goal or signal finality — those are leader-only actions tied to the role, not the token.
|
|
20
|
+
- If you are a member holding the token, use it to complete delegated work, then transfer it back to the leader.
|
|
21
|
+
|
|
22
|
+
## When you lose the token
|
|
23
|
+
|
|
24
|
+
- You will be notified via a `hub:token:transferred` event in the channel log.
|
|
25
|
+
- After losing the token, wait for a message token (ordered response request) before acting.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Leader
|
|
3
|
+
type: unique
|
|
4
|
+
default: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Leader Role
|
|
8
|
+
|
|
9
|
+
You are the **leader** of this hub. You coordinate the conversation and own completion.
|
|
10
|
+
|
|
11
|
+
## Responsibilities
|
|
12
|
+
|
|
13
|
+
1. **Receive user requests** — when a user message arrives, you define the hub goal and orchestrate work across hub members.
|
|
14
|
+
2. **Set the goal** — use `storyboard hub goal --hub <hubId> --goal "..."` to set the high-level objective. This is a leader-only action (not tied to the hub token).
|
|
15
|
+
3. **Delegate with tokens** — when you hold the hub token, send requests to peers via `storyboard hub send --hub <hubId> --sender <yourId> --body "..."`. You can transfer the token to a peer with `storyboard hub token --hub <hubId> --to <peerId>` for autonomous work.
|
|
16
|
+
4. **Aggregate responses** — poll `storyboard messages read --channel <channel> --since <lastId>` to collect peer responses as message tokens resolve.
|
|
17
|
+
5. **Own completion** — you decide when the task is done. Render the final result on the canvas (add or update widgets), then signal finality via `storyboard hub conversation finality --hub <hubId> --sender <yourId>`. Finality is a leader-only action — it does not require the hub token.
|
|
18
|
+
|
|
19
|
+
## Hub Protocol
|
|
20
|
+
|
|
21
|
+
- Read your hub context from the terminal config file at `.storyboard/terminals/{yourWidgetId}.json` — the `hubs` array lists your peers, your channel, and whether you hold the hub token.
|
|
22
|
+
- Start a conversation with `storyboard hub conversation start --hub <hubId> --sender <yourId>` before sending your first hub message.
|
|
23
|
+
- Use `storyboard hub goal --hub <hubId> --goal "..."` to set the high-level objective visible to all peers.
|
|
24
|
+
- Poll `storyboard messages read --channel <channel> --since <lastId>` every 2 seconds to check for new messages.
|
|
25
|
+
- After all peer responses arrive, synthesize and act. If the task is complete, render output on the canvas and call finality.
|
|
26
|
+
- You may reopen a finalized conversation with `storyboard hub conversation reopen --hub <hubId> --sender <yourId>` if new context arrives.
|
|
27
|
+
|
|
28
|
+
## Canvas Output
|
|
29
|
+
|
|
30
|
+
- **Iterate, don't duplicate.** When a peer provides feedback on an existing canvas widget (markdown, sticky note, component, etc.), **update that widget** using `storyboard canvas update <id>` — do not create a new one. Only create a new widget when the output is genuinely a separate deliverable (e.g. a second document the user asked for).
|
|
31
|
+
- Use your judgment: if the user asked for "a markdown document," there should be exactly one markdown widget at the end — refined through rounds of feedback, not a trail of drafts.
|
|
32
|
+
|
|
33
|
+
## Important
|
|
34
|
+
|
|
35
|
+
- **Never signal finality before the canvas reflects the outcome.** Finality means "the user can see the result."
|
|
36
|
+
- If a peer times out, skip them and proceed with available responses.
|
|
37
|
+
- Keep messages concise — peers see the full conversation log.
|
|
38
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Member
|
|
3
|
+
type: shared
|
|
4
|
+
default: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Member Role
|
|
8
|
+
|
|
9
|
+
You are a **member** of this hub. You contribute work when the leader delegates to you.
|
|
10
|
+
|
|
11
|
+
## Responsibilities
|
|
12
|
+
|
|
13
|
+
1. **Wait for your token** — monitor your message token status by polling `storyboard messages read --channel <channel> --since <lastId>`. When a `hub:message:request` arrives and your token is active, respond.
|
|
14
|
+
2. **Respond promptly** — read the full conversation context, do your work, then respond via `storyboard hub respond --hub <hubId> --sender <yourId> --body "..."` with your analysis, implementation, or feedback.
|
|
15
|
+
3. **Report clearly** — include what you did, what you found, or what you recommend. The leader aggregates responses from all peers.
|
|
16
|
+
4. **Defer finality** — never signal conversation finality. The leader owns completion decisions and canvas rendering.
|
|
17
|
+
|
|
18
|
+
## Hub Protocol
|
|
19
|
+
|
|
20
|
+
- Read your hub context from `.storyboard/terminals/{yourWidgetId}.json` — the `hubs` array tells you your role, peers, channel, and active token status.
|
|
21
|
+
- Poll `storyboard messages read --channel <channel> --since <lastId>` every 2 seconds.
|
|
22
|
+
- When you see a `hub:message:request` event where your widget is the active token holder, process the request and respond.
|
|
23
|
+
- Your response automatically advances the token to the next peer.
|
|
24
|
+
- If you receive the hub token (via `hub:token:transferred`), you may send messages to the channel, but defer major decisions to the leader.
|
|
25
|
+
|
|
26
|
+
## Important
|
|
27
|
+
|
|
28
|
+
- **Do not create output widgets on the canvas unless explicitly asked by the leader.** The leader renders final results.
|
|
29
|
+
- **Iterate, don't duplicate.** If the leader asks you to refine or improve a widget that already exists on the canvas, update it with `storyboard canvas update <id>` — do not create a new widget alongside it.
|
|
30
|
+
- Keep responses focused and concise — the leader reads all peer responses to synthesize.
|
|
31
|
+
- If you need clarification, include your question in your response body — the leader will follow up.
|
|
32
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Starter
|
|
3
|
+
type: unique
|
|
4
|
+
default: false
|
|
5
|
+
transient: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Starter Role
|
|
9
|
+
|
|
10
|
+
You are the **starter** of a hub. Your job is to spawn real, autonomous agent sessions on the canvas, connect them, and kick off the conversation. Each agent widget you create becomes an **independent AI process** — its own tmux session running its own CLI agent. Once the hub is running, your role transitions to **leader**.
|
|
11
|
+
|
|
12
|
+
## When This Role Is Assigned
|
|
13
|
+
|
|
14
|
+
This role is injected when the user asks you to create a hub (e.g., "create a hub for…", "spawn a hub with…", "Hub: [task]"). It provides the context you need to bootstrap the hub without guessing.
|
|
15
|
+
|
|
16
|
+
## Hub Creation Procedure
|
|
17
|
+
|
|
18
|
+
### 1. Determine Composition
|
|
19
|
+
|
|
20
|
+
Based on the user's request, decide:
|
|
21
|
+
- How many agents are needed (minimum 2 total, including yourself)
|
|
22
|
+
- What each agent's specialization/name should be
|
|
23
|
+
- Keep it small (2–5 agents is typical)
|
|
24
|
+
|
|
25
|
+
### 2. Create Agent Widgets and Connectors
|
|
26
|
+
|
|
27
|
+
Use `storyboard canvas batch` to create all agents and connect them in one call. Use `$0`, `$1`, etc. to reference widget IDs from earlier operations:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
storyboard canvas batch --canvas "$STORYBOARD_CANVAS_ID" --ops '[
|
|
31
|
+
{ "op": "create-widget", "type": "agent", "props": { "prettyName": "<agent-name>", "agentId": "copilot" } },
|
|
32
|
+
{ "op": "create-connector", "startWidgetId": "'"$STORYBOARD_WIDGET_ID"'", "startAnchor": "right", "endWidgetId": "$0", "endAnchor": "left" }
|
|
33
|
+
]'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For multiple agents, add more `create-widget` + `create-connector` pairs. Reference `$0` for the first widget, `$1` for the second, etc.
|
|
37
|
+
|
|
38
|
+
### 3. Wait for Agent Sessions
|
|
39
|
+
|
|
40
|
+
Agent widgets auto-start when the browser renders them — the TerminalWidget connects via WebSocket and the terminal-server launches the agent using the `startupCommand` from the widget's `agentId`. **You do not need to call `agent/spawn`** — just wait a few seconds for the browser to render the new widgets and for the agents to boot.
|
|
41
|
+
|
|
42
|
+
### 4. Enable Broadcast
|
|
43
|
+
|
|
44
|
+
Turn on messaging across the full hub:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
storyboard canvas broadcast \
|
|
48
|
+
--canvas "$STORYBOARD_CANVAS_ID" \
|
|
49
|
+
--widget "$STORYBOARD_WIDGET_ID" \
|
|
50
|
+
--mode two-way \
|
|
51
|
+
--pass-through
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 5. Start Conversation
|
|
55
|
+
|
|
56
|
+
Wait 2–3 seconds for hub materialization, then read your hub ID and start a conversation:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Read hub ID from terminal config
|
|
60
|
+
HUB_ID=$(cat .storyboard/terminals/$(echo $STORYBOARD_WIDGET_ID | tr '-' '_').json 2>/dev/null | jq -r '.hubs[0].hubId // empty')
|
|
61
|
+
|
|
62
|
+
# If hub ID isn't available yet, check the hub state endpoint
|
|
63
|
+
if [ -z "$HUB_ID" ]; then
|
|
64
|
+
HUB_ID=$(storyboard hub state --canvas "$STORYBOARD_CANVAS_ID" 2>/dev/null | jq -r '.hubs[0].hubId // empty')
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Start conversation
|
|
68
|
+
storyboard hub conversation start --hub "$HUB_ID" --sender "$STORYBOARD_WIDGET_ID"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## After Hub Creation
|
|
72
|
+
|
|
73
|
+
Once all agents are spawned and the conversation has started, your role automatically transitions to **leader**. Read `.agents/roles/leader.role.md` for your ongoing responsibilities.
|
|
74
|
+
|
|
75
|
+
## Guardrails
|
|
76
|
+
|
|
77
|
+
- **Explicit only** — only create a hub when the user explicitly asks ("create a hub", "spawn a hub", "Hub: [task]")
|
|
78
|
+
- **Max 5 agents** — keep hubs small and focused unless the user specifies otherwise
|
|
79
|
+
- **You are the leader** — you always become the hub leader; spawned agents are members
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture-scanner
|
|
3
|
+
description: Architecture scanner and documentation generator. Use when scanning the codebase architecture, updating architecture docs, or generating architecture documentation.
|
|
4
|
+
metadata:
|
|
5
|
+
author: Daniel Fosco
|
|
6
|
+
version: "2026.3.09"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Architecture Scanner Skill
|
|
10
|
+
|
|
11
|
+
> Triggered by: "scan the codebase architecture", "update the architecture", "update arch", "generate architecture docs", "scan arch", "full update", "full architecture update", "full refresh architecture"
|
|
12
|
+
|
|
13
|
+
## What This Does
|
|
14
|
+
|
|
15
|
+
Generates documentation files in `.agents/architecture/` that describe every architecturally significant file in the codebase. The system has two layers:
|
|
16
|
+
|
|
17
|
+
- **`architecture.index.md`** — The architectural overview. Groups files by category (ordered and configured via the `categories` array in `files.json`) and includes prose summaries. Categories with `"priority": "critical"` get 2-3x more detailed overviews. A reader should be able to understand the system's architecture from this file alone.
|
|
18
|
+
- **Per-file docs** (`{filepath}.md`) — Detailed documentation for individual files, including what they do, how they work (with code samples), their dependencies, and dependents. Every file reference is cross-linked to its architecture doc.
|
|
19
|
+
|
|
20
|
+
## How to Execute
|
|
21
|
+
|
|
22
|
+
### Step 0: Inventory package topology (required)
|
|
23
|
+
|
|
24
|
+
Before discovery, identify **every** `package.json` in the repo (root + workspace packages), excluding `node_modules`, and read each manifest:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
find . -name package.json \
|
|
28
|
+
-not -path './node_modules/*' \
|
|
29
|
+
-not -path './packages/*/node_modules/*' \
|
|
30
|
+
-not -path './worktrees/*' \
|
|
31
|
+
| sort
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use this inventory to build your architecture mental model (package names, responsibilities, and internal package dependencies). This step is mandatory and prevents stale assumptions like "the repo only has two packages."
|
|
35
|
+
|
|
36
|
+
### Step 1: Discover files
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
.agents/skills/architecture-scanner/scan.sh --discover
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This scans the repo using discovery rules and creates or updates `files.json` in the skill folder. If `files.json` doesn't exist yet, it creates it with default priorities. If it already exists, it **adds new files** and **removes deleted files**, but **preserves user-set `importance` values** — those are never overwritten.
|
|
43
|
+
|
|
44
|
+
Discovery includes the root `package.json` and every workspace package manifest at `packages/*/package.json`, so package-level architecture is always represented in the docs.
|
|
45
|
+
|
|
46
|
+
Run this first to ensure the file list is current.
|
|
47
|
+
|
|
48
|
+
### Step 2: Determine what needs to be done
|
|
49
|
+
|
|
50
|
+
Run `--stale` to get the incremental manifest. This is the **default for all runs** unless architecture docs don't exist yet.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
.agents/skills/architecture-scanner/scan.sh --stale
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This uses **git history** to detect changes: it finds the most recent commit that touched `.agents/architecture/`, then diffs against `HEAD` to identify changed source files, and also includes uncommitted (staged/unstaged) changes.
|
|
57
|
+
|
|
58
|
+
`--stale` returns a JSON object with three incremental buckets:
|
|
59
|
+
|
|
60
|
+
- **`files`** — docs to create/update:
|
|
61
|
+
- `"missing"` = source exists but doc does not (added/new file docs)
|
|
62
|
+
- `"stale"` = source changed since last architecture update
|
|
63
|
+
- **`removed`** — docs to delete because source was removed/moved or is no longer tracked
|
|
64
|
+
- **`index`** — whether `architecture.index.md` should be regenerated (`"status": "stale"`) and why
|
|
65
|
+
|
|
66
|
+
If `files` and `removed` are both empty and `index.status` is `"fresh"`, docs are up to date.
|
|
67
|
+
|
|
68
|
+
**When `--stale` suggests a full scan:** If more than 50% of documented files need updates, output includes `"suggestion": "full_scan"` and a message. In this case, switch to a full scan:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
.agents/skills/architecture-scanner/scan.sh --manifest
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can also force a full scan explicitly with:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
.agents/skills/architecture-scanner/scan.sh --full
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This outputs every non-low file regardless of change status. Use this for:
|
|
81
|
+
- **First-time runs** (no architecture docs exist yet)
|
|
82
|
+
- **Template changes** (when the doc format itself changed, so all docs need regeneration)
|
|
83
|
+
- **When `--stale` suggests it** (many files changed across multiple commits)
|
|
84
|
+
- **When the user explicitly requests a full scan**
|
|
85
|
+
- **When the user says natural-language variants like "full update" / "full refresh"**
|
|
86
|
+
|
|
87
|
+
**Low importance files are excluded from both manifests and should NOT get architecture docs.**
|
|
88
|
+
|
|
89
|
+
### Step 3: Generate or update documentation for each file
|
|
90
|
+
|
|
91
|
+
For each entry in `files` (from `--stale`) or each entry in the full manifest (`--manifest`/`--full`), produce a markdown file at:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
.agents/architecture/{filepath}.md
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For example:
|
|
98
|
+
- `src/storyboard/core/loader.js` → `.agents/architecture/src/storyboard/core/loader.js.md`
|
|
99
|
+
- `vite.config.js` → `.agents/architecture/vite.config.js.md`
|
|
100
|
+
|
|
101
|
+
#### For NEW files (status `"missing"`, or first full scan):
|
|
102
|
+
|
|
103
|
+
Create subdirectories as needed with `mkdir -p`. Use the **create** tool to write the doc file. The manifest's `doc` field contains the exact relative path to use.
|
|
104
|
+
|
|
105
|
+
#### For STALE files (status `"stale"`):
|
|
106
|
+
|
|
107
|
+
The doc already exists but the source file has changed. Follow this process:
|
|
108
|
+
|
|
109
|
+
1. **Read the source file** to understand what changed
|
|
110
|
+
2. **Read the existing doc file** to see what's already documented
|
|
111
|
+
3. **Use the edit tool** to update only the sections that are affected by the source changes — preserve the existing structure and any manually-added context that's still accurate
|
|
112
|
+
4. Do NOT recreate the file from scratch — make surgical updates
|
|
113
|
+
|
|
114
|
+
#### For REMOVED files (status `"removed"` in `removed` array):
|
|
115
|
+
|
|
116
|
+
Delete the stale architecture doc file referenced by the entry's `doc` field. If any docs are deleted, regenerate the index in Step 4.
|
|
117
|
+
|
|
118
|
+
**What to check when updating a stale doc:**
|
|
119
|
+
- Has the file's purpose changed? → Update **Goal**
|
|
120
|
+
- Have exports/functions/components changed? → Update **Composition**
|
|
121
|
+
- Have imports changed? → Update **Dependencies**
|
|
122
|
+
- Have downstream consumers changed? → Update **Dependents** (re-grep)
|
|
123
|
+
- Any new edge cases or behavior changes? → Update **Notes**
|
|
124
|
+
|
|
125
|
+
#### Doc template
|
|
126
|
+
|
|
127
|
+
Each doc file MUST follow this template:
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
# `{filepath}`
|
|
131
|
+
|
|
132
|
+
<!--
|
|
133
|
+
source: {filepath}
|
|
134
|
+
category: {category}
|
|
135
|
+
importance: {importance}
|
|
136
|
+
-->
|
|
137
|
+
|
|
138
|
+
> [← Architecture Index](../architecture.index.md)
|
|
139
|
+
|
|
140
|
+
(Adjust the relative path based on nesting depth — e.g., `../../architecture.index.md` for files 2 levels deep like `src/storyboard/core/loader.js.md`)
|
|
141
|
+
|
|
142
|
+
## Goal
|
|
143
|
+
|
|
144
|
+
{1-2 paragraph architectural summary: what this file does, why it exists, and how it fits into the broader system. This should be readable by someone unfamiliar with the codebase.}
|
|
145
|
+
|
|
146
|
+
## Composition
|
|
147
|
+
|
|
148
|
+
{Detailed description of the file's structure: what it exports, key functions/components, internal organization, type signatures, parameter details. Include code samples from the actual source file to illustrate key exports, signatures, and patterns — don't just describe them in prose.}
|
|
149
|
+
|
|
150
|
+
## Dependencies
|
|
151
|
+
|
|
152
|
+
{List of significant imports — what this file depends on, and why}
|
|
153
|
+
|
|
154
|
+
## Dependents
|
|
155
|
+
|
|
156
|
+
{What depends on this file — who imports it, derived by grepping}
|
|
157
|
+
|
|
158
|
+
## Notes
|
|
159
|
+
|
|
160
|
+
{Any non-obvious behavior, edge cases, circular dependency considerations, or architectural decisions worth noting. Omit this section if there's nothing notable.}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Rules for writing docs:**
|
|
164
|
+
- Read each file's actual content before writing its doc — do NOT guess
|
|
165
|
+
- The **Goal** section is the most important — it should be a clear, standalone summary (1-2 paragraphs) that anyone can read without expanding the details
|
|
166
|
+
- The remaining sections (Composition, Dependencies, Dependents, Notes) are all top-level headings — do NOT wrap them in a `<details>` element
|
|
167
|
+
- **Include code samples** — when describing exports, function signatures, component props, data shapes, or usage patterns, include actual code snippets from the source file. This makes docs scannable and concrete.
|
|
168
|
+
- **Cross-link file references** — every time a file path is mentioned anywhere in the documentation (Goal, Composition, Dependencies, Dependents, Notes, or the index), it MUST be a markdown hyperlink to that file's architecture doc. Use relative paths from the current doc to the target doc. For example, in a doc at `.agents/architecture/src/storyboard/context.jsx.md`, a reference to the loader would be written as [`src/storyboard/core/loader.js`](./core/loader.js.md). If the referenced file has no architecture doc (e.g., low-importance files), link to the source file on GitHub or leave it as plain text with a backtick code span.
|
|
169
|
+
- The "Dependents" section should be derived by grepping for imports of this file
|
|
170
|
+
- For `medium` importance files, keep it concise — shorter Goal, fewer code samples
|
|
171
|
+
- For `high` importance files, write a thorough Goal (2 paragraphs), comprehensive Composition with multiple code samples, and complete dependency/dependent lists
|
|
172
|
+
|
|
173
|
+
### Step 4: Generate the index
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
.agents/skills/architecture-scanner/scan.sh --index
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
This reads the generated doc files and creates `architecture.index.md` with a categorized table of contents.
|
|
180
|
+
|
|
181
|
+
Run this whenever `--stale` reports `index.status: "stale"` (including when files were changed, added, or removed).
|
|
182
|
+
|
|
183
|
+
**After the script generates the index**, you MUST enhance it by adding a prose overview for each category section. Read the `categories` array in `files.json` to determine category order, display names, and priority levels. The final index should follow this structure:
|
|
184
|
+
|
|
185
|
+
```markdown
|
|
186
|
+
# Architecture Index
|
|
187
|
+
|
|
188
|
+
> Auto-generated documentation of architecturally significant files.
|
|
189
|
+
> Run `scan the codebase architecture` to regenerate.
|
|
190
|
+
|
|
191
|
+
## {Category Name}
|
|
192
|
+
|
|
193
|
+
{Overview paragraph(s) — see priority rules below}
|
|
194
|
+
|
|
195
|
+
- [`path/to/file.js`](./path/to/file.js.md) — {one-line description}
|
|
196
|
+
- [`path/to/other.js`](./path/to/other.js.md) — {one-line description}
|
|
197
|
+
|
|
198
|
+
## {Next Category}
|
|
199
|
+
...
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Category configuration** is defined in `files.json` under the `categories` array:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
"categories": [
|
|
206
|
+
{ "id": "storyboard", "name": "Storyboard System", "priority": "critical", "order": 1 },
|
|
207
|
+
{ "id": "config", "name": "Configuration", "priority": "normal", "order": 5 }
|
|
208
|
+
]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
- **`order`** — Controls the display order of categories in the index (ascending)
|
|
212
|
+
- **`name`** — The display heading used in the index (`## {name}`)
|
|
213
|
+
- **`priority`** — Controls the depth of the overview:
|
|
214
|
+
- **`critical`** — The overview for this category should be 2-3x longer than normal. Write 3-4 paragraphs covering key concepts, data flow, architectural decisions, and how the parts interact. Include code samples or diagrams in the overview itself when helpful. These are the categories a new contributor must deeply understand.
|
|
215
|
+
- **`normal`** — Standard 1-2 paragraph overview explaining purpose, key patterns, and relationships between files.
|
|
216
|
+
|
|
217
|
+
**Rules for the index:**
|
|
218
|
+
- Category sections are ordered by the `order` field in the `categories` array
|
|
219
|
+
- Each category section gets an architectural overview — length determined by `priority`
|
|
220
|
+
- Each link gets a brief one-line description (pulled from the file doc's Goal section)
|
|
221
|
+
- **Cross-link file references** — every file path mentioned in the overview text must link to its architecture doc (same rule as per-file docs)
|
|
222
|
+
- The opening architecture narrative must reflect the **full package inventory** from Step 0 (all `package.json` files), not just the packages currently documented in one category
|
|
223
|
+
- Write for someone unfamiliar with the codebase — the index is the entry point to understanding the architecture
|
|
224
|
+
|
|
225
|
+
### Step 5: Verify
|
|
226
|
+
|
|
227
|
+
- Confirm every file in the manifest has a corresponding `.md` doc
|
|
228
|
+
- Confirm every entry in `removed` had its doc file deleted
|
|
229
|
+
- Confirm `architecture.index.md` links to all docs
|
|
230
|
+
- Confirm every doc has a backlink to the index
|
|
231
|
+
|
|
232
|
+
### Step 6: Commit
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
git add .agents/architecture/ .agents/skills/architecture-scanner/
|
|
236
|
+
git commit -m "Update architecture documentation"
|
|
237
|
+
```
|