@bastani/atomic 0.6.4-0 → 0.6.5-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 (120) hide show
  1. package/.agents/skills/create-spec/SKILL.md +6 -3
  2. package/.agents/skills/tdd/SKILL.md +107 -0
  3. package/.agents/skills/tdd/deep-modules.md +33 -0
  4. package/.agents/skills/tdd/interface-design.md +31 -0
  5. package/.agents/skills/tdd/mocking.md +59 -0
  6. package/.agents/skills/tdd/refactoring.md +10 -0
  7. package/.agents/skills/tdd/tests.md +61 -0
  8. package/.agents/skills/workflow-creator/SKILL.md +550 -0
  9. package/.agents/skills/workflow-creator/references/agent-sessions.md +891 -0
  10. package/.agents/skills/workflow-creator/references/agent-setup-recipe.md +266 -0
  11. package/.agents/skills/workflow-creator/references/computation-and-validation.md +201 -0
  12. package/.agents/skills/workflow-creator/references/control-flow.md +470 -0
  13. package/.agents/skills/workflow-creator/references/failure-modes.md +1014 -0
  14. package/.agents/skills/workflow-creator/references/getting-started.md +392 -0
  15. package/.agents/skills/workflow-creator/references/registry-and-validation.md +141 -0
  16. package/.agents/skills/workflow-creator/references/running-workflows.md +418 -0
  17. package/.agents/skills/workflow-creator/references/session-config.md +384 -0
  18. package/.agents/skills/workflow-creator/references/state-and-data-flow.md +356 -0
  19. package/.agents/skills/workflow-creator/references/user-input.md +234 -0
  20. package/.agents/skills/workflow-creator/references/workflow-inputs.md +392 -0
  21. package/.claude/agents/debugger.md +2 -2
  22. package/.claude/agents/reviewer.md +1 -1
  23. package/.claude/agents/worker.md +2 -2
  24. package/.github/agents/debugger.md +1 -1
  25. package/.github/agents/worker.md +1 -1
  26. package/.mcp.json +5 -1
  27. package/.opencode/agents/debugger.md +1 -1
  28. package/.opencode/agents/worker.md +1 -1
  29. package/README.md +236 -201
  30. package/dist/sdk/define-workflow.d.ts +11 -6
  31. package/dist/sdk/define-workflow.d.ts.map +1 -1
  32. package/dist/sdk/errors.d.ts +10 -0
  33. package/dist/sdk/errors.d.ts.map +1 -1
  34. package/dist/sdk/index.d.ts +21 -9
  35. package/dist/sdk/index.d.ts.map +1 -1
  36. package/dist/sdk/primitives/inputs.d.ts +36 -0
  37. package/dist/sdk/primitives/inputs.d.ts.map +1 -0
  38. package/dist/sdk/primitives/metadata.d.ts +40 -0
  39. package/dist/sdk/primitives/metadata.d.ts.map +1 -0
  40. package/dist/sdk/primitives/run.d.ts +57 -0
  41. package/dist/sdk/primitives/run.d.ts.map +1 -0
  42. package/dist/sdk/primitives/sessions.d.ts +128 -0
  43. package/dist/sdk/primitives/sessions.d.ts.map +1 -0
  44. package/dist/sdk/runtime/executor.d.ts +24 -56
  45. package/dist/sdk/runtime/executor.d.ts.map +1 -1
  46. package/dist/sdk/runtime/orchestrator-entry.d.ts +26 -0
  47. package/dist/sdk/runtime/orchestrator-entry.d.ts.map +1 -0
  48. package/dist/sdk/runtime/tmux.d.ts +20 -0
  49. package/dist/sdk/runtime/tmux.d.ts.map +1 -1
  50. package/dist/sdk/types.d.ts +26 -86
  51. package/dist/sdk/types.d.ts.map +1 -1
  52. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
  53. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
  54. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
  55. package/dist/sdk/workflows/builtin/open-claude-design/claude/index.d.ts.map +1 -1
  56. package/dist/sdk/workflows/builtin/open-claude-design/copilot/index.d.ts.map +1 -1
  57. package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts.map +1 -1
  58. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
  59. package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -1
  60. package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -1
  61. package/dist/sdk/workflows/index.d.ts +20 -12
  62. package/dist/sdk/workflows/index.d.ts.map +1 -1
  63. package/dist/services/config/additional-instructions.d.ts +1 -1
  64. package/dist/services/config/additional-instructions.d.ts.map +1 -1
  65. package/package.json +4 -4
  66. package/src/cli.ts +39 -56
  67. package/src/commands/builtin-registry.ts +37 -0
  68. package/src/commands/cli/chat/index.ts +1 -3
  69. package/src/{sdk → commands/cli}/management-commands.ts +15 -55
  70. package/src/commands/cli/session.ts +1 -1
  71. package/src/commands/cli/workflow-command.test.ts +250 -16
  72. package/src/commands/cli/workflow-inputs.test.ts +1 -0
  73. package/src/commands/cli/workflow-inputs.ts +13 -3
  74. package/src/commands/cli/workflow-list.test.ts +1 -0
  75. package/src/commands/cli/workflow-list.ts +0 -0
  76. package/src/commands/cli/workflow-status.ts +1 -1
  77. package/src/commands/cli/workflow.ts +191 -11
  78. package/src/sdk/define-workflow.test.ts +47 -16
  79. package/src/sdk/define-workflow.ts +24 -6
  80. package/src/sdk/errors.test.ts +11 -0
  81. package/src/sdk/errors.ts +13 -0
  82. package/src/sdk/index.test.ts +92 -0
  83. package/src/sdk/index.ts +71 -15
  84. package/src/sdk/primitives/inputs.ts +48 -0
  85. package/src/sdk/primitives/metadata.ts +63 -0
  86. package/src/sdk/primitives/run.ts +81 -0
  87. package/src/sdk/primitives/sessions.test.ts +594 -0
  88. package/src/sdk/primitives/sessions.ts +328 -0
  89. package/src/sdk/runtime/executor.ts +36 -115
  90. package/src/sdk/runtime/orchestrator-entry.ts +110 -0
  91. package/src/sdk/runtime/tmux.ts +33 -0
  92. package/src/sdk/types.ts +26 -91
  93. package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +1 -0
  94. package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +1 -0
  95. package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +1 -0
  96. package/src/sdk/workflows/builtin/open-claude-design/claude/index.ts +1 -0
  97. package/src/sdk/workflows/builtin/open-claude-design/copilot/index.ts +1 -0
  98. package/src/sdk/workflows/builtin/open-claude-design/opencode/index.ts +1 -0
  99. package/src/sdk/workflows/builtin/ralph/claude/index.ts +1 -0
  100. package/src/sdk/workflows/builtin/ralph/copilot/index.ts +1 -0
  101. package/src/sdk/workflows/builtin/ralph/opencode/index.ts +1 -0
  102. package/src/sdk/workflows/index.ts +68 -51
  103. package/src/services/config/additional-instructions.ts +1 -1
  104. package/.agents/skills/test-driven-development/SKILL.md +0 -371
  105. package/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
  106. package/dist/commands/cli/session.d.ts +0 -67
  107. package/dist/commands/cli/session.d.ts.map +0 -1
  108. package/dist/commands/cli/workflow-status.d.ts +0 -63
  109. package/dist/commands/cli/workflow-status.d.ts.map +0 -1
  110. package/dist/sdk/commander.d.ts +0 -74
  111. package/dist/sdk/commander.d.ts.map +0 -1
  112. package/dist/sdk/management-commands.d.ts +0 -42
  113. package/dist/sdk/management-commands.d.ts.map +0 -1
  114. package/dist/sdk/workflow-cli.d.ts +0 -103
  115. package/dist/sdk/workflow-cli.d.ts.map +0 -1
  116. package/dist/sdk/workflows/builtin-registry.d.ts +0 -113
  117. package/dist/sdk/workflows/builtin-registry.d.ts.map +0 -1
  118. package/src/sdk/commander.ts +0 -161
  119. package/src/sdk/workflow-cli.ts +0 -409
  120. package/src/sdk/workflows/builtin-registry.ts +0 -23
@@ -0,0 +1,392 @@
1
+ # Workflow Inputs
2
+
3
+ Workflows collect structured data from the user at invocation time through
4
+ a single uniform API: `ctx.inputs` (and `s.inputs` inside stage
5
+ callbacks). This reference covers how the inputs pipe works, how to
6
+ declare input schemas, and how values reach the workflow from the CLI
7
+ and the interactive picker.
8
+
9
+ ## The inputs pipe
10
+
11
+ Every workflow run receives a typed inputs object. When the workflow
12
+ declares an `inputs` schema, only the declared field names are valid
13
+ keys — accessing undeclared fields is a compile-time error. The
14
+ runtime populates it from whichever invocation surface the user chose.
15
+
16
+ ### Input precedence (highest → lowest)
17
+
18
+ CLI flags always win. Under them, the order depends on the composition shape:
19
+
20
+ - **Single-workflow worker** (`runWorkflow({ workflow })`):
21
+ ```
22
+ CLI flags > runWorkflow({ workflow, inputs }) > defineWorkflow defaults
23
+ ```
24
+ - **Multi-workflow cli** (`iterating registry, with inputs })`):
25
+ ```
26
+ CLI flags > runWorkflow({ workflow, inputs }) > runWorkflow({ inputs }) > defineWorkflow defaults
27
+ ```
28
+
29
+ With ``, the CLI-flags layer is skipped entirely — `inputs`
30
+ become the top-of-chain value. Use this from tests or any programmatic
31
+ caller that doesn't want its host process argv parsed.
32
+
33
+ `defineWorkflow` field `default` is always the final fallback if no
34
+ higher-precedence value supplies one.
35
+
36
+ ### Invocation surfaces
37
+
38
+ | Surface | How values are supplied | How they land in `ctx.inputs` |
39
+ |---|---|---|
40
+ | **Single-worker, positional** — `bun run src/claude-worker.ts "fix the bug"` | The dev wires a `[prompt...]` Commander argument; the collected string is passed as `prompt` | `{ prompt: "fix the bug" }` |
41
+ | **Single-worker, structured** — `bun run src/claude-worker.ts --research_doc=notes.md --focus=standard` | The dev registers one `--<field> <value>` option per declared input via `getInputSchema(wf)` | `{ research_doc: "notes.md", focus: "standard" }` |
42
+ | **Multi-workflow CLI** — `bun run src/cli.ts gen-spec --research_doc=notes.md` | The dev registers one Commander subcommand per workflow; the subcommand's `--<field>` options match the workflow's declared inputs | Same as above |
43
+ | **Interactive picker** — `atomic workflow -a claude` (atomic builtins only) | User fills in a form rendered from the declared schema | Whatever the user typed, keyed by field name |
44
+ | **Picker in user app** — dev mounts `WorkflowPickerPanel` from `@bastani/atomic/workflows/components` | Same form-based collection, against the dev's own registry | Same as above |
45
+ | **Programmatic** — `runWorkflow({ workflow, inputs })` | Plain `Record<string, string>` passed directly — no argv parsing | Top-of-chain value; falls back to `defineWorkflow` defaults |
46
+
47
+ Workflow code is the same either way — it always reads
48
+ `ctx.inputs.<name>`. The invocation surface is a CLI concern, not a
49
+ workflow concern.
50
+
51
+ ### CLI flags in user-app CLIs
52
+
53
+ `runWorkflow` and `createRegistry`/`listWorkflows` are pure SDK primitives —
54
+ they do not auto-register CLI flags. It is the developer's responsibility to
55
+ wire flags using whatever CLI library they prefer. The canonical pattern is to
56
+ iterate `getInputSchema(wf)` and call `.option(--<name> <value>)` for each
57
+ declared input. See §"Scaffold a new workflow from scratch" in `SKILL.md` for
58
+ the full template.
59
+
60
+ The atomic CLI builds its own per-input flags internally by iterating
61
+ `getInputSchema(wf)` when the user passes `-n <name> -a <agent>`. That is
62
+ atomic's own implementation, not an SDK feature.
63
+
64
+ ## Reading inputs
65
+
66
+ Workflows that accept a user prompt should declare it explicitly as an
67
+ input. Destructure it once at the top of `.run()` so every stage can
68
+ close over a bare string:
69
+
70
+ ```ts
71
+ defineWorkflow({
72
+ name: "answer",
73
+ source: import.meta.path,
74
+ description: "Single-turn answer",
75
+ inputs: [
76
+ { name: "prompt", type: "text", required: true, description: "question to answer" },
77
+ ],
78
+ })
79
+ .for("claude")
80
+ .run(async (ctx) => {
81
+ const prompt = ctx.inputs.prompt ?? "";
82
+
83
+ await ctx.stage({ name: "answer" }, {}, {}, async (s) => {
84
+ await s.session.query(prompt);
85
+ s.save(s.sessionId);
86
+ });
87
+ })
88
+ .compile();
89
+ ```
90
+
91
+ For structured workflows, read each declared field by name. Pull them
92
+ out of `ctx.inputs` once for readability and so downstream stages can
93
+ close over locals:
94
+
95
+ ```ts
96
+ defineWorkflow({
97
+ name: "gen-spec",
98
+ source: import.meta.path,
99
+ description: "Convert a research doc into a detailed execution spec",
100
+ inputs: [
101
+ { name: "research_doc", type: "string", required: true },
102
+ {
103
+ name: "focus",
104
+ type: "enum",
105
+ required: true,
106
+ values: ["minimal", "standard", "exhaustive"],
107
+ default: "standard",
108
+ },
109
+ { name: "notes", type: "text" },
110
+ ],
111
+ })
112
+ .for("claude")
113
+ .run(async (ctx) => {
114
+ const { research_doc, focus } = ctx.inputs;
115
+ const notes = ctx.inputs.notes ?? "";
116
+
117
+ await ctx.stage({ name: "write-spec" }, {}, {}, async (s) => {
118
+ await s.session.query(
119
+ `Read ${research_doc} and produce a ${focus} spec.` +
120
+ (notes ? `\n\nExtra guidance:\n${notes}` : ""),
121
+ );
122
+ s.save(s.sessionId);
123
+ });
124
+ })
125
+ .compile();
126
+ ```
127
+
128
+ The nullish coalescing on `notes` handles the optional field case —
129
+ declared-but-unset inputs resolve to `undefined` unless they have a
130
+ `default`.
131
+
132
+ **Style convention.** Inside a stage callback, both `s.inputs.<name>` and
133
+ `ctx.inputs.<name>` resolve to the same value. Either of these patterns
134
+ works:
135
+
136
+ - **Destructure once at the top of `.run()`** so each stage closes over a
137
+ bare local. Best when many stages reference the same input.
138
+ - **Inline access** with `(s.inputs.<name> ?? "")` at each call site. Best
139
+ for short workflows or when each stage uses a different field.
140
+
141
+ Pick whichever reads cleaner for your workflow. Examples in other reference
142
+ files use the inline form for brevity in focused snippets.
143
+
144
+ ## Declaring an input schema
145
+
146
+ Pass an `inputs` array to `defineWorkflow({ ... })`. Each entry is a
147
+ `WorkflowInput`:
148
+
149
+ ```ts
150
+ interface WorkflowInput {
151
+ /** Field name — becomes the CLI flag (`--<name>`) and form label. */
152
+ name: string;
153
+ /** Input kind: string | text | enum */
154
+ type: "string" | "text" | "enum";
155
+ /** Whether the field must be non-empty before the workflow can run. */
156
+ required?: boolean;
157
+ /** Short description shown as the field caption. */
158
+ description?: string;
159
+ /** Placeholder shown when the field is empty. */
160
+ placeholder?: string;
161
+ /** Default value — enums use this to pick their initial value. */
162
+ default?: string;
163
+ /** Allowed values — required when `type` is `"enum"`. */
164
+ values?: readonly string[];
165
+ }
166
+ ```
167
+
168
+ ### Picking a field type
169
+
170
+ | Type | Use when | Picker renders as | Example |
171
+ |---|---|---|---|
172
+ | `string` | Short single-line values — identifiers, file paths, branch names | Single-row text input | `research_doc: "notes.md"` |
173
+ | `text` | Longer free-form prose — specs, prompts, extra context | Multi-row text area | `spec: "Build a..."` |
174
+ | `enum` | A fixed set of allowed values | Radio-button row | `focus: "standard" \| "minimal" \| "exhaustive"` |
175
+
176
+ Rule of thumb: use `enum` whenever there's a closed set of options — it
177
+ gives users discoverable choices instead of making them remember magic
178
+ strings, and the CLI will reject invalid values at parse time.
179
+
180
+ ### Validation enforced by the runtime
181
+
182
+ The `defineWorkflow` builder validates the schema at compile time and
183
+ rejects authoring mistakes immediately — you won't discover them in
184
+ production:
185
+
186
+ - **Input names must be valid CLI flag tails** — start with a letter,
187
+ then letters/digits/underscores/dashes. `1bad` is rejected because
188
+ `--1bad` isn't a parseable flag.
189
+ - **Enum inputs must declare `values`** — an enum with no choices is
190
+ always invalid.
191
+ - **Enum `default` must be in `values`** — prevents drift between the
192
+ default and the allowed set.
193
+ - **No duplicate names** — two inputs with the same `name` shadow each
194
+ other and are rejected.
195
+
196
+ At invocation time, the CLI does a second pass to catch runtime errors
197
+ before spinning up any tmux session:
198
+
199
+ - **Required fields must be non-empty** (whitespace-only strings are
200
+ treated as empty). Missing required fields produce a clear
201
+ `Missing required input --<name>` error and exit non-zero.
202
+ - **Enum values must be in the allowed list.** `--focus=bogus` produces
203
+ `Invalid value for --focus: "bogus". Expected one of: minimal, standard, exhaustive.`
204
+ - **Unknown flags are rejected.** A `--random_flag=value` that isn't in
205
+ the schema produces `Unknown input --random_flag` with the valid
206
+ flag list appended.
207
+
208
+ This validation runs before any workflow code, so a malformed
209
+ invocation can never reach your `.run()` callback in a half-filled
210
+ state.
211
+
212
+ ## Declaring a prompt input
213
+
214
+ Workflows that accept a user prompt should declare it explicitly in their
215
+ `inputs` array rather than relying on an implicit key:
216
+
217
+ ```ts
218
+ inputs: [
219
+ { name: "prompt", type: "text", required: true, description: "task to perform" },
220
+ ]
221
+ ```
222
+
223
+ Declaring `prompt` explicitly gives compile-time safety — `ctx.inputs.prompt` is typed and accessing an undeclared key is a type error. For atomic builtins you can still pass a positional string (`atomic workflow -n ralph -a claude "fix the bug"`); user-app workers handle positional args however the dev wired their Commander entrypoint (e.g., `program.argument("[prompt...]", ...)`), and the collected string is passed as the `prompt` input value.
224
+
225
+ For workflows that need both a free-form prompt AND structured parameters,
226
+ declare all fields in the schema:
227
+
228
+ ```ts
229
+ inputs: [
230
+ { name: "prompt", type: "text", required: true, description: "what to build" },
231
+ { name: "focus", type: "enum", required: true, values: ["minimal", "standard", "exhaustive"], default: "standard" },
232
+ { name: "notes", type: "text", description: "extra context" },
233
+ ]
234
+ ```
235
+
236
+ ## Reserved input names
237
+
238
+ The following input names are rejected by `defineWorkflow` because they
239
+ collide with the atomic CLI's `workflow` subcommand flags and management
240
+ subcommands:
241
+
242
+ ```
243
+ name, agent, detach, list, help, version, session, status
244
+ ```
245
+
246
+ The first six (`name`, `agent`, `detach`, `list`, `help`, `version`) collide
247
+ with the atomic CLI's `workflow` subcommand flags (`-n/--name`,
248
+ `-a/--agent`, `-d/--detach`, `-l/--list`, `-h/--help`, `-v/--version`).
249
+ The last two (`session`, `status`) collide with the atomic CLI's management
250
+ subcommands (`atomic workflow session …`, `atomic workflow status`).
251
+
252
+ Declaring an input with any of these names throws at `defineWorkflow` time
253
+ (before the workflow can be registered into any registry):
254
+
255
+ ```
256
+ [atomic] defineWorkflow: input name "name" is reserved by the worker CLI.
257
+ Rename it. Reserved names: name, agent, detach, list, help, version, session, status.
258
+ ```
259
+
260
+ This is enforced in `defineWorkflow`, not at runtime, so the error surfaces
261
+ at workflow authoring time — the workflow cannot be registered.
262
+
263
+ User-app CLIs built on the SDK primitives are **not** bound by these
264
+ reservations at runtime. The check exists only to keep workflows portable
265
+ to the atomic CLI without needing to rename inputs later.
266
+
267
+ ## The interactive picker
268
+
269
+ ### Atomic builtins — `atomic workflow -a <agent>`
270
+
271
+ `atomic workflow -a <agent>` (no `-n`) launches the interactive picker for
272
+ atomic builtins (TTY only — non-interactive contexts skip straight to
273
+ `--help`). All direct attached or detached builtin runs should include
274
+ `-n <workflow-name>` explicitly; omitting `-n` is the intentional
275
+ picker-discovery path.
276
+
277
+ The picker is the `WorkflowPickerPanel` component from
278
+ `@bastani/atomic/workflows/components`. It:
279
+
280
+ 1. Calls `registry.list()` and filters to workflows whose `agent` field
281
+ matches `<agent>`. No source labels — registry entries are just
282
+ workflows someone registered; where they came from is irrelevant.
283
+ 2. Shows a Telescope-style fuzzy list. The user types to filter,
284
+ arrows (or ⌃j/⌃k) to navigate, ↵ to lock in a selection.
285
+ 3. Renders the selected workflow's form. One field per declared input,
286
+ type-specific rendering (`string` → single-row input, `text` →
287
+ multi-row textarea, `enum` → radio row). Free-form workflows
288
+ (no declared inputs) fall back to a single `prompt` text field.
289
+ 4. Validates required fields on ⌃d. If any are empty, focus jumps to
290
+ the first invalid field.
291
+ 5. Confirms with a y/n modal, then tears down the picker and hands
292
+ off to the workflow executor — same live-run surface users see
293
+ when they invoke the workflow with `-n` directly.
294
+
295
+ The picker is the preferred discovery path for users who don't remember
296
+ flag names. Structured workflows benefit the most from it because the
297
+ form teaches the schema as the user fills it in.
298
+
299
+ ### User apps — mount `WorkflowPickerPanel` yourself
300
+
301
+ `runWorkflow` does **not** auto-launch a picker. If a user app wants a
302
+ picker UX, the developer mounts `WorkflowPickerPanel` from
303
+ `@bastani/atomic/workflows/components` against their own registry:
304
+
305
+ ```ts
306
+ import { WorkflowPickerPanel } from "@bastani/atomic/workflows/components";
307
+
308
+ const panel = await WorkflowPickerPanel.create({ agent: "claude", registry });
309
+ const result = await panel.waitForSelection();
310
+ panel.destroy();
311
+ if (result) {
312
+ await runWorkflow({ workflow: result.workflow, inputs: result.inputs });
313
+ }
314
+ ```
315
+
316
+ Single-workflow workers have no picker — the file already identifies the
317
+ workflow, so the user just passes the declared `--<input>` flags directly.
318
+
319
+ ## Duplicate registration
320
+
321
+ Registering the same `${agent}/${name}` key twice throws at composition-root
322
+ time (before any workflow runs):
323
+
324
+ ```
325
+ [atomic] Duplicate workflow registration: "claude/my-workflow" is already registered.
326
+ ```
327
+
328
+ There is no silent shadowing. Pick distinct `(agent, name)` pairs across all
329
+ workflows in the registry. For the full key-scheme and validate-on-register
330
+ contract see `registry-and-validation.md`.
331
+
332
+ ## Invocation details
333
+
334
+ See SKILL.md §"Invocation surfaces" for the full table. This section covers
335
+ flag-parsing nuances specific to structured inputs.
336
+
337
+ Both `--flag=value` and `--flag value` forms are accepted by Commander. Short
338
+ flags (`-x value`) are NOT parsed as structured inputs — only long-form
339
+ `--<name>` flags resolve against the schema.
340
+
341
+ For user-app CLIs, the dev wires the flags via `getInputSchema(wf)` and
342
+ Commander; there is no `-n`/`-a`/`-d` built into user-app workers. If the
343
+ dev wants detached runs, they pass `detach: true` to `runWorkflow` or wire
344
+ their own `--detach` Commander option.
345
+
346
+ ```bash
347
+ # User's own app — single-workflow worker
348
+ bun run src/claude-worker.ts --focus=standard --research_doc=notes.md
349
+ bun run src/claude-worker.ts --focus standard --research_doc notes.md
350
+
351
+ # User's own app — multi-workflow CLI
352
+ bun run src/cli.ts gen-spec --focus=standard --research_doc=notes.md
353
+
354
+ # Atomic builtins — use atomic CLI's -n/-a/-d flags
355
+ atomic workflow -n gen-spec -a claude --focus=standard --research_doc=notes.md
356
+ atomic workflow -n gen-spec -a claude -d --focus=standard # detached
357
+ ```
358
+
359
+ ## Pitfalls
360
+
361
+ ### Declare every field you access
362
+
363
+ With typed inputs, accessing `ctx.inputs.foo` when `foo` is not declared
364
+ in the workflow's `inputs` array is a compile-time error. If your workflow
365
+ needs a prompt field, declare it:
366
+
367
+ ```ts
368
+ inputs: [
369
+ { name: "prompt", type: "text", required: true, description: "task prompt" },
370
+ ]
371
+ ```
372
+
373
+ If the developer has wired a `[prompt...]` Commander argument in their
374
+ entrypoint, the collected string is passed as the `prompt` input value —
375
+ but only if the workflow actually declares a `prompt` input. Accessing
376
+ `ctx.inputs.prompt` without declaring it is a compile-time error. The
377
+ atomic CLI applies the same rule for builtins: a positional string is
378
+ rejected if the builtin workflow does not declare a `prompt` input.
379
+
380
+ ### Don't rename inputs across workflow versions
381
+
382
+ Declared input names are part of the workflow's public API — they map
383
+ directly to `--<name>` flags and field identifiers in the picker.
384
+ Renaming a field is a breaking change for any script that invokes the
385
+ workflow. If you need to rename, add the new name alongside the old,
386
+ migrate callers, then remove the old name in a later change.
387
+
388
+ ### Don't put secrets in `default`
389
+
390
+ Defaults are visible in the picker and printed in CLI errors. They're
391
+ fine for values like `"standard"` but not for API keys or auth tokens.
392
+ Read those from environment variables inside the workflow instead.
@@ -3,7 +3,7 @@ name: debugger
3
3
  description: Debug errors, test failures, and unexpected behavior. Use PROACTIVELY when encountering issues, analyzing stack traces, or investigating system problems.
4
4
  tools: Bash, Agent, Edit, Grep, Glob, Read, TaskCreate, TaskList, TaskGet, TaskUpdate, LSP, WebFetch, WebSearch
5
5
  skills:
6
- - test-driven-development
6
+ - tdd
7
7
  - playwright-cli
8
8
  model: opus
9
9
  ---
@@ -18,7 +18,7 @@ Available tools:
18
18
  - PREFER to use the playwright-cli (refer to playwright-cli skill) OVER web fetch/search tools
19
19
  - ALWAYS load the playwright-cli skill before usage with the Skill tool.
20
20
  - ALWAYS ASSUME you have the playwright-cli tool installed (if the `playwright-cli` command fails, fallback to `npx playwright-cli`).
21
- - ALWAYS invoke your test-driven-development skill BEFORE creating or modifying any tests.
21
+ - ALWAYS invoke your tdd skill BEFORE creating or modifying any tests.
22
22
  </EXTREMELY_IMPORTANT>
23
23
 
24
24
  ## Search Strategy
@@ -3,7 +3,7 @@ name: reviewer
3
3
  description: Code reviewer for proposed code changes.
4
4
  tools: Bash, Agent, Glob, Grep, Read, TodoWrite, TaskCreate, TaskList, TaskGet, TaskUpdate, WebFetch, WebSearch
5
5
  skills:
6
- - test-driven-development
6
+ - tdd
7
7
  - playwright-cli
8
8
  model: opus
9
9
  ---
@@ -3,7 +3,7 @@ name: worker
3
3
  description: Implement a SINGLE task from a task list.
4
4
  tools: Bash, Agent, Edit, Grep, Glob, Read, LSP, TaskCreate, TaskList, TaskGet, TaskUpdate
5
5
  skills:
6
- - test-driven-development
6
+ - tdd
7
7
  model: sonnet
8
8
  ---
9
9
 
@@ -82,7 +82,7 @@ Frequently use unit tests, integration tests, and end-to-end tests to verify you
82
82
 
83
83
  ### Testing Anti-Patterns
84
84
 
85
- Use your test-driven-development skill to avoid common pitfalls when writing tests.
85
+ Use your tdd skill to avoid common pitfalls when writing tests.
86
86
 
87
87
  ## Design Principles
88
88
 
@@ -25,7 +25,7 @@ Available tools:
25
25
  - PREFER to use the playwright-cli (refer to playwright-cli skill) OVER web fetch/search tools
26
26
  - ALWAYS load the playwright-cli skill before usage with the Skill tool.
27
27
  - ALWAYS ASSUME you have the playwright-cli tool installed (if the `playwright-cli` command fails, fallback to `npx playwright-cli`).
28
- - ALWAYS invoke your test-driven-development skill BEFORE creating or modifying any tests.
28
+ - ALWAYS invoke your tdd skill BEFORE creating or modifying any tests.
29
29
  </EXTREMELY_IMPORTANT>
30
30
 
31
31
  ## Search Strategy
@@ -143,7 +143,7 @@ Frequently use unit tests, integration tests, and end-to-end tests to verify you
143
143
 
144
144
  ### Testing Anti-Patterns
145
145
 
146
- Use your test-driven-development skill to avoid common pitfalls when writing tests.
146
+ Use your tdd skill to avoid common pitfalls when writing tests.
147
147
 
148
148
  ## Design Principles
149
149
 
package/.mcp.json CHANGED
@@ -10,7 +10,11 @@
10
10
  "azure-devops": {
11
11
  "type": "stdio",
12
12
  "command": "bunx",
13
- "args": ["-y", "@azure-devops/mcp", "<your-org>"]
13
+ "args": [
14
+ "-y",
15
+ "@azure-devops/mcp",
16
+ "<your-org>"
17
+ ]
14
18
  }
15
19
  }
16
20
  }
@@ -26,7 +26,7 @@ Available tools:
26
26
  - PREFER to use the playwright-cli (refer to playwright-cli skill) OVER web fetch/search tools
27
27
  - ALWAYS load the playwright-cli skill before usage with the Skill tool.
28
28
  - ALWAYS ASSUME you have the playwright-cli tool installed (if the `playwright-cli` command fails, fallback to `npx playwright-cli`).
29
- - ALWAYS invoke your test-driven-development skill BEFORE creating or modifying any tests.
29
+ - ALWAYS invoke your tdd skill BEFORE creating or modifying any tests.
30
30
  </EXTREMELY_IMPORTANT>
31
31
 
32
32
  ## Search Strategy
@@ -83,7 +83,7 @@ Frequently use unit tests, integration tests, and end-to-end tests to verify you
83
83
 
84
84
  ### Testing Anti-Patterns
85
85
 
86
- Use your test-driven-development skill to avoid common pitfalls when writing tests.
86
+ Use your tdd skill to avoid common pitfalls when writing tests.
87
87
 
88
88
  ## Design Principles
89
89