@wrongstack/core 0.277.2 → 0.280.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.
Files changed (83) hide show
  1. package/dist/{agent-bridge-BFJ2ODzI.d.ts → agent-bridge-DXC6QDJ4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-BimKihiC.d.ts → agent-subagent-runner-PoqNKiR4.d.ts} +563 -471
  3. package/dist/{compactor-D3BGw26y.d.ts → compactor-U3agvUIG.d.ts} +1 -1
  4. package/dist/{config-DAOjriz9.d.ts → config-Cr3312zc.d.ts} +102 -4
  5. package/dist/coordination/index.d.ts +1087 -998
  6. package/dist/coordination/index.js +12235 -12052
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +31 -30
  9. package/dist/defaults/index.js +403 -189
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{brain-CCfuEOdp.d.ts → events-Bs2fmldo.d.ts} +117 -112
  12. package/dist/execution/index.d.ts +27 -19
  13. package/dist/execution/index.js +216 -63
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/execution/prompt-enhancer.d.ts +1 -1
  16. package/dist/execution/prompt-enhancer.js.map +1 -1
  17. package/dist/extension/index.d.ts +8 -7
  18. package/dist/{global-mailbox-Dr4cTKqL.d.ts → global-mailbox-Ct7IorLJ.d.ts} +84 -6
  19. package/dist/{goal-store-C1uH4srH.d.ts → goal-store-C4F6DjC0.d.ts} +1 -1
  20. package/dist/hq/index.d.ts +504 -7
  21. package/dist/hq/index.js +1069 -20
  22. package/dist/hq/index.js.map +1 -1
  23. package/dist/{index-DJXj-dcr.d.ts → index-kidebiDh.d.ts} +8 -5
  24. package/dist/{index-cMEmzCVN.d.ts → index-nP09-oP2.d.ts} +2 -2
  25. package/dist/index.d.ts +153 -76
  26. package/dist/index.js +5791 -3163
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +7 -6
  29. package/dist/kernel/index.d.ts +14 -13
  30. package/dist/kernel/index.js +31 -15
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mailbox-types-DTl7bRH3.d.ts → mailbox-types-BGZWrYTJ.d.ts} +38 -0
  33. package/dist/{mcp-servers-CFb60-pH.d.ts → mcp-servers-D910X5_r.d.ts} +3 -3
  34. package/dist/models/index.d.ts +5 -5
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{models-registry-5Ufn7f2m.d.ts → models-registry-CLkoOcHk.d.ts} +1 -1
  37. package/dist/{multi-agent-coordinator-CcrcncvG.d.ts → multi-agent-coordinator-CieyUoEL.d.ts} +1 -1
  38. package/dist/{null-fleet-bus-C9KsYyrI.d.ts → null-fleet-bus-DkdmZJ_W.d.ts} +464 -464
  39. package/dist/observability/index.d.ts +3 -2
  40. package/dist/{path-resolver-CEeX9I7O.d.ts → path-resolver-XfZ9eLxG.d.ts} +3 -3
  41. package/dist/{permission-DbsGOA1C.d.ts → permission-Dx6dIqS2.d.ts} +2 -7
  42. package/dist/{permission-policy-BpEea3r7.d.ts → permission-policy-C8vJcnX5.d.ts} +2 -2
  43. package/dist/{pipeline-CEjBjzVA.d.ts → pipeline-BwAP21_4.d.ts} +9 -4
  44. package/dist/{provider-model-resolve-BpfXp3Jj.d.ts → provider-model-resolve-CwQNZWt_.d.ts} +3 -3
  45. package/dist/{provider-runner-CnOSr5BN.d.ts → provider-runner-CYHFImzV.d.ts} +3 -3
  46. package/dist/{retry-policy-Git9WF6d.d.ts → retry-policy-D4feSLk3.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +11 -10
  48. package/dist/sdd/index.js +2 -2
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
  51. package/dist/{secret-vault-DDSMHqIm.d.ts → secret-vault-CImt2XrR.d.ts} +1 -1
  52. package/dist/security/index.d.ts +6 -5
  53. package/dist/security/index.js.map +1 -1
  54. package/dist/{selector-Cq72C0Oy.d.ts → selector-Dy-MzKp1.d.ts} +1 -1
  55. package/dist/{session-event-bridge-DG94B3Bk.d.ts → session-event-bridge-CqdiGnfU.d.ts} +1 -1
  56. package/dist/{session-reader-BzT-iMQT.d.ts → session-reader-Hk0WbNm9.d.ts} +1 -1
  57. package/dist/{skill-DGIXCtdv.d.ts → skill-DHniprNl.d.ts} +15 -1
  58. package/dist/skills/index.d.ts +472 -26
  59. package/dist/skills/index.js +872 -129
  60. package/dist/skills/index.js.map +1 -1
  61. package/dist/storage/index.d.ts +27 -14
  62. package/dist/storage/index.js +264 -85
  63. package/dist/storage/index.js.map +1 -1
  64. package/dist/{strategy-compactor-Bt_ZH6R0.d.ts → strategy-compactor-CQwhbErd.d.ts} +32 -17
  65. package/dist/{todos-checkpoint-CH1pcua9.d.ts → todos-checkpoint-Bk2uP7Ex.d.ts} +6 -6
  66. package/dist/{context-DPlA6kid.d.ts → tool-BkOgs_KL.d.ts} +306 -286
  67. package/dist/{tool-executor-SVFq7IOR.d.ts → tool-executor-SiE1wlZo.d.ts} +9 -9
  68. package/dist/tools/index.d.ts +2 -2
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/types/index.d.ts +22 -21
  71. package/dist/types/index.js +7 -9
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/index.d.ts +30 -4
  74. package/dist/utils/index.js +50 -1
  75. package/dist/utils/index.js.map +1 -1
  76. package/dist/{worktree-manager-C4YIf1Fa.d.ts → worktree-manager-BjOFF6bt.d.ts} +1 -1
  77. package/dist/{wstack-paths-_NrRovdr.d.ts → wstack-paths-CMl_cYgq.d.ts} +8 -0
  78. package/package.json +1 -1
  79. package/skills/mailbox-bridge/SKILL.md +1 -0
  80. package/skills/plugin-author/SKILL.md +350 -0
  81. package/skills/sdd/SKILL.md +134 -134
  82. package/skills/skill-creator/SKILL.md +45 -7
  83. package/skills/wrongstack-mailbox/SKILL.md +40 -21
@@ -1,4 +1,4 @@
1
- import { E as EventBus } from './brain-CCfuEOdp.js';
1
+ import { E as EventBus } from './events-Bs2fmldo.js';
2
2
 
3
3
  /**
4
4
  * Lifecycle of a single worktree handle.
@@ -9,6 +9,10 @@
9
9
  interface WstackPaths {
10
10
  /** ~/.wrongstack — global root. */
11
11
  globalRoot: string;
12
+ /** Absolute project root. */
13
+ projectRoot: string;
14
+ /** Home directory (~) — base for foreign tool state (~/.codex, ~/.agents, …). */
15
+ homeDir: string;
12
16
  /**
13
17
  * ~/.wrongstack — directory for user-global stateful config files
14
18
  * (mode.json, theme.json, …). Currently an alias for `globalRoot`;
@@ -24,6 +28,8 @@ interface WstackPaths {
24
28
  globalMemory: string;
25
29
  /** ~/.wrongstack/skills — user-global skills. */
26
30
  globalSkills: string;
31
+ /** ~/.claude/skills — user-global skills from foreign coding agents (Claude Code, Codex, …). Read-only. */
32
+ globalClaudeSkills: string;
27
33
  /** ~/.wrongstack/design-kits — user-global Design Studio kits. */
28
34
  globalDesignKits: string;
29
35
  /** ~/.wrongstack/prompts — user-global prompt library. */
@@ -67,6 +73,8 @@ interface WstackPaths {
67
73
  inProjectAgentsFile: string;
68
74
  /** <project>/.wrongstack/skills — committed project skills. */
69
75
  inProjectSkills: string;
76
+ /** <project>/.claude/skills — project skills authored for foreign coding agents (Claude Code, …). Read-only. */
77
+ inProjectClaudeSkills: string;
70
78
  /** <project>/.wrongstack/prompts — committed project prompt library. */
71
79
  inProjectPrompts: string;
72
80
  /** <project>/.wrongstack/instructions — committed project instruction overrides. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/core",
3
- "version": "0.277.2",
3
+ "version": "0.280.0",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack core: kernel, types, defaults, and shared utilities for the WrongStack CLI agent.",
6
6
  "repository": {
@@ -126,6 +126,7 @@ require `Authorization: Bearer <token>`. All responses are JSON.
126
126
  |--------|------|-------|
127
127
  | POST | `/mailbox/send` | `GlobalMailbox.send` |
128
128
  | POST | `/mailbox/query` | `GlobalMailbox.query` |
129
+ | POST | `/mailbox/check` | convenience inbox check: direct/base/broadcast query plus optional read/completion batch ack |
129
130
  | POST | `/mailbox/ack` | `GlobalMailbox.ack` |
130
131
  | POST | `/mailbox/ack-many` | `GlobalMailbox.ackMany` (batch under one lock + rewrite) |
131
132
  | POST | `/mailbox/unread-count` | `GlobalMailbox.unreadCount` |
@@ -0,0 +1,350 @@
1
+ ---
2
+ name: plugin-author
3
+ description: |
4
+ Use this skill when creating, reviewing, or refactoring a WrongStack plugin
5
+ in `packages/plugins/`. Covers the Plugin interface, tool registration, config
6
+ schema, the H1 audit pattern (teardown + health), PluginAPI extension for host
7
+ data, and the entry-point registration steps (tsup, package.json, index.ts).
8
+ Triggers: user says "new plugin", "add a plugin", "plugin teardown", "plugin
9
+ health", "register a tool", "PluginAPI extension".
10
+ version: 1.0.0
11
+ ---
12
+
13
+ # Plugin Author — WrongStack
14
+
15
+ ## Overview
16
+
17
+ Guides the creation and maintenance of first-party plugins in
18
+ `packages/plugins/`. A plugin is a TypeScript module that implements
19
+ the `Plugin` interface from `@wrongstack/core`, registering tools,
20
+ hooks, slash commands, or pipelines into the agent's runtime.
21
+
22
+ There are currently **21 official plugins** in the suite:
23
+
24
+ | Plugin | Tools | Hooks | Stateful |
25
+ |--------|-------|-------|----------|
26
+ | `auto-doc` | `auto_doc` | — | ✅ teardown+health |
27
+ | `git-autocommit` | `git_autocommit` | — | ✅ teardown+health |
28
+ | `shell-check` | `shellcheck` | — | ✅ teardown+health |
29
+ | `cost-tracker` | `cost_summary`, `cost_reset`, `cost_export` | — | ✅ teardown+health |
30
+ | `file-watcher` | `watch_start`, `watch_stop`, `watch_list` | — | ✅ teardown+health |
31
+ | `cron` | `cron_schedule`, `cron_list`, `cron_cancel` | — | ✅ teardown+health |
32
+ | `template-engine` | `template_expand`, `template_render`, `template_create`, `template_list` | — | ✅ teardown+health |
33
+ | `semver-bump` | `semver_bump`, `semver_current`, `semver_changelog` | — | ✅ teardown+health |
34
+ | `secret-scanner` | `secret_scanner_status`, `secret_scanner_test` | `PreToolUse` + `PostToolUse` | ✅ teardown+health |
35
+ | `todo-tracker` | `todo_tracker_list/add/complete/drop/remove/pull/status` | — | ✅ teardown+health |
36
+ | `token-budget` | `token_budget_status` | `Stop` + `PostToolUse` | ✅ teardown+health |
37
+ | `lint-gate` | `lint_gate_status` | `PreToolUse` (`write\|edit`) | ✅ teardown+health |
38
+ | `branch-guard` | `branch_guard_status` | `PreToolUse` (`bash\|git_autocommit`) | ✅ teardown+health |
39
+ | `diff-summary` | `diff_summary_status` | `PostToolUse` (`write\|edit`) | ✅ teardown+health |
40
+ | `commit-validator` | `commit_validator_status` | `PreToolUse` (`bash\|git_autocommit`) | ✅ teardown+health |
41
+ | `format-on-save` | `format_on_save_status` | `PostToolUse` (`write\|edit`) | ✅ teardown+health |
42
+ | `test-runner-gate` | `test_gate_status` | `PostToolUse` (`write\|edit`) | ✅ teardown+health |
43
+ | `import-organizer` | `import_organizer_status` | `PostToolUse` (`write\|edit`) | ✅ teardown+health |
44
+ | `todo-listener` | `todo_listener_status` | `PostToolUse` (`todo`) | ✅ teardown+health |
45
+ | `session-recap` | `session_recap_status` | `Stop` | ✅ teardown+health |
46
+ | `spec-linker` | `spec_linker_status` | `PostToolUse` (`write\|edit`) | ✅ teardown+health |
47
+
48
+ ## Rules
49
+
50
+ 1. **Every plugin must implement `teardown()` and `health()`.** Even
51
+ stateless plugins (shell-check, semver-bump) add both — the teardown
52
+ logs a completion line with per-session counters, and `health()`
53
+ reports `ok: true` + counters for `/diag plugins`. This is the **H1
54
+ audit pattern** (see below).
55
+ 2. **State at module scope, not in the setup() closure.** The Plugin
56
+ interface does not thread state from `setup()` → `teardown()`. If
57
+ teardown needs to clean up a resource (timer, watcher, counter),
58
+ the reference must live at module scope. State in the setup
59
+ closure is unreachable from teardown and **leaks on reload**.
60
+ 3. **`setup()` is idempotent.** It must zero/clear state before
61
+ re-initializing. Calling `setup()` twice (e.g. across a hot-reload)
62
+ leaves a clean slate, not accumulated state.
63
+ 4. **`teardown()` never deletes on-disk state.** File-based plugins
64
+ (todo-tracker) leave the file in place — the user may return. Only
65
+ in-memory counters and resource handles (timers, watchers) are
66
+ cleaned up.
67
+ 5. **Tool names use `snake_case`.** Plugin-level tools registered via
68
+ `api.tools.register()` must be unique across the suite. The built-in
69
+ tools (`bash`, `write`, `read`, `edit`, `fetch`, `search`, `json`,
70
+ `todo`, `git`, etc.) are always present; don't collide.
71
+ 6. **`apiVersion` must satisfy `^0.1` (current kernel API = `0.1.10`).**
72
+ Bump only when the PluginAPI surface breaks. Additive changes (new
73
+ optional fields on PluginAPI) do NOT require a bump.
74
+ 7. **Config goes under `config.extensions['<plugin-name>']`**, not
75
+ `config.plugins`. The loader's `buildPluginOptions` merges both
76
+ surfaces; plugins read from `api.config.extensions`.
77
+
78
+ ## The Plugin interface
79
+
80
+ ```typescript
81
+ import type { Plugin } from '@wrongstack/core';
82
+
83
+ const plugin: Plugin = {
84
+ name: 'my-plugin',
85
+ version: '0.1.0',
86
+ description: 'One-line summary for wstack plugins list',
87
+ apiVersion: '^0.1.10',
88
+ capabilities: { tools: true }, // hints for /diag
89
+
90
+ // Optional: JSON Schema for config validation
91
+ defaultConfig: { enabled: true },
92
+ configSchema: {
93
+ type: 'object',
94
+ properties: {
95
+ enabled: { type: 'boolean', default: true },
96
+ },
97
+ },
98
+
99
+ // Called by the host to activate the plugin.
100
+ setup(api) { /* register tools, hooks, events */ },
101
+
102
+ // Called by the host during unload. Same api instance as setup.
103
+ teardown(api) { /* clear state, release resources, log */ },
104
+
105
+ // Called by /diag plugins. Return ok + message + counters.
106
+ async health() {
107
+ return { ok: true, message: 'healthy', invocationCount: 0 };
108
+ },
109
+ };
110
+
111
+ export default plugin;
112
+ ```
113
+
114
+ ## H1 audit pattern
115
+
116
+ After the 2026-06-03 audit found that several plugins leaked resources
117
+ on reload (timers, chokidar watchers, in-memory caches unreachable from
118
+ teardown), the following lifecycle pattern was formalized. **All 10
119
+ plugins follow it.**
120
+
121
+ ### 1. State at module scope
122
+
123
+ ```typescript
124
+ // ✅ Module scope — teardown can reach this
125
+ const state = {
126
+ invocationCount: 0,
127
+ timers: new Map<string, NodeJS.Timeout>(),
128
+ lastRun: null as null | { when: string; result: string },
129
+ };
130
+
131
+ // ❌ NEVER — setup closure, unreachable from teardown
132
+ setup(api) {
133
+ const timers = new Map(); // LEAKS on reload
134
+ }
135
+ ```
136
+
137
+ ### 2. Idempotent setup
138
+
139
+ ```typescript
140
+ setup(api) {
141
+ // Clear everything first, then re-init from config.
142
+ state.invocationCount = 0;
143
+ for (const t of state.timers.values()) clearTimeout(t);
144
+ state.timers.clear();
145
+ state.lastRun = null;
146
+
147
+ // Now register tools, apply config, subscribe to events.
148
+ api.tools.register({ /* ... */ });
149
+ }
150
+ ```
151
+
152
+ ### 3. Teardown releases resources
153
+
154
+ ```typescript
155
+ teardown(api) {
156
+ const count = state.invocationCount;
157
+ state.invocationCount = 0;
158
+ state.lastRun = null;
159
+ // Release every resource that was acquired in setup().
160
+ for (const t of state.timers.values()) clearTimeout(t);
161
+ state.timers.clear();
162
+ api.log.info('my-plugin: teardown complete', { invocations: count });
163
+ }
164
+ ```
165
+
166
+ ### 4. Health reports per-session visibility
167
+
168
+ ```typescript
169
+ async health() {
170
+ return {
171
+ ok: true,
172
+ message: state.lastRun === null
173
+ ? 'my-plugin: no calls yet'
174
+ : `my-plugin: last call at ${state.lastRun.when}`,
175
+ invocationCount: state.invocationCount,
176
+ lastRun: state.lastRun,
177
+ };
178
+ }
179
+ ```
180
+
181
+ ## Tool registration
182
+
183
+ ```typescript
184
+ api.tools.register({
185
+ name: 'my_tool',
186
+ description: 'What this tool does. Include when to use and what it returns.',
187
+ inputSchema: {
188
+ type: 'object',
189
+ properties: {
190
+ path: { type: 'string', description: 'File path' },
191
+ },
192
+ required: ['path'],
193
+ },
194
+ permission: 'auto', // 'auto' | 'confirm'
195
+ mutating: false, // does it change external state?
196
+ category: 'Project',
197
+ async execute(input: Record<string, unknown>) {
198
+ const path = input['path'] as string;
199
+ // ... do the work ...
200
+ return { ok: true, path, result: '...' };
201
+ },
202
+ });
203
+ ```
204
+
205
+ ### Permission levels
206
+
207
+ | Permission | When |
208
+ |------------|------|
209
+ | `auto` | Safe operations (read, list, query). No user confirmation. |
210
+ | `confirm` | Destructive or side-effecting operations (write, commit, delete). User must approve. |
211
+
212
+ ## Config surface
213
+
214
+ Two surfaces exist. The loader merges them:
215
+
216
+ 1. **`config.plugins`** — loading control: `[{ name: 'my-plugin', enabled: false }]`
217
+ 2. **`config.extensions['my-plugin']`** — options: `{ option1: value1 }`
218
+
219
+ Plugins read from `api.config.extensions`:
220
+
221
+ ```typescript
222
+ setup(api) {
223
+ const ext = api.config.extensions?.['my-plugin'] as Record<string, unknown> | undefined;
224
+ const myOption = (ext?.['myOption'] as string) ?? 'default';
225
+ }
226
+ ```
227
+
228
+ If the plugin declares `configSchema`, the loader validates the
229
+ options section before calling `setup` and rejects the plugin with a
230
+ clear error on failure.
231
+
232
+ ## Hook registration (PreToolUse, PostToolUse, etc.)
233
+
234
+ ```typescript
235
+ // secret-scanner pattern: block tools whose args contain secrets
236
+ api.registerHook('PreToolUse', 'bash|write|edit', (input) => {
237
+ const text = JSON.stringify(input.toolInput ?? {});
238
+ if (detectSecret(text)) {
239
+ return {
240
+ decision: 'block',
241
+ reason: 'Plaintext credential detected in tool arguments',
242
+ };
243
+ }
244
+ // Omitted decision = allow (no-op)
245
+ });
246
+ ```
247
+
248
+ Available events: `PreToolUse`, `PostToolUse`, `UserPromptSubmit`,
249
+ `SessionStart`, `Stop`.
250
+
251
+ `HookOutcome` fields:
252
+ - `decision: 'block' | 'allow'` — block stops the action
253
+ - `reason: string` — surfaced to the model when blocking
254
+ - `modifiedInput: Record<string, unknown>` — PreToolUse replacement args
255
+ - `additionalContext: string` — extra context folded back to the model
256
+
257
+ ## PluginAPI extension (cross-package host data)
258
+
259
+ When a plugin needs host data not yet on `PluginAPI` (e.g.
260
+ `modelsRegistry`, `projectDir`), extend the surface in three steps:
261
+
262
+ 1. **`packages/core/src/types/plugin.ts`** — add the optional field to `PluginAPI`
263
+ 2. **`packages/core/src/plugin/api.ts`** — add to `PluginAPIInit` + `DefaultPluginAPI`
264
+ 3. **`packages/cli/src/wiring/plugins.ts`** — destructure + forward in `setupPlugins`
265
+
266
+ Precedent: commit `9bed619f` added `modelsRegistry?: ModelsRegistry` for
267
+ cost-tracker's pricing hydration.
268
+
269
+ ## Entry-point registration (3 files)
270
+
271
+ After writing `src/<name>/index.ts`, wire it into three files:
272
+
273
+ ### 1. `src/index.ts` — named re-export
274
+
275
+ ```typescript
276
+ export { default as myPluginPlugin } from './my-plugin/index.js';
277
+ ```
278
+
279
+ ### 2. `tsup.config.ts` — build entry
280
+
281
+ ```typescript
282
+ entry: {
283
+ // ...
284
+ 'my-plugin': 'src/my-plugin/index.ts',
285
+ },
286
+ ```
287
+
288
+ ### 3. `package.json` — subpath export
289
+
290
+ ```json
291
+ "./my-plugin": {
292
+ "types": "./dist/my-plugin.d.ts",
293
+ "import": "./dist/my-plugin.js"
294
+ }
295
+ ```
296
+
297
+ ### 4. `packages/cli/src/wiring/plugins.ts` — built-in factory
298
+
299
+ ```typescript
300
+ async () => (await import('@wrongstack/plugins/my-plugin')).default,
301
+ ```
302
+
303
+ ## Tests
304
+
305
+ Every plugin gets two test files:
306
+
307
+ - **`tests/<name>.test.ts`** — unit tests (mock API, tool registration,
308
+ config validation, teardown log line, health() shape)
309
+ - **`tests/<name>-exec.test.ts`** — integration tests (real filesystem,
310
+ real CLI tools if applicable)
311
+
312
+ For the H1 pattern, extend `tests/plugin-teardown.test.ts` with a
313
+ `describe('<name>')` block covering:
314
+ - `teardown` logs a completion line and does not throw
315
+ - `health()` reports ok + non-empty message
316
+ - `teardown` zeros counters
317
+
318
+ ## Anti-patterns
319
+
320
+ - **State in setup closure** — leaks on reload. Always module scope.
321
+ - **Missing teardown** — `/diag plugins` shows a gap; reload leaks.
322
+ - **Missing health()** — operator can't confirm the plugin is alive.
323
+ - **Tool name collision** — `read`, `write`, `bash`, etc. are built-in.
324
+ - **Deleting on-disk state in teardown** — the user may return.
325
+ - **Blocking setup with async hydration** — use `void (async () => { ... })()`
326
+ for fire-and-forget; let the first call fall through to fallback if
327
+ the async hasn't completed yet.
328
+ - **Not lowercasing model/config keys** — case-insensitive lookup is
329
+ the convention; `model.toLowerCase()` everywhere.
330
+
331
+ ## Workflow
332
+
333
+ 1. **Create the plugin directory**: `src/<name>/index.ts`
334
+ 2. **Write the Plugin object**: name, version, apiVersion, setup, teardown, health
335
+ 3. **Register tools/hooks** in `setup()`
336
+ 4. **Add state + teardown + health** following the H1 pattern
337
+ 5. **Wire into 3 files**: `index.ts`, `tsup.config.ts`, `package.json`
338
+ 6. **Add to `BUILTIN_PLUGIN_FACTORIES`** in CLI wiring
339
+ 7. **Write tests**: `<name>.test.ts` (unit) + extend `plugin-teardown.test.ts`
340
+ 8. **Run verification**: `npx vitest run packages/plugins` + `npx tsc --noEmit` + `npx tsup`
341
+ 9. **Update `src/index.ts` doc comment** — bump the plugin count
342
+
343
+ ## Skills in scope
344
+
345
+ - `skill-creator` — for the SKILL.md format and frontmatter rules
346
+ - `prompt-engineering` — for crafting tool descriptions and usageHint
347
+ - `typescript-strict` — for strict TypeScript patterns in plugin code
348
+ - `node-modern` — for ESM imports, AbortSignal, and async patterns
349
+ - `testing` — for vitest patterns and mock API construction
350
+ - `output-standards` — for standardized `<next_steps>` formatting
@@ -1,135 +1,135 @@
1
- ---
2
- name: sdd
3
- description: |
4
- Use this skill when starting a non-trivial implementation, bug fix, or refactor
5
- in WrongStack. Triggers: user says "/sdd", "spec", "specification", "task graph",
6
- "SDD", "acceptance criteria", or starts a new feature.
7
- version: 2.1.0
8
- ---
9
-
10
- # Spec-Driven Development — WrongStack
11
-
12
- ## Overview
13
-
14
- Every non-trivial change starts with a spec. The spec is the source of truth — it defines what to build, how to verify it, and what counts as done. SDD uses `/sdd` slash commands to create specs, generate task graphs, and track execution.
15
-
16
- ## Rules
17
-
18
- 1. Every non-trivial task needs a spec before writing code — you'll rewrite it anyway.
19
- 2. Spec must have acceptance criteria — without them, you can't know when it's done.
20
- 3. Tasks must have dependencies — everything is a dependency of something.
21
- 4. Spec must be specific: "Users authenticate via OAuth2 with PKCE" not "improve auth".
22
- 5. Skipping `/sdd` for urgent tasks backfires — the spec is what makes "urgent" possible.
23
- 6. When the spec reveals a multi-file refactor, delegate to `refactor-planner` first.
24
-
25
- ## When to use
26
-
27
- - New feature implementation
28
- - Bug fix with complexity
29
- - Refactoring with scope
30
- - Any task requiring more than 1 hour
31
-
32
- ## The SDD workflow
33
-
34
- ```
35
- 1. /sdd new [title] → Build spec from questions
36
- 2. /sdd tasks <id> → Generate task graph from spec
37
- 3. /sdd graph <id> → Visualize dependencies
38
- 4. /sdd critical <id> → Find bottlenecks
39
- 5. /sdd execute <id> → Run tasks (or execute manually)
40
- ```
41
-
42
- ## Task lifecycle commands
43
-
44
- | Command | What it does |
45
- |---------|--------------|
46
- | `/sdd tasks` | Show task list with progress bar (sorted: in_progress → pending → review → blocked → failed → completed) |
47
- | `/sdd next` | Show next executable task + blockers |
48
- | `/sdd done <N>` | Complete a task (by number or fuzzy title match) |
49
- | `/sdd skip <N>` | Skip a task back to pending |
50
- | `/sdd fail <N>` | Mark a task as failed |
51
- | `/sdd review <N>` | Send a task to review |
52
- | `/sdd edit <N> <text>` | Edit task title (short text) or description (long text) |
53
- | `/sdd undo` | Undo last task completion |
54
- | `/sdd graph` | ASCII task dependency visualization |
55
- | `/sdd critical` | Critical path analysis + bottlenecks |
56
-
57
- ## Spec templates
58
-
59
- | Template | Best for |
60
- |---|---|
61
- | `feature` | New feature development |
62
- | `bugfix` | Bug fix with root cause analysis |
63
- | `refactor` | Code refactoring with goals |
64
- | `infra` | Infrastructure/tooling changes |
65
- | `integration` | External service integration |
66
- | `cli-command` | New CLI commands/slash commands |
67
-
68
- ## Spec structure
69
-
70
- A complete spec has:
71
- 1. **Overview** — What problem does this solve?
72
- 2. **Requirements** — `[priority] description` format
73
- 3. **Architecture** — High-level design (if needed)
74
- 4. **API Design** — Endpoints, inputs, outputs (if applicable)
75
- 5. **Acceptance Criteria** — How do we know it's done?
76
-
77
- ### Requirement format
78
-
79
- ```
80
- [critical] Users can authenticate with OAuth2
81
- [high] Rate limiting: 100 req/min per user
82
- [medium] Response time < 200ms p95
83
- [low] Support dark mode
84
- ```
85
-
86
- ## Task graph generation
87
-
88
- Each requirement generates one or more tasks. Tasks have states:
89
- ```
90
- pending → in_progress → review → completed
91
-
92
- blocked (waiting on dependencies)
93
-
94
- failed
95
- ```
96
-
97
- ## Critical path
98
-
99
- The critical path finds:
100
- - **Bottleneck tasks** blocking the most downstream work
101
- - **Parallel groups** that can run concurrently
102
- - **Ready tasks** that can start immediately
103
- - **Execution order** respecting all dependencies
104
-
105
- ## Goal & Eternal Mode
106
-
107
- `/sdd` pairs with `/goal` for autonomous execution:
108
-
109
- | Command | What it does |
110
- |---------|--------------|
111
- | `/goal set <text>` | Set an autonomous mission |
112
- | `/goal pause` | Pause at end of current iteration |
113
- | `/goal resume` | Resume a paused goal |
114
- | `/goal journal [N]` | Show recent journal entries |
115
- | `/goal clear` | Clear goal and stop eternal mode |
116
- | `/autonomy eternal` | Run goal loop indefinitely |
117
- | `/autonomy stop` | Stop eternal mode |
118
-
119
- **Eternal stage flow:** `decide → execute → reflect → sleep | paused | stopped`
120
- Stage shown in real-time. Pause stops after current iteration completes.
121
-
122
- ## Anti-patterns
123
-
124
- - **Writing code before the spec** — you'll rewrite it anyway
125
- - **Spec that's too vague** — "improve auth" is not a spec, "Users authenticate via OAuth2 with PKCE" is
126
- - **Tasks with no dependencies** — everything is a dependency of something
127
- - **Spec without acceptance criteria** — how do you know when it's done?
128
- - **Skipping /sdd for urgent tasks** — the spec is what makes "urgent" possible
129
-
130
- ## Skills in scope
131
-
132
- - `refactor-planner` — when the spec reveals a multi-file refactor
133
- - `bug-hunter` — when a bugfix spec needs a root cause analysis section
134
- - `multi-agent` — for executing parallel task groups
1
+ ---
2
+ name: sdd
3
+ description: |
4
+ Use this skill when starting a non-trivial implementation, bug fix, or refactor
5
+ in WrongStack. Triggers: user says "/sdd", "spec", "specification", "task graph",
6
+ "SDD", "acceptance criteria", or starts a new feature.
7
+ version: 2.1.0
8
+ ---
9
+
10
+ # Spec-Driven Development — WrongStack
11
+
12
+ ## Overview
13
+
14
+ Every non-trivial change starts with a spec. The spec is the source of truth — it defines what to build, how to verify it, and what counts as done. SDD uses `/sdd` slash commands to create specs, generate task graphs, and track execution.
15
+
16
+ ## Rules
17
+
18
+ 1. Every non-trivial task needs a spec before writing code — you'll rewrite it anyway.
19
+ 2. Spec must have acceptance criteria — without them, you can't know when it's done.
20
+ 3. Tasks must have dependencies — everything is a dependency of something.
21
+ 4. Spec must be specific: "Users authenticate via OAuth2 with PKCE" not "improve auth".
22
+ 5. Skipping `/sdd` for urgent tasks backfires — the spec is what makes "urgent" possible.
23
+ 6. When the spec reveals a multi-file refactor, delegate to `refactor-planner` first.
24
+
25
+ ## When to use
26
+
27
+ - New feature implementation
28
+ - Bug fix with complexity
29
+ - Refactoring with scope
30
+ - Any task requiring more than 1 hour
31
+
32
+ ## The SDD workflow
33
+
34
+ ```
35
+ 1. /sdd new [title] → Build spec from questions
36
+ 2. /sdd tasks <id> → Generate task graph from spec
37
+ 3. /sdd graph <id> → Visualize dependencies
38
+ 4. /sdd critical <id> → Find bottlenecks
39
+ 5. /sdd execute <id> → Run tasks (or execute manually)
40
+ ```
41
+
42
+ ## Task lifecycle commands
43
+
44
+ | Command | What it does |
45
+ |---------|--------------|
46
+ | `/sdd tasks` | Show task list with progress bar (sorted: in_progress → pending → review → blocked → failed → completed) |
47
+ | `/sdd next` | Show next executable task + blockers |
48
+ | `/sdd done <N>` | Complete a task (by number or fuzzy title match) |
49
+ | `/sdd skip <N>` | Skip a task back to pending |
50
+ | `/sdd fail <N>` | Mark a task as failed |
51
+ | `/sdd review <N>` | Send a task to review |
52
+ | `/sdd edit <N> <text>` | Edit task title (short text) or description (long text) |
53
+ | `/sdd undo` | Undo last task completion |
54
+ | `/sdd graph` | ASCII task dependency visualization |
55
+ | `/sdd critical` | Critical path analysis + bottlenecks |
56
+
57
+ ## Spec templates
58
+
59
+ | Template | Best for |
60
+ |---|---|
61
+ | `feature` | New feature development |
62
+ | `bugfix` | Bug fix with root cause analysis |
63
+ | `refactor` | Code refactoring with goals |
64
+ | `infra` | Infrastructure/tooling changes |
65
+ | `integration` | External service integration |
66
+ | `cli-command` | New CLI commands/slash commands |
67
+
68
+ ## Spec structure
69
+
70
+ A complete spec has:
71
+ 1. **Overview** — What problem does this solve?
72
+ 2. **Requirements** — `[priority] description` format
73
+ 3. **Architecture** — High-level design (if needed)
74
+ 4. **API Design** — Endpoints, inputs, outputs (if applicable)
75
+ 5. **Acceptance Criteria** — How do we know it's done?
76
+
77
+ ### Requirement format
78
+
79
+ ```
80
+ [critical] Users can authenticate with OAuth2
81
+ [high] Rate limiting: 100 req/min per user
82
+ [medium] Response time < 200ms p95
83
+ [low] Support dark mode
84
+ ```
85
+
86
+ ## Task graph generation
87
+
88
+ Each requirement generates one or more tasks. Tasks have states:
89
+ ```
90
+ pending → in_progress → review → completed
91
+
92
+ blocked (waiting on dependencies)
93
+
94
+ failed
95
+ ```
96
+
97
+ ## Critical path
98
+
99
+ The critical path finds:
100
+ - **Bottleneck tasks** blocking the most downstream work
101
+ - **Parallel groups** that can run concurrently
102
+ - **Ready tasks** that can start immediately
103
+ - **Execution order** respecting all dependencies
104
+
105
+ ## Goal & Eternal Mode
106
+
107
+ `/sdd` pairs with `/goal` for autonomous execution:
108
+
109
+ | Command | What it does |
110
+ |---------|--------------|
111
+ | `/goal set <text>` | Set an autonomous mission |
112
+ | `/goal pause` | Pause at end of current iteration |
113
+ | `/goal resume` | Resume a paused goal |
114
+ | `/goal journal [N]` | Show recent journal entries |
115
+ | `/goal clear` | Clear goal and stop eternal mode |
116
+ | `/autonomy eternal` | Run goal loop indefinitely |
117
+ | `/autonomy stop` | Stop eternal mode |
118
+
119
+ **Eternal stage flow:** `decide → execute → reflect → sleep | paused | stopped`
120
+ Stage shown in real-time. Pause stops after current iteration completes.
121
+
122
+ ## Anti-patterns
123
+
124
+ - **Writing code before the spec** — you'll rewrite it anyway
125
+ - **Spec that's too vague** — "improve auth" is not a spec, "Users authenticate via OAuth2 with PKCE" is
126
+ - **Tasks with no dependencies** — everything is a dependency of something
127
+ - **Spec without acceptance criteria** — how do you know when it's done?
128
+ - **Skipping /sdd for urgent tasks** — the spec is what makes "urgent" possible
129
+
130
+ ## Skills in scope
131
+
132
+ - `refactor-planner` — when the spec reveals a multi-file refactor
133
+ - `bug-hunter` — when a bugfix spec needs a root cause analysis section
134
+ - `multi-agent` — for executing parallel task groups
135
135
  - `output-standards` — for standardized `<next_steps>` formatting