draht-claude 2026.4.26 → 2026.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/LICENSE +1 -2
- package/README.md +43 -0
- package/agents/architect.md +11 -0
- package/agents/debugger.md +10 -0
- package/agents/git-committer.md +9 -0
- package/agents/implementer.md +10 -0
- package/agents/reviewer.md +10 -0
- package/agents/security-auditor.md +10 -0
- package/agents/spec-reviewer.md +65 -0
- package/agents/verifier.md +11 -0
- package/bin/draht-tools.cjs +53 -0
- package/cli.mjs +121 -2
- package/commands/atomic-commit.md +12 -0
- package/commands/execute-phase.md +81 -21
- package/commands/fix.md +88 -19
- package/commands/map-codebase.md +7 -3
- package/commands/orchestrate.md +31 -6
- package/commands/plan-phase.md +38 -5
- package/commands/quick.md +52 -7
- package/commands/review.md +39 -9
- package/commands/verify-work.md +67 -20
- package/package.json +2 -2
- package/skills/atomic-reasoning/SKILL.md +103 -0
- package/skills/brainstorming/SKILL.md +118 -0
- package/skills/debugging-workflow/SKILL.md +97 -0
- package/skills/gsd-workflow/SKILL.md +32 -7
- package/skills/verification-gate/SKILL.md +81 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2026.5.12] - 2026-05-12
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- flag plan placeholders and empty sections in validate-plans
|
|
8
|
+
- refresh gsd-workflow skill with subagent roster and STATUS protocol
|
|
9
|
+
- add verification-gate, brainstorming, debugging-workflow, atomic-reasoning skills
|
|
10
|
+
- integrate spec-reviewer, STATUS protocol, and Red Flag gates across commands
|
|
11
|
+
- rewrite /fix as 4-phase systematic debugging protocol
|
|
12
|
+
- add spec-reviewer agent for per-task spec compliance
|
|
13
|
+
- add STATUS protocol footer to all subagents
|
|
14
|
+
- add configure subcommand and agent model defaults
|
|
15
|
+
|
|
3
16
|
## [2026.4.25] - 2026-04-25
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/LICENSE
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026 Oskar Freye
|
|
4
|
-
Copyright (c) 2025 Mario Zechner
|
|
3
|
+
Copyright (c) 2026 Oskar Freye
|
|
5
4
|
|
|
6
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -98,6 +98,11 @@ npx draht-claude install --path /path/to/plugins/draht
|
|
|
98
98
|
# Check install status
|
|
99
99
|
npx draht-claude status
|
|
100
100
|
|
|
101
|
+
# Configure subagent models
|
|
102
|
+
npx draht-claude configure --agent architect --model opus
|
|
103
|
+
npx draht-claude configure --agent implementer --model sonnet
|
|
104
|
+
npx draht-claude configure --list
|
|
105
|
+
|
|
101
106
|
# Remove
|
|
102
107
|
npx draht-claude uninstall
|
|
103
108
|
```
|
|
@@ -158,6 +163,44 @@ Between every step, run `/clear` to start a fresh session. This is a feature —
|
|
|
158
163
|
|
|
159
164
|
## Configuration
|
|
160
165
|
|
|
166
|
+
### Subagent models
|
|
167
|
+
|
|
168
|
+
Each specialist subagent ships with a default model tuned to its workload:
|
|
169
|
+
|
|
170
|
+
| Agent | Default | Used by |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| `architect` | `opus` | `/plan-phase` — deep reasoning for architectural plans |
|
|
173
|
+
| `implementer` | `sonnet` | `/execute-phase` — fast, reliable code changes |
|
|
174
|
+
| `verifier` | `sonnet` | `/verify-work` — lint, typecheck, test runs |
|
|
175
|
+
| `security-auditor` | `opus` | `/verify-work` — security audit and CVE analysis |
|
|
176
|
+
| `reviewer` | `inherit` | `/verify-work`, `/review` — code review |
|
|
177
|
+
| `debugger` | `inherit` | `/fix` — bug diagnosis |
|
|
178
|
+
| `git-committer` | `inherit` | `/atomic-commit` — commit staging |
|
|
179
|
+
|
|
180
|
+
You can override any agent with the `configure` command:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Set architect (planning) to Opus and implementer to Sonnet
|
|
184
|
+
npx draht-claude configure --agent architect --model opus
|
|
185
|
+
npx draht-claude configure --agent implementer --model sonnet
|
|
186
|
+
|
|
187
|
+
# Use a full model ID
|
|
188
|
+
npx draht-claude configure --agent verifier --model claude-opus-4-7
|
|
189
|
+
|
|
190
|
+
# List current assignments
|
|
191
|
+
npx draht-claude configure --list
|
|
192
|
+
|
|
193
|
+
# Reset a single agent to default
|
|
194
|
+
npx draht-claude configure --agent architect --reset
|
|
195
|
+
|
|
196
|
+
# Reset all agents to defaults
|
|
197
|
+
npx draht-claude configure --reset
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Supported values: `opus`, `sonnet`, `haiku`, a full model ID (e.g. `claude-sonnet-4-6`), or `inherit`.
|
|
201
|
+
|
|
202
|
+
### Hooks
|
|
203
|
+
|
|
161
204
|
Create `.planning/config.json` in your project to tune the hooks:
|
|
162
205
|
|
|
163
206
|
```json
|
package/agents/architect.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: architect
|
|
3
3
|
description: Reads codebase, analyzes requirements, and produces structured implementation plans with file lists, dependencies, and phased task breakdowns. Use when planning new features, refactors, or any multi-step implementation that needs architectural thinking before code is written.
|
|
4
4
|
tools: Read, Bash, Grep, Glob
|
|
5
|
+
model: opus
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
You are the Architect agent. Your job is to analyze requirements and produce clear, actionable implementation plans.
|
|
@@ -43,3 +44,13 @@ Numbered list of concrete tasks. For each task:
|
|
|
43
44
|
- DO NOT produce code — only plans
|
|
44
45
|
- DO NOT make assumptions about APIs without reading the source
|
|
45
46
|
- DO NOT suggest removing existing functionality unless explicitly asked
|
|
47
|
+
- DO NOT use placeholders in plans: `[TBD]`, `[files]`, "appropriate error handling", "similar to Task N" are forbidden. Every task must list real files, real test cases, real verification commands.
|
|
48
|
+
|
|
49
|
+
## Final Status
|
|
50
|
+
|
|
51
|
+
End your output with exactly one of these lines:
|
|
52
|
+
|
|
53
|
+
- `STATUS: DONE` — plan is complete, all tasks have real files/tests/verification, no open questions.
|
|
54
|
+
- `STATUS: DONE_WITH_CONCERNS` — plan is usable but you flagged risks the caller should weigh (ambiguous spec areas, alternative approaches considered, unknowns surfaced during code-reading).
|
|
55
|
+
- `STATUS: NEEDS_CONTEXT` — you cannot produce a plan without more information. List exactly what is missing (which file, which decision, which domain term).
|
|
56
|
+
- `STATUS: BLOCKED` — the request as stated cannot be planned because of an architectural conflict, missing prerequisite phase, or scope problem. Explain the blocker — do not guess your way through it.
|
package/agents/debugger.md
CHANGED
|
@@ -55,3 +55,13 @@ Show that the fix works (test output, command output).
|
|
|
55
55
|
- Keep fixes minimal — do not refactor unrelated code
|
|
56
56
|
- If the fix is non-obvious, add a comment explaining why
|
|
57
57
|
- Run verification after fixing to confirm the issue is resolved
|
|
58
|
+
- After **3 failed fix attempts**, STOP. This pattern indicates an architectural problem, not a hypothesis problem. Report back instead of trying a 4th fix — the human partner needs to discuss before continuing.
|
|
59
|
+
|
|
60
|
+
## Final Status
|
|
61
|
+
|
|
62
|
+
End your output with exactly one of these lines:
|
|
63
|
+
|
|
64
|
+
- `STATUS: DONE` — root cause identified, fix applied, verification passes.
|
|
65
|
+
- `STATUS: DONE_WITH_CONCERNS` — fix applied but you noticed related bugs, fragile patterns, or test gaps that should be tracked separately.
|
|
66
|
+
- `STATUS: NEEDS_CONTEXT` — you cannot diagnose without more information (logs, reproduction steps, env details). List exactly what is missing.
|
|
67
|
+
- `STATUS: BLOCKED` — diagnosis points to an architectural issue or 3+ fix attempts failed. Do NOT keep trying. Report the symptom chain, the failed hypotheses, and recommend the user step back before continuing.
|
package/agents/git-committer.md
CHANGED
|
@@ -50,3 +50,12 @@ Use the package directory name or feature area (e.g., `auth`, `billing`, `api`).
|
|
|
50
50
|
- Keep the first line under 72 characters
|
|
51
51
|
- No emojis in commit messages
|
|
52
52
|
- If there is a related issue, include `fixes #<number>` or `closes #<number>`
|
|
53
|
+
|
|
54
|
+
## Final Status
|
|
55
|
+
|
|
56
|
+
End your output with exactly one of these lines:
|
|
57
|
+
|
|
58
|
+
- `STATUS: DONE` — all relevant changes committed cleanly, one logical change per commit.
|
|
59
|
+
- `STATUS: DONE_WITH_CONCERNS` — committed, but you noticed unstaged files left behind, mixed concerns that you split as best you could, or pre-commit hook warnings.
|
|
60
|
+
- `STATUS: NEEDS_CONTEXT` — you cannot commit safely because diffs span unrelated concerns and you need the user to clarify intent.
|
|
61
|
+
- `STATUS: BLOCKED` — pre-commit hooks failed, the working tree is in a bad state, or staged content includes likely secrets. Do NOT commit. Report the blocker.
|
package/agents/implementer.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: implementer
|
|
3
3
|
description: Implements code changes based on a plan or task description. Reads existing code, writes new code, and edits files. Use when executing a planned task that needs actual code changes, especially inside a TDD red→green→refactor cycle.
|
|
4
4
|
tools: Read, Bash, Edit, Write, Grep, Glob
|
|
5
|
+
model: sonnet
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
You are the Implementer agent. Your job is to write code that fulfills the given task.
|
|
@@ -33,3 +34,12 @@ Skip the TDD cycle only for pure config or documentation-only changes with no te
|
|
|
33
34
|
- Keep changes minimal — do only what the task asks for
|
|
34
35
|
- If a task is ambiguous, implement the most conservative interpretation
|
|
35
36
|
- Run `npm run check` or equivalent after changes if the project has one
|
|
37
|
+
|
|
38
|
+
## Final Status
|
|
39
|
+
|
|
40
|
+
End your output with exactly one of these lines so the caller can branch deterministically:
|
|
41
|
+
|
|
42
|
+
- `STATUS: DONE` — task complete, tests green, no concerns.
|
|
43
|
+
- `STATUS: DONE_WITH_CONCERNS` — task complete and tests green, but list concerns: tech debt incurred, edge cases the spec didn't cover, surprises uncovered while implementing. The caller decides whether to address before moving on.
|
|
44
|
+
- `STATUS: NEEDS_CONTEXT` — you cannot proceed without more information. List exactly what is missing (file content, decision, design choice, missing dependency). Do not guess.
|
|
45
|
+
- `STATUS: BLOCKED` — the task cannot be completed as specified. State the blocker type: `context` (info missing), `complexity` (task is bigger than 2–5 minutes — needs decomposing), `scope` (task asks for something that conflicts with the codebase), `plan` (the spec is internally inconsistent). Do not write partial code; revert and report.
|
package/agents/reviewer.md
CHANGED
|
@@ -55,3 +55,13 @@ If no issues found, state that explicitly.
|
|
|
55
55
|
- Be actionable — say what to change, not just what is wrong
|
|
56
56
|
- Do not nitpick formatting if the project has a formatter
|
|
57
57
|
- Focus on substance over style
|
|
58
|
+
- This agent is the **code quality** review. Spec compliance is the `spec-reviewer` agent's job and runs first inside `/execute-phase`. If you find a spec mismatch, escalate it under `Must fix` — do not silently accept it.
|
|
59
|
+
|
|
60
|
+
## Final Status
|
|
61
|
+
|
|
62
|
+
End your output with exactly one of these lines:
|
|
63
|
+
|
|
64
|
+
- `STATUS: DONE` — no issues found, or only `Consider`-level suggestions.
|
|
65
|
+
- `STATUS: DONE_WITH_CONCERNS` — `Should fix` issues exist but nothing blocking. List them under that heading.
|
|
66
|
+
- `STATUS: NEEDS_CONTEXT` — you could not review because the diff or surrounding code was not accessible. List what is missing.
|
|
67
|
+
- `STATUS: BLOCKED` — `Must fix` issues exist. The diff should not be merged or proceed to the next task until they are addressed.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: security-auditor
|
|
3
3
|
description: Audits code changes for security vulnerabilities, injection risks, secrets exposure, and unsafe patterns. Use during code review or before merging changes that touch auth, data handling, input parsing, file operations, or external/AI API calls.
|
|
4
4
|
tools: Read, Bash, Grep, Glob
|
|
5
|
+
model: opus
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
You are the Security Auditor agent. Your job is to find **exploitable** vulnerabilities in code changes — both **zero-day** issues (pattern-based hunting in the code itself) and **known CVEs** (matching dependencies against vulnerability databases).
|
|
@@ -107,3 +108,12 @@ For each issue:
|
|
|
107
108
|
- ALWAYS cite exact file:line and quote the vulnerable snippet if under 80 chars
|
|
108
109
|
- ALWAYS check existing project patterns before flagging "missing X" (middleware, framework defaults, central validators may already handle it)
|
|
109
110
|
- If the diff touches no security boundary, output `no findings — diff does not touch security boundaries` and stop
|
|
111
|
+
|
|
112
|
+
## Final Status
|
|
113
|
+
|
|
114
|
+
End your output with exactly one of these lines:
|
|
115
|
+
|
|
116
|
+
- `STATUS: DONE` — no findings, or only Low-severity defense-in-depth gaps.
|
|
117
|
+
- `STATUS: DONE_WITH_CONCERNS` — Medium findings exist; safe to merge but should be tracked.
|
|
118
|
+
- `STATUS: NEEDS_CONTEXT` — you cannot finish the audit without more information (env config, threat model, where this code runs).
|
|
119
|
+
- `STATUS: BLOCKED` — Critical or High findings exist. The change must NOT merge until they are addressed. List exploit vector and fix for each.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-reviewer
|
|
3
|
+
description: Reviews a completed task's diff against the original spec — does the implementation cover exactly what the plan asked for, no more, no less. Use inside /execute-phase between implementer and quality reviewer. Distinct from `reviewer`, which evaluates code quality; spec-reviewer ONLY checks spec compliance.
|
|
4
|
+
tools: Read, Bash, Grep, Glob
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the Spec Reviewer agent. You have ONE job: verify that the diff implements exactly what the task spec asked for — no omissions, no additions.
|
|
9
|
+
|
|
10
|
+
You are NOT a code-quality reviewer. You do NOT comment on naming, structure, abstractions, or style. That is the `reviewer` agent's job, which runs after you.
|
|
11
|
+
|
|
12
|
+
## The Iron Rule
|
|
13
|
+
|
|
14
|
+
A spec-compliant diff:
|
|
15
|
+
- Implements every `<test>` case the task lists
|
|
16
|
+
- Implements every behaviour the `<action>` describes
|
|
17
|
+
- Satisfies every assertion in `<done>`
|
|
18
|
+
- Touches the files listed in `<files>` and no unrelated files
|
|
19
|
+
- Does NOT add features the task did not request
|
|
20
|
+
- Does NOT skip checkpoints (`checkpoint:human-verify`, `checkpoint:decision` must surface, not auto-proceed)
|
|
21
|
+
|
|
22
|
+
If the diff fails ANY of these, the task is **not** spec-compliant — report it and stop. The quality review does not run until spec compliance is ✅.
|
|
23
|
+
|
|
24
|
+
## Process
|
|
25
|
+
|
|
26
|
+
1. **Read the task spec** — get the `<test>`, `<action>`, `<refactor>`, `<verify>`, `<done>` sections from the plan
|
|
27
|
+
2. **Read the diff** — `git diff <range>` or as provided in your task instructions
|
|
28
|
+
3. **Map diff → spec** — for each spec item, find the diff hunk that fulfils it
|
|
29
|
+
4. **Flag gaps** — any spec item with no corresponding diff = omission
|
|
30
|
+
5. **Flag extras** — any diff hunk that doesn't trace to a spec item = over-build (unless it's a trivial fix-up the spec implied)
|
|
31
|
+
6. **Verify tests exist for every behaviour** — the `<test>` section must show up as concrete test files in the diff, not just be inferred from the implementation
|
|
32
|
+
|
|
33
|
+
## Output Format
|
|
34
|
+
|
|
35
|
+
### Spec Compliance Verdict
|
|
36
|
+
One of: `✅ COMPLIANT` / `❌ NON-COMPLIANT`
|
|
37
|
+
|
|
38
|
+
### Spec ↔ Diff Mapping
|
|
39
|
+
For each spec item, the diff lines that fulfil it (or `MISSING`).
|
|
40
|
+
|
|
41
|
+
### Omissions
|
|
42
|
+
Spec items with no implementation. List each with severity.
|
|
43
|
+
|
|
44
|
+
### Over-builds
|
|
45
|
+
Diff content not requested by the spec. List each.
|
|
46
|
+
|
|
47
|
+
### Required Fixes
|
|
48
|
+
Bulleted, in order: what the implementer must change to become compliant.
|
|
49
|
+
|
|
50
|
+
## Final Status
|
|
51
|
+
|
|
52
|
+
End your output with exactly one of these lines:
|
|
53
|
+
|
|
54
|
+
- `STATUS: DONE` — the diff is fully spec-compliant. Quality review may proceed.
|
|
55
|
+
- `STATUS: DONE_WITH_CONCERNS` — the diff is spec-compliant but you noticed gaps the caller should know about (e.g., the spec itself is thin, or the impl exposed an ambiguity). Quality review may proceed.
|
|
56
|
+
- `STATUS: NEEDS_CONTEXT` — you could not evaluate because the task spec or the diff was not provided. List what is missing.
|
|
57
|
+
- `STATUS: BLOCKED` — the diff is non-compliant. List the required fixes. Quality review MUST NOT proceed until a re-run returns `DONE`.
|
|
58
|
+
|
|
59
|
+
## Rules
|
|
60
|
+
|
|
61
|
+
- Be specific — reference exact spec items and diff line ranges
|
|
62
|
+
- Do not nitpick code style — that is the next reviewer's job
|
|
63
|
+
- Do not propose refactorings — only flag omissions and over-builds
|
|
64
|
+
- If a `checkpoint:human-verify` task was auto-completed without surfacing for human review, that is an omission
|
|
65
|
+
- "Close enough" is not compliant — return BLOCKED and list the specific gaps
|
package/agents/verifier.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: verifier
|
|
3
3
|
description: Runs lint, typecheck, and test suites to verify code quality. Reports failures with context. Use to check that a phase, task, or set of changes is actually ready — does not attempt fixes, only reports.
|
|
4
4
|
tools: Read, Bash, Grep, Glob
|
|
5
|
+
model: sonnet
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
You are the Verifier agent. Your job is to run all available verification checks and report results.
|
|
@@ -42,3 +43,13 @@ State whether the code is ready for production or what must be fixed first.
|
|
|
42
43
|
- Do not attempt to fix issues — only report them
|
|
43
44
|
- If a check command is not found, note it and move on
|
|
44
45
|
- Include the full error output for failures (truncated if very long)
|
|
46
|
+
- **Evidence before claims**: never report a check as "passing" without showing the command and its output. "Looks fine" is not a verdict.
|
|
47
|
+
|
|
48
|
+
## Final Status
|
|
49
|
+
|
|
50
|
+
End your output with exactly one of these lines:
|
|
51
|
+
|
|
52
|
+
- `STATUS: DONE` — all available checks ran and passed.
|
|
53
|
+
- `STATUS: DONE_WITH_CONCERNS` — checks passed but you flagged things like coverage drops, slow tests, or missing check configs.
|
|
54
|
+
- `STATUS: NEEDS_CONTEXT` — you could not run checks (missing scripts, missing dependencies, ambiguous which command to run). List what's missing.
|
|
55
|
+
- `STATUS: BLOCKED` — one or more required checks failed. List which, with command output. Do NOT mark the work ready — the caller must route to a fix loop.
|
package/bin/draht-tools.cjs
CHANGED
|
@@ -523,6 +523,46 @@ commands["read-plan"] = function (n, p) {
|
|
|
523
523
|
};
|
|
524
524
|
|
|
525
525
|
// --- validate-plans ---
|
|
526
|
+
// Placeholder patterns that indicate a task isn't actually executable.
|
|
527
|
+
// Borrowed from superpowers' writing-plans discipline: tasks with these aren't
|
|
528
|
+
// usable input for an implementer subagent.
|
|
529
|
+
const PLACEHOLDER_PATTERNS = [
|
|
530
|
+
{ pattern: /\[TBD\]/i, label: "[TBD]" },
|
|
531
|
+
{ pattern: /\[files?\]/i, label: "[file] or [files]" },
|
|
532
|
+
{ pattern: /\[description\]/i, label: "[description]" },
|
|
533
|
+
{ pattern: /\[task\s*name\]/i, label: "[task name]" },
|
|
534
|
+
{ pattern: /\bappropriate\s+error\s+handling\b/i, label: '"appropriate error handling"' },
|
|
535
|
+
{ pattern: /\bsimilar\s+to\s+task\s+[NX0-9]+\b/i, label: '"similar to Task N"' },
|
|
536
|
+
{ pattern: /\bsee\s+previous\s+task\b/i, label: '"see previous task"' },
|
|
537
|
+
{ pattern: /\bfill\s+in\s+later\b/i, label: '"fill in later"' },
|
|
538
|
+
{ pattern: /\bfigure\s+(?:this\s+)?out\s+later\b/i, label: '"figure out later"' },
|
|
539
|
+
];
|
|
540
|
+
|
|
541
|
+
function findPlaceholders(content) {
|
|
542
|
+
const hits = [];
|
|
543
|
+
for (const { pattern, label } of PLACEHOLDER_PATTERNS) {
|
|
544
|
+
if (pattern.test(content)) hits.push(label);
|
|
545
|
+
}
|
|
546
|
+
return hits;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function findEmptySections(content) {
|
|
550
|
+
// Detect <test>, <action>, <verify>, <done> blocks that are empty or contain only whitespace/placeholders
|
|
551
|
+
const sections = ["test", "action", "verify", "done", "files"];
|
|
552
|
+
const empty = [];
|
|
553
|
+
for (const tag of sections) {
|
|
554
|
+
const re = new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, "g");
|
|
555
|
+
let match;
|
|
556
|
+
while ((match = re.exec(content)) !== null) {
|
|
557
|
+
const inner = match[1].trim();
|
|
558
|
+
if (inner.length === 0 || /^\.\.\.$/.test(inner) || /^\[.*\]$/.test(inner)) {
|
|
559
|
+
empty.push(`<${tag}>`);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return empty;
|
|
564
|
+
}
|
|
565
|
+
|
|
526
566
|
commands["validate-plans"] = function (n) {
|
|
527
567
|
const num = parseInt(n, 10);
|
|
528
568
|
if (!num) { console.error("Usage: draht-tools validate-plans N"); process.exit(1); }
|
|
@@ -547,6 +587,18 @@ commands["validate-plans"] = function (n) {
|
|
|
547
587
|
const taskCount = (content.match(/<task/g) || []).length;
|
|
548
588
|
if (taskCount > 5) issues.push(`${file}: ${taskCount} tasks (max recommended: 5)`);
|
|
549
589
|
if (taskCount === 0) issues.push(`${file}: No tasks defined`);
|
|
590
|
+
|
|
591
|
+
// Placeholder linter — flag tasks that aren't actually executable
|
|
592
|
+
const placeholders = findPlaceholders(content);
|
|
593
|
+
if (placeholders.length > 0) {
|
|
594
|
+
issues.push(`${file}: contains placeholder text → ${placeholders.join(", ")} (tasks must be concrete to dispatch to subagents)`);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Empty section linter — <test>, <action>, <verify>, <done>, <files> must have real content
|
|
598
|
+
const emptySections = findEmptySections(content);
|
|
599
|
+
if (emptySections.length > 0) {
|
|
600
|
+
issues.push(`${file}: empty or placeholder-only sections → ${emptySections.join(", ")}`);
|
|
601
|
+
}
|
|
550
602
|
}
|
|
551
603
|
|
|
552
604
|
console.log(banner(`VALIDATE PHASE ${num}`));
|
|
@@ -556,6 +608,7 @@ commands["validate-plans"] = function (n) {
|
|
|
556
608
|
} else {
|
|
557
609
|
console.log(`\n⚠️ ${issues.length} issue(s):`);
|
|
558
610
|
for (const issue of issues) console.log(` - ${issue}`);
|
|
611
|
+
process.exit(1);
|
|
559
612
|
}
|
|
560
613
|
};
|
|
561
614
|
|
package/cli.mjs
CHANGED
|
@@ -49,7 +49,7 @@ const IGNORE = new Set([
|
|
|
49
49
|
function parseArgs(argv) {
|
|
50
50
|
const args = argv.slice(2);
|
|
51
51
|
const command = args[0];
|
|
52
|
-
const flags = { path: null, force: false, help: false };
|
|
52
|
+
const flags = { path: null, force: false, help: false, agent: null, model: null, list: false, reset: false };
|
|
53
53
|
for (let i = 1; i < args.length; i++) {
|
|
54
54
|
const a = args[i];
|
|
55
55
|
if (a === "--path" || a === "-p") {
|
|
@@ -58,6 +58,14 @@ function parseArgs(argv) {
|
|
|
58
58
|
flags.force = true;
|
|
59
59
|
} else if (a === "--help" || a === "-h") {
|
|
60
60
|
flags.help = true;
|
|
61
|
+
} else if (a === "--agent" || a === "-a") {
|
|
62
|
+
flags.agent = args[++i];
|
|
63
|
+
} else if (a === "--model" || a === "-m") {
|
|
64
|
+
flags.model = args[++i];
|
|
65
|
+
} else if (a === "--list" || a === "-l") {
|
|
66
|
+
flags.list = true;
|
|
67
|
+
} else if (a === "--reset" || a === "-r") {
|
|
68
|
+
flags.reset = true;
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
if (!command || command === "--help" || command === "-h") flags.help = true;
|
|
@@ -65,7 +73,7 @@ function parseArgs(argv) {
|
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
function printHelp() {
|
|
68
|
-
console.log(`draht-claude — install the draht Claude Code plugin
|
|
76
|
+
console.log(`draht-claude — install and configure the draht Claude Code plugin
|
|
69
77
|
|
|
70
78
|
Usage:
|
|
71
79
|
npx draht-claude install Install as a Claude Code plugin
|
|
@@ -74,6 +82,11 @@ Usage:
|
|
|
74
82
|
npx draht-claude uninstall Remove the plugin and marketplace
|
|
75
83
|
npx draht-claude update Reinstall (same as install --force)
|
|
76
84
|
npx draht-claude status Show install + enabled state
|
|
85
|
+
npx draht-claude configure Configure subagent models
|
|
86
|
+
--agent <name> --model <model> Set model for a specific agent
|
|
87
|
+
--agent <name> --reset Reset agent to inherit default model
|
|
88
|
+
--reset Reset all agents to inherit
|
|
89
|
+
--list List current agent model assignments
|
|
77
90
|
|
|
78
91
|
Options:
|
|
79
92
|
-p, --path <dir> Custom local marketplace directory
|
|
@@ -154,6 +167,25 @@ function runClaude(args, { allowFail = false } = {}) {
|
|
|
154
167
|
return res.status === 0;
|
|
155
168
|
}
|
|
156
169
|
|
|
170
|
+
function setModelInFrontmatter(content, model) {
|
|
171
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
172
|
+
if (!match) return content;
|
|
173
|
+
const lines = match[1].split("\n");
|
|
174
|
+
const modelIdx = lines.findIndex((l) => l.trim().startsWith("model:"));
|
|
175
|
+
if (model === null || model === undefined) {
|
|
176
|
+
if (modelIdx >= 0) lines.splice(modelIdx, 1);
|
|
177
|
+
} else {
|
|
178
|
+
const modelLine = `model: ${model}`;
|
|
179
|
+
if (modelIdx >= 0) {
|
|
180
|
+
lines[modelIdx] = modelLine;
|
|
181
|
+
} else {
|
|
182
|
+
lines.push(modelLine);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const body = content.slice(match[0].length);
|
|
186
|
+
return `---\n${lines.join("\n")}\n---\n${body}`;
|
|
187
|
+
}
|
|
188
|
+
|
|
157
189
|
function writeMarketplaceManifest(marketplaceDir, pluginManifest) {
|
|
158
190
|
const manifest = {
|
|
159
191
|
$schema: "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
@@ -317,6 +349,90 @@ function cmdStatus(flags) {
|
|
|
317
349
|
}
|
|
318
350
|
}
|
|
319
351
|
|
|
352
|
+
function cmdConfigure(flags) {
|
|
353
|
+
const marketplaceDir = flags.path || DEFAULT_MARKETPLACE_DIR;
|
|
354
|
+
const pluginDir = path.join(marketplaceDir, "plugins", PLUGIN_NAME);
|
|
355
|
+
const agentsDir = path.join(pluginDir, "agents");
|
|
356
|
+
|
|
357
|
+
if (!fs.existsSync(pluginDir)) {
|
|
358
|
+
err(`plugin not installed at ${pluginDir}`);
|
|
359
|
+
err("run 'draht-claude install' first");
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (flags.list) {
|
|
364
|
+
if (!fs.existsSync(agentsDir)) {
|
|
365
|
+
log("no agents directory found");
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
369
|
+
if (files.length === 0) {
|
|
370
|
+
log("no agents found");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
log("Agent models:");
|
|
374
|
+
for (const file of files.sort()) {
|
|
375
|
+
const content = fs.readFileSync(path.join(agentsDir, file), "utf-8");
|
|
376
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
377
|
+
let model = "inherit (default)";
|
|
378
|
+
if (match) {
|
|
379
|
+
const modelLine = match[1].split("\n").find((l) => l.trim().startsWith("model:"));
|
|
380
|
+
if (modelLine) {
|
|
381
|
+
model = modelLine.split(":").slice(1).join(":").trim();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
log(` ${file.replace(".md", "")}: ${model}`);
|
|
385
|
+
}
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (flags.reset) {
|
|
390
|
+
if (flags.agent) {
|
|
391
|
+
const agentFile = path.join(agentsDir, `${flags.agent}.md`);
|
|
392
|
+
if (!fs.existsSync(agentFile)) {
|
|
393
|
+
err(`agent not found: ${flags.agent}`);
|
|
394
|
+
process.exit(1);
|
|
395
|
+
}
|
|
396
|
+
const content = fs.readFileSync(agentFile, "utf-8");
|
|
397
|
+
const updated = setModelInFrontmatter(content, null);
|
|
398
|
+
fs.writeFileSync(agentFile, updated);
|
|
399
|
+
log(`✓ reset model for ${flags.agent} to inherit`);
|
|
400
|
+
} else {
|
|
401
|
+
if (!fs.existsSync(agentsDir)) return;
|
|
402
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
403
|
+
for (const file of files) {
|
|
404
|
+
const agentFile = path.join(agentsDir, file);
|
|
405
|
+
const content = fs.readFileSync(agentFile, "utf-8");
|
|
406
|
+
const updated = setModelInFrontmatter(content, null);
|
|
407
|
+
fs.writeFileSync(agentFile, updated);
|
|
408
|
+
}
|
|
409
|
+
log("✓ reset model for all agents to inherit");
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (!flags.agent || !flags.model) {
|
|
415
|
+
err("configure requires --agent <name> and --model <model>");
|
|
416
|
+
err("run 'draht-claude configure --help' for usage");
|
|
417
|
+
process.exit(1);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const agentFile = path.join(agentsDir, `${flags.agent}.md`);
|
|
421
|
+
if (!fs.existsSync(agentFile)) {
|
|
422
|
+
err(`agent not found: ${flags.agent}`);
|
|
423
|
+
const available = fs.existsSync(agentsDir)
|
|
424
|
+
? fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")).join(", ")
|
|
425
|
+
: "(none)";
|
|
426
|
+
err(`available agents: ${available}`);
|
|
427
|
+
process.exit(1);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const content = fs.readFileSync(agentFile, "utf-8");
|
|
431
|
+
const updated = setModelInFrontmatter(content, flags.model);
|
|
432
|
+
fs.writeFileSync(agentFile, updated);
|
|
433
|
+
log(`✓ set model for ${flags.agent} to ${flags.model}`);
|
|
434
|
+
}
|
|
435
|
+
|
|
320
436
|
// ─── main ───────────────────────────────────────────────────────────────────
|
|
321
437
|
|
|
322
438
|
const { command, flags } = parseArgs(process.argv);
|
|
@@ -341,6 +457,9 @@ switch (command) {
|
|
|
341
457
|
case "status":
|
|
342
458
|
cmdStatus(flags);
|
|
343
459
|
break;
|
|
460
|
+
case "configure":
|
|
461
|
+
cmdConfigure(flags);
|
|
462
|
+
break;
|
|
344
463
|
default:
|
|
345
464
|
err(`unknown command: ${command}`);
|
|
346
465
|
err("run 'draht-claude --help' for usage");
|
|
@@ -7,6 +7,18 @@ allowed-tools: Bash, Read, Task
|
|
|
7
7
|
|
|
8
8
|
Analyze changes and create atomic commits.
|
|
9
9
|
|
|
10
|
+
## Red Flags — STOP
|
|
11
|
+
|
|
12
|
+
Do NOT proceed with a commit if **any** of these is true:
|
|
13
|
+
|
|
14
|
+
- A single proposed commit mixes unrelated concerns (e.g., a feature + an unrelated refactor + a config tweak)
|
|
15
|
+
- The change set contains potential secrets (`.env`, credentials, API keys in source)
|
|
16
|
+
- Staged content includes files unrelated to the user's stated intent (stale build artifacts, IDE configs, scratch files)
|
|
17
|
+
- Pre-commit hooks fail — fix the cause, never use `--no-verify`
|
|
18
|
+
- You cannot articulate the "why" of a commit in one sentence — that's a sign it contains more than one logical change
|
|
19
|
+
|
|
20
|
+
If any of these triggers, surface the issue to the user and split the change set before continuing.
|
|
21
|
+
|
|
10
22
|
## Atomic Reasoning
|
|
11
23
|
|
|
12
24
|
Before creating commits, decompose changes into atomic reasoning units:
|