Problem
-v, --verbose is advertised (packages/cli/src/index.ts:90, help.ts:133) and parsed into GlobalOptions.verbose (index.ts:104) but never read by any command handler — output is identical with or without it. Both top-level catches print only error.message and discard the stack and any cause chain: CLI at index.ts:744-749, orchestrator at packages/orchestrator/src/index.ts:299-304. Errors are constructed with { cause } (e.g. packages/core/src/workflow/render.ts:237-244) but the cause is never surfaced.
Impact (OSS user)
An operator hitting an opaque failure re-runs with -v expecting more detail, gets none, and can never obtain a stack trace for a useful bug report without editing source.
Evidence (real files)
packages/cli/src/index.ts:90, 104, 744-749; packages/cli/src/commands/help.ts:133.
packages/orchestrator/src/index.ts:299-304; packages/core/src/workflow/render.ts:237-244.
Proposed fix
In both top-level catches, when verbose is set print error.stack and walk error.cause instead of just error.message. Thread the verbose flag into handlers (or read argv for -v/--verbose in the orchestrator catch). Document that -v adds stack traces.
Re-examination (re-verified against current code)
All claims confirmed against current code. (1) -v, --verbose is declared at packages/cli/src/index.ts:90, parsed into GlobalOptions.verbose at :104 (and :165 for the version path), advertised in help at packages/cli/src/commands/help.ts:133. A repo-wide grep for verbose shows GlobalOptions.verbose is NEVER read by any command handler — the only verbose mentions inside commands/ are the help string and packages/cli/src/workflow/workflow-runtime.ts:15, which is a --verbose arg passed to a Claude CLI subprocess (unrelated to the global flag). So the flag is genuinely inert. (2) The CLI top-level catch (index.ts:744-749) prints only error.message; the orchestrator top-level catch (packages/orchestrator/src/index.ts:299-304) does the same. Both discard error.stack and error.cause. (3) Errors are constructed with { cause } at packages/core/src/workflow/render.ts:237,241,244, confirming cause chains exist but are never surfaced. Added nuance the original missed: (a) the orchestrator already controls verbosity via a SEPARATE --log-level verbose / SYMPHONY_LOG_LEVEL mechanism (orchestrator/src/index.ts:31-41,75-76; service.ts:98,2193) that is fully disconnected from the CLI -v flag; (b) the codebase already surfaces error.stack elsewhere (packages/cli/src/commands/start.ts:522, packages/orchestrator/src/service.ts:1112), so the fix has an in-repo precedent; (c) the orchestrator binary is a hidden internal subprocess spawned by start (start.ts:1086), not normally run directly by users, so the orchestrator-catch half has narrower reach than the CLI half.
Deeper context / scenario: Root cause: -v was wired into the option-parsing layer (GlobalOptions) but no consumer was ever implemented, while a parallel and unrelated verbosity path (--log-level verbose/SYMPHONY_LOG_LEVEL) was built for the orchestrator service — leaving two diverging "verbose" concepts where the user-facing one does nothing. Compounding this, both process-level error sinks reduce any thrown Error to its single-line .message, deliberately throwing away .stack and the .cause chain even though core code (render.ts) carefully attaches causes via new Error(msg, { cause }). Blast radius: every CLI command (doctor, start, workflow, status, run, upgrade, etc.) inherits the dead -v flag, and any uncaught error from any command or from the orchestrator subprocess prints only a terse message such as template_render_error: undefined variable: foo with no file/line, no stack, and no underlying ParseError/RenderError cause. Concrete scenario: I run gh-symphony workflow ..., hit template_render_error: ..., re-run with -v exactly as the help text invites, and get byte-for-byte identical output; I have no way to produce a stack trace or see the wrapped LiquidJS parse error for a bug report without checking out the source and editing the catch block. Related nuance: even fixing the catches to print stacks unconditionally would help, but the cleanest fix is to (a) thread GlobalOptions.verbose into the catch (or re-scan argv in the orchestrator catch, mirroring index.ts:165) and walk the cause chain, and (b) optionally bridge -v to --log-level verbose so the two verbosity concepts converge. There is also a latent expectation mismatch: a user may reasonably expect -v to increase orchestrator log verbosity too, which it currently cannot.
Priority: P2 (re-ranked P2-A, overall #1 of 16) · impact: medium · reach: many-users · type: ux-polish · effort: S · quick win
Re-classified from an OSS-user-perspective P2 re-assessment.
Problem
-v, --verboseis advertised (packages/cli/src/index.ts:90,help.ts:133) and parsed intoGlobalOptions.verbose(index.ts:104) but never read by any command handler — output is identical with or without it. Both top-level catches print onlyerror.messageand discard the stack and anycausechain: CLI atindex.ts:744-749, orchestrator atpackages/orchestrator/src/index.ts:299-304. Errors are constructed with{ cause }(e.g.packages/core/src/workflow/render.ts:237-244) but the cause is never surfaced.Impact (OSS user)
An operator hitting an opaque failure re-runs with
-vexpecting more detail, gets none, and can never obtain a stack trace for a useful bug report without editing source.Evidence (real files)
packages/cli/src/index.ts:90, 104, 744-749;packages/cli/src/commands/help.ts:133.packages/orchestrator/src/index.ts:299-304;packages/core/src/workflow/render.ts:237-244.Proposed fix
In both top-level catches, when verbose is set print
error.stackand walkerror.causeinstead of justerror.message. Thread the verbose flag into handlers (or read argv for-v/--verbosein the orchestrator catch). Document that-vadds stack traces.Re-examination (re-verified against current code)
All claims confirmed against current code. (1)
-v, --verboseis declared at packages/cli/src/index.ts:90, parsed into GlobalOptions.verbose at :104 (and :165 for the version path), advertised in help at packages/cli/src/commands/help.ts:133. A repo-wide grep forverboseshows GlobalOptions.verbose is NEVER read by any command handler — the onlyverbosementions inside commands/ are the help string and packages/cli/src/workflow/workflow-runtime.ts:15, which is a--verbosearg passed to a Claude CLI subprocess (unrelated to the global flag). So the flag is genuinely inert. (2) The CLI top-level catch (index.ts:744-749) prints onlyerror.message; the orchestrator top-level catch (packages/orchestrator/src/index.ts:299-304) does the same. Both discarderror.stackanderror.cause. (3) Errors are constructed with{ cause }at packages/core/src/workflow/render.ts:237,241,244, confirming cause chains exist but are never surfaced. Added nuance the original missed: (a) the orchestrator already controls verbosity via a SEPARATE--log-level verbose/SYMPHONY_LOG_LEVELmechanism (orchestrator/src/index.ts:31-41,75-76; service.ts:98,2193) that is fully disconnected from the CLI-vflag; (b) the codebase already surfaceserror.stackelsewhere (packages/cli/src/commands/start.ts:522, packages/orchestrator/src/service.ts:1112), so the fix has an in-repo precedent; (c) the orchestrator binary is a hidden internal subprocess spawned bystart(start.ts:1086), not normally run directly by users, so the orchestrator-catch half has narrower reach than the CLI half.Deeper context / scenario: Root cause:
-vwas wired into the option-parsing layer (GlobalOptions) but no consumer was ever implemented, while a parallel and unrelated verbosity path (--log-level verbose/SYMPHONY_LOG_LEVEL) was built for the orchestrator service — leaving two diverging "verbose" concepts where the user-facing one does nothing. Compounding this, both process-level error sinks reduce any thrown Error to its single-line.message, deliberately throwing away.stackand the.causechain even though core code (render.ts) carefully attaches causes vianew Error(msg, { cause }). Blast radius: every CLI command (doctor, start, workflow, status, run, upgrade, etc.) inherits the dead-vflag, and any uncaught error from any command or from the orchestrator subprocess prints only a terse message such astemplate_render_error: undefined variable: foowith no file/line, no stack, and no underlying ParseError/RenderError cause. Concrete scenario: I rungh-symphony workflow ..., hittemplate_render_error: ..., re-run with-vexactly as the help text invites, and get byte-for-byte identical output; I have no way to produce a stack trace or see the wrapped LiquidJS parse error for a bug report without checking out the source and editing the catch block. Related nuance: even fixing the catches to print stacks unconditionally would help, but the cleanest fix is to (a) thread GlobalOptions.verbose into the catch (or re-scan argv in the orchestrator catch, mirroring index.ts:165) and walk thecausechain, and (b) optionally bridge-vto--log-level verboseso the two verbosity concepts converge. There is also a latent expectation mismatch: a user may reasonably expect-vto increase orchestrator log verbosity too, which it currently cannot.Priority: P2 (re-ranked P2-A, overall #1 of 16) · impact: medium · reach: many-users · type: ux-polish · effort: S · quick win
Re-classified from an OSS-user-perspective P2 re-assessment.