-
args arrives as a JSON string, not an object. args.foo is always undefined → silent fallback to defaults. Normalize at the top of every script:
const A = (() => { try { return typeof args === 'string' ? JSON.parse(args) : (args && typeof args === 'object' ? args : {}) } catch { return {} } })()
Then read A.foo. (A no-arg args-probe workflow that return { typeofArgs: typeof args } confirms this.)
-
Nesting is ONE level. workflow() inside a child throws. So dev-loop → review is fine, but review must NOT call workflow() — its dogfood is an inline phase (agent + Playwright), not a nested workflow. reconcile only detects/judges; the integrator does the actual fold.
-
Parallel dev = main session fans out, not a parent workflow. A parent-workflow → dev-loop → review would be 2 levels. Instead the main session launches several dev-loop runs concurrently (each its own task), and folds results via reconcile.
-
Parallel dev-loops run in isolated worktrees. A bare git worktree has no node_modules, but node .claude/scripts/new-worktree.mjs <name> [baseRef] does git worktree add .claude/worktrees/<name> + pnpm install --prefer-offline (~6s, warm pnpm store) so tests/typecheck run isolated there. Parallel pattern: the integrator (main session) creates one ready worktree per independent item, launches a dev-loop with cwd=<that worktree> (cwd-aware: git -C <cwd> + agents edit under it), runs several concurrently, then reconcile before folding. The main session stays at repo root (never cds away — see #5). A single-task dev-loop may still run on the main tree (implement stages only its files, never -A).
-
Compose with a REPO-ROOT-RELATIVE scriptPath (.claude/workflows/review.workflow.mjs) and NEVER cd away from repo root while workflows run. The runtime resolves a relative scriptPath against the session cwd at call time. Because the repo mandates that the main session stays at repo root (it passes absolute paths to Bash / uses git -C, never cds away), a repo-relative scriptPath always resolves. An absolute /Users/... path is banned for shared workflows — it breaks for every other contributor and clone location (this repo is public OSS). The workflow sandbox has no import.meta/__dirname/process.cwd/fs, so there is no programmatic path anchor; relative-path-plus-no-cd-discipline is the only portable mechanism. (History: an unguarded relative path once broke a 43-min/3M-token run when a Bash cd changed cwd mid-run — the fix is the no-cd discipline, not an absolute path.)
-
.claude/workflows/ is NOT name-registered. Workflow({name:'review'}) fails; launch with Workflow({scriptPath:'.claude/workflows/review.workflow.mjs'}). The dir is tracked in git like the rest of .claude/'s shared tooling — a new/edited workflow script lands as a normal commit, no git add -f needed.
-
Custom agents added mid-session are NOT in the agentType registry until a session reload. Writing .claude/agents/foo.md and immediately launching a workflow that does agent({agentType:'foo'}) throws agent type 'foo' not found (the registry is snapshotted at session start) — the workflow still runs but every such agent() call fails (verified: investigate fanned out 6 dimensions, all failed, only the registered architect synth survived). Default workflow agentTypes to already-registered agents (architect, Explore, developer, general-purpose, reviewer-dimension, plan-reviewer, qa-scenario, security-scanner, code-simplifier:code-simplifier, the planning panel, codex:codex-rescue…) and thread an override arg for the tuned custom one (e.g. investigate defaults its investigator to Explore, overridable via args.investigatorAgent). Reload the session before relying on a newly-authored agent as a workflow agentType.
-
Fold from the branch TIP, not implReport.headSha. A dev-loop commits again after the implement phase (simplify, fix rounds, an extra docs/test fix), so the returned implReport.headSha is mid-run and stale. When the integrator folds (cherry-pick/merge), resolve the range from the live branch tip — git -C <worktree> rev-parse HEAD or git rev-parse <branch> — never the reported impl sha. Cherry-picking base..<implHeadSha> silently drops every later commit. After folding, verify with git cherry HEAD <oldTip> (any + line = an unapplied commit) before deleting the branch.