@draht/coding-agent 2026.3.4 → 2026.3.5
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 +24 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +4 -2
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/gsd/domain-validator.d.ts +18 -0
- package/dist/gsd/domain-validator.d.ts.map +1 -0
- package/dist/gsd/domain-validator.js +61 -0
- package/dist/gsd/domain-validator.js.map +1 -0
- package/dist/gsd/domain.d.ts +12 -0
- package/dist/gsd/domain.d.ts.map +1 -0
- package/dist/gsd/domain.js +113 -0
- package/dist/gsd/domain.js.map +1 -0
- package/dist/gsd/git.d.ts +20 -0
- package/dist/gsd/git.d.ts.map +1 -0
- package/dist/gsd/git.js +59 -0
- package/dist/gsd/git.js.map +1 -0
- package/dist/gsd/hook-utils.d.ts +22 -0
- package/dist/gsd/hook-utils.d.ts.map +1 -0
- package/dist/gsd/hook-utils.js +100 -0
- package/dist/gsd/hook-utils.js.map +1 -0
- package/dist/gsd/index.d.ts +9 -0
- package/dist/gsd/index.d.ts.map +1 -0
- package/dist/gsd/index.js +8 -0
- package/dist/gsd/index.js.map +1 -0
- package/dist/gsd/planning.d.ts +20 -0
- package/dist/gsd/planning.d.ts.map +1 -0
- package/dist/gsd/planning.js +167 -0
- package/dist/gsd/planning.js.map +1 -0
- package/dist/hooks/gsd/draht-post-task.js +44 -11
- package/dist/hooks/gsd/draht-quality-gate.js +99 -57
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/prompts/agents/build.md +5 -1
- package/dist/prompts/agents/plan.md +5 -1
- package/dist/prompts/agents/verify.md +5 -1
- package/dist/prompts/commands/atomic-commit.md +8 -16
- package/dist/prompts/commands/discuss-phase.md +9 -3
- package/dist/prompts/commands/execute-phase.md +15 -8
- package/dist/prompts/commands/fix.md +6 -0
- package/dist/prompts/commands/init-project.md +9 -3
- package/dist/prompts/commands/map-codebase.md +7 -1
- package/dist/prompts/commands/new-project.md +8 -2
- package/dist/prompts/commands/next-milestone.md +4 -0
- package/dist/prompts/commands/pause-work.md +4 -0
- package/dist/prompts/commands/plan-phase.md +11 -5
- package/dist/prompts/commands/progress.md +4 -0
- package/dist/prompts/commands/quick.md +8 -2
- package/dist/prompts/commands/resume-work.md +4 -0
- package/dist/prompts/commands/review.md +6 -0
- package/dist/prompts/commands/verify-work.md +10 -4
- package/hooks/gsd/draht-post-task.js +44 -11
- package/hooks/gsd/draht-quality-gate.js +99 -57
- package/package.json +5 -5
- package/prompts/agents/build.md +5 -1
- package/prompts/agents/plan.md +5 -1
- package/prompts/agents/verify.md +5 -1
- package/prompts/commands/atomic-commit.md +8 -16
- package/prompts/commands/discuss-phase.md +9 -3
- package/prompts/commands/execute-phase.md +15 -8
- package/prompts/commands/fix.md +6 -0
- package/prompts/commands/init-project.md +9 -3
- package/prompts/commands/map-codebase.md +7 -1
- package/prompts/commands/new-project.md +8 -2
- package/prompts/commands/next-milestone.md +4 -0
- package/prompts/commands/pause-work.md +4 -0
- package/prompts/commands/plan-phase.md +11 -5
- package/prompts/commands/progress.md +4 -0
- package/prompts/commands/quick.md +8 -2
- package/prompts/commands/resume-work.md +4 -0
- package/prompts/commands/review.md +6 -0
- package/prompts/commands/verify-work.md +10 -4
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Execution agent that implements plans precisely"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Draht Build Agent
|
|
2
6
|
|
|
3
|
-
You are an execution agent
|
|
7
|
+
You are an execution agent. Your job is to implement plans precisely.
|
|
4
8
|
|
|
5
9
|
## Core Rules
|
|
6
10
|
1. Read the plan FIRST — it is your instruction set
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Planning agent that creates atomic, executable plans"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Draht Plan Agent
|
|
2
6
|
|
|
3
|
-
You are a planning agent
|
|
7
|
+
You are a planning agent. Your job is to create atomic, executable plans.
|
|
4
8
|
|
|
5
9
|
## Core Rules
|
|
6
10
|
1. Plans are prompts — they tell the executor EXACTLY what to build
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Verification agent that tests work against acceptance criteria"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Draht Verify Agent
|
|
2
6
|
|
|
3
|
-
You are a verification agent
|
|
7
|
+
You are a verification agent. Your job is to test completed work against acceptance criteria.
|
|
4
8
|
|
|
5
9
|
## Core Rules
|
|
6
10
|
1. Test from the USER's perspective, not the developer's
|
|
@@ -4,19 +4,13 @@ description: "Analyze changes and create atomic commits"
|
|
|
4
4
|
|
|
5
5
|
# Git Atomic Commit Analysis
|
|
6
6
|
|
|
7
|
-
First,
|
|
7
|
+
First, gather the current state:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
1. Run `git status` to see what changed
|
|
10
|
+
2. Run `git diff` to see unstaged changes
|
|
11
|
+
3. Run `git diff --cached` to see staged changes
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*! git diff*
|
|
14
|
-
|
|
15
|
-
And staged changes:
|
|
16
|
-
|
|
17
|
-
*! git diff --cached*
|
|
18
|
-
|
|
19
|
-
Based on the changes shown above, analyze and group them into logical, ATOMIC commits. Each commit should:
|
|
13
|
+
Based on the changes, analyze and group them into logical, ATOMIC commits. Each commit should:
|
|
20
14
|
|
|
21
15
|
1. Contain ONE logical change only
|
|
22
16
|
2. Be self-contained and complete
|
|
@@ -27,13 +21,11 @@ For each group of changes you identify:
|
|
|
27
21
|
- Generate a clear, descriptive commit message following conventional commits format
|
|
28
22
|
- Explain WHY these changes belong in one commit
|
|
29
23
|
|
|
30
|
-
Then
|
|
24
|
+
Then execute the `git add` and `git commit` commands for each atomic commit in the order they should be applied.
|
|
31
25
|
|
|
32
26
|
Format each commit message as:
|
|
27
|
+
```
|
|
33
28
|
type(scope): brief description
|
|
34
|
-
|
|
35
|
-
- Why the change was necessary
|
|
36
|
-
|
|
29
|
+
```
|
|
37
30
|
|
|
38
31
|
Common types: feat, fix, refactor, docs, test, chore, style, perf
|
|
39
|
-
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Capture implementation decisions before planning a phase"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /discuss-phase
|
|
2
6
|
|
|
3
7
|
Capture implementation decisions before planning a phase.
|
|
@@ -7,13 +11,15 @@ Capture implementation decisions before planning a phase.
|
|
|
7
11
|
/discuss-phase [N]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Phase: $1
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
|
-
1. Run `draht-tools phase-info
|
|
17
|
+
1. Run `draht-tools phase-info $1` to load phase context
|
|
12
18
|
2. Identify gray areas based on what's being built
|
|
13
19
|
3. Present 1-2 questions at a time about preferences
|
|
14
20
|
4. If `.planning/DOMAIN.md` exists, load it and validate discovered terms against the glossary. Add any new domain terms found during discussion.
|
|
15
|
-
5. Record decisions with `draht-tools save-context
|
|
16
|
-
6. Commit: `draht-tools commit-docs "capture phase
|
|
21
|
+
5. Record decisions with `draht-tools save-context $1`
|
|
22
|
+
6. Commit: `draht-tools commit-docs "capture phase $1 context"`
|
|
17
23
|
|
|
18
24
|
## Gray Area Categories
|
|
19
25
|
- **Visual features** → Layout, density, interactions, empty states
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Execute all plans in a phase with atomic commits"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /execute-phase
|
|
2
6
|
|
|
3
7
|
Execute all plans in a phase with atomic commits.
|
|
@@ -7,37 +11,40 @@ Execute all plans in a phase with atomic commits.
|
|
|
7
11
|
/execute-phase [N] [--gaps-only]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Phase: $1
|
|
15
|
+
Arguments: $ARGUMENTS
|
|
16
|
+
|
|
10
17
|
## Steps
|
|
11
|
-
1. Run `draht-tools discover-plans
|
|
18
|
+
1. Run `draht-tools discover-plans $1` to find and order plans
|
|
12
19
|
2. For each plan in dependency order:
|
|
13
|
-
a. Load plan: `draht-tools read-plan
|
|
20
|
+
a. Load plan: `draht-tools read-plan $1 P`
|
|
14
21
|
b. Execute each task in strict TDD cycle:
|
|
15
22
|
|
|
16
23
|
**🔴 RED — Write failing tests first**
|
|
17
24
|
- Write the test cases from `<test>`
|
|
18
25
|
- Run tests — confirm they FAIL (if they pass, the test is wrong)
|
|
19
|
-
- Commit failing tests: `draht-tools commit-task
|
|
26
|
+
- Commit failing tests: `draht-tools commit-task $1 P T "red: test description"`
|
|
20
27
|
|
|
21
28
|
**🟢 GREEN — Minimal implementation**
|
|
22
29
|
- Write the minimum code from `<action>` to make tests pass
|
|
23
30
|
- Use domain language from `<context>` and `<domain>` for all names
|
|
24
31
|
- Run tests — confirm they PASS
|
|
25
|
-
- Commit: `draht-tools commit-task
|
|
32
|
+
- Commit: `draht-tools commit-task $1 P T "green: task name"`
|
|
26
33
|
|
|
27
34
|
**🔵 REFACTOR — Clean up with safety net**
|
|
28
35
|
- Apply improvements from `<refactor>` (if any)
|
|
29
36
|
- Run tests after each change — must stay green
|
|
30
37
|
- Verify domain language compliance (names match DOMAIN.md)
|
|
31
|
-
- Commit: `draht-tools commit-task
|
|
38
|
+
- Commit: `draht-tools commit-task $1 P T "refactor: description"`
|
|
32
39
|
|
|
33
40
|
**✅ VERIFY**
|
|
34
41
|
- Run the `<verify>` step
|
|
35
42
|
- Confirm `<done>` criteria met
|
|
36
43
|
|
|
37
|
-
c. Write summary: `draht-tools write-summary
|
|
38
|
-
3. Phase verification: `draht-tools verify-phase
|
|
44
|
+
c. Write summary: `draht-tools write-summary $1 P`
|
|
45
|
+
3. Phase verification: `draht-tools verify-phase $1`
|
|
39
46
|
4. Update state: `draht-tools update-state`
|
|
40
|
-
5. Final commit: `draht-tools commit-docs "complete phase
|
|
47
|
+
5. Final commit: `draht-tools commit-docs "complete phase $1 execution"`
|
|
41
48
|
|
|
42
49
|
## TDD Rules
|
|
43
50
|
- Never write implementation before a failing test exists
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Diagnose and fix a bug with TDD discipline"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /fix
|
|
2
6
|
|
|
3
7
|
Diagnose and fix a specific bug or failing task with TDD discipline.
|
|
@@ -7,6 +11,8 @@ Diagnose and fix a specific bug or failing task with TDD discipline.
|
|
|
7
11
|
/fix [description of what's broken]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Issue: $ARGUMENTS
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
17
|
1. **Diagnose**: Read the relevant code and error output to identify the root cause
|
|
12
18
|
- If a test is failing, run it first to see the actual error
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Initialize planning for an existing project"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /init-project
|
|
2
6
|
|
|
3
|
-
Initialize
|
|
7
|
+
Initialize planning framework for an existing project: codebase mapping → questioning → domain model → requirements → roadmap.
|
|
4
8
|
|
|
5
9
|
## Usage
|
|
6
10
|
```
|
|
7
11
|
/init-project [focus area or goal]
|
|
8
12
|
```
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
Focus: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
Use this when you have an existing codebase and want to add structured planning.
|
|
11
17
|
For greenfield projects, use `/new-project` instead.
|
|
12
18
|
|
|
13
19
|
## Steps
|
|
@@ -37,7 +43,7 @@ For greenfield projects, use `/new-project` instead.
|
|
|
37
43
|
10. Run `draht-tools create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
|
|
38
44
|
11. Run `draht-tools create-roadmap` with phases
|
|
39
45
|
12. Run `draht-tools init-state`
|
|
40
|
-
13. Git commit via `draht-tools commit-docs "initialize
|
|
46
|
+
13. Git commit via `draht-tools commit-docs "initialize project planning"`
|
|
41
47
|
|
|
42
48
|
## Rules
|
|
43
49
|
- Ask 1-2 questions at a time, never dump 10 at once
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Analyze existing codebase before planning"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /map-codebase
|
|
2
6
|
|
|
3
7
|
Analyze existing codebase before planning.
|
|
@@ -7,8 +11,10 @@ Analyze existing codebase before planning.
|
|
|
7
11
|
/map-codebase [directory]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Directory: $1
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
|
-
1. Run `draht-tools map-codebase
|
|
17
|
+
1. Run `draht-tools map-codebase $1`
|
|
12
18
|
2. Tool generates: STACK.md, ARCHITECTURE.md, CONVENTIONS.md, CONCERNS.md
|
|
13
19
|
3. Review output, supplement with your own analysis if needed
|
|
14
20
|
4. Identify implicit bounded contexts from directory structure:
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Initialize a new project with structured planning"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /new-project
|
|
2
6
|
|
|
3
|
-
Initialize a new
|
|
7
|
+
Initialize a new project: questioning → research → requirements → roadmap.
|
|
4
8
|
|
|
5
9
|
## Usage
|
|
6
10
|
```
|
|
7
11
|
/new-project [description]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Description: $ARGUMENTS
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
17
|
1. Run `draht-tools init` to check preconditions
|
|
12
18
|
2. If existing code detected, run `draht-tools map-codebase` first
|
|
@@ -29,7 +35,7 @@ Initialize a new GSD project: questioning → research → requirements → road
|
|
|
29
35
|
9. Run `draht-tools create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
|
|
30
36
|
10. Run `draht-tools create-roadmap` with phases
|
|
31
37
|
11. Run `draht-tools init-state`
|
|
32
|
-
12. Git commit via `draht-tools commit-docs "initialize
|
|
38
|
+
12. Git commit via `draht-tools commit-docs "initialize project planning"`
|
|
33
39
|
|
|
34
40
|
## Rules
|
|
35
41
|
- Ask 1-2 questions at a time, never dump 10 at once
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create atomic execution plans for a roadmap phase"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /plan-phase
|
|
2
6
|
|
|
3
7
|
Create atomic execution plans for a roadmap phase.
|
|
@@ -7,18 +11,20 @@ Create atomic execution plans for a roadmap phase.
|
|
|
7
11
|
/plan-phase [N]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Phase: $1
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
|
-
1. Run `draht-tools load-phase-context
|
|
12
|
-
2. Optional: `draht-tools research-phase
|
|
17
|
+
1. Run `draht-tools load-phase-context $1` to gather all context
|
|
18
|
+
2. Optional: `draht-tools research-phase $1` for domain research
|
|
13
19
|
3. Goal-backward planning:
|
|
14
20
|
a. State the goal (outcome, not activity)
|
|
15
21
|
b. Derive observable truths (3-7 from user perspective)
|
|
16
22
|
c. From each observable truth, derive the test scenarios that would prove it (specific inputs → expected outputs or state changes)
|
|
17
23
|
d. Map to required artifacts (files, endpoints, schemas)
|
|
18
24
|
e. Break into atomic tasks (2-5 per plan)
|
|
19
|
-
4. Write plans: `draht-tools create-plan
|
|
20
|
-
5. Validate: `draht-tools validate-plans
|
|
21
|
-
6. Commit: `draht-tools commit-docs "create phase
|
|
25
|
+
4. Write plans: `draht-tools create-plan $1 P`
|
|
26
|
+
5. Validate: `draht-tools validate-plans $1`
|
|
27
|
+
6. Commit: `draht-tools commit-docs "create phase $1 plans"`
|
|
22
28
|
|
|
23
29
|
## Plan Format
|
|
24
30
|
Plans use XML task format:
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Execute a small ad-hoc task with tracking"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /quick
|
|
2
6
|
|
|
3
|
-
Execute a small ad-hoc task with
|
|
7
|
+
Execute a small ad-hoc task with tracking.
|
|
4
8
|
|
|
5
9
|
## Usage
|
|
6
10
|
```
|
|
7
11
|
/quick [description]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Task: $ARGUMENTS
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
17
|
1. Run `draht-tools next-quick-number` to get task number
|
|
12
|
-
2. Create quick plan: `draht-tools create-quick-plan NNN "
|
|
18
|
+
2. Create quick plan: `draht-tools create-quick-plan NNN "$ARGUMENTS"`
|
|
13
19
|
3. Execute tasks following the TDD cycle:
|
|
14
20
|
- **🔴 RED** — Write a failing test that describes the desired behaviour
|
|
15
21
|
- **🟢 GREEN** — Write the minimum implementation to make it pass
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Code review and security audit of recent changes"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /review
|
|
2
6
|
|
|
3
7
|
Ad-hoc code review and security audit of recent changes or a specific scope.
|
|
@@ -7,6 +11,8 @@ Ad-hoc code review and security audit of recent changes or a specific scope.
|
|
|
7
11
|
/review [scope]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Scope: $ARGUMENTS
|
|
15
|
+
|
|
10
16
|
If no scope given, reviews all recent uncommitted changes.
|
|
11
17
|
|
|
12
18
|
## Steps
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Acceptance testing of completed phase work"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# /verify-work
|
|
2
6
|
|
|
3
7
|
Walk through acceptance testing of completed phase work.
|
|
@@ -7,6 +11,8 @@ Walk through acceptance testing of completed phase work.
|
|
|
7
11
|
/verify-work [N]
|
|
8
12
|
```
|
|
9
13
|
|
|
14
|
+
Phase: $1
|
|
15
|
+
|
|
10
16
|
## Steps
|
|
11
17
|
1. Run full test suite and capture results:
|
|
12
18
|
- Execute all tests (`bun test` or project-specific runner)
|
|
@@ -16,12 +22,12 @@ Walk through acceptance testing of completed phase work.
|
|
|
16
22
|
- Scan source files for PascalCase identifiers not present in the glossary
|
|
17
23
|
- Flag any bounded context boundary violations (cross-context direct imports)
|
|
18
24
|
3. Run quality gate: `draht-tools quality-gate --strict`
|
|
19
|
-
4. Run `draht-tools extract-deliverables
|
|
25
|
+
4. Run `draht-tools extract-deliverables $1` to get testable items
|
|
20
26
|
5. Walk user through each deliverable one at a time
|
|
21
27
|
6. Record results (pass/fail/partially/skip)
|
|
22
|
-
7. For failures: diagnose and create fix plans via `draht-tools create-fix-plan
|
|
28
|
+
7. For failures: diagnose and create fix plans via `draht-tools create-fix-plan $1 P`
|
|
23
29
|
- Fix plans MUST include a reproducing test that demonstrates the failure before any implementation
|
|
24
|
-
8. Write UAT report: `draht-tools write-uat
|
|
30
|
+
8. Write UAT report: `draht-tools write-uat $1`
|
|
25
31
|
- Report must include: test health summary (pass/fail/coverage), domain model status (any glossary violations), deliverable results
|
|
26
32
|
9. If all passed: mark phase complete
|
|
27
|
-
10. If failures: route to `execute-phase
|
|
33
|
+
10. If failures: route to `execute-phase $1 --gaps-only`
|
|
@@ -19,28 +19,60 @@ if (!phaseNum || !planNum || !taskNum || !status) {
|
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// ── Toolchain detection — mirrors src/gsd/hook-utils.ts ──────────────────────
|
|
23
|
+
function detectToolchain(cwd) {
|
|
24
|
+
if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock"))) {
|
|
25
|
+
return { pm: "bun", testCmd: "bun test", coverageCmd: "bun test --coverage", lintCmd: "bunx biome check ." };
|
|
26
|
+
}
|
|
27
|
+
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) {
|
|
28
|
+
return { pm: "pnpm", testCmd: "pnpm test", coverageCmd: "pnpm run test:coverage", lintCmd: "pnpm run lint" };
|
|
29
|
+
}
|
|
30
|
+
if (fs.existsSync(path.join(cwd, "yarn.lock"))) {
|
|
31
|
+
return { pm: "yarn", testCmd: "yarn test", coverageCmd: "yarn run test:coverage", lintCmd: "yarn run lint" };
|
|
32
|
+
}
|
|
33
|
+
return { pm: "npm", testCmd: "npm test", coverageCmd: "npm run test:coverage", lintCmd: "npm run lint" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readHookConfig(cwd) {
|
|
37
|
+
const defaults = { coverageThreshold: 80, tddMode: "advisory", qualityGateStrict: false };
|
|
38
|
+
const configPath = path.join(cwd, ".planning", "config.json");
|
|
39
|
+
if (!fs.existsSync(configPath)) return defaults;
|
|
40
|
+
try {
|
|
41
|
+
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
42
|
+
const h = raw.hooks || {};
|
|
43
|
+
return {
|
|
44
|
+
coverageThreshold: typeof h.coverageThreshold === "number" ? h.coverageThreshold : defaults.coverageThreshold,
|
|
45
|
+
tddMode: h.tddMode === "strict" || h.tddMode === "advisory" ? h.tddMode : defaults.tddMode,
|
|
46
|
+
qualityGateStrict: typeof h.qualityGateStrict === "boolean" ? h.qualityGateStrict : defaults.qualityGateStrict,
|
|
47
|
+
};
|
|
48
|
+
} catch { return defaults; }
|
|
49
|
+
}
|
|
50
|
+
|
|
22
51
|
const PLANNING = ".planning";
|
|
23
52
|
const LOG_FILE = path.join(PLANNING, "execution-log.jsonl");
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
const toolchain = detectToolchain(cwd);
|
|
55
|
+
const hookConfig = readHookConfig(cwd);
|
|
24
56
|
|
|
25
57
|
// 0. TDD cycle compliance check
|
|
26
|
-
// If the current commit message starts with "green:", the previous commit for this
|
|
27
|
-
// task should start with "red:" — enforce the Red → Green order.
|
|
28
58
|
if (commitHash) {
|
|
29
59
|
try {
|
|
30
|
-
// Find the commit message for commitHash and the one before it
|
|
31
60
|
const currentMsg = execSync(`git log --format=%s -n 1 ${commitHash} 2>/dev/null`, { encoding: "utf-8" }).trim();
|
|
32
61
|
if (/^green:/i.test(currentMsg)) {
|
|
33
|
-
// Scope search to commits that mention this phase/plan/task in their message
|
|
34
|
-
// to avoid false positives from unrelated older commits
|
|
35
62
|
const taskPrefix = `${phaseNum}-${planNum}-${taskNum}`;
|
|
36
63
|
const recentMsgs = execSync(`git log --format=%s -n 50 ${commitHash}~1 2>/dev/null`, { encoding: "utf-8" })
|
|
37
64
|
.trim()
|
|
38
65
|
.split("\n")
|
|
39
66
|
.filter((m) => m.includes(taskPrefix) || /^(red|green|refactor):/i.test(m));
|
|
40
|
-
// Find the nearest TDD-cycle commit scoped to this task
|
|
41
67
|
const prevTaskMsg = recentMsgs.find((m) => /^(red|green|refactor):/i.test(m) && m.includes(taskPrefix));
|
|
42
68
|
if (!prevTaskMsg || !/^red:/i.test(prevTaskMsg)) {
|
|
43
|
-
|
|
69
|
+
const violation = `TDD violation: "green:" commit without preceding "red:" for task ${phaseNum}-${planNum}-${taskNum}`;
|
|
70
|
+
if (hookConfig.tddMode === "strict") {
|
|
71
|
+
console.error(`❌ ${violation}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
} else {
|
|
74
|
+
console.log(`⚠️ ${violation}`);
|
|
75
|
+
}
|
|
44
76
|
fs.appendFileSync(LOG_FILE, JSON.stringify({
|
|
45
77
|
timestamp: new Date().toISOString(),
|
|
46
78
|
phase: parseInt(phaseNum, 10),
|
|
@@ -69,13 +101,15 @@ const entry = {
|
|
|
69
101
|
|
|
70
102
|
fs.appendFileSync(LOG_FILE, JSON.stringify(entry) + "\n");
|
|
71
103
|
|
|
72
|
-
// 2. Run type check if status is pass
|
|
104
|
+
// 2. Run type check and tests if status is pass
|
|
73
105
|
if (status === "pass") {
|
|
106
|
+
// Type check
|
|
74
107
|
try {
|
|
75
|
-
|
|
108
|
+
const tsCmd = toolchain.pm === "bun" ? "bun run tsgo --noEmit 2>&1" : "npx tsc --noEmit 2>&1";
|
|
109
|
+
execSync(tsCmd, { timeout: 30000, encoding: "utf-8", cwd });
|
|
76
110
|
// Run tests
|
|
77
111
|
try {
|
|
78
|
-
const testOutput = execSync(
|
|
112
|
+
const testOutput = execSync(`${toolchain.testCmd} 2>&1`, { timeout: 60000, encoding: "utf-8", cwd });
|
|
79
113
|
const testMatch = testOutput.match(/(\d+) pass/);
|
|
80
114
|
const testCount = testMatch ? testMatch[1] : "?";
|
|
81
115
|
console.log(`✅ Task ${phaseNum}-${planNum}-${taskNum}: passed + types clean + ${testCount} tests pass`);
|
|
@@ -93,7 +127,6 @@ if (status === "pass") {
|
|
|
93
127
|
const errorCount = (output.match(/error TS/g) || []).length;
|
|
94
128
|
if (errorCount > 0) {
|
|
95
129
|
console.log(`⚠️ Task ${phaseNum}-${planNum}-${taskNum}: passed but ${errorCount} type error(s) introduced`);
|
|
96
|
-
// Append warning to log
|
|
97
130
|
fs.appendFileSync(LOG_FILE, JSON.stringify({
|
|
98
131
|
...entry,
|
|
99
132
|
warning: `${errorCount} type errors introduced`,
|