You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,14 +57,14 @@ Priority: 0-4 (0=critical, 4=backlog). Never use "high"/"medium"/"low".
57
57
58
58
## Architecture
59
59
60
-
**Ticket system v3 (event-sourced)**: The ticket system uses an orphan git branch named `tickets` mounted as a worktree at `.tickets-tracker/`. All mutations append JSON event files to per-ticket directories; the compiled state is produced on-demand by the Python reducer (`ticket-reducer.py`). Writes are serialized with `fcntl.flock` to prevent concurrent corruption. The primary CLI entry point is `ticket <subcommand>` (dispatcher at `plugins/dso/scripts/ticket`); the higher-level `tk-sync-lib.sh` library adds Jira sync, dependency trees, and human-friendly output. Full CLI reference: `plugins/dso/docs/ticket-cli-reference.md`. **Jira bridge**: `.claude/scripts/dso ticket sync` (incremental default, `--full` to force, `--check` for dry-run). Requires `JIRA_URL`, `JIRA_USER`, `JIRA_API_TOKEN`.
60
+
**Ticket system v3 (event-sourced)**: The ticket system uses an orphan git branch named `tickets` mounted as a worktree at `.tickets-tracker/`. All mutations append JSON event files to per-ticket directories; the compiled state is produced on-demand by the Python reducer (`ticket-reducer.py`). Writes are serialized with `fcntl.flock` to prevent concurrent corruption. The primary CLI entry point is `ticket <subcommand>` (dispatcher at `plugins/dso/scripts/ticket`); higher-level utility scripts add Jira sync, dependency trees, and human-friendly output. Full CLI reference: `plugins/dso/docs/ticket-cli-reference.md`. **Jira bridge**: `.claude/scripts/dso ticket sync` (incremental default, `--full` to force, `--check` for dry-run). Requires `JIRA_URL`, `JIRA_USER`, `JIRA_API_TOKEN`.
61
61
**Hook architecture**: Consolidated dispatchers (2 processes per Bash tool call: `pre-bash.sh` + `post-bash.sh`). All hooks are jq-free — use `parse_json_field`, `json_build`, and `python3` for JSON parsing. Hook optimization: `tool_logging` and `tool_use_guard` removed from per-call dispatchers; `validation_gate` removed from Edit/Write dispatchers (kept in pre-bash.sh); early-exit guards skip narrow hooks when command keywords don't match. Review workflow timing fix: hash capture occurs after auto-fix passes to prevent drift. On review gate mismatch, diagnostic dump writes to `$ARTIFACTS_DIR/mismatch-diagnostics-<timestamp>.log`; breadcrumb trail in `$ARTIFACTS_DIR/commit-breadcrumbs.log`. See `plugins/dso/hooks/dispatchers/` and `plugins/dso/hooks/lib/`. **Review gate (two-layer defense-in-depth)**: Layer 1 — `pre-commit-review-gate.sh` is a git pre-commit hook (registered in `.pre-commit-config.yaml`); uses `git diff --cached --name-only` for reliable staged-file detection (no command-string parsing); default-deny allowlist from `review-gate-allowlist.conf`; checks review-status file + diff hash; writes JSONL telemetry to `$ARTIFACTS_DIR/review-gate-telemetry.jsonl`; formatting-only hash mismatches self-heal by re-running `ruff format`. Layer 2 — `review-gate.sh` is a PreToolUse hook (thin wrapper around `review-gate-bypass-sentinel.sh`); blocks bypass vectors: `--no-verify`, `-n` on git commit, `core.hooksPath=` override, `git commit-tree`, direct `.git/hooks/` writes, direct writes/deletions to `test-gate-status` and `test-exemptions` (only `record-test-status.sh` and `record-test-exemption.sh` are authorized writers). Test suite: `bash tests/hooks/test-two-layer-review-gate.sh` (or via `bash tests/run-all.sh`). **test gate (two-layer defense-in-depth)**: Layer 1 — `pre-commit-test-gate.sh` is a git pre-commit hook (registered in `.pre-commit-config.yaml`); for each staged source file with an associated test (found via fuzzy matching or `.test-index`), verifies that `test-gate-status` in `$ARTIFACTS_DIR` is present, has `passed` on line 1, and has a matching `diff_hash`; files with no associated test are exempt. Test directories are configurable via `test_gate.test_dirs` in `.claude/dso-config.conf` (default: `tests/`). `.test-index` — a repo-root file for mapping source files to unconventionally-named tests; format: `source/path.ext: test/path1.ext, test/path2.ext` (one entry per line; `#` comments and blank lines ignored); associations from `.test-index` are unioned with fuzzy-match results; the hook self-heals by pruning stale entries (test paths that no longer exist on disk) atomically before each commit and auto-staging the result; `.test-index` is excluded from the diff hash (via `review-gate-allowlist.conf`) to prevent mismatch loops when pruning modifies it. **RED marker format**: `source/path.ext: test/path.ext [first_red_test_name]` — the optional `[marker]` after a test path marks the boundary between GREEN tests (already passing) and RED tests (not yet implemented); failures at or after `first_red_test_name` are tolerated (non-blocking), failures before it still block. RED tests must be placed at the end of the test file. **TDD workflow for agents**: When writing a TDD test for a not-yet-implemented feature, add the test at the end of the test file and add a `[test_name]` marker to the `.test-index` entry — e.g., `source/foo.sh: tests/test_foo.sh [test_new_feature]`. After implementation passes, remove the `[marker]` from `.test-index`. **Epic closure enforcement**: `.claude/scripts/dso ticket transition <epic-id> open closed` is blocked while any `[marker]` entries remain in `.test-index` — remove all RED markers before closing an epic. Layer 2 — `review-gate-bypass-sentinel.sh` blocks direct writes/deletions to `test-gate-status` and `test-exemptions`; only `record-test-status.sh` (authorized by COMMIT-WORKFLOW.md Step 3.5) and `record-test-exemption.sh` (for inherently slow tests, exit 124) may write these files.
62
62
**Validation gate**: `validate.sh` writes state; hooks block sprint/epic if validation hasn't passed. `--verbose` for real-time progress.
63
63
**Agent routing** (dynamic discovery): `discover-agents.sh` resolves routing categories (e.g., `test_fix_unit`, `complex_debug`) to the best available agent using `agent-routing.conf`. Optional plugins (feature-dev, error-debugging, playwright) are preferred when installed; all categories fall back to `general-purpose` with category-specific prompts from `prompts/fallback/<category>.md`. See `plugins/dso/docs/INSTALL.md` for optional plugin documentation. **Named-agent dispatch** (distinct from routing-category dispatch): dedicated plugin agents are dispatched directly via `subagent_type` — `dso:complexity-evaluator` (haiku; dispatched by `/dso:sprint` and `/dso:brainstorm`, read inline by `/dso:fix-bug` due to nesting constraints; uses a 6-dimension rubric including a **blast-radius scoring step**: discovered files are piped into `plugins/dso/scripts/blast-radius-score.py`, which outputs `blast_radius_score` and `complex_override`; when `complex_override=true` the evaluator forces COMPLEX regardless of other dimensions; the script is gracefully skipped if absent or non-zero) and `dso:conflict-analyzer` (sonnet; dispatched by `/dso:resolve-conflicts`). The complexity evaluator also emits `pattern_familiarity`, `external_boundary_count`, and `feasibility_review_recommended` fields for integration risk assessment. Additional planning agents: `dso:feasibility-reviewer` (sonnet; dispatched by `/dso:brainstorm` as a conditional 4th fidelity reviewer for epics with external integration signals), `dso:red-team-reviewer` (opus; dispatched by `/dso:preplanning` Phase 2.5 adversarial review — dedicated agent replacing generic agent with prompted template; covers 6 taxonomy categories including Consumer Impact and Operational Readiness), `dso:blue-team-filter` (sonnet; dispatched by `/dso:preplanning` Phase 2.5 — replaces generic agent, persists full exchange to `$ARTIFACTS_DIR/adversarial-review-<epic-id>.json`), and `dso:completion-verifier` (sonnet; dispatched by `/dso:sprint` at story closure Step 10a and epic closure Phase 7 Step 0.75 — answers "did we build what the spec says?" by verifying success criteria for epics and done definitions for stories; test pass/fail, code quality, and lint are explicitly out of scope). The **tiered code-review agents** are also named-agent dispatched by `/dso:review` (REVIEW-WORKFLOW.md Step 4): `dso:code-reviewer-light` (haiku; light tier), `dso:code-reviewer-standard` (sonnet; standard tier), `dso:code-reviewer-deep-correctness` + `dso:code-reviewer-deep-verification` + `dso:code-reviewer-deep-hygiene` (three parallel sonnet agents; deep tier), and `dso:code-reviewer-deep-arch` (opus; deep tier architectural synthesis). **Tiered review system**: `plugins/dso/scripts/review-complexity-classifier.sh` scores each diff on 7 factors (`blast_radius`, `critical_path`, `anti_shortcut`, `staleness`, `cross_cutting`, `diff_lines`, `change_volume`); score 0–2 → light tier (haiku), 3–6 → standard tier (sonnet), 7+ → deep tier (3 parallel sonnet + opus arch synthesis); floor rules ensure sensitive changes get adequate scrutiny; diff size thresholds: 300+ lines → opus model upgrade, 600+ lines → rejection; merge commits bypass size limits. See `plugins/dso/docs/contracts/classifier-tier-output.md` and `plugins/dso/docs/contracts/classifier-size-output.md` for the classifier output contracts. **Review output schema** (5 dimensions): `correctness`, `verification`, `hygiene`, `design`, `maintainability` — these are the current dimension key names in `reviewer-findings.json`; light/standard tier agents score all five, deep tier sonnet agents each score a subset with N/A for the rest, and the opus arch agent synthesizes the final result. All these agents are defined in `plugins/dso/agents/` and are not resolved through `discover-agents.sh`.
**brainstorm SC alignment gate**: `/dso:brainstorm` Phase 2 Step 2.5 runs an **artifact contradiction detection** pass before the fidelity review. It extracts all artifact names the user explicitly mentioned (file paths, CLI tool names, API endpoints, config keys, etc.) and checks whether each is covered — directly or by fuzzy/partial match — by at least one success criterion. Uncovered artifacts are surfaced to the user as gaps before the fidelity reviewers run. This prevents success criteria from silently omitting capabilities the user explicitly requested. After resolving artifact gaps, the same step runs a technical approach self-review (sync loops, race conditions, parsing ambiguities).
66
66
**implementation-plan bidirectional TDD**: `/dso:implementation-plan` Step 3 treats test modification as a first-class RED-phase activity. Before drafting tasks, it builds a **file impact table** classifying each affected source file as `create`, `modify`, `remove`, or no-change. Files classified `needs-modification` require a **modify-existing-test** RED task — the test is updated to assert the new expected behavior before the implementation runs, then fails (RED) until implementation is complete. Files classified `needs-creation` get the standard create-test RED task. Files classified `needs-removal` get a remove-test task. Files classified `still-valid` require no test task. This ensures existing tests are updated when behavior changes, not left stale.
67
-
**This repo is the `dso` plugin.** Skills: interface-contracts, resolve-conflicts, tickets-health, design-onboarding, design-review, design-wireframe, ui-discover, debug-everything, sprint, brainstorm, preplanning, implementation-plan, fix-bug (canonical bug-fix workflow; replaces tdd-workflow for bug fixes), tdd-workflow (new feature TDD only), etc. Commands (commit, end, review) also come from the plugin. Skills are invoked as `/dso:skill-name` (fully qualified, required) or `/skill-name` (command alias, allowed but not preferred in docs). **Skill namespace qualification policy**: all skill invocations in in-scope files (plugins/dso/skills/, plugins/dso/docs/, plugins/dso/hooks/, plugins/dso/commands/, CLAUDE.md) MUST use the qualified `/dso:<skill-name>` form. `plugins/dso/scripts/check-skill-refs.sh` enforces this as a fatal CI check via `plugins/dso/scripts/validate.sh`; it exits non-zero when any unqualified reference is found. `plugins/dso/scripts/qualify-skill-refs.sh` is the one-shot bulk rewriter (idempotent) that transforms `/skill-name` → `/dso:skill-name` across all in-scope files — run it after adding new in-scope content with unqualified refs. Ticket scripts in `plugins/dso/scripts/` (`ticket` dispatcher, `tk-sync-lib.sh`, and 22+ utility scripts). Project-specific config in `.claude/dso-config.conf` (flat KEY=VALUE format; keys: `format.*`, `ci.*`, `commands.*`, `jira.*`, `design.*`, `tickets.*`, `merge.*`, `version.*`). `version.*` config keys: `version.file_path` (path to the file holding the project's semver string; absent = skip version bumping; supported formats: `.json` → `version` key, `.toml` → `version` field, plaintext/no-extension → single semver line). `test.*` config keys: `test.suite.<name>.command` (shell command to run the suite; config-only suites get `runner=config`), `test.suite.<name>.speed_class` (`fast|slow`; overrides auto-discovered default of `unknown`). Config entries merge with auto-discovered suites by name: config wins on explicitly set fields. Use `project-detect.sh --suites [REPO_ROOT]` to discover test suites — outputs a JSON array with `name`, `command`, `speed_class`, `runner` fields (exit 0 always). Heuristics in precedence order: config > Makefile `/^test[-_]/` > pytest dirs > npm scripts > bash runners. **CI workflow generation** (`/dso:project-setup`): when no `.github/workflows/*.yml` exist, `project-detect.sh --suites` feeds directly into `ci-generator.sh --suites-json <json> --output-dir .github/workflows/` to generate `ci.yml` (fast suites, pull_request trigger) and `ci-slow.yml` (slow suites, push-to-main trigger); YAML is validated via actionlint or `yaml.safe_load` before writing. For existing projects with uncovered suites, `/dso:project-setup` prompts the user for each suite: `fast-gate` (append job to gating workflow), `separate` (new workflow file), or `skip` (writes `test.suite.<name>.ci_placement=skip` to `.claude/dso-config.conf` to suppress future prompts). Non-interactive mode defaults fast suites to fast-gate and slow/unknown suites to separate.
67
+
**This repo is the `dso` plugin.** Skills: interface-contracts, resolve-conflicts, tickets-health, design-onboarding, design-review, design-wireframe, ui-discover, debug-everything, sprint, brainstorm, preplanning, implementation-plan, fix-bug (canonical bug-fix workflow; replaces tdd-workflow for bug fixes), tdd-workflow (new feature TDD only), etc. Commands (commit, end, review) also come from the plugin. Skills are invoked as `/dso:skill-name` (fully qualified, required) or `/skill-name` (command alias, allowed but not preferred in docs). **Skill namespace qualification policy**: all skill invocations in in-scope files (plugins/dso/skills/, plugins/dso/docs/, plugins/dso/hooks/, plugins/dso/commands/, CLAUDE.md) MUST use the qualified `/dso:<skill-name>` form. `plugins/dso/scripts/check-skill-refs.sh` enforces this as a fatal CI check via `plugins/dso/scripts/validate.sh`; it exits non-zero when any unqualified reference is found. `plugins/dso/scripts/qualify-skill-refs.sh` is the one-shot bulk rewriter (idempotent) that transforms `/skill-name` → `/dso:skill-name` across all in-scope files — run it after adding new in-scope content with unqualified refs. Ticket scripts in `plugins/dso/scripts/` (`ticket` dispatcher and 22+ utility scripts). Project-specific config in `.claude/dso-config.conf` (flat KEY=VALUE format; keys: `format.*`, `ci.*`, `commands.*`, `jira.*`, `design.*`, `tickets.*`, `merge.*`, `version.*`). `version.*` config keys: `version.file_path` (path to the file holding the project's semver string; absent = skip version bumping; supported formats: `.json` → `version` key, `.toml` → `version` field, plaintext/no-extension → single semver line). `test.*` config keys: `test.suite.<name>.command` (shell command to run the suite; config-only suites get `runner=config`), `test.suite.<name>.speed_class` (`fast|slow`; overrides auto-discovered default of `unknown`). Config entries merge with auto-discovered suites by name: config wins on explicitly set fields. Use `project-detect.sh --suites [REPO_ROOT]` to discover test suites — outputs a JSON array with `name`, `command`, `speed_class`, `runner` fields (exit 0 always). Heuristics in precedence order: config > Makefile `/^test[-_]/` > pytest dirs > npm scripts > bash runners. **CI workflow generation** (`/dso:project-setup`): when no `.github/workflows/*.yml` exist, `project-detect.sh --suites` feeds directly into `ci-generator.sh --suites-json <json> --output-dir .github/workflows/` to generate `ci.yml` (fast suites, pull_request trigger) and `ci-slow.yml` (slow suites, push-to-main trigger); YAML is validated via actionlint or `yaml.safe_load` before writing. For existing projects with uncovered suites, `/dso:project-setup` prompts the user for each suite: `fast-gate` (append job to gating workflow), `separate` (new workflow file), or `skip` (writes `test.suite.<name>.ci_placement=skip` to `.claude/dso-config.conf` to suppress future prompts). Non-interactive mode defaults fast suites to fast-gate and slow/unknown suites to separate.
68
68
`ci.*` config keys: `ci.workflow_name` (GitHub Actions workflow name for `gh workflow run`; absent = skip post-push CI trigger recovery — **preferred** over deprecated `merge.ci_workflow_name`). `merge.*` config keys: `merge.visual_baseline_path` (path to snapshot dir; absent = skip baseline intent check), `merge.ci_workflow_name` (**deprecated** — use `ci.workflow_name` instead; `merge-to-main.sh` falls back to this key with a deprecation warning when `ci.workflow_name` is absent), `merge.message_exclusion_pattern` (regex passed to `grep -vE` when composing merge message; default `^chore: post-merge cleanup`). Source of truth: `plugins/dso/scripts/merge-to-main.sh`. Phased workflow: `sync → merge → version_bump → validate → push → archive → ci_trigger`; state file at `/tmp/merge-to-main-state-<branch>.json` (4h TTL) records completed phases for `--resume`; lock file at `/tmp/merge-to-main-lock-<hash>` prevents concurrent runs; SIGURG trap saves current phase to state file on interrupt. The `version_bump` phase runs `bump-version.sh --patch` when `version.file_path` is configured and `--bump` is passed (or bump mode is on); patch bumps happen at merge time, not commit time. **Plugin portability**: All host-project path assumptions (app dir, make targets, Python version) are config-driven via `.claude/dso-config.conf` — the plugin is portable to projects with different directory structures. **Host project script invocation**: Host projects call DSO scripts via `.claude/scripts/dso <script-name>` (shim). Install with `bash plugins/dso/scripts/dso-setup.sh [TARGET_REPO]` from the repo root; the shim resolves DSO_ROOT from `CLAUDE_PLUGIN_ROOT` env var or `dso.plugin_root` in `.claude/dso-config.conf`.
69
69
70
70
The pre-commit review gate (`pre-commit-review-gate.sh`) handles merge commits (`MERGE_HEAD`) natively — when MERGE_HEAD exists, it computes the merge base and filters out incoming-only files (files changed on main but not on the worktree branch) from review consideration, since those were already reviewed on main. Fail-safe: if MERGE_HEAD equals HEAD or merge-base computation fails, normal review enforcement applies.
0 commit comments