Skip to content

Latest commit

 

History

History
142 lines (104 loc) · 9.98 KB

settings.md

File metadata and controls

142 lines (104 loc) · 9.98 KB

Settings

Settings live in three places, by who has to agree on them and their shape: a value the whole team shares goes in beads config; a list the team shares goes in .claude/sdlc.md; anything true only on this machine goes in .claude/sdlc.local.md. /sdlc:init creates all three with defaults, and changes them when run again with options, for example /sdlc:init --integration epic-merge --parallel 3.

Beyond these, an epic or a task can override part of the project's settings for itself, in its own beads metadata. scripts/settings.sh prints every project-wide value; scripts/settings.sh <key> prints one; scripts/settings.sh sources prints the docs sources. /sdlc:status shows the same values.

.claude/sdlc.local.md

YAML frontmatter in the main checkout. It is personal to this machine, so keep it out of git (/sdlc:init adds .claude/*.local.md to .gitignore).

---
parallel: 3
workflow: build
---
Key Default Read by Meaning
parallel 2 settings.sh, sdlc:dispatch workers running at a time on this machine
workflow unset hooks/session-start.sh build: a SessionStart hook tells new sessions in this project to start new work with /sdlc:build. Any other value, or unset, does nothing

Beads config (custom.dispatch.*)

Stored in the beads database, so every machine and person dispatching the repository sees the same values.

bd config set custom.dispatch.integration epic-merge
bd config set custom.dispatch.target main
bd config set custom.dispatch.review none
Key Default Read by Meaning
custom.dispatch.integration direct run-task.sh direct, epic-merge or epic-pr; see integration
custom.dispatch.target the main checkout's current branch, else main run-task.sh, settings.sh branch the work ends up in
custom.dispatch.review agent finish-task.py none, agent or human: review level for a task with no review metadata of its own; see reviews
custom.dispatch.debug unset verify.sh free text a failed verify command prints for the worker, naming the debugging skill or command to reach for, e.g. use the debugging-python skill or pytest -x --pdb
custom.dispatch.ccn 15 analyse-branch.sh, metrics.sh (via /sdlc:review) cyclomatic complexity a function may reach before it's a finding
custom.dispatch.function_length 100 analyse-branch.sh, metrics.sh (via /sdlc:review) lines of code a function may reach before it's a finding
custom.dispatch.analysis off supervise.py off or auto: whether the supervisor runs the branch analysis on its sweeps

Per-epic metadata overrides

Set on an epic bead, they override the project-wide beads config for that epic only.

Key Default Read by Meaning
dispatch_integration falls back to custom.dispatch.integration run-task.sh this epic's integration mode; set with bd update <epic> --set-metadata dispatch_integration=epic-pr before the epic's first dispatch — it has no effect afterward
review none finish-task.py this epic's own review level, applied to the epic diff (target...epic-branch) by the integration task before it merges or opens the pull request. Never falls back to custom.dispatch.review, so an epic with no review metadata skips review entirely

Per-task metadata hints

Set by create-task.sh (used by /sdlc:create-task and /sdlc:split), or by hand with bd update <task> --set-metadata <key>=<value>.

Key Read by Meaning
execution_agent_type run-task.sh (put in the worker's prompt) the installed agent (Agent tool) the worker hands the implementation to. Doesn't change which CLI agent runs the worker session
execution_suggested_model start-worker.sh --model for the worker session; with none set, the worker's own agent frontmatter (sdlc:worker/sdlc:integrator/sdlc:analyst) decides
execution_reasoning_effort start-worker.sh --effort for the worker session
review finish-task.py this task's review level (none, agent or human), overriding custom.dispatch.review
verify run-task.sh (required before dispatch), verify.sh, finish-task.py the command that must exit 0 for the task to be considered done
scope put into the worker's prompt and into /sdlc:review's summary comma-separated path prefixes the task changes; informational, not enforced by any script
complexity start-worker.sh, shown in the worker prompt small, medium or large; large runs the worker on opus unless execution_suggested_model is set, and makes it coordinate sonnet subagents instead of implementing

Without execution_agent_type/execution_suggested_model/execution_reasoning_effort, the worker is a plain sdlc:worker session on its default model (sonnet), or opus for a large task. Its execution mode comes from complexity (see agents/worker.md) and overrides any delegation rule in the project's CLAUDE.md.

Prompt templates: .config/sdlc/

run-task.sh builds the worker's prompt from a template. The plugin's defaults are templates/worker-prompt.md and templates/integration-prompt.md (the latter for an epic's integration task). A file of the same name in .config/sdlc/ of the project's main checkout replaces the default. An override that exists but can't be read fails the dispatch before the task is claimed (exit 2).

Placeholders are rendered by scripts/render-template.py:

  • {{id}}, {{title}} and any other top-level field of bd show <task> --json
  • {{metadata.<key>}} for a task metadata key
  • {{epic.id}}, {{epic.title}}, {{epic.description}} for the nearest epic above the task
  • {{base}}, {{branch}}, {{target}}, {{epic}} from --var NAME=VALUE: the branch the worktree starts from, the task's branch, the dispatch target branch, and the epic id (empty without an epic)

A missing or null value renders empty, and a line whose placeholders all rendered empty is dropped, so an optional line is one line per placeholder. An unclosed {{ is left as written.

Docs outside the repository: sources

The sources key lists places /sdlc:prior-art searches before the repository, in the order given. Shared ones go in .claude/sdlc.md (committed); paths that exist only on this machine go in .claude/sdlc.local.md. /sdlc:init creates sdlc.md with an empty list.

---
sources:
  - name: Engineering wiki
    via: notion
    where: https://www.notion.so/acme/Engineering-1a2b
    holds: designs and ADRs before 2025
  - name: Product vault
    via: path
    where: ~/vaults/acme
    holds: product notes, meeting summaries
---
Field Meaning
name how the source is named in the prior-art report
via path for a directory on disk; otherwise the word that finds the tool that reaches it, such as notion, drive, confluence or jira. The plugin installs no such tool; when none matches, the report says the source was unreachable
where the directory, URL or folder name; a value starting with ~/ expands to $HOME
holds what the source can answer, so it's skipped for questions it can't

A listed source is consented: /sdlc:prior-art searches it without asking, in headless sessions too. See prior art for how sources are searched.

Project hooks: .config/wt.toml

Hooks are optional: sdlc works with none configured. /sdlc:hooks reads the project (manifests, lock files, CI, task runners, git hook managers) and proposes wt hooks for what sdlc itself triggers:

pre-start = "pnpm install --frozen-lockfile"

[pre-merge]
lint = "npm run lint"
typecheck = "npm run typecheck"
test = "npm test"
Hook Triggered by Purpose
pre-start a task's worktree is created (run-task.sh via wt switch --create) install dependencies from the lock file, generate env files, before the worker starts
[pre-merge] before a task merges (finish-task.py, and the project's own wt merge) the project's fast checks (type check, lint, unit tests); never slow end-to-end, deploy or release steps

The project's own git hooks (husky, lefthook, pre-commit, .git/hooks) keep running on every worker commit, in every worktree, since workers commit with plain git; wt.toml hooks are separate from them.

The first time a machine runs one of these commands, wt asks for approval; non-interactively it fails instead. An unapproved pre-start hook stops a task from starting — wt switch --create fails and the supervisor reports the task as not started — and an unapproved pre-merge hook fails the merge, which finish-task.py reports as needing a person. A person approves once, in the main checkout:

wt config approvals add

Environment variables

Variable Set by Read by Meaning
DISPATCH_TASK start-worker.sh (via env) hooks/session-start.sh, hooks/worker-guard.sh, hooks/worker-stop.sh the task id a worker session is running; its presence marks the session as a worker, gating the worker hooks
SDLC_SUPERVISOR supervise.py, for its own bd calls the beads hooks /sdlc:init installs (.beads/hooks/on_*) when set, a beads hook's write to the wake pipe is skipped, so the supervisor's own writes don't wake itself again. start-worker.sh unsets it (env -u SDLC_SUPERVISOR) before running a worker or record-task.sh, so their writes do wake the supervisor
SDLC_REVIEW_MODEL set by hand, in the environment of the machine that dispatches finish-task.py the model an agent-level review runs on when no reviewer agent is installed (~/.claude/agents/reviewer.md or .claude/agents/reviewer.md); default sonnet

See task fields for the dispatch_* metadata the scripts set on a task as it runs, and hooks for what the plugin's own hooks do.