@kadj-amoah/showrunner 1.1.6 → 1.1.7

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to Showrunner are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project tracks loose semver — minor bumps for new capability, patch for fixes.
4
4
 
5
+ ## [1.1.7] — 2026-05-24
6
+
7
+ Hot-fix the most embarrassing thing about v1.1.6: `showrunner understand --agent` was pointing the agent at the wrong directory.
8
+
9
+ ### Fixed
10
+
11
+ - **`understand --agent` now anchors the agent at the actual product codebase, not the Showrunner scaffold.** v1.1.6 spawned `claude` with `cwd = process.cwd()`. The canonical workflow has the user `cd` into their Showrunner scaffold (`cd my-demo`) before running commands, which meant the agent explored a directory containing only template files (the scaffold's stub README, PRD stub, `scripts/`, `segments/`, `output/`) — nothing about the actual product. The agent spent 180s exploring noise and timed out.
12
+ - **Resolution order in v1.1.7** when `--agent` is set:
13
+ 1. `--project-dir <path>` flag (explicit per-invocation override)
14
+ 2. `project.codebase_root` field in `demo.yaml`, resolved relative to the config's directory
15
+ 3. `configDir/..` (the canonical scaffold-inside-product layout) — used when `-c demo.yaml` is given but no explicit anchor exists
16
+ 4. `process.cwd()` (only when no `-c` was given)
17
+ - Resolved path is now logged prominently before the agent spawns: `Generating product_model via local claude agent { projectDir: ..., source: ... }`. The `source` field tells you which rule resolved the path.
18
+
19
+ ### Added
20
+
21
+ - **`--project-dir <path>`** flag on `showrunner understand`. Override the agent's exploration root for a single invocation.
22
+ - **`project.codebase_root`** field in the config schema. Persistent override per project.
23
+ - **`init`'s generated `demo.yaml` now writes `codebase_root: ..` by default**, so newly scaffolded projects get the right behaviour without the user having to know about the field.
24
+
25
+ ### Changed
26
+
27
+ - **Claude spawn now passes `--allowedTools "Read,Glob,Grep"`** to be explicit about which tools the agent may use without prompting. v1.1.6 relied on claude's `default` permission mode, which is supposed to auto-approve reads but leaves room for ambiguity around Glob/Grep/Bash. Being explicit short-circuits any related stalling.
28
+ - **Agent spawn timeout dropped from 180s to 90s.** Failure should fail fast; three-minute waits on retest are painful.
29
+
5
30
  ## [1.1.6] — 2026-05-24
6
31
 
7
32
  Closes a long-latent gap: `showrunner understand` now has an `--agent` mode that delegates codebase exploration to the local `claude` CLI rather than relying on `comprehension.sources` to be set up correctly.
package/dist/cli.js CHANGED
@@ -76,7 +76,14 @@ import "zod";
76
76
  import { z } from "zod";
77
77
  var projectSchema = z.object({
78
78
  name: z.string().min(1),
79
- product_model: z.string().optional()
79
+ product_model: z.string().optional(),
80
+ /**
81
+ * Path to the product's codebase, resolved relative to demo.yaml's directory.
82
+ * Used by `understand --agent` to anchor the agent's exploration.
83
+ * Defaults to `..` because the canonical scaffold layout places the
84
+ * Showrunner project inside or beside the product directory.
85
+ */
86
+ codebase_root: z.string().optional()
80
87
  });
81
88
  var comprehensionSourceSchema = z.object({
82
89
  type: z.enum(["prd", "readme", "codebase", "openapi", "changelog", "custom"]),
@@ -6423,6 +6430,11 @@ function demoYamlTemplate(opts) {
6423
6430
  project:
6424
6431
  name: ${opts.name}
6425
6432
  # product_model: ./product_model.json # uncomment to skip comprehension
6433
+ # Where the product codebase lives, relative to this demo.yaml. Used by
6434
+ # \`showrunner understand --agent\` to anchor the agent's exploration.
6435
+ # Default \`..\` matches the canonical layout where the Showrunner scaffold
6436
+ # sits inside (or beside) the product directory.
6437
+ codebase_root: ..
6426
6438
 
6427
6439
  comprehension:
6428
6440
  mode: documents
@@ -7623,8 +7635,17 @@ async function generateProductModelViaAgent(opts) {
7623
7635
  const provider = new AgentBridgeLLMProvider({
7624
7636
  mode: "spawn",
7625
7637
  command: opts.command ?? "claude",
7626
- args: opts.args ?? ["-p", "--output-format", "json"],
7627
- timeoutMs: opts.timeoutMs ?? 18e4,
7638
+ args: opts.args ?? [
7639
+ "-p",
7640
+ "--output-format",
7641
+ "json",
7642
+ // Explicitly allow read-only filesystem tools so claude doesn't stall on
7643
+ // permission ambiguity in headless mode. Comma-separated per claude CLI syntax.
7644
+ "--allowedTools",
7645
+ "Read,Glob,Grep"
7646
+ ],
7647
+ // 90s cap — was 180s in v1.1.6, dropped here because failures should fail fast.
7648
+ timeoutMs: opts.timeoutMs ?? 9e4,
7628
7649
  cwd: opts.projectDir
7629
7650
  });
7630
7651
  const userPrompt = [
@@ -7748,6 +7769,7 @@ async function understandCommand(opts) {
7748
7769
  let outputRel = opts.output ?? "./product_model.json";
7749
7770
  let sources = [];
7750
7771
  let llmConfig;
7772
+ let loadedCodebaseRoot;
7751
7773
  if (opts.config) {
7752
7774
  let loaded;
7753
7775
  try {
@@ -7765,6 +7787,7 @@ async function understandCommand(opts) {
7765
7787
  }
7766
7788
  sources = loaded.config.comprehension.sources.map((s) => ({ path: s.path, type: s.type }));
7767
7789
  llmConfig = loaded.config.llm;
7790
+ loadedCodebaseRoot = loaded.config.project.codebase_root;
7768
7791
  const envFile = resolve25(loaded.configDir, ".env");
7769
7792
  try {
7770
7793
  process.loadEnvFile(envFile);
@@ -7776,8 +7799,19 @@ async function understandCommand(opts) {
7776
7799
  let productModel;
7777
7800
  try {
7778
7801
  if (opts.agent) {
7779
- const projectDir = process.cwd();
7780
- logger.info("Generating product_model via local `claude` agent", { projectDir });
7802
+ const projectDir = resolveAgentProjectDir({
7803
+ flagOverride: opts.projectDir,
7804
+ codebaseRoot: opts.config ? loadedCodebaseRoot : void 0,
7805
+ configDir: opts.config ? configDir : void 0
7806
+ });
7807
+ logger.info("Generating product_model via local `claude` agent", {
7808
+ projectDir,
7809
+ source: resolveAgentProjectDirSource({
7810
+ flagOverride: opts.projectDir,
7811
+ codebaseRoot: opts.config ? loadedCodebaseRoot : void 0,
7812
+ configDir: opts.config ? configDir : void 0
7813
+ })
7814
+ });
7781
7815
  productModel = await generateProductModelViaAgent({ projectDir });
7782
7816
  } else if (opts.interactive) {
7783
7817
  const answers = await runInteractiveQA();
@@ -7822,6 +7856,24 @@ async function understandCommand(opts) {
7822
7856
  await writeFile15(outputPath, JSON.stringify(productModel, null, 2) + "\n", "utf8");
7823
7857
  logger.info("Wrote product_model.json", { path: outputPath });
7824
7858
  }
7859
+ function resolveAgentProjectDir(input) {
7860
+ if (input.flagOverride) {
7861
+ return isAbsolute13(input.flagOverride) ? input.flagOverride : resolve25(process.cwd(), input.flagOverride);
7862
+ }
7863
+ if (input.codebaseRoot && input.configDir) {
7864
+ return isAbsolute13(input.codebaseRoot) ? input.codebaseRoot : resolve25(input.configDir, input.codebaseRoot);
7865
+ }
7866
+ if (input.configDir) {
7867
+ return resolve25(input.configDir, "..");
7868
+ }
7869
+ return process.cwd();
7870
+ }
7871
+ function resolveAgentProjectDirSource(input) {
7872
+ if (input.flagOverride) return "--project-dir flag";
7873
+ if (input.codebaseRoot && input.configDir) return "project.codebase_root in demo.yaml";
7874
+ if (input.configDir) return "configDir/.. (default; set project.codebase_root to override)";
7875
+ return "cwd (no -c flag)";
7876
+ }
7825
7877
 
7826
7878
  // src/commands/instrument.ts
7827
7879
  import { mkdir as mkdir16, readdir as readdir4, writeFile as writeFile16 } from "fs/promises";
@@ -8442,7 +8494,7 @@ async function fileExists10(path) {
8442
8494
 
8443
8495
  // src/cli.ts
8444
8496
  var program = new Command();
8445
- program.name("showrunner").description("Automated product demo recording & production tool").version("1.1.6").option("--json", "emit structured JSON logs to stdout").option("--log-level <level>", "log level (debug|info|warn|error)").hook("preAction", (thisCmd) => {
8497
+ program.name("showrunner").description("Automated product demo recording & production tool").version("1.1.7").option("--json", "emit structured JSON logs to stdout").option("--log-level <level>", "log level (debug|info|warn|error)").hook("preAction", (thisCmd) => {
8446
8498
  const opts = thisCmd.opts();
8447
8499
  if (opts.json) logger.setJson(true);
8448
8500
  if (opts.logLevel) logger.setLevel(opts.logLevel);
@@ -8481,7 +8533,10 @@ program.command("doctor").description("Run preflight checks on the current confi
8481
8533
  program.command("validate").description("Validate a demo.yaml config file").requiredOption("-c, --config <path>", "path to demo.yaml").option("--strict", "exit nonzero on any warning (e.g. missing provider env var)").action(validateCommand);
8482
8534
  program.command("understand").description("Build product_model.json from documents, interactive Q&A, or agent-driven repo exploration").option("-c, --config <path>", "path to demo.yaml").option("--interactive", "use interactive Q&A mode (5 prompts, no LLM)").option(
8483
8535
  "--agent",
8484
- "delegate to the local `claude` CLI: it explores the current directory with its read tools and synthesizes the product model. Closes the type=codebase gap in demo.yaml sources."
8536
+ "delegate to the local `claude` CLI: it explores the project with its read tools and synthesizes the product model. Closes the type=codebase gap in demo.yaml sources."
8537
+ ).option(
8538
+ "--project-dir <path>",
8539
+ "directory the --agent run should explore. Overrides project.codebase_root from demo.yaml. Defaults to configDir/.. when -c is given, or cwd otherwise."
8485
8540
  ).option("--output <path>", "output path for product_model.json").action(understandCommand);
8486
8541
  program.command("instrument").description("Suggest data-testid attributes for a codebase").requiredOption("-c, --config <path>", "path to demo.yaml").requiredOption("--output <path>", "unified diff output path").option("--glob <pattern>", "override comprehension.sources with an ad-hoc glob (relative to configDir)").action(instrumentCommand);
8487
8542
  program.command("record-actions").description("Author manifest actions by demonstrating them in a live browser").requiredOption("-c, --config <path>", "path to demo.yaml").option("--segment <id>", "replace actions for an existing segment id").option("--output <path>", "manifest output path (default ./scripts/manifest.json)").action(recordActionsCommand);
@@ -8507,7 +8562,7 @@ async function printWelcome() {
8507
8562
  } catch {
8508
8563
  }
8509
8564
  const browserMissing = await isChromiumMissing();
8510
- const lines = ["", `Showrunner v1.1.6`, ""];
8565
+ const lines = ["", `Showrunner v1.1.7`, ""];
8511
8566
  if (browserMissing) {
8512
8567
  lines.push(`Showrunner records using Chromium. You haven't installed it yet.`);
8513
8568
  lines.push(``);