Skip to content

Commit edb090b

Browse files
Merge remote-tracking branch 'origin/main' into worktree-20260324-145918
2 parents 5d60a12 + 5bbe584 commit edb090b

File tree

12 files changed

+984
-45
lines changed

12 files changed

+984
-45
lines changed

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Priority: 0-4 (0=critical, 4=backlog). Never use "high"/"medium"/"low".
6363
**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) and `dso:conflict-analyzer` (sonnet; dispatched by `/dso:resolve-conflicts`). 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`.
6464
**Conflict avoidance** (multi-agent): Static file impact analysis, shared blackboard, agent discovery protocol, semantic conflict check — integrated into `/dso:sprint` and `/dso:debug-everything`.
6565
**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, the tk wrapper, `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.
66-
`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 → 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. **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`.
66+
`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`.
6767

6868
**Ticket index merge driver**: `.tickets/.index.json` conflicts auto-resolve via `plugins/dso/scripts/merge-ticket-index.py` (JSON union merge; theirs-wins on true conflicts). `.gitattributes` maps the file to the `tickets-index-merge` driver (register per-clone; see Quick Reference). `worktree-sync-from-main.sh` includes a script-level fallback for CI/fresh-clone environments where the driver is not registered. 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.
6969

@@ -149,7 +149,7 @@ After ExitPlanMode approval, do NOT begin implementation. Create a ticket epic (
149149
# On attempt 2+, /dso:oscillation-check runs automatically if same files targeted.
150150
# 2. git push (or plugins/dso/scripts/merge-to-main.sh in worktree sessions — handles .claude/scripts/dso ticket sync + merge + push)
151151
# Supports --resume (continue from last state file checkpoint).
152-
# Phases: sync → merge → validate → push → archive → ci_trigger
152+
# Phases: sync → merge → version_bump → validate → push → archive → ci_trigger
153153
# # REVIEW-DEFENSE: checkpoint_verify phase removed from docs here intentionally — story dso-q0df (batch 2) removes _phase_checkpoint_verify() from merge-to-main.sh. Docs lead code in this multi-story epic.
154154
# State file: /tmp/merge-to-main-state-<branch>.json (expires after 4h); lock file: /tmp/merge-to-main-lock-<hash>
155155
# On interruption (SIGURG), current phase is saved to state file — re-run with --resume to continue.

plugins/dso/docs/VERSIONING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ For reproducible environments, pin to a specific tag rather than a branch. Recor
6161

6262
## Release Workflow
6363

64+
### Patch Bumps (automated, merge-time)
65+
66+
Patch version bumps happen automatically during the `merge-to-main.sh` workflow when `version.file_path` is configured in `.claude/dso-config.conf` and `--bump` is passed (or bump mode is on). The `version_bump` phase (between `merge` and `validate`) runs `bump-version.sh --patch` — no manual commit step is required.
67+
68+
### Minor and Major Releases (manual, via tag-release.sh)
69+
70+
For MINOR and MAJOR version bumps (new capabilities or breaking changes), use the standalone `tag-release.sh` workflow:
71+
6472
1. Determine the next version per the policy above.
6573
2. Run `.claude/scripts/dso tag-release.sh <VERSION>` — this updates `plugin.json` and `marketplace.json` and prints the `git tag` command.
6674
3. Commit the version bump (`git commit -m "chore: bump version to vX.Y.Z"`).

plugins/dso/docs/WORKTREE-GUIDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ ${CLAUDE_PLUGIN_ROOT}/scripts/merge-to-main.sh
580580
|-------|-------------|
581581
| `sync` | Sync ticket state from main before merging |
582582
| `merge` | Merge worktree branch into main |
583+
| `version_bump` | Bump patch version (when `version.file_path` is configured and `--bump` is passed) |
583584
| `validate` | Run post-merge validation checks |
584585
| `push` | Push main to origin (idempotent if already up to date) |
585586
| `archive` | Archive worktree branch |

plugins/dso/docs/workflows/COMMIT-WORKFLOW.md

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -359,29 +359,6 @@ echo "passed" > "$ARTIFACTS_DIR/validation-status"
359359
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) step-3a-validation-state" >> "$ARTIFACTS_DIR/commit-breadcrumbs.log"
360360
```
361361

362-
## Step 3b: Version Bump
363-
364-
> **Skip this step when executing COMMIT-WORKFLOW.md inline from within the `/dso:sprint` skill.** The sprint skill manages version bumping separately — it calls `bump-version.sh --minor` at epic completion and coordinates increments across all stories. Running Step 3b during a sprint-orchestrated commit would produce duplicate or conflicting version increments. When this workflow is being executed as part of `/dso:sprint` batch execution or epic completion, proceed directly to Step 4.
365-
366-
Bump the patch version and stage the modified version file so it is included in the commit. This step runs after format/lint/type-check (Steps 2-3) so the version file write happens after all other file edits are complete.
367-
368-
```bash
369-
REPO_ROOT=$(git rev-parse --show-toplevel)
370-
bash "$REPO_ROOT/plugins/dso/scripts/bump-version.sh" --patch
371-
```
372-
373-
`bump-version.sh` exits 0 with no changes when `version.file_path` is not configured in `dso-config.conf`. In that case, the `git add -u` below is a no-op for the version file (safe to run regardless).
374-
375-
Stage the bumped version file (if any) along with any other tracked modifications touched by format/lint:
376-
377-
```bash
378-
git add -u
379-
```
380-
381-
```bash
382-
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) step-3b-version-bump" >> "$ARTIFACTS_DIR/commit-breadcrumbs.log"
383-
```
384-
385362
## Step 4: Stage
386363

387364
If you intend to include new (untracked) files in this commit, add them explicitly by name first.

plugins/dso/scripts/claude-safe

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ _offer_worktree_cleanup() {
113113
local is_merged=0
114114
if git -C "$main_root" merge-base --is-ancestor "$branch" main 2>/dev/null; then
115115
is_merged=1
116+
elif git -C "$main_root" log main --oneline --grep="(merge $branch)" -1 2>/dev/null | grep -q .; then
117+
# Fallback: the branch tip may have been amended after the merge
118+
# (e.g., orchestrator recovery after merge-to-main.sh timeout).
119+
# The amend changes the SHA so is-ancestor fails, but main's merge
120+
# commit message still references this branch name.
121+
is_merged=1
116122
fi
117123

118124
# Check for uncommitted changes — any dirty file blocks auto-removal.

0 commit comments

Comments
 (0)