@smithers-orchestrator/cli 0.20.1 → 0.20.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.
Files changed (40) hide show
  1. package/package.json +17 -19
  2. package/src/agent-detection.js +2 -2
  3. package/src/event-categories.js +5 -0
  4. package/src/find-db.js +6 -6
  5. package/src/index.js +117 -59
  6. package/src/mcp/semantic-tools.js +1 -2
  7. package/src/node-detail.js +1 -6
  8. package/src/watch.js +1 -2
  9. package/src/why-diagnosis.js +1 -2
  10. package/src/workflow-pack.js +23 -11
  11. package/src/tui/app.jsx +0 -139
  12. package/src/tui/app.tsx +0 -5
  13. package/src/tui/components/AskModal.jsx +0 -109
  14. package/src/tui/components/AskModal.tsx +0 -3
  15. package/src/tui/components/AttentionPane.jsx +0 -112
  16. package/src/tui/components/AttentionPane.tsx +0 -6
  17. package/src/tui/components/ChatPane.jsx +0 -57
  18. package/src/tui/components/ChatPane.tsx +0 -7
  19. package/src/tui/components/CronList.jsx +0 -87
  20. package/src/tui/components/CronList.tsx +0 -5
  21. package/src/tui/components/DetailsPane.jsx +0 -96
  22. package/src/tui/components/DetailsPane.tsx +0 -7
  23. package/src/tui/components/FramesPane.jsx +0 -147
  24. package/src/tui/components/FramesPane.tsx +0 -8
  25. package/src/tui/components/LogsPane.jsx +0 -46
  26. package/src/tui/components/LogsPane.tsx +0 -6
  27. package/src/tui/components/MetricsPane.jsx +0 -108
  28. package/src/tui/components/MetricsPane.tsx +0 -5
  29. package/src/tui/components/NodeDetailView.jsx +0 -284
  30. package/src/tui/components/NodeDetailView.tsx +0 -7
  31. package/src/tui/components/NodeInspector.jsx +0 -51
  32. package/src/tui/components/NodeInspector.tsx +0 -7
  33. package/src/tui/components/RunDetailView.jsx +0 -190
  34. package/src/tui/components/RunDetailView.tsx +0 -7
  35. package/src/tui/components/RunsList.jsx +0 -184
  36. package/src/tui/components/RunsList.tsx +0 -7
  37. package/src/tui/components/SqliteBrowser.jsx +0 -131
  38. package/src/tui/components/SqliteBrowser.tsx +0 -5
  39. package/src/tui/components/WorkflowLauncher.jsx +0 -63
  40. package/src/tui/components/WorkflowLauncher.tsx +0 -3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@smithers-orchestrator/cli",
3
- "version": "0.20.1",
4
- "description": "Smithers command-line interface, TUI, MCP server, and local workflow tools",
3
+ "version": "0.20.4",
4
+ "description": "Smithers command-line interface, MCP server, and local workflow tools",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "exports": {
@@ -25,8 +25,6 @@
25
25
  "@effect/workflow": "^0.18.0",
26
26
  "@clack/prompts": "^0.10.1",
27
27
  "@modelcontextprotocol/sdk": "^1.29.0",
28
- "@opentui/core": "^0.1.100",
29
- "@opentui/react": "^0.1.100",
30
28
  "cron-parser": "^5.5.0",
31
29
  "drizzle-orm": "^0.45.2",
32
30
  "effect": "^3.21.1",
@@ -34,21 +32,21 @@
34
32
  "picocolors": "^1.1.1",
35
33
  "react": "^19.2.5",
36
34
  "zod": "^4.3.6",
37
- "@smithers-orchestrator/accounts": "0.20.1",
38
- "@smithers-orchestrator/agents": "0.20.1",
39
- "@smithers-orchestrator/components": "0.20.1",
40
- "@smithers-orchestrator/db": "0.20.1",
41
- "@smithers-orchestrator/devtools": "0.20.1",
42
- "@smithers-orchestrator/driver": "0.20.1",
43
- "@smithers-orchestrator/engine": "0.20.1",
44
- "@smithers-orchestrator/errors": "0.20.1",
45
- "@smithers-orchestrator/memory": "0.20.1",
46
- "@smithers-orchestrator/observability": "0.20.1",
47
- "@smithers-orchestrator/openapi": "0.20.1",
48
- "@smithers-orchestrator/protocol": "0.20.1",
49
- "@smithers-orchestrator/scheduler": "0.20.1",
50
- "@smithers-orchestrator/server": "0.20.1",
51
- "@smithers-orchestrator/time-travel": "0.20.1"
35
+ "@smithers-orchestrator/accounts": "0.20.4",
36
+ "@smithers-orchestrator/agents": "0.20.4",
37
+ "@smithers-orchestrator/components": "0.20.4",
38
+ "@smithers-orchestrator/db": "0.20.4",
39
+ "@smithers-orchestrator/devtools": "0.20.4",
40
+ "@smithers-orchestrator/driver": "0.20.4",
41
+ "@smithers-orchestrator/errors": "0.20.4",
42
+ "@smithers-orchestrator/observability": "0.20.4",
43
+ "@smithers-orchestrator/protocol": "0.20.4",
44
+ "@smithers-orchestrator/scheduler": "0.20.4",
45
+ "@smithers-orchestrator/engine": "0.20.4",
46
+ "@smithers-orchestrator/server": "0.20.4",
47
+ "@smithers-orchestrator/time-travel": "0.20.4",
48
+ "@smithers-orchestrator/memory": "0.20.4",
49
+ "@smithers-orchestrator/openapi": "0.20.4"
52
50
  },
53
51
  "devDependencies": {
54
52
  "@types/bun": "latest",
@@ -91,7 +91,7 @@ const AGENT_VARIANTS = [
91
91
  displayName: "Claude Sonnet",
92
92
  constructor: {
93
93
  importName: "ClaudeCodeAgent",
94
- expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-6", cwd: process.cwd() })',
94
+ expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-7", cwd: process.cwd() })',
95
95
  },
96
96
  },
97
97
  ];
@@ -108,7 +108,7 @@ const TIER_PREFERENCES = {
108
108
  const CONSTRUCTORS = {
109
109
  claude: {
110
110
  importName: "ClaudeCodeAgent",
111
- expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-6", cwd: process.cwd() })',
111
+ expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-7", cwd: process.cwd() })',
112
112
  },
113
113
  codex: {
114
114
  importName: "CodexAgent",
@@ -8,6 +8,7 @@ const EVENT_CATEGORY_BY_TYPE = {
8
8
  RunAutoResumeSkipped: "run",
9
9
  RunStarted: "run",
10
10
  RunStatusChanged: "run",
11
+ RunStateChanged: "run",
11
12
  RunFinished: "run",
12
13
  RunFailed: "run",
13
14
  RunCancelled: "run",
@@ -49,6 +50,7 @@ const EVENT_CATEGORY_BY_TYPE = {
49
50
  RevertFinished: "revert",
50
51
  TimeTravelStarted: "revert",
51
52
  TimeTravelFinished: "revert",
53
+ TimeTravelJumped: "revert",
52
54
  WorkflowReloadDetected: "workflow",
53
55
  WorkflowReloaded: "workflow",
54
56
  WorkflowReloadFailed: "workflow",
@@ -67,6 +69,9 @@ const EVENT_CATEGORY_BY_TYPE = {
67
69
  TimerCreated: "timer",
68
70
  TimerFired: "timer",
69
71
  TimerCancelled: "timer",
72
+ AgentTraceEvent: "agent",
73
+ AgentTraceSummary: "agent",
74
+ AgentSessionEvent: "agent",
70
75
  };
71
76
  const CATEGORY_ALIASES = {
72
77
  agent: "agent",
package/src/find-db.js CHANGED
@@ -15,16 +15,16 @@ import { SmithersError } from "@smithers-orchestrator/errors";
15
15
  export function findSmithersDb(from) {
16
16
  let dir = resolve(from ?? process.cwd());
17
17
  const root = resolve("/");
18
- while (true) {
18
+ while (dir !== root) {
19
19
  const candidate = resolve(dir, "smithers.db");
20
20
  if (existsSync(candidate))
21
21
  return candidate;
22
- const parent = dirname(dir);
23
- if (parent === dir || dir === root) {
24
- throw new SmithersError("CLI_DB_NOT_FOUND", "No smithers.db found. Run this command from a directory containing a smithers.db, or use 'smithers up <workflow>' to start a run first.");
25
- }
26
- dir = parent;
22
+ dir = dirname(dir);
27
23
  }
24
+ const rootCandidate = resolve(root, "smithers.db");
25
+ if (existsSync(rootCandidate))
26
+ return rootCandidate;
27
+ throw new SmithersError("CLI_DB_NOT_FOUND", "No smithers.db found. Run this command from a directory containing a smithers.db, or use 'smithers up <workflow>' to start a run first.");
28
28
  }
29
29
  /**
30
30
  * @param {number} ms
package/src/index.js CHANGED
@@ -484,6 +484,41 @@ function isRunStatusTerminal(status) {
484
484
  status !== "waiting-timer" &&
485
485
  status !== "waiting-event");
486
486
  }
487
+ /**
488
+ * Fetch a docs file from smithers.sh and write it to stdout.
489
+ * Honors --json (global) by emitting `{ url, content }`.
490
+ *
491
+ * @param {{ error: Function; ok: Function; format?: string; options?: { json?: boolean } }} c
492
+ * @param {string} url
493
+ * @param {string} errorCode
494
+ */
495
+ async function printSmithersDocs(c, url, errorCode) {
496
+ let body;
497
+ try {
498
+ const res = await fetch(url);
499
+ if (!res.ok) {
500
+ return c.error({
501
+ code: errorCode,
502
+ message: `Failed to fetch ${url}: HTTP ${res.status}`,
503
+ exitCode: 1,
504
+ });
505
+ }
506
+ body = await res.text();
507
+ }
508
+ catch (err) {
509
+ return c.error({
510
+ code: errorCode,
511
+ message: `Failed to fetch ${url}: ${err?.message ?? String(err)}`,
512
+ exitCode: 1,
513
+ });
514
+ }
515
+ const wantsJson = Boolean(c.options?.json) || c.format === "json";
516
+ if (wantsJson) {
517
+ return c.ok({ url, content: body });
518
+ }
519
+ process.stdout.write(body.endsWith("\n") ? body : `${body}\n`);
520
+ return c.ok(undefined);
521
+ }
487
522
  /**
488
523
  * @param {string | undefined} format
489
524
  * @param {unknown} payload
@@ -2266,10 +2301,10 @@ let lastDevtoolsCommandOutcome;
2266
2301
  * friendly typed error the helper already wrote to stderr (finding #2).
2267
2302
  *
2268
2303
  * @param {"tree"|"diff"|"output"|"rewind"} cmd
2269
- * @param {{ args: any; options: any; ok: (d?: unknown) => unknown }} c
2304
+ * @param {{ args: any; options: any }} c
2270
2305
  * @param {() => Promise<number>} handler
2271
2306
  */
2272
- async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
2307
+ async function* runDevtoolsCommandWithTelemetry(cmd, c, handler) {
2273
2308
  const startedAt = Date.now();
2274
2309
  let exitCode = 0;
2275
2310
  try {
@@ -2327,9 +2362,8 @@ async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
2327
2362
  // best-effort metrics.
2328
2363
  }
2329
2364
  }
2330
- // Return c.ok(undefined) so incur does not emit an additional
2331
- // envelope on stdout (finding #2).
2332
- return c.ok(undefined);
2365
+ // This is an empty stream so Incur does not emit an additional envelope
2366
+ // or framework CTA on stdout after the helper has already written output.
2333
2367
  }
2334
2368
 
2335
2369
  /**
@@ -2551,8 +2585,8 @@ const cli = Cli.create({
2551
2585
  { command: "workflow run implement", description: "Run the implementation workflow" },
2552
2586
  ]
2553
2587
  : [
2554
- { command: "tui", description: "Open the interactive dashboard" },
2555
2588
  { command: "workflow list", description: "View all available workflows" },
2589
+ { command: "workflow run implement", description: "Run the implementation workflow" },
2556
2590
  ],
2557
2591
  },
2558
2592
  });
@@ -2641,49 +2675,6 @@ const cli = Cli.create({
2641
2675
  cleanup();
2642
2676
  }
2643
2677
  },
2644
- })
2645
- // =========================================================================
2646
- // smithers tui
2647
- // =========================================================================
2648
- .command("tui", {
2649
- description: "Open the interactive Smithers observability dashboard",
2650
- async run(c) {
2651
- const fail = (opts) => {
2652
- commandExitOverride = opts.exitCode ?? 1;
2653
- return c.error(opts);
2654
- };
2655
- let cleanup;
2656
- let renderer;
2657
- try {
2658
- const db = await findAndOpenDb(undefined, {
2659
- timeoutMs: 5000,
2660
- intervalMs: 100,
2661
- });
2662
- const adapter = db.adapter;
2663
- cleanup = db.cleanup;
2664
- const { createCliRenderer } = await import("@opentui/core");
2665
- const { createRoot } = await import("@opentui/react");
2666
- const { TuiApp } = await import("./tui/app.jsx");
2667
- const React = await import("react");
2668
- renderer = await createCliRenderer({ exitOnCtrlC: false });
2669
- const root = createRoot(renderer);
2670
- await new Promise((resolve) => {
2671
- root.render(React.createElement(TuiApp, {
2672
- adapter,
2673
- onExit: () => resolve(true),
2674
- }));
2675
- });
2676
- return c.ok(undefined);
2677
- }
2678
- catch (err) {
2679
- return fail({ code: "TUI_FAILED", message: err?.message ?? String(err), exitCode: 1 });
2680
- }
2681
- finally {
2682
- if (renderer)
2683
- renderer.destroy();
2684
- cleanup?.();
2685
- }
2686
- }
2687
2678
  })
2688
2679
  // =========================================================================
2689
2680
  // smithers ps
@@ -3437,8 +3428,8 @@ const cli = Cli.create({
3437
3428
  // =========================================================================
3438
3429
  // smithers inspect <run_id>
3439
3430
  // =========================================================================
3440
- .command("inspect", {
3441
- description: "Output detailed state of a run: steps, agents, approvals, and outputs.",
3431
+ .command("inspect", {
3432
+ description: "Output detailed run state, including steps, agents, approvals, and outputs.",
3442
3433
  args: inspectArgs,
3443
3434
  options: inspectOptions,
3444
3435
  alias: { watch: "w", interval: "i" },
@@ -4364,8 +4355,8 @@ const cli = Cli.create({
4364
4355
  // =========================================================================
4365
4356
  // smithers timetravel <workflow>
4366
4357
  // =========================================================================
4367
- .command("timetravel", {
4368
- description: "Time-travel to a previous task state: revert filesystem, reset DB, and optionally resume.",
4358
+ .command("timetravel", {
4359
+ description: "Time-travel to a previous task state by reverting filesystem state, resetting DB state, and optionally resuming.",
4369
4360
  args: workflowArgs,
4370
4361
  options: z.object({
4371
4362
  runId: z.string().describe("Run ID"),
@@ -4649,7 +4640,7 @@ const cli = Cli.create({
4649
4640
  // rewrites raw `--json` → `-j` for these commands so it lands as a
4650
4641
  // command option, not a format directive.
4651
4642
  alias: { json: "j" },
4652
- async run(c) {
4643
+ run(c) {
4653
4644
  return runDevtoolsCommandWithTelemetry("tree", c, async () => {
4654
4645
  const { runTreeOnce, runTreeWatch } = await import("./tree.js");
4655
4646
  const { adapter, cleanup } = await findAndOpenDb();
@@ -4715,7 +4706,7 @@ const cli = Cli.create({
4715
4706
  color: z.enum(["auto", "always", "never"]).default("auto").describe("Colorize output"),
4716
4707
  }),
4717
4708
  alias: { json: "j" },
4718
- async run(c) {
4709
+ run(c) {
4719
4710
  return runDevtoolsCommandWithTelemetry("diff", c, async () => {
4720
4711
  const { runDiffOnce } = await import("./diff.js");
4721
4712
  const { adapter, cleanup } = await findAndOpenDb();
@@ -4754,7 +4745,7 @@ const cli = Cli.create({
4754
4745
  pretty: z.boolean().default(false).describe("Schema-ordered render"),
4755
4746
  }),
4756
4747
  alias: { json: "j" },
4757
- async run(c) {
4748
+ run(c) {
4758
4749
  return runDevtoolsCommandWithTelemetry("output", c, async () => {
4759
4750
  const { runOutputOnce } = await import("./output.js");
4760
4751
  const { adapter, cleanup } = await findAndOpenDb();
@@ -4790,7 +4781,7 @@ const cli = Cli.create({
4790
4781
  json: z.boolean().default(false).describe("Emit JumpResult JSON"),
4791
4782
  }),
4792
4783
  alias: { json: "j" },
4793
- async run(c) {
4784
+ run(c) {
4794
4785
  return runDevtoolsCommandWithTelemetry("rewind", c, async () => {
4795
4786
  const { runRewindOnce } = await import("./rewind.js");
4796
4787
  const { adapter, cleanup } = await findAndOpenDb();
@@ -4966,6 +4957,22 @@ const cli = Cli.create({
4966
4957
  return c.error({ code: "GUI_LAUNCH_FAILED", message: err?.message ?? String(err), exitCode: 1 });
4967
4958
  }
4968
4959
  },
4960
+ })
4961
+ // =========================================================================
4962
+ // smithers docs / smithers docs-full
4963
+ // Print the published llms.txt / llms-full.txt from smithers.sh.
4964
+ // =========================================================================
4965
+ .command("docs", {
4966
+ description: "Print llms.txt (concise docs index for LLMs) from smithers.sh.",
4967
+ async run(c) {
4968
+ return printSmithersDocs(c, "https://smithers.sh/llms.txt", "DOCS_FETCH_FAILED");
4969
+ },
4970
+ })
4971
+ .command("docs-full", {
4972
+ description: "Print llms-full.txt (full docs bundle for LLMs) from smithers.sh.",
4973
+ async run(c) {
4974
+ return printSmithersDocs(c, "https://smithers.sh/llms-full.txt", "DOCS_FULL_FETCH_FAILED");
4975
+ },
4969
4976
  })
4970
4977
  .command(workflowCli)
4971
4978
  .command(cronCli)
@@ -5185,6 +5192,54 @@ function argvRequestsJsonMode(argv) {
5185
5192
  }
5186
5193
  return false;
5187
5194
  }
5195
+ /**
5196
+ * Some commands own stdout completely and promise a raw JSON document even
5197
+ * without `--format json`. Run those before Incur can append framework CTAs
5198
+ * such as the stale-skills reminder, which would make stdout unparsable.
5199
+ *
5200
+ * @param {string[]} argv
5201
+ * @returns {boolean}
5202
+ */
5203
+ function runRawJsonAgentCommandIfMatched(argv) {
5204
+ const positionals = [];
5205
+ let jsonOutput = false;
5206
+ for (let index = 0; index < argv.length; index++) {
5207
+ const arg = argv[index];
5208
+ if (arg === "--json") {
5209
+ jsonOutput = true;
5210
+ continue;
5211
+ }
5212
+ if (arg === "--format") {
5213
+ if (argv[index + 1] !== "json") {
5214
+ return false;
5215
+ }
5216
+ jsonOutput = true;
5217
+ index += 1;
5218
+ continue;
5219
+ }
5220
+ if (arg === "--format=json") {
5221
+ jsonOutput = true;
5222
+ continue;
5223
+ }
5224
+ if (arg.startsWith("-")) {
5225
+ return false;
5226
+ }
5227
+ positionals.push(arg);
5228
+ }
5229
+ if (positionals.length !== 2 || positionals[0] !== "agents") {
5230
+ return false;
5231
+ }
5232
+ if (positionals[1] === "capabilities") {
5233
+ process.stdout.write(`${JSON.stringify(getCliAgentCapabilityReport(), null, 2)}\n`);
5234
+ process.exit(0);
5235
+ }
5236
+ if (positionals[1] === "doctor" && jsonOutput) {
5237
+ const report = getCliAgentCapabilityDoctorReport();
5238
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
5239
+ process.exit(report.ok ? 0 : 1);
5240
+ }
5241
+ return false;
5242
+ }
5188
5243
  /**
5189
5244
  * @param {string[]} argv
5190
5245
  */
@@ -5268,7 +5323,7 @@ function normalizeResumeOption(value) {
5268
5323
  const CHAT_CREATE_PROMPT = [
5269
5324
  "Start an interactive chat session with the user and help them directly.",
5270
5325
  "Stay in this conversation until the user is done.",
5271
- 'When you are completely finished and want to hand control back to Smithers, end your final response with an empty JSON object in a ```json fence: {}.',
5326
+ 'When you are completely finished and want to hand control back to Smithers, return ONLY this raw JSON object with no prose, markdown, or code fence: {}.',
5272
5327
  ].join("\n\n");
5273
5328
  /**
5274
5329
  * @param {"claude-code" | "codex" | "gemini"} agentId
@@ -5280,7 +5335,7 @@ async function createChatAgent(agentId, cwd) {
5280
5335
  const { ClaudeCodeAgent } = await import("@smithers-orchestrator/agents/ClaudeCodeAgent");
5281
5336
  return new ClaudeCodeAgent({
5282
5337
  cwd,
5283
- model: "claude-opus-4-6",
5338
+ model: "claude-opus-4-7",
5284
5339
  });
5285
5340
  }
5286
5341
  case "codex": {
@@ -5387,6 +5442,9 @@ async function main() {
5387
5442
  if (argvRequestsJsonMode(argv)) {
5388
5443
  setJsonMode(true);
5389
5444
  }
5445
+ if (runRawJsonAgentCommandIfMatched(argv)) {
5446
+ return;
5447
+ }
5390
5448
  // Finding #1: pre-validate argv for devtools commands so missing-args
5391
5449
  // / invalid-flag errors go to stderr with exit 1 (not incur's
5392
5450
  // remap-to-4 VALIDATION_ERROR envelope on stdout).
@@ -601,8 +601,7 @@ async function listAllEvents(adapter, runId) {
601
601
  break;
602
602
  events.push(...batch);
603
603
  lastSeq = batch[batch.length - 1].seq;
604
- if (batch.length < 1_000)
605
- break;
604
+ if (batch.length < 1_000) break;
606
605
  }
607
606
  return events;
608
607
  }
@@ -89,12 +89,7 @@ function parseErrorSummary(raw) {
89
89
  if (message) {
90
90
  return { message, detail: parsed };
91
91
  }
92
- try {
93
- return { message: JSON.stringify(parsed), detail: parsed };
94
- }
95
- catch {
96
- return { message: String(parsed), detail: parsed };
97
- }
92
+ return { message: JSON.stringify(parsed), detail: parsed };
98
93
  }
99
94
  return { message: String(parsed), detail: parsed };
100
95
  }
package/src/watch.js CHANGED
@@ -110,7 +110,7 @@ export async function runWatchLoop(options) {
110
110
  tickCount += 1;
111
111
  latest = await options.fetch();
112
112
  await renderSnapshot(latest, false);
113
- if (options.isTerminal?.(latest)) {
113
+ if (options.isTerminal?.(latest))
114
114
  return {
115
115
  intervalMs,
116
116
  tickCount,
@@ -118,7 +118,6 @@ export async function runWatchLoop(options) {
118
118
  reachedTerminal: true,
119
119
  lastData: latest,
120
120
  };
121
- }
122
121
  }
123
122
  }
124
123
  finally {
@@ -461,8 +461,7 @@ function computeSignalName(node, descriptor, attempts, events) {
461
461
  correlationId ??
462
462
  parseString(payload.correlationId) ??
463
463
  null;
464
- if (signalName && correlationId)
465
- break;
464
+ if (signalName && correlationId) break;
466
465
  }
467
466
  return { signalName, correlationId };
468
467
  }
@@ -133,7 +133,6 @@ function renderPackageJson(versions) {
133
133
  dependencies: {
134
134
  react: versions.reactVersion,
135
135
  "react-dom": versions.reactDomVersion,
136
- skills: "github:mattpocock/skills",
137
136
  "smithers-orchestrator": smithersSpec,
138
137
  zod: versions.zodVersion,
139
138
  },
@@ -184,7 +183,7 @@ function renderAgentScaffoldFiles() {
184
183
  '// Built-in Claude Code CLI agent (cliEngine: "claude-code").',
185
184
  "// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
186
185
  "export const ClaudeCodeAgent = new SmithersClaudeCodeAgent({",
187
- ' model: "claude-opus-4-6",',
186
+ ' model: "claude-opus-4-7",',
188
187
  " cwd: process.cwd(),",
189
188
  ' // systemPrompt: "Add shared instructions for every Claude run.",',
190
189
  " // timeoutMs: 10 * 60 * 1000,",
@@ -280,9 +279,10 @@ function renderPrompts() {
280
279
  "",
281
280
  "Reviewer: {props.reviewer}",
282
281
  "",
283
- "Review the following request and respond with a concise JSON object.",
284
- "Be a very thorough reviewer who only accepts production ready tested",
285
- "code.",
282
+ "Review the following request and return ONLY the required JSON object.",
283
+ "Do not include prose, markdown, headings, commentary, or code fences.",
284
+ "The first character of your response must be `{` and the last character must be `}`.",
285
+ "Be a very thorough reviewer who only accepts production ready tested code.",
286
286
  "",
287
287
  "REQUEST:",
288
288
  "{props.prompt}",
@@ -290,6 +290,8 @@ function renderPrompts() {
290
290
  "REQUIRED OUTPUT:",
291
291
  "{props.schema}",
292
292
  "",
293
+ "Return ONLY raw JSON matching the required output schema.",
294
+ "",
293
295
  ].join("\n"),
294
296
  },
295
297
  {
@@ -413,6 +415,17 @@ function renderPrompts() {
413
415
  "",
414
416
  ].join("\n"),
415
417
  },
418
+ {
419
+ path: ".smithers/prompts/grill-me.mdx",
420
+ contents: [
421
+ "Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.",
422
+ "",
423
+ "Ask the questions one at a time.",
424
+ "",
425
+ "If a question can be answered by exploring the codebase, explore the codebase instead.",
426
+ "",
427
+ ].join("\n"),
428
+ },
416
429
  {
417
430
  path: ".smithers/prompts/write-a-prd.mdx",
418
431
  contents: [
@@ -1185,7 +1198,7 @@ function renderComponents() {
1185
1198
  "/** @jsxImportSource smithers-orchestrator */",
1186
1199
  'import { Loop, Sequence, Task, type AgentLike, type OutputTarget } from "smithers-orchestrator";',
1187
1200
  'import { z } from "zod/v4";',
1188
- 'import GrillMeSkill from "skills/grill-me/SKILL.md";',
1201
+ 'import GrillMeSkill from "../prompts/grill-me.mdx";',
1189
1202
  'import AskUserInstructions from "../prompts/ask-user-instructions.mdx";',
1190
1203
  "",
1191
1204
  "export const grillOutputSchema = z.looseObject({",
@@ -3211,7 +3224,7 @@ function renderWorkflows() {
3211
3224
  " return (",
3212
3225
  " <Worktree",
3213
3226
  " key={ticket.slug}",
3214
- " path={`.worktrees/${ticket.slug}`}",
3227
+ ' path={resolve(process.cwd(), ".worktrees", ticket.slug)}',
3215
3228
  " branch={`ticket/${ticket.slug}`}",
3216
3229
  " >",
3217
3230
  " <Sequence>",
@@ -3417,10 +3430,9 @@ export function initWorkflowPack(options = {}) {
3417
3430
  };
3418
3431
  }
3419
3432
  /**
3420
- * Install `.smithers/` workspace deps so git-specifier packages like
3421
- * `github:mattpocock/skills` which Bun's runtime auto-install doesn't fetch
3422
- * are available the first time a workflow runs. Failures here don't fail init:
3423
- * the scaffold is on disk, the user can always re-run `bun install` by hand.
3433
+ * Install `.smithers/` workspace deps so the first workflow run isn't blocked
3434
+ * on a cold install. Failures here don't fail init: the scaffold is on disk,
3435
+ * the user can always re-run `bun install` by hand.
3424
3436
  *
3425
3437
  * @param {string} rootDir
3426
3438
  * @param {boolean} skip