@draht/coding-agent 2026.3.2 → 2026.3.4

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.
Files changed (194) hide show
  1. package/CHANGELOG.md +194 -13
  2. package/README.md +90 -106
  3. package/agents/architect.md +45 -0
  4. package/agents/debugger.md +57 -0
  5. package/agents/git-committer.md +46 -0
  6. package/agents/implementer.md +25 -0
  7. package/agents/reviewer.md +52 -0
  8. package/agents/security-auditor.md +61 -0
  9. package/agents/verifier.md +44 -0
  10. package/bin/draht-tools.cjs +20 -20
  11. package/dist/agents/architect.md +45 -0
  12. package/dist/agents/debugger.md +57 -0
  13. package/dist/agents/git-committer.md +46 -0
  14. package/dist/agents/implementer.md +25 -0
  15. package/dist/agents/reviewer.md +52 -0
  16. package/dist/agents/security-auditor.md +61 -0
  17. package/dist/agents/verifier.md +44 -0
  18. package/dist/cli/args.d.ts.map +1 -1
  19. package/dist/cli/args.js +1 -0
  20. package/dist/cli/args.js.map +1 -1
  21. package/dist/cli.d.ts.map +1 -1
  22. package/dist/cli.js +5 -0
  23. package/dist/cli.js.map +1 -1
  24. package/dist/config.d.ts +0 -7
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +2 -14
  27. package/dist/config.js.map +1 -1
  28. package/dist/core/agent-session.d.ts +14 -4
  29. package/dist/core/agent-session.d.ts.map +1 -1
  30. package/dist/core/agent-session.js +167 -49
  31. package/dist/core/agent-session.js.map +1 -1
  32. package/dist/core/auth-storage.d.ts +1 -1
  33. package/dist/core/auth-storage.d.ts.map +1 -1
  34. package/dist/core/auth-storage.js +2 -1
  35. package/dist/core/auth-storage.js.map +1 -1
  36. package/dist/core/builtins/subagent.d.ts +14 -0
  37. package/dist/core/builtins/subagent.d.ts.map +1 -0
  38. package/dist/core/builtins/subagent.js +492 -0
  39. package/dist/core/builtins/subagent.js.map +1 -0
  40. package/dist/core/compaction/compaction.d.ts.map +1 -1
  41. package/dist/core/compaction/compaction.js +4 -1
  42. package/dist/core/compaction/compaction.js.map +1 -1
  43. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  44. package/dist/core/export-html/tool-renderer.js +6 -0
  45. package/dist/core/export-html/tool-renderer.js.map +1 -1
  46. package/dist/core/extensions/loader.d.ts.map +1 -1
  47. package/dist/core/extensions/loader.js +19 -8
  48. package/dist/core/extensions/loader.js.map +1 -1
  49. package/dist/core/extensions/runner.d.ts.map +1 -1
  50. package/dist/core/extensions/runner.js +1 -0
  51. package/dist/core/extensions/runner.js.map +1 -1
  52. package/dist/core/extensions/types.d.ts +8 -2
  53. package/dist/core/extensions/types.d.ts.map +1 -1
  54. package/dist/core/extensions/types.js.map +1 -1
  55. package/dist/core/model-registry.d.ts +1 -0
  56. package/dist/core/model-registry.d.ts.map +1 -1
  57. package/dist/core/model-registry.js +9 -6
  58. package/dist/core/model-registry.js.map +1 -1
  59. package/dist/core/model-resolver.d.ts.map +1 -1
  60. package/dist/core/model-resolver.js +35 -5
  61. package/dist/core/model-resolver.js.map +1 -1
  62. package/dist/core/prompt-templates.js.map +1 -1
  63. package/dist/core/resource-loader.d.ts +2 -0
  64. package/dist/core/resource-loader.d.ts.map +1 -1
  65. package/dist/core/resource-loader.js +5 -1
  66. package/dist/core/resource-loader.js.map +1 -1
  67. package/dist/core/sdk.d.ts +1 -1
  68. package/dist/core/sdk.d.ts.map +1 -1
  69. package/dist/core/sdk.js.map +1 -1
  70. package/dist/core/session-manager.js.map +1 -1
  71. package/dist/core/settings-manager.d.ts +3 -0
  72. package/dist/core/settings-manager.d.ts.map +1 -1
  73. package/dist/core/settings-manager.js +4 -0
  74. package/dist/core/settings-manager.js.map +1 -1
  75. package/dist/core/system-prompt.d.ts +4 -0
  76. package/dist/core/system-prompt.d.ts.map +1 -1
  77. package/dist/core/system-prompt.js +34 -12
  78. package/dist/core/system-prompt.js.map +1 -1
  79. package/dist/core/tools/edit-diff.js.map +1 -1
  80. package/dist/core/tools/path-utils.js.map +1 -1
  81. package/dist/index.d.ts +1 -1
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +1 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +5 -5
  87. package/dist/main.js.map +1 -1
  88. package/dist/migrations.d.ts +1 -1
  89. package/dist/migrations.d.ts.map +1 -1
  90. package/dist/migrations.js +3 -3
  91. package/dist/migrations.js.map +1 -1
  92. package/dist/modes/interactive/components/armin.js.map +1 -1
  93. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  94. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  95. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  96. package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
  97. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  98. package/dist/modes/interactive/components/extension-editor.js +9 -1
  99. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  100. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  101. package/dist/modes/interactive/components/footer.js.map +1 -1
  102. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  103. package/dist/modes/interactive/components/login-dialog.js +1 -1
  104. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  105. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  106. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  107. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  108. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  109. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  110. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  111. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  112. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  113. package/dist/modes/interactive/components/session-selector.js +1 -1
  114. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  115. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  116. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  117. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  118. package/dist/modes/interactive/components/tool-execution.js +28 -3
  119. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  120. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  121. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  122. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  123. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  124. package/dist/modes/interactive/components/user-message.js +11 -0
  125. package/dist/modes/interactive/components/user-message.js.map +1 -1
  126. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  127. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  128. package/dist/modes/interactive/interactive-mode.js +28 -27
  129. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  130. package/dist/modes/interactive/theme/dark.json +1 -1
  131. package/dist/modes/interactive/theme/light.json +1 -1
  132. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  133. package/dist/modes/interactive/theme/theme.js +5 -0
  134. package/dist/modes/interactive/theme/theme.js.map +1 -1
  135. package/dist/prompts/commands/discuss-phase.md +3 -3
  136. package/dist/prompts/commands/execute-phase.md +9 -9
  137. package/dist/prompts/commands/fix.md +29 -0
  138. package/dist/prompts/commands/init-project.md +49 -0
  139. package/dist/prompts/commands/map-codebase.md +2 -2
  140. package/dist/prompts/commands/new-project.md +9 -9
  141. package/dist/prompts/commands/next-milestone.md +44 -0
  142. package/dist/prompts/commands/pause-work.md +2 -2
  143. package/dist/prompts/commands/plan-phase.md +5 -5
  144. package/dist/prompts/commands/progress.md +1 -1
  145. package/dist/prompts/commands/quick.md +4 -4
  146. package/dist/prompts/commands/resume-work.md +1 -1
  147. package/dist/prompts/commands/review.md +26 -0
  148. package/dist/prompts/commands/verify-work.md +4 -4
  149. package/docs/compaction.md +14 -14
  150. package/docs/custom-provider.md +19 -11
  151. package/docs/development.md +1 -1
  152. package/docs/extensions.md +52 -33
  153. package/docs/json.md +4 -4
  154. package/docs/packages.md +1 -1
  155. package/docs/providers.md +4 -2
  156. package/docs/rpc.md +1 -1
  157. package/docs/sdk.md +24 -24
  158. package/docs/session.md +6 -6
  159. package/docs/settings.md +1 -0
  160. package/docs/termux.md +1 -1
  161. package/docs/themes.md +2 -2
  162. package/docs/tui.md +20 -20
  163. package/examples/extensions/README.md +5 -4
  164. package/examples/extensions/antigravity-image-gen.ts +3 -1
  165. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  166. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  167. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  168. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  169. package/examples/extensions/doom-overlay/README.md +1 -1
  170. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  171. package/examples/extensions/dynamic-tools.ts +74 -0
  172. package/examples/extensions/subagent/README.md +11 -11
  173. package/examples/extensions/with-deps/package-lock.json +2 -2
  174. package/examples/extensions/with-deps/package.json +1 -1
  175. package/examples/sdk/README.md +3 -3
  176. package/package.json +11 -8
  177. package/prompts/commands/discuss-phase.md +3 -3
  178. package/prompts/commands/execute-phase.md +9 -9
  179. package/prompts/commands/fix.md +29 -0
  180. package/prompts/commands/init-project.md +49 -0
  181. package/prompts/commands/map-codebase.md +2 -2
  182. package/prompts/commands/new-project.md +9 -9
  183. package/prompts/commands/next-milestone.md +44 -0
  184. package/prompts/commands/pause-work.md +2 -2
  185. package/prompts/commands/plan-phase.md +5 -5
  186. package/prompts/commands/progress.md +1 -1
  187. package/prompts/commands/quick.md +4 -4
  188. package/prompts/commands/resume-work.md +1 -1
  189. package/prompts/commands/review.md +26 -0
  190. package/prompts/commands/verify-work.md +4 -4
  191. package/dist/extensions/gsd-commands.ts +0 -338
  192. package/dist/extensions/subagent.ts +0 -312
  193. package/extensions/gsd-commands.ts +0 -338
  194. package/extensions/subagent.ts +0 -312
@@ -8,11 +8,11 @@ Initialize a new GSD project: questioning → research → requirements → road
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht init` to check preconditions
12
- 2. If existing code detected, run `draht map-codebase` first
11
+ 1. Run `draht-tools init` to check preconditions
12
+ 2. If existing code detected, run `draht-tools map-codebase` first
13
13
  3. Deep questioning phase (3-7 rounds, 1-2 questions at a time)
14
- 4. Run `draht create-project` with gathered info
15
- 5. Run `draht create-domain-model` to define bounded contexts, entities, and ubiquitous language
14
+ 4. Run `draht-tools create-project` with gathered info
15
+ 5. Run `draht-tools create-domain-model` to define bounded contexts, entities, and ubiquitous language
16
16
  6. Create `.planning/DOMAIN.md` with:
17
17
  - `## Bounded Contexts` — each context with name, responsibility, and brief description
18
18
  - `## Ubiquitous Language` — glossary of domain terms agreed with the user (term → definition)
@@ -25,11 +25,11 @@ Initialize a new GSD project: questioning → research → requirements → road
25
25
  - `## Coverage Goals` — target coverage percentage and which paths are critical
26
26
  - `## Testing Levels` — what is tested at unit level vs integration vs e2e, with examples
27
27
  - `## Excluded` — what is explicitly not tested and why (config files, generated code, etc.)
28
- 8. Optional research phase via `draht research`
29
- 9. Run `draht create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
30
- 10. Run `draht create-roadmap` with phases
31
- 11. Run `draht init-state`
32
- 12. Git commit via `draht commit-docs "initialize GSD project"`
28
+ 8. Optional research phase via `draht-tools research`
29
+ 9. Run `draht-tools create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
30
+ 10. Run `draht-tools create-roadmap` with phases
31
+ 11. Run `draht-tools init-state`
32
+ 12. Git commit via `draht-tools commit-docs "initialize GSD project"`
33
33
 
34
34
  ## Rules
35
35
  - Ask 1-2 questions at a time, never dump 10 at once
@@ -0,0 +1,44 @@
1
+ # /next-milestone
2
+
3
+ Plan the next milestone after the current one is complete.
4
+
5
+ ## Usage
6
+ ```
7
+ /next-milestone
8
+ ```
9
+
10
+ ## Prerequisites
11
+ - `.planning/ROADMAP.md` must exist
12
+ - Current milestone should be complete or nearly complete
13
+
14
+ ## Steps
15
+ 1. Load project context:
16
+ - Read `.planning/ROADMAP.md` — identify the completed milestone and its phases
17
+ - Read `.planning/STATE.md` — understand current status
18
+ - Read `.planning/REQUIREMENTS.md` — check which requirements are satisfied
19
+ - Read `.planning/DOMAIN.md` (if exists) — review domain model for evolution needs
20
+ 2. Review completed work:
21
+ - Scan `.planning/phases/` for all UAT reports (`*-UAT.md`) and summaries (`*-SUMMARY.md`)
22
+ - Note what was built, what worked well, what had issues
23
+ 3. Assess requirements:
24
+ - Which v1 requirements are now satisfied?
25
+ - Which v1 requirements remain?
26
+ - Should any v2 requirements be promoted based on what we learned?
27
+ - Are there new requirements discovered during implementation?
28
+ 4. Propose next milestone:
29
+ - Define 3-5 phases, each with a clear goal (outcome, not activity)
30
+ - Order phases by dependency
31
+ - Map each phase to specific requirements
32
+ - Estimate relative complexity
33
+ 5. Present the proposed milestone for user approval before writing files
34
+ 6. After approval:
35
+ - Update `ROADMAP.md` with the new milestone and phases
36
+ - Update `STATE.md` to reflect milestone transition
37
+ - Update `REQUIREMENTS.md` if requirements changed
38
+ - Update `DOMAIN.md` if domain model needs evolution
39
+ - Commit: `draht-tools commit-docs "plan next milestone"`
40
+
41
+ ## Rules
42
+ - Always review what was actually built, not just what was planned
43
+ - Be honest about requirements that slipped or changed scope
44
+ - Each phase goal must be testable — "user can X" not "implement Y"
@@ -8,5 +8,5 @@ Create a handoff document for session continuity.
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht pause` — creates CONTINUE-HERE.md
12
- 2. Commit: `draht commit-docs "pause work"`
11
+ 1. Run `draht-tools pause` — creates CONTINUE-HERE.md
12
+ 2. Commit: `draht-tools commit-docs "pause work"`
@@ -8,17 +8,17 @@ Create atomic execution plans for a roadmap phase.
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht load-phase-context N` to gather all context
12
- 2. Optional: `draht research-phase N` for domain research
11
+ 1. Run `draht-tools load-phase-context N` to gather all context
12
+ 2. Optional: `draht-tools research-phase N` for domain research
13
13
  3. Goal-backward planning:
14
14
  a. State the goal (outcome, not activity)
15
15
  b. Derive observable truths (3-7 from user perspective)
16
16
  c. From each observable truth, derive the test scenarios that would prove it (specific inputs → expected outputs or state changes)
17
17
  d. Map to required artifacts (files, endpoints, schemas)
18
18
  e. Break into atomic tasks (2-5 per plan)
19
- 4. Write plans: `draht create-plan N P`
20
- 5. Validate: `draht validate-plans N`
21
- 6. Commit: `draht commit-docs "create phase N plans"`
19
+ 4. Write plans: `draht-tools create-plan N P`
20
+ 5. Validate: `draht-tools validate-plans N`
21
+ 6. Commit: `draht-tools commit-docs "create phase N plans"`
22
22
 
23
23
  ## Plan Format
24
24
  Plans use XML task format:
@@ -8,5 +8,5 @@ Show current project status.
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht progress` — outputs formatted status
11
+ 1. Run `draht-tools progress` — outputs formatted status
12
12
  2. Display the result as-is
@@ -8,12 +8,12 @@ Execute a small ad-hoc task with GSD tracking.
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht next-quick-number` to get task number
12
- 2. Create quick plan: `draht create-quick-plan NNN "description"`
11
+ 1. Run `draht-tools next-quick-number` to get task number
12
+ 2. Create quick plan: `draht-tools create-quick-plan NNN "description"`
13
13
  3. Execute tasks following the TDD cycle:
14
14
  - **🔴 RED** — Write a failing test that describes the desired behaviour
15
15
  - **🟢 GREEN** — Write the minimum implementation to make it pass
16
16
  - **🔵 REFACTOR** — Clean up while keeping the test green
17
17
  - *Exception: skip the TDD cycle only for pure config or documentation-only tasks that have no testable behaviour*
18
- 4. Write summary: `draht write-quick-summary NNN`
19
- 5. Update state: `draht update-state`
18
+ 4. Write summary: `draht-tools write-quick-summary NNN`
19
+ 5. Update state: `draht-tools update-state`
@@ -8,6 +8,6 @@ Resume from last session state.
8
8
  ```
9
9
 
10
10
  ## Steps
11
- 1. Run `draht resume` — loads CONTINUE-HERE.md or STATE.md
11
+ 1. Run `draht-tools resume` — loads CONTINUE-HERE.md or STATE.md
12
12
  2. Display context and ask to continue
13
13
  3. Delete CONTINUE-HERE.md after confirmation
@@ -0,0 +1,26 @@
1
+ # /review
2
+
3
+ Ad-hoc code review and security audit of recent changes or a specific scope.
4
+
5
+ ## Usage
6
+ ```
7
+ /review [scope]
8
+ ```
9
+
10
+ If no scope given, reviews all recent uncommitted changes.
11
+
12
+ ## Steps
13
+ 1. Identify the scope:
14
+ - If argument given: review those files/directories/description
15
+ - If no argument: run `git diff --stat` and `git diff --cached --stat` to find changes
16
+ 2. For each changed file, examine:
17
+ - Correctness: logic errors, off-by-one, null handling, error paths
18
+ - Type safety: any `as` casts, `any` types, missing null checks
19
+ - Conventions: naming, file organization, import style
20
+ - Security: injection risks, auth bypasses, secrets in code, unsafe deserialization
21
+ - Performance: unnecessary allocations, missing indexes, N+1 queries
22
+ 3. Produce a prioritized findings report:
23
+ - **Critical** — must fix before merge (security, data loss, crashes)
24
+ - **Important** — should fix (bugs, type issues, missing error handling)
25
+ - **Minor** — style, naming, or optional improvements
26
+ 4. For each finding: cite the exact file and line, explain the issue, suggest the fix
@@ -15,13 +15,13 @@ Walk through acceptance testing of completed phase work.
15
15
  - Load `.planning/DOMAIN.md` and extract all defined terms
16
16
  - Scan source files for PascalCase identifiers not present in the glossary
17
17
  - Flag any bounded context boundary violations (cross-context direct imports)
18
- 3. Run quality gate: `draht quality-gate --strict`
19
- 4. Run `draht extract-deliverables N` to get testable items
18
+ 3. Run quality gate: `draht-tools quality-gate --strict`
19
+ 4. Run `draht-tools extract-deliverables N` to get testable items
20
20
  5. Walk user through each deliverable one at a time
21
21
  6. Record results (pass/fail/partially/skip)
22
- 7. For failures: diagnose and create fix plans via `draht create-fix-plan N P`
22
+ 7. For failures: diagnose and create fix plans via `draht-tools create-fix-plan N P`
23
23
  - Fix plans MUST include a reproducing test that demonstrates the failure before any implementation
24
- 8. Write UAT report: `draht write-uat N`
24
+ 8. Write UAT report: `draht-tools write-uat N`
25
25
  - Report must include: test health summary (pass/fail/coverage), domain model status (any glossary violations), deliverable results
26
26
  9. If all passed: mark phase complete
27
27
  10. If failures: route to `execute-phase N --gaps-only`
@@ -1,338 +0,0 @@
1
- /**
2
- * GSD — Get Shit Done
3
- *
4
- * Batteries-included phase commands for structured AI-assisted development.
5
- *
6
- * Full workflow:
7
- * /discuss <feature> — clarify requirements before planning
8
- * /plan <feature> — architect produces implementation plan
9
- * /execute <task1, task2...> — parallel implement → review → commit
10
- * /verify — parallel lint/typecheck/tests + security audit
11
- *
12
- * Utilities:
13
- * /review <scope> — ad-hoc code review + security audit
14
- * /fix <issue> — targeted fix plan for a failing task
15
- * /quick <task> — one-shot implement + commit (skip full GSD)
16
- * /resume — pick up interrupted work from CONTINUE-HERE.md
17
- * /status — show .planning/STATE.md overview
18
- * /new-project <name> [path] — create project dir, git init, scaffold .draht/
19
- * /init-project — scaffold .draht/ in existing project
20
- */
21
-
22
- import * as fs from "node:fs";
23
- import * as path from "node:path";
24
- import type { ExtensionAPI } from "@draht/coding-agent";
25
-
26
- function isBusy(ctx: { isIdle: () => boolean }, ui: { notify: (msg: string, level: string) => void }): boolean {
27
- if (!ctx.isIdle()) {
28
- ui.notify("Agent is busy", "warning");
29
- return true;
30
- }
31
- return false;
32
- }
33
-
34
- export default function (pi: ExtensionAPI) {
35
- // ── /discuss ─────────────────────────────────────────────────────────────
36
- pi.registerCommand("discuss", {
37
- description: "Clarify requirements before planning. Architect asks questions and defines scope. Usage: /discuss <feature>",
38
- handler: async (args, ctx) => {
39
- if (!args.trim()) {
40
- ctx.ui.notify("Usage: /discuss <feature description>", "warning");
41
- return;
42
- }
43
- if (isBusy(ctx, ctx.ui)) return;
44
-
45
- pi.sendUserMessage(
46
- `Use the subagent tool to delegate to the architect agent with this task:
47
-
48
- "We are in the DISCUSS phase for: ${args.trim()}
49
-
50
- Your job is NOT to plan yet. First:
51
- 1. Read relevant existing code to understand the current state
52
- 2. Identify ambiguities, unknowns, and risks
53
- 3. List clarifying questions that need answers before planning can begin
54
- 4. Define a clear, bounded scope for what will and won't be built
55
- 5. Output a DISCUSS summary with: scope, assumptions, open questions, risks
56
-
57
- Do not produce file lists or implementation details yet."
58
-
59
- Set agentScope to "project".`,
60
- );
61
- },
62
- });
63
-
64
- // ── /plan ────────────────────────────────────────────────────────────────
65
- pi.registerCommand("plan", {
66
- description: "Plan a feature — architect reads codebase and produces structured implementation plan. Usage: /plan <feature>",
67
- handler: async (args, ctx) => {
68
- if (!args.trim()) {
69
- ctx.ui.notify("Usage: /plan <feature description>", "warning");
70
- return;
71
- }
72
- if (isBusy(ctx, ctx.ui)) return;
73
-
74
- pi.sendUserMessage(
75
- `Use the subagent tool to delegate to the architect agent with this task: "${args.trim()}"\n\nSet agentScope to "project".`,
76
- );
77
- },
78
- });
79
-
80
- // ── /execute ─────────────────────────────────────────────────────────────
81
- pi.registerCommand("execute", {
82
- description: "Execute tasks in parallel, then chain reviewer + git-committer. Usage: /execute task1, task2, task3",
83
- handler: async (args, ctx) => {
84
- if (!args.trim()) {
85
- ctx.ui.notify("Usage: /execute task1, task2, task3", "warning");
86
- return;
87
- }
88
- if (isBusy(ctx, ctx.ui)) return;
89
-
90
- const tasks = args.split(",").map((t) => t.trim()).filter(Boolean);
91
-
92
- if (tasks.length === 1) {
93
- pi.sendUserMessage(
94
- `Use the subagent tool in chain mode with agentScope "project":
95
- 1. agent: implementer — task: "${tasks[0]}"
96
- 2. agent: reviewer — task: "Review the changes just made: {previous}"
97
- 3. agent: git-committer — task: "Commit all changes. Review context: {previous}"`,
98
- );
99
- } else {
100
- const parallelList = tasks.map((t, i) => `${i + 1}. agent: implementer — task: "${t}"`).join("\n");
101
- pi.sendUserMessage(
102
- `Use the subagent tool with agentScope "project":
103
-
104
- Step 1 — PARALLEL mode (run all simultaneously):
105
- ${parallelList}
106
-
107
- Step 2 — CHAIN mode (after all parallel tasks complete):
108
- 1. agent: reviewer — task: "Review all changes just implemented"
109
- 2. agent: git-committer — task: "Commit all changes. Review findings: {previous}"`,
110
- );
111
- }
112
- },
113
- });
114
-
115
- // ── /verify ──────────────────────────────────────────────────────────────
116
- pi.registerCommand("verify", {
117
- description: "Parallel verification: lint, typecheck, tests, and security audit",
118
- handler: async (_args, ctx) => {
119
- if (isBusy(ctx, ctx.ui)) return;
120
-
121
- pi.sendUserMessage(
122
- `Use the subagent tool in PARALLEL mode with agentScope "project":
123
- 1. agent: verifier — task: "Run all lint, typecheck, and test checks"
124
- 2. agent: security-auditor — task: "Audit all recent changes for security vulnerabilities"
125
-
126
- After both complete, merge findings into a single prioritized report. List what must be fixed before this is production-ready.`,
127
- );
128
- },
129
- });
130
-
131
- // ── /review ──────────────────────────────────────────────────────────────
132
- pi.registerCommand("review", {
133
- description: "Ad-hoc code review + security audit. Usage: /review <scope or files>",
134
- handler: async (args, ctx) => {
135
- if (isBusy(ctx, ctx.ui)) return;
136
-
137
- const scope = args.trim() || "all recent changes";
138
- pi.sendUserMessage(
139
- `Use the subagent tool in PARALLEL mode with agentScope "project":
140
- 1. agent: reviewer — task: "Review ${scope} for correctness, type safety, and conventions"
141
- 2. agent: security-auditor — task: "Audit ${scope} for security vulnerabilities"
142
-
143
- After both complete, merge into a single prioritized findings report.`,
144
- );
145
- },
146
- });
147
-
148
- // ── /fix ─────────────────────────────────────────────────────────────────
149
- pi.registerCommand("fix", {
150
- description: "Create a targeted fix plan for a failing task or bug. Usage: /fix <description of what's broken>",
151
- handler: async (args, ctx) => {
152
- if (!args.trim()) {
153
- ctx.ui.notify("Usage: /fix <description of what's broken>", "warning");
154
- return;
155
- }
156
- if (isBusy(ctx, ctx.ui)) return;
157
-
158
- pi.sendUserMessage(
159
- `Use the subagent tool in chain mode with agentScope "project":
160
- 1. agent: architect — task: "Diagnose this issue and produce a minimal fix plan: ${args.trim()}. Read the relevant code first. Output: root cause, exact files to change, fix steps."
161
- 2. agent: implementer — task: "Apply this fix plan exactly: {previous}"
162
- 3. agent: reviewer — task: "Verify the fix is correct and doesn't introduce regressions: {previous}"
163
- 4. agent: git-committer — task: "Commit the fix. Fix summary: {previous}"`,
164
- );
165
- },
166
- });
167
-
168
- // ── /quick ───────────────────────────────────────────────────────────────
169
- pi.registerCommand("quick", {
170
- description: "One-shot task: implement + commit. Skips full GSD workflow. Usage: /quick <task>",
171
- handler: async (args, ctx) => {
172
- if (!args.trim()) {
173
- ctx.ui.notify("Usage: /quick <task description>", "warning");
174
- return;
175
- }
176
- if (isBusy(ctx, ctx.ui)) return;
177
-
178
- pi.sendUserMessage(
179
- `Use the subagent tool in chain mode with agentScope "project":
180
- 1. agent: implementer — task: "${args.trim()}"
181
- 2. agent: git-committer — task: "Commit the changes just made: {previous}"`,
182
- );
183
- },
184
- });
185
-
186
- // ── /resume ──────────────────────────────────────────────────────────────
187
- pi.registerCommand("resume", {
188
- description: "Resume interrupted work — reads CONTINUE-HERE.md and picks up where we left off",
189
- handler: async (_args, ctx) => {
190
- if (isBusy(ctx, ctx.ui)) return;
191
-
192
- const continueFile = path.join(ctx.cwd, ".planning", "CONTINUE-HERE.md");
193
- const stateFile = path.join(ctx.cwd, ".planning", "STATE.md");
194
-
195
- if (!fs.existsSync(continueFile) && !fs.existsSync(stateFile)) {
196
- ctx.ui.notify("No .planning/CONTINUE-HERE.md or STATE.md found. Nothing to resume.", "warning");
197
- return;
198
- }
199
-
200
- let context = "";
201
- if (fs.existsSync(continueFile)) {
202
- context += `\nCONTINUE-HERE.md:\n${fs.readFileSync(continueFile, "utf-8")}`;
203
- }
204
- if (fs.existsSync(stateFile)) {
205
- context += `\nSTATE.md:\n${fs.readFileSync(stateFile, "utf-8")}`;
206
- }
207
-
208
- pi.sendUserMessage(
209
- `Read the following project state and resume work from where it was interrupted. Identify the next incomplete task and proceed with it using the appropriate subagent.${context}`,
210
- );
211
- },
212
- });
213
-
214
- // ── /status ──────────────────────────────────────────────────────────────
215
- pi.registerCommand("status", {
216
- description: "Show current GSD project state from .planning/STATE.md",
217
- handler: async (_args, ctx) => {
218
- const stateFile = path.join(ctx.cwd, ".planning", "STATE.md");
219
- const logFile = path.join(ctx.cwd, ".planning", "execution-log.jsonl");
220
-
221
- if (!fs.existsSync(stateFile)) {
222
- ctx.ui.notify("No .planning/STATE.md found. Run /init-project or /new-project first.", "warning");
223
- return;
224
- }
225
-
226
- let output = fs.readFileSync(stateFile, "utf-8");
227
-
228
- if (fs.existsSync(logFile)) {
229
- const entries = fs.readFileSync(logFile, "utf-8")
230
- .split("\n").filter(Boolean)
231
- .map((l) => { try { return JSON.parse(l); } catch { return null; } })
232
- .filter(Boolean);
233
-
234
- const passed = entries.filter((e) => e.status === "pass").length;
235
- const failed = entries.filter((e) => e.status === "fail").length;
236
- const skipped = entries.filter((e) => e.status === "skip").length;
237
- output += `\n\n---\n**Execution log:** ${passed} passed, ${failed} failed, ${skipped} skipped`;
238
- }
239
-
240
- pi.sendUserMessage(`Here is the current project state:\n\n${output}`);
241
- },
242
- });
243
-
244
- // ── /new-project ─────────────────────────────────────────────────────────
245
- pi.registerCommand("new-project", {
246
- description: "Create a new project: mkdir, git init, scaffold .draht/. Usage: /new-project <name> [/base/path]",
247
- handler: async (args, ctx) => {
248
- const parts = args.trim().split(/\s+/);
249
- const name = parts[0];
250
- if (!name) {
251
- ctx.ui.notify("Usage: /new-project <name> [/optional/base/path]", "warning");
252
- return;
253
- }
254
-
255
- const basePath = parts[1] ?? ctx.cwd;
256
- const projectDir = path.join(basePath, name);
257
-
258
- if (fs.existsSync(projectDir)) {
259
- ctx.ui.notify(`Directory already exists: ${projectDir}`, "warning");
260
- return;
261
- }
262
-
263
- fs.mkdirSync(projectDir, { recursive: true });
264
-
265
- const { execSync } = await import("node:child_process");
266
- execSync("git init", { cwd: projectDir });
267
-
268
- // Scaffold .draht/ from global agents
269
- const agentSrc = path.join(process.env.HOME ?? "~", ".draht", "agent", "agents");
270
- const agentDest = path.join(projectDir, ".draht", "agents");
271
- const extDest = path.join(projectDir, ".draht", "extensions");
272
- fs.mkdirSync(agentDest, { recursive: true });
273
- fs.mkdirSync(extDest, { recursive: true });
274
-
275
- let agentsCopied = 0;
276
- if (fs.existsSync(agentSrc)) {
277
- for (const file of fs.readdirSync(agentSrc)) {
278
- if (!file.endsWith(".md")) continue;
279
- fs.copyFileSync(path.join(agentSrc, file), path.join(agentDest, file));
280
- agentsCopied++;
281
- }
282
- }
283
-
284
- // Copy shipped extensions into the new project
285
- const extSrc = path.dirname(new URL(import.meta.url).pathname);
286
- for (const file of ["subagent.ts", "gsd-commands.ts"]) {
287
- const src = path.join(extSrc, file);
288
- if (fs.existsSync(src)) {
289
- fs.copyFileSync(src, path.join(extDest, file));
290
- }
291
- }
292
-
293
- fs.writeFileSync(path.join(projectDir, ".gitignore"), "node_modules/\n.env\n.env.local\n");
294
-
295
- ctx.ui.notify(
296
- `✓ ${projectDir} created — ${agentsCopied} agents, git initialized. Customize .draht/agents/*.md for your stack.`,
297
- "info",
298
- );
299
-
300
- pi.sendUserMessage(
301
- `New project "${name}" created at ${projectDir} with ${agentsCopied} GSD agents scaffolded. What should we build first?`,
302
- );
303
- },
304
- });
305
-
306
- // ── /init-project ────────────────────────────────────────────────────────
307
- pi.registerCommand("init-project", {
308
- description: "Scaffold .draht/ config into an existing project from global agent defaults",
309
- handler: async (_args, ctx) => {
310
- const targetDir = path.join(ctx.cwd, ".draht");
311
-
312
- if (fs.existsSync(targetDir)) {
313
- ctx.ui.notify(".draht/ already exists in this project", "warning");
314
- return;
315
- }
316
-
317
- const agentSrc = path.join(process.env.HOME ?? "~", ".draht", "agent", "agents");
318
- const agentDest = path.join(targetDir, "agents");
319
- const extDest = path.join(targetDir, "extensions");
320
- fs.mkdirSync(agentDest, { recursive: true });
321
- fs.mkdirSync(extDest, { recursive: true });
322
-
323
- let copied = 0;
324
- if (fs.existsSync(agentSrc)) {
325
- for (const file of fs.readdirSync(agentSrc)) {
326
- if (!file.endsWith(".md")) continue;
327
- fs.copyFileSync(path.join(agentSrc, file), path.join(agentDest, file));
328
- copied++;
329
- }
330
- }
331
-
332
- ctx.ui.notify(
333
- `.draht/ scaffolded with ${copied} agents. Customize .draht/agents/*.md for this project's stack.`,
334
- "info",
335
- );
336
- },
337
- });
338
- }