k-harness 0.8.4 → 0.9.1

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/README.md CHANGED
@@ -127,7 +127,7 @@ See [docs/reference.md](docs/reference.md) for detailed descriptions of every sk
127
127
  | Focus | Enterprise SDLC methodology | 1-person software factory | Full lifecycle automation | Project direction management |
128
128
  | Files | 200+ | ~40 | Hundreds | ~20 |
129
129
  | Dependencies | Node 20+ | Bun + Node + Playwright | Node 18+ | Zero |
130
- | IDE support | 20+ (installer) | 5 (setup --host) | 13 (runtime select) | 7 (native format) |
130
+ | IDE support | 20+ (installer) | 5 (setup --host) | 13 (runtime select) | 6 (native format) |
131
131
  | Direction management | ❌ | ❌ | ❌ | ✅ (Direction Guard + pivot + Decision Log) |
132
132
  | Iron Laws (code quality rules) | ❌ | ❌ | ❌ | ✅ (6 laws embedded in skills) |
133
133
  | Cold start | ❌ | ❌ | `/gsd-new-project` | ✅ (`bootstrap` skill) |
@@ -18,6 +18,7 @@ The Planner is the entry point for new features — use it BEFORE writing code.
18
18
  - docs/dependency-map.md
19
19
  - docs/project-state.md
20
20
  - docs/failure-patterns.md
21
+ - docs/agent-memory/planner.md — Past estimation accuracy and architecture insights
21
22
 
22
23
  ## Input
23
24
 
@@ -38,6 +39,17 @@ Before proceeding, verify that required state files have content (not just TODO
38
39
  If ALL files are empty/placeholder-only → **Stop and run the `bootstrap` skill first.** Report: "State files are empty. Running bootstrap to onboard this project."
39
40
  If `docs/project-brief.md` alone is empty → Warn the user but proceed (the plan will lack direction guard).
40
41
 
42
+ ### Step 0.5: Load Agent Memory
43
+
44
+ Read `docs/agent-memory/planner.md` for past learnings:
45
+ - Estimation accuracy from previous sprints (did Wave estimates match reality?)
46
+ - Architecture patterns that worked or failed in this project
47
+ - Repeated planning mistakes to avoid
48
+
49
+ Apply these insights when creating the implementation plan. If the memory file is empty or contains only placeholders, skip this step.
50
+
51
+ > **Team Mode**: In Team mode, agent memory is personal (`.harness/agent-memory/`). Each developer accumulates their own planning insights.
52
+
41
53
  ### For New Feature
42
54
 
43
55
  1. Read `docs/project-brief.md` to understand project vision, goals, **non-goals**, and **Decision Log**
@@ -13,9 +13,12 @@ Finds issues and auto-fixes where safe, escalates where not.
13
13
 
14
14
  ## Referenced Files
15
15
 
16
+ - docs/project-brief.md — Project vision, goals, non-goals, and Decision Log
17
+ - docs/features.md — Feature registry (for Step 6 Feature Registry Check)
16
18
  - docs/failure-patterns.md — Project failure patterns
17
19
  - docs/project-state.md — Current Story scope
18
20
  - docs/dependency-map.md — Module dependency graph
21
+ - docs/agent-memory/reviewer.md — Past review patterns and frequently missed items
19
22
 
20
23
  ## Procedure
21
24
 
@@ -27,6 +30,15 @@ Before reviewing, verify that required state files exist and are not empty:
27
30
 
28
31
  If state files are empty/placeholder-only → Warn: "State files are not filled. Review will proceed but scope check and failure pattern cross-check will be limited. Consider running `bootstrap` skill."
29
32
 
33
+ ### Step 0.5: Load Agent Memory
34
+
35
+ Read `docs/agent-memory/reviewer.md` for past learnings:
36
+ - Frequently missed review items in this project
37
+ - Common code patterns that caused issues
38
+ - Review statistics (pass rate, common failure categories)
39
+
40
+ Pay extra attention to items flagged in past reviews. If the memory file is empty or contains only placeholders, skip this step.
41
+
30
42
  ### Input
31
43
 
32
44
  Changed file list (user-provided or from `git diff --name-only`)
@@ -138,3 +150,10 @@ Report using: **DONE** | **DONE_WITH_CONCERNS** | **BLOCKED** | **NEEDS_CONTEXT*
138
150
  - Do not refactor beyond the review scope
139
151
  - Auto-apply security fixes but always record them in output
140
152
  - Escalate with NEEDS_CONTEXT after 3 uncertain judgments
153
+
154
+ ## STATE-AUDIT Handoff
155
+
156
+ When Step 8 (State File Audit) produces `[STATE-AUDIT]` flags:
157
+ 1. List all flagged items in the review output
158
+ 2. The `learn` skill (run at session end) will verify and resolve these flags
159
+ 3. If a flag is critical (missing module in dependency-map, unregistered feature), recommend fixing immediately rather than deferring to learn
@@ -5,10 +5,21 @@
5
5
  Manage Sprint/Story state, guide development sequence, and prevent scope drift.
6
6
  Keeps the LLM focused on the current work item.
7
7
 
8
+ ## Referenced Skills
9
+
10
+ - bootstrap — Recommended when state files are empty
11
+ - learn — Recommended at session end or when all stories are done
12
+ - pivot — Recommended when direction change is detected
13
+ - investigate — Recommended when bug is blocking progress
14
+
8
15
  ## Referenced Files
9
16
 
10
17
  - docs/project-state.md — Current state (this is the core file)
18
+ - docs/project-brief.md — Project vision and goals (for direction checks)
19
+ - docs/features.md — Feature registry (for progress overview)
20
+ - docs/dependency-map.md — Module graph (for scope validation)
11
21
  - docs/failure-patterns.md — Recurring failure tracking
22
+ - docs/agent-memory/sprint-manager.md — Past velocity and scope drift data
12
23
 
13
24
  ## Procedure
14
25
 
@@ -18,7 +29,18 @@ Before handling any request, verify `docs/project-state.md` has content:
18
29
  - Quick Summary must not be all TODO placeholders
19
30
  - Story Status table must have at least one row
20
31
 
21
- If `docs/project-state.md` is empty/placeholder-only → **Recommend running `bootstrap` skill first.** Report: docs/project-state.md is empty. Run bootstrap to initialize project state before tracking sprints."
32
+ If `docs/project-state.md` is empty/placeholder-only → **Recommend running `bootstrap` skill first.** Report: "docs/project-state.md is empty. Run bootstrap to initialize project state before tracking sprints."
33
+
34
+ ### Step 0.5: Load Agent Memory
35
+
36
+ Read `docs/agent-memory/sprint-manager.md` for past learnings:
37
+ - Team velocity data (stories per sprint)
38
+ - Scope drift history (how often did scope expand?)
39
+ - Story sizing accuracy (were estimates correct?)
40
+
41
+ Use these insights when recommending story order and estimating sprint capacity. If the memory file is empty or contains only placeholders, skip this step.
42
+
43
+ > **Team Mode**: In Team mode, agent memory is personal (`.harness/agent-memory/`). Each developer tracks their own velocity and scope drift patterns.
22
44
 
23
45
  ### Input
24
46
 
@@ -63,8 +85,10 @@ After every status check, recommend the next action based on current context:
63
85
  **Request: "new story" / "next task"**
64
86
  1. Find next `todo` Story in docs/project-state.md
65
87
  2. Change its status to `in-progress`
66
- 3. Specify Story scope (related files/directories)
67
- 4. Alert relevant docs/failure-patterns.md items
88
+ 3. Read `docs/dependency-map.md` to identify modules involved in this Story
89
+ 4. Specify Story scope (related files/directories from dependency-map)
90
+ 5. Alert relevant docs/failure-patterns.md items
91
+ 6. Recommend relevant skill: "Consider running `planner` if this story needs detailed breakdown"
68
92
 
69
93
  **Request: "new sprint"**
70
94
  1. Check all Stories in current Sprint
@@ -108,3 +132,7 @@ STATUS: DONE
108
132
  - Do not modify code directly — manage state only
109
133
  - Only write to docs/project-state.md; read-only for all other files
110
134
  - Always confirm with user before modifying scope boundaries
135
+
136
+ ## Related Failure Patterns
137
+
138
+ - FP-003: Scope drift → Scope Check handler detects out-of-scope modifications and warns the user before proceeding
@@ -9,6 +9,8 @@ Read `docs/project-state.md` first. If all state files are empty, run `bootstrap
9
9
 
10
10
  ## Workflow
11
11
 
12
+ - First time / empty state → run `bootstrap`
13
+ - Session start → run `sprint-manager` to check status
12
14
  - New feature → run `planner` before coding
13
15
  - Before commit → run `reviewer`
14
16
  - Bug or issue → run `investigate`
@@ -12,6 +12,7 @@ A living document of module relationships. Update whenever modules are added or
12
12
  | services | application | Business logic | auth, database | api |
13
13
  | database | infrastructure| Data persistence | - | services |
14
14
  -->
15
+ <!-- Add new modules above this line -->
15
16
 
16
17
  ## Dependency Rules
17
18
 
@@ -13,6 +13,7 @@ This is LLM's map to understand "what exists" — without this, features get for
13
13
  | Admin Dashboard | ⬜ planned | - | - | - |
14
14
  | Legacy REST API | ❌ dropped | - | - | - |
15
15
  -->
16
+ <!-- Add new features above this line -->
16
17
 
17
18
  ## Status Legend
18
19
 
@@ -5,6 +5,10 @@
5
5
  Decompose a feature into implementation tasks ordered by dependency.
6
6
  Ensures bottom-up implementation: foundations first, then layers that depend on them.
7
7
 
8
+ ## Invoked By
9
+
10
+ - **planner** agent — Step 8: Create ordered task list for new features
11
+
8
12
  ## When to Apply
9
13
 
10
14
  - Starting a new feature or Story
@@ -15,24 +19,26 @@ Ensures bottom-up implementation: foundations first, then layers that depend on
15
19
  ## Procedure
16
20
 
17
21
  1. **Describe the feature** in one sentence
18
- 2. **Read docs/dependency-map.md** to understand current module relationships
19
- 3. **Identify affected modules**: List every module that needs changes
20
- 4. **Classify changes per module**:
22
+ 2. **Read docs/project-brief.md** verify the feature aligns with Goals and does not violate Non-Goals. If it conflicts with Non-Goals, **stop and warn the user** before proceeding. (Direction Guard — prevents breakdown of out-of-scope features even when invoked directly without planner)
23
+ 3. **Read docs/dependency-map.md** to understand current module relationships
24
+ 4. **Identify affected modules**: List every module that needs changes
25
+ 5. **Classify changes per module**:
21
26
  - NEW_MODULE: Entirely new module to create
22
27
  - INTERFACE_CHANGE: Existing module's public interface changes
23
28
  - INTERNAL_CHANGE: Only internal implementation changes
24
29
  - TEST_ONLY: Only test updates needed
25
- 5. **Build dependency order**:
30
+ 6. **Build dependency order**:
26
31
  - Draw a mini dependency graph for just the affected modules
27
32
  - Sort topologically: modules with no dependencies come first
28
33
  - Group into implementation waves (parallel-safe batches)
29
- 6. **Create task sequence**: Convert waves into numbered tasks
30
- 7. **Annotate each task** with:
34
+ 7. **Create task sequence**: Convert waves into numbered tasks
35
+ 8. **Annotate each task** with:
31
36
  - Module name
32
- - Change type (from step 4)
37
+ - Change type (from step 5)
33
38
  - Files to create/modify
34
39
  - Tests to write
35
40
  - Dependency (which prior task must finish first)
41
+ - ⚠️ Relevant failure patterns (check docs/failure-patterns.md)
36
42
 
37
43
  ## Output Format
38
44
 
@@ -87,3 +93,9 @@ After completing the breakdown, update these files in the same session:
87
93
  | Skip dependency-map registration | Register immediately when creating module |
88
94
  | Tests "later" | Tests in the same task |
89
95
  | Produce breakdown but skip state file updates | State file updates are part of the breakdown, not a separate step |
96
+
97
+ ## Related Failure Patterns
98
+
99
+ - FP-001: Interface changed, mock not updated → When creating tasks that modify interfaces, include "Update mock" as an explicit sub-task
100
+ - FP-002: Type confusion → When annotating tasks, specify expected types for new interfaces
101
+ - FP-003: Scope drift → If the breakdown exceeds the current Story scope, stop and report
@@ -5,6 +5,11 @@
5
5
  Before modifying any module, trace all affected modules to prevent cascade failures.
6
6
  The most common cause of regressions in growing projects is changing one module without updating its dependents.
7
7
 
8
+ ## Invoked By
9
+
10
+ - **planner** agent — Step 9: for each existing module being modified
11
+ - **reviewer** agent — Step 7: when interface changes affect 2+ dependent modules
12
+
8
13
  ## When to Apply
9
14
 
10
15
  - Adding, removing, or changing a module's public interface
@@ -16,21 +21,25 @@ The most common cause of regressions in growing projects is changing one module
16
21
 
17
22
  1. **Identify the target module**: Which module are you about to change?
18
23
  2. **Read docs/dependency-map.md**: Find the target module's row
19
- 3. **List dependents**: Read the "Depended By" column these are the blast radius
20
- 4. **Check interface impact**: Does your change affect the module's public interface?
24
+ 3. **Read docs/failure-patterns.md**: Check if any active patterns (FP-001, FP-002, etc.) apply to the target module or change type. If FP-001 frequency > 0, flag mock updates as mandatory in step 6.
25
+ 4. **List dependents**: Read the "Depended By" column — these are the blast radius
26
+ 5. **Read docs/features.md**: Identify which features include the target module in their Key Files column. These features may need status or Key Files updates.
27
+ 6. **Check interface impact**: Does your change affect the module's public interface?
21
28
  - If NO (internal-only change) → proceed, but still run dependent tests
22
- - If YES → continue to step 5
23
- 5. **Trace each dependent**:
29
+ - If YES → continue to step 7
30
+ 7. **Trace each dependent**:
24
31
  - List files in each dependent module that import from the target
25
32
  - Identify which functions/types they use
26
33
  - Determine if the interface change breaks them
27
- 6. **Plan updates**: Create a task list of all files that need modification
28
- 7. **Verify scope**: Confirm all files are within the current Story scope docs/project-state.md)
34
+ 8. **Plan updates**: Create a task list of all files that need modification
35
+ 9. **Verify scope**: Confirm all files are within the current Story scope (docs/project-state.md)
29
36
 
30
37
  ## Checklist
31
38
 
32
39
  - [ ] Target module identified in docs/dependency-map.md
40
+ - [ ] docs/failure-patterns.md checked for active patterns
33
41
  - [ ] All dependent modules listed
42
+ - [ ] Affected features identified from docs/features.md
34
43
  - [ ] Interface vs internal change classified
35
44
  - [ ] Files importing from target module enumerated
36
45
  - [ ] Mock/test updates planned for each dependent (FP-001)
@@ -62,9 +71,10 @@ Plan: 4 files to update, all within S3-2 scope
62
71
  After completing the analysis, update these files:
63
72
 
64
73
  - [ ] **docs/dependency-map.md**: Update the Interface Change Log table with: Date, Module, Change description, Affected Modules, Status. **This is mandatory for ALL interface changes** — do not skip even if the change seems minor.
74
+ - [ ] **docs/features.md**: If the interface change affects a feature's Key Files, update the Key Files column. If test files change, update the Test Files column.
65
75
  - [ ] **docs/project-state.md**: If scope exceeds current Story, add a note to Recent Changes.
66
76
 
67
77
  ## Related Failure Patterns
68
78
 
69
- - FP-001: Interface changed, mock not updated → Checklist item 5
70
- - FP-002: Type confusion across modules → Step 5 verification
79
+ - FP-001: Interface changed, mock not updated → Checklist item 7 (mock/test updates planned)
80
+ - FP-002: Type confusion across modules → Step 7 (trace each dependent, verify types)
@@ -26,8 +26,10 @@ Debug bugs systematically. Prevent "symptom patching" — fixing without underst
26
26
  ### Phase 2: Scope Lock
27
27
 
28
28
  1. Identify the module/directory containing the root cause
29
- 2. Exclude files outside that scope from modification
30
- 3. Check docs/failure-patterns.md for matching patterns
29
+ 2. **Read docs/dependency-map.md**: Find the target module's row. Check "Depended By" column to understand which other modules might be affected by the same root cause or by your fix.
30
+ 3. **Read docs/project-state.md**: Verify the fix scope is within the current Story scope. If the root cause is in a module outside the current Story, **warn the user** before proceeding (Iron Law #3: Scope Compliance).
31
+ 4. Exclude files outside that scope from modification
32
+ 5. Check docs/failure-patterns.md for matching patterns
31
33
 
32
34
  ### Phase 3: Hypothesis + Fix
33
35
 
@@ -45,6 +47,8 @@ Debug bugs systematically. Prevent "symptom patching" — fixing without underst
45
47
 
46
48
  - [ ] Root cause hypothesis is stated explicitly
47
49
  - [ ] Did NOT skip Phase 1 (evidence collection) and jump straight to fixing
50
+ - [ ] docs/dependency-map.md consulted for blast radius understanding
51
+ - [ ] Fix scope verified against current Story in docs/project-state.md
48
52
  - [ ] Fix scope is limited to the problem's scope
49
53
  - [ ] All related tests pass after the fix
50
54
  - [ ] Regression test is added
@@ -82,5 +86,6 @@ After the fix is verified (Phase 4):
82
86
 
83
87
  ## Related Failure Patterns
84
88
 
85
- - FP-002: Type confusion → Phase 1 requires verifying actual types
86
89
  - FP-001: Mock not updated → Phase 4 requires checking mock sync
90
+ - FP-002: Type confusion → Phase 1 requires verifying actual types
91
+ - FP-003: Scope drift → Phase 2 Scope Lock must verify fix is within current Story scope
@@ -60,6 +60,22 @@ For each issue/error that occurred in this session:
60
60
  2. If existing features were modified → update Key Files and Test Files columns
61
61
  3. If features were completed → update Status to `✅ done`
62
62
 
63
+ ### Step 4.5: Verify docs/dependency-map.md (mandatory)
64
+
65
+ 1. Check if any new modules were created in this session (scan `git diff --stat` for new directories)
66
+ 2. Check if any module interfaces changed
67
+ 3. For each finding:
68
+ - New module without dependency-map entry → **add it now**
69
+ - Interface change without Interface Change Log entry → **add it now**
70
+ 4. Cross-reference `docs/features.md` Key Files against `docs/dependency-map.md` modules — flag orphaned modules
71
+
72
+ ### Step 4.6: Resolve STATE-AUDIT Flags (if applicable)
73
+
74
+ If the `reviewer` agent was run in this session and produced `[STATE-AUDIT]` flags:
75
+ 1. Review each flagged item
76
+ 2. Apply the recommended state file update
77
+ 3. If the flag was already resolved during the session, skip it
78
+
63
79
  ### Step 5: Update Agent Memory (if applicable)
64
80
 
65
81
  If an agent (reviewer, planner, sprint-manager) was used in this session, update its memory file in `docs/agent-memory/`:
@@ -88,9 +104,10 @@ Present a summary of all updates made.
88
104
  - [FP-NNN] (new/updated): [description]
89
105
 
90
106
  ### State Files Updated:
91
- - [x]docs/project-state.md — Quick Summary refreshed
92
- - [x]docs/failure-patterns.md — [N] patterns added/updated
93
- - [x]docs/features.md — [N] features updated (if applicable)
107
+ - [x] docs/project-state.md — Quick Summary refreshed
108
+ - [x] docs/failure-patterns.md — [N] patterns added/updated
109
+ - [x] docs/features.md — [N] features updated (if applicable)
110
+ - [x] docs/dependency-map.md — [N] modules verified/added (if applicable)
94
111
  - [x] docs/agent-memory/{name}.md — [N] agents updated (if applicable)
95
112
 
96
113
  ### Next Session Should:
@@ -100,3 +100,16 @@ Add an entry to the Decision Log section in docs/project-brief.md:
100
100
  - **Never update partially** — if you update docs/project-brief.md, you MUST check and update all other state files too
101
101
  - **Preserve history** — mark dropped features as `⛔ dropped`, don't delete rows
102
102
  - **Record the why** — every pivot must have a Decision Log entry with reasoning
103
+
104
+ ## Team Mode
105
+
106
+ If `.harness/` directory exists (Team mode is active):
107
+
108
+ - **pivot MUST be run on the main branch** by the team lead or architect only
109
+ - Feature branches should NOT run pivot independently
110
+ - If a direction change is needed from a feature branch:
111
+ 1. Document the proposed change
112
+ 2. Share with the team
113
+ 3. Team lead runs pivot on main
114
+ 4. All developers pull main to get updated shared state files
115
+ 5. Each developer's `.harness/` personal state is unaffected (update manually if needed)
@@ -5,6 +5,10 @@
5
5
  Inspect for security risks before committing code.
6
6
  Prevents credential leaks and accidental commits of sensitive files. (FP-004)
7
7
 
8
+ ## Invoked By
9
+
10
+ - **reviewer** agent — Step 4: Security risk inspection
11
+
8
12
  ## When to Apply
9
13
 
10
14
  - Before running `git add` or committing
@@ -15,13 +19,15 @@ Prevents credential leaks and accidental commits of sensitive files. (FP-004)
15
19
  ## Procedure
16
20
 
17
21
  1. **Check staging area**: Run `git diff --cached --name-only` to list files staged for commit
18
- 2. **Scan for forbidden files**: Check if .env, credentials, *.pem, *.key files are staged
19
- 3. **Scan for hardcoded secrets**: Search staged files for passwords, API keys, tokens
20
- 4. **Verify .gitignore**: Ensure new environment files are covered by .gitignore
21
- 5. **Check for temp files**: Verify tmp_*, debug_*, coverage_* files are not staged
22
+ 2. **Read docs/failure-patterns.md**: Check FP-004 status. If frequency > 0, apply extra scrutiny to all staged files and verify .gitignore coverage is comprehensive.
23
+ 3. **Scan for forbidden files**: Check if .env, credentials, *.pem, *.key files are staged
24
+ 4. **Scan for hardcoded secrets**: Search staged files for passwords, API keys, tokens
25
+ 5. **Verify .gitignore**: Ensure new environment files are covered by .gitignore
26
+ 6. **Check for temp files**: Verify tmp_*, debug_*, coverage_* files are not staged
22
27
 
23
28
  ## Checklist
24
29
 
30
+ - [ ] docs/failure-patterns.md reviewed for FP-004 history
25
31
  - [ ] (FP-004) No .env, credentials, *.key files in staging area
26
32
  - [ ] (FP-004) No hardcoded passwords, API keys, or tokens in code
27
33
  - [ ] Sensitive file patterns are registered in .gitignore
@@ -49,7 +55,8 @@ const dbPassword = "super_secret_123";
49
55
  After completing the security check:
50
56
 
51
57
  - [ ] **docs/failure-patterns.md**: If a security issue was found (credentials staged, hardcoded secret), add a new FP-NNN entry or increment FP-004 Frequency.
58
+ - [ ] **docs/project-state.md**: If a security issue was found, add to Recent Changes: "⚠️ Security: [description of issue found/fixed]". This ensures the next session's Quick Summary includes the security context.
52
59
 
53
60
  ## Related Failure Patterns
54
61
 
55
- - FP-004: Dangerous file committed → Checklist items 1, 4
62
+ - FP-004: Dangerous file committed → Checklist items 2, 5 (no forbidden files, no temp files)
@@ -5,6 +5,10 @@
5
5
  Ensure test mocks stay synchronized when repository/service interfaces change.
6
6
  Prevents the most common LLM coding failure: updating an interface but forgetting to update corresponding mocks. (FP-001)
7
7
 
8
+ ## Invoked By
9
+
10
+ - **reviewer** agent — Step 3: Mock synchronization verification
11
+
8
12
  ## When to Apply
9
13
 
10
14
  - Adding, removing, or modifying methods on a repository/service interface
@@ -13,16 +17,18 @@ Prevents the most common LLM coding failure: updating an interface but forgettin
13
17
 
14
18
  ## Procedure
15
19
 
16
- 1. **Identify changed interfaces**: Find modified files in your interface directory
17
- 2. **Map to mock files**: Locate the corresponding mock file for each changed interface
18
- 3. **Sync methods**: Verify every interface method exists in the mock
19
- 4. **Verify return types**: Confirm mock return values match the interface return types
20
- 5. **Check consumers**: Verify use case tests configure the mock correctly for new methods
20
+ 1. **Read docs/failure-patterns.md**: Check FP-001 status. If frequency > 0, this project has a history of mock sync failures — apply extra scrutiny to every interface change.
21
+ 2. **Identify changed interfaces**: Find modified files in your interface directory
22
+ 3. **Map to mock files**: Locate the corresponding mock file for each changed interface
23
+ 4. **Sync methods**: Verify every interface method exists in the mock
24
+ 5. **Verify return types**: Confirm mock return values match the interface return types (FP-002: watch for type confusion)
25
+ 6. **Check consumers**: Verify use case tests configure the mock correctly for new methods
21
26
 
22
27
  ## Checklist
23
28
 
29
+ - [ ] docs/failure-patterns.md reviewed for FP-001 history
24
30
  - [ ] (FP-001) Every changed interface method is reflected in its mock
25
- - [ ] Mock return types match interface signatures
31
+ - [ ] (FP-002) Mock return types match interface signatures (no type confusion)
26
32
  - [ ] New methods have default mock return values set
27
33
  - [ ] Use case tests correctly use the new mock methods
28
34
  - [ ] Existing tests still pass
@@ -47,6 +53,7 @@ After synchronizing mocks:
47
53
 
48
54
  - [ ] **docs/failure-patterns.md**: If mock sync was missed and caused a test failure, increment FP-001 Frequency.
49
55
  - [ ] **docs/dependency-map.md**: If the interface change altered module relationships, update the relevant row.
56
+ - [ ] **docs/project-state.md**: If mock sync issues were found and fixed, add to Recent Changes: "🔧 Test: [interface] mock synchronized". This ensures the next session is aware of the fix.
50
57
 
51
58
  ## Testing Rules (enforced during this skill)
52
59
 
@@ -59,4 +66,5 @@ After synchronizing mocks:
59
66
 
60
67
  ## Related Failure Patterns
61
68
 
62
- - FP-001: Interface changed, mock not updated → Checklist item 1
69
+ - FP-001: Interface changed, mock not updated → Checklist item 2
70
+ - FP-002: Type confusion → Step 5 return type verification
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k-harness",
3
- "version": "0.8.4",
3
+ "version": "0.9.1",
4
4
  "description": "LLM Development Harness — IDE-agnostic rules, skills, and agents that prevent common AI coding failures",
5
5
  "keywords": [
6
6
  "llm",
package/src/init.js CHANGED
@@ -57,7 +57,43 @@ const AGENT_MEMORY_FILES = [
57
57
  'agent-memory/sprint-manager.md',
58
58
  ];
59
59
 
60
+ const PERSONAL_STATE_FILES = ['project-state.md', 'failure-patterns.md'];
61
+ const PERSONAL_DIRS = ['agent-memory/'];
62
+
60
63
  const STATE_DEST_DIR = 'docs';
64
+ const PERSONAL_DEST_DIR = '.harness';
65
+
66
+ // ─── Team mode path resolver ─────────────────────────────────
67
+ const TEAM_MODE_SECTION = `
68
+
69
+ ## Team Mode
70
+
71
+ This project uses Team mode. State files are split into shared and personal.
72
+
73
+ ### File Locations
74
+ - **Shared** (docs/, git committed): project-brief.md, features.md, dependency-map.md
75
+ - **Personal** (.harness/, gitignored): project-state.md, failure-patterns.md, agent-memory/
76
+
77
+ ### Rules
78
+ 1. Shared files: only modify your own rows (check Owner column)
79
+ 2. Other developers' Owner rows are READ ONLY
80
+ 3. New rows go at the bottom of the table
81
+ 4. The \`pivot\` skill must be run on the main branch by the team lead only
82
+ `;
83
+
84
+ function resolveContent(content, mode) {
85
+ if (mode !== 'team') return content;
86
+ let result = content
87
+ .replaceAll('docs/project-state.md', '.harness/project-state.md')
88
+ .replaceAll('docs/failure-patterns.md', '.harness/failure-patterns.md')
89
+ .replaceAll('docs/agent-memory/', '.harness/agent-memory/');
90
+
91
+ // Append Team Mode section to core-rules (detected by the heading)
92
+ if (result.includes('## State Files') && result.includes('## Session Start')) {
93
+ result += TEAM_MODE_SECTION;
94
+ }
95
+ return result;
96
+ }
61
97
 
62
98
  // ─── Language detection ──────────────────────────────────────
63
99
  function detectLanguage(targetDir) {
@@ -80,18 +116,22 @@ function detectLanguage(targetDir) {
80
116
 
81
117
  // ─── Shared writers ──────────────────────────────────────────
82
118
 
83
- function writeStateFiles(targetDir, overwrite) {
119
+ function writeStateFiles(targetDir, overwrite, mode = 'solo') {
84
120
  for (const file of STATE_FILES) {
85
- writeFile(targetDir, `${STATE_DEST_DIR}/${file}`, readTemplate(file), overwrite);
121
+ const isPersonal = PERSONAL_STATE_FILES.includes(file);
122
+ const destDir = (mode === 'team' && isPersonal) ? PERSONAL_DEST_DIR : STATE_DEST_DIR;
123
+ const content = resolveContent(readTemplate(file), mode);
124
+ writeFile(targetDir, `${destDir}/${file}`, content, overwrite);
86
125
  }
87
126
  for (const file of AGENT_MEMORY_FILES) {
88
- writeFile(targetDir, `${STATE_DEST_DIR}/${file}`, readTemplate(file), overwrite);
127
+ const destDir = mode === 'team' ? PERSONAL_DEST_DIR : STATE_DEST_DIR;
128
+ writeFile(targetDir, `${destDir}/${file}`, readTemplate(file), overwrite);
89
129
  }
90
130
  }
91
131
 
92
- function writeSkills(targetDir, skillsDir, overwrite) {
132
+ function writeSkills(targetDir, skillsDir, overwrite, mode = 'solo') {
93
133
  for (const skill of SKILLS) {
94
- const content = readTemplate(`skills/${skill.id}.md`);
134
+ const content = resolveContent(readTemplate(`skills/${skill.id}.md`), mode);
95
135
  const skillMd =
96
136
  `---\nname: ${skill.id}\ndescription: '${skill.desc}'\n---\n\n` +
97
137
  content;
@@ -99,9 +139,9 @@ function writeSkills(targetDir, skillsDir, overwrite) {
99
139
  }
100
140
  }
101
141
 
102
- function writeAgentsAsSkills(targetDir, skillsDir, overwrite) {
142
+ function writeAgentsAsSkills(targetDir, skillsDir, overwrite, mode = 'solo') {
103
143
  for (const agent of AGENTS) {
104
- const content = readTemplate(agent.file);
144
+ const content = resolveContent(readTemplate(agent.file), mode);
105
145
  const skillMd =
106
146
  `---\nname: ${agent.id}\ndescription: '${agent.desc}'\n---\n\n` +
107
147
  content;
@@ -111,18 +151,18 @@ function writeAgentsAsSkills(targetDir, skillsDir, overwrite) {
111
151
 
112
152
  // ─── IDE Generators ──────────────────────────────────────────
113
153
 
114
- function generateVscode(targetDir, overwrite) {
115
- const coreRules = readTemplate('core-rules.md');
154
+ function generateVscode(targetDir, overwrite, mode = 'solo') {
155
+ const coreRules = resolveContent(readTemplate('core-rules.md'), mode);
116
156
 
117
157
  // Global instructions (dispatcher only — rules are embedded in skills)
118
158
  writeFile(targetDir, '.github/copilot-instructions.md', coreRules, overwrite);
119
159
 
120
160
  // Skills (.github/skills — VS Code default search path, SKILL.md with frontmatter)
121
- writeSkills(targetDir, '.github/skills', overwrite);
161
+ writeSkills(targetDir, '.github/skills', overwrite, mode);
122
162
 
123
163
  // Agents (.github/agents — VS Code uses .agent.md format with frontmatter)
124
164
  for (const agent of AGENTS) {
125
- const content = readTemplate(agent.file);
165
+ const content = resolveContent(readTemplate(agent.file), mode);
126
166
  const agentMd =
127
167
  `---\nname: ${agent.id}\ndescription: "${agent.desc}"\n---\n\n` +
128
168
  content;
@@ -130,87 +170,87 @@ function generateVscode(targetDir, overwrite) {
130
170
  }
131
171
 
132
172
  // State files
133
- writeStateFiles(targetDir, overwrite);
173
+ writeStateFiles(targetDir, overwrite, mode);
134
174
  }
135
175
 
136
- function generateClaude(targetDir, overwrite) {
176
+ function generateClaude(targetDir, overwrite, mode = 'solo') {
137
177
  // .claude/rules/core.md — dispatcher only (no paths = always loaded)
138
- writeFile(targetDir, '.claude/rules/core.md', readTemplate('core-rules.md'), overwrite);
178
+ writeFile(targetDir, '.claude/rules/core.md', resolveContent(readTemplate('core-rules.md'), mode), overwrite);
139
179
 
140
180
  // Skills (SKILL.md with frontmatter)
141
- writeSkills(targetDir, '.claude/skills', overwrite);
181
+ writeSkills(targetDir, '.claude/skills', overwrite, mode);
142
182
 
143
183
  // Agents as skills (Claude Code skills pattern)
144
- writeAgentsAsSkills(targetDir, '.claude/skills', overwrite);
184
+ writeAgentsAsSkills(targetDir, '.claude/skills', overwrite, mode);
145
185
 
146
186
  // State files
147
- writeStateFiles(targetDir, overwrite);
187
+ writeStateFiles(targetDir, overwrite, mode);
148
188
  }
149
189
 
150
- function generateCursor(targetDir, overwrite) {
190
+ function generateCursor(targetDir, overwrite, mode = 'solo') {
151
191
  // .cursor/rules/core.mdc — dispatcher only (always active)
152
- const coreRules = readTemplate('core-rules.md');
192
+ const coreRules = resolveContent(readTemplate('core-rules.md'), mode);
153
193
  const coreMdc =
154
194
  '---\ndescription: K-Harness dispatcher — workflow guidance and state file references\nalwaysApply: true\n---\n\n' +
155
195
  coreRules;
156
196
  writeFile(targetDir, '.cursor/rules/core.mdc', coreMdc, overwrite);
157
197
 
158
198
  // Skills (.cursor/skills — invokable by mentioning skill name)
159
- writeSkills(targetDir, '.cursor/skills', overwrite);
199
+ writeSkills(targetDir, '.cursor/skills', overwrite, mode);
160
200
 
161
201
  // Agents as skills
162
- writeAgentsAsSkills(targetDir, '.cursor/skills', overwrite);
202
+ writeAgentsAsSkills(targetDir, '.cursor/skills', overwrite, mode);
163
203
 
164
204
  // State files
165
- writeStateFiles(targetDir, overwrite);
205
+ writeStateFiles(targetDir, overwrite, mode);
166
206
  }
167
207
 
168
- function generateCodex(targetDir, overwrite) {
208
+ function generateCodex(targetDir, overwrite, mode = 'solo') {
169
209
  // AGENTS.md — dispatcher only
170
- writeFile(targetDir, 'AGENTS.md', readTemplate('core-rules.md'), overwrite);
210
+ writeFile(targetDir, 'AGENTS.md', resolveContent(readTemplate('core-rules.md'), mode), overwrite);
171
211
 
172
212
  // Skills (SKILL.md with frontmatter — invokable via $skill-name)
173
- writeSkills(targetDir, '.agents/skills', overwrite);
213
+ writeSkills(targetDir, '.agents/skills', overwrite, mode);
174
214
 
175
215
  // Agents as skills
176
- writeAgentsAsSkills(targetDir, '.agents/skills', overwrite);
216
+ writeAgentsAsSkills(targetDir, '.agents/skills', overwrite, mode);
177
217
 
178
218
  // State files
179
- writeStateFiles(targetDir, overwrite);
219
+ writeStateFiles(targetDir, overwrite, mode);
180
220
  }
181
221
 
182
- function generateWindsurf(targetDir, overwrite) {
222
+ function generateWindsurf(targetDir, overwrite, mode = 'solo') {
183
223
  // .windsurf/rules/core.md — dispatcher (trigger: always_on)
184
- const coreRules = readTemplate('core-rules.md');
224
+ const coreRules = resolveContent(readTemplate('core-rules.md'), mode);
185
225
  const coreRule =
186
226
  '---\ntrigger: always_on\n---\n\n' +
187
227
  coreRules;
188
228
  writeFile(targetDir, '.windsurf/rules/core.md', coreRule, overwrite);
189
229
 
190
230
  // Skills (.windsurf/skills — Agent Skills standard)
191
- writeSkills(targetDir, '.windsurf/skills', overwrite);
231
+ writeSkills(targetDir, '.windsurf/skills', overwrite, mode);
192
232
 
193
233
  // Agents as skills
194
- writeAgentsAsSkills(targetDir, '.windsurf/skills', overwrite);
234
+ writeAgentsAsSkills(targetDir, '.windsurf/skills', overwrite, mode);
195
235
 
196
236
  // State files
197
- writeStateFiles(targetDir, overwrite);
237
+ writeStateFiles(targetDir, overwrite, mode);
198
238
  }
199
239
 
200
- function generateAntigravity(targetDir, overwrite) {
240
+ function generateAntigravity(targetDir, overwrite, mode = 'solo') {
201
241
  // .agent/rules/core.md — dispatcher only
202
- const coreRules = readTemplate('core-rules.md');
242
+ const coreRules = resolveContent(readTemplate('core-rules.md'), mode);
203
243
  const coreRule =
204
244
  '---\ndescription: K-Harness dispatcher — workflow guidance and state file references\ntype: always\n---\n\n' +
205
245
  coreRules;
206
246
  writeFile(targetDir, '.agent/rules/core.md', coreRule, overwrite);
207
247
 
208
248
  // .agent/skills/ — SKILL.md format (enables / slash commands)
209
- writeSkills(targetDir, '.agent/skills', overwrite);
210
- writeAgentsAsSkills(targetDir, '.agent/skills', overwrite);
249
+ writeSkills(targetDir, '.agent/skills', overwrite, mode);
250
+ writeAgentsAsSkills(targetDir, '.agent/skills', overwrite, mode);
211
251
 
212
252
  // State files
213
- writeStateFiles(targetDir, overwrite);
253
+ writeStateFiles(targetDir, overwrite, mode);
214
254
  }
215
255
 
216
256
  // ─── IDE registry ────────────────────────────────────────────
@@ -251,6 +291,85 @@ async function promptIde() {
251
291
  return keys[idx];
252
292
  }
253
293
 
294
+ async function promptMode() {
295
+ console.log(' Project mode:\n');
296
+ console.log(' 1. Solo — Single developer (all state files in docs/)');
297
+ console.log(' 2. Team — Multiple developers (personal state in .harness/, shared in docs/)');
298
+ console.log();
299
+
300
+ const answer = await askQuestion(' Choice (1-2, default: 1): ');
301
+ if (answer === '2' || answer.toLowerCase() === 'team') return 'team';
302
+ return 'solo';
303
+ }
304
+
305
+ // ─── Team mode helpers ───────────────────────────────────────
306
+ function appendGitignore(targetDir) {
307
+ const gitignorePath = path.join(targetDir, '.gitignore');
308
+ const entry = '\n# K-Harness personal state (Team mode)\n.harness/\n';
309
+ if (fs.existsSync(gitignorePath)) {
310
+ const content = fs.readFileSync(gitignorePath, 'utf8');
311
+ if (content.includes('.harness/')) {
312
+ console.log(' ⏭ Skipped (exists): .gitignore entry');
313
+ return;
314
+ }
315
+ fs.appendFileSync(gitignorePath, entry);
316
+ } else {
317
+ fs.writeFileSync(gitignorePath, entry.trimStart());
318
+ }
319
+ console.log(' ✓ .gitignore — added .harness/');
320
+ }
321
+
322
+ function writeGitattributes(targetDir) {
323
+ const content =
324
+ '# K-Harness Team mode — merge strategy for shared state files\n' +
325
+ 'docs/features.md merge=union\n' +
326
+ 'docs/dependency-map.md merge=union\n';
327
+ writeFile(targetDir, '.gitattributes', content, false);
328
+ }
329
+
330
+ // ─── Post-install guide ──────────────────────────────────────
331
+ function showPostInstallGuide(ideName, mode) {
332
+ const modeLabel = mode === 'team' ? 'Team' : 'Solo';
333
+ const lines = [
334
+ '',
335
+ ' ──────────────────────────────────────────',
336
+ ' ✅ K-Harness initialized successfully!',
337
+ '',
338
+ ` Mode: ${modeLabel}`,
339
+ ` IDE: ${ideName}`,
340
+ '',
341
+ ];
342
+
343
+ if (mode === 'team') {
344
+ lines.push(
345
+ ' 📁 Files:',
346
+ ' docs/ — shared state (git committed)',
347
+ ' .harness/ — personal state (gitignored)',
348
+ ' .gitignore — .harness/ added',
349
+ ' .gitattributes — merge=union for shared files',
350
+ );
351
+ } else {
352
+ lines.push(
353
+ ' 📁 Files:',
354
+ ' docs/ — all state files',
355
+ );
356
+ }
357
+
358
+ lines.push(
359
+ '',
360
+ ' 🚀 Next steps:',
361
+ ' 1. Ask your AI: "Run bootstrap to onboard this project"',
362
+ ' 2. AI scans your codebase and fills state files automatically',
363
+ ' 3. Start coding with: @planner "Add [feature name]"',
364
+ '',
365
+ ' 📖 Docs: https://www.npmjs.com/package/k-harness',
366
+ ' ──────────────────────────────────────────',
367
+ '',
368
+ );
369
+
370
+ console.log(lines.join('\n'));
371
+ }
372
+
254
373
  // ─── CLI entry ───────────────────────────────────────────────
255
374
  function showHelp() {
256
375
  console.log(`
@@ -261,6 +380,7 @@ function showHelp() {
261
380
 
262
381
  Options:
263
382
  --ide <name> IDE target: vscode, claude, cursor, codex, windsurf, antigravity
383
+ --mode <mode> Project mode: solo (default) or team
264
384
  --dir <path> Target directory (default: current directory)
265
385
  --overwrite Overwrite existing files
266
386
  --help Show this help
@@ -268,16 +388,19 @@ function showHelp() {
268
388
  Examples:
269
389
  npx k-harness init
270
390
  npx k-harness init --ide vscode
391
+ npx k-harness init --ide vscode --mode team
271
392
  npx k-harness init --ide claude --dir ./my-project
272
393
  `);
273
394
  }
274
395
 
275
396
  function parseArgs(argv) {
276
- const args = { command: null, ide: null, dir: process.cwd(), overwrite: false, help: false };
397
+ const args = { command: null, ide: null, mode: null, dir: process.cwd(), overwrite: false, help: false };
277
398
  for (let i = 0; i < argv.length; i++) {
278
399
  const arg = argv[i];
279
400
  if (arg === 'init') args.command = 'init';
280
401
  else if (arg === '--ide' && argv[i + 1]) { args.ide = argv[++i]; }
402
+ else if (arg === '--mode' && argv[i + 1]) { args.mode = argv[++i]; }
403
+ else if (arg === '--team') { args.mode = 'team'; }
281
404
  else if (arg === '--dir' && argv[i + 1]) { args.dir = path.resolve(argv[++i]); }
282
405
  else if (arg === '--overwrite') args.overwrite = true;
283
406
  else if (arg === '--help' || arg === '-h') args.help = true;
@@ -307,11 +430,29 @@ async function run(argv) {
307
430
  ide = await promptIde();
308
431
  }
309
432
 
433
+ // Determine mode
434
+ let mode = args.mode;
435
+ if (mode && !['solo', 'team'].includes(mode)) {
436
+ console.error(` Unknown mode: ${mode}`);
437
+ console.error(' Available: solo, team');
438
+ process.exit(1);
439
+ }
440
+ if (!mode) {
441
+ mode = await promptMode();
442
+ }
443
+
310
444
  const gen = GENERATORS[ide];
311
445
  const lang = detectLanguage(args.dir);
312
- console.log(`\n Installing for ${gen.name}... (detected language: ${lang})\n`);
313
- gen.fn(args.dir, args.overwrite);
314
- console.log(`\n Done! Run "bootstrap" in your AI chat to auto-fill state files and rules.\n`);
446
+ console.log(`\n Installing for ${gen.name} (${mode} mode)... (detected language: ${lang})\n`);
447
+ gen.fn(args.dir, args.overwrite, mode);
448
+
449
+ // Team mode extras
450
+ if (mode === 'team') {
451
+ appendGitignore(args.dir);
452
+ writeGitattributes(args.dir);
453
+ }
454
+
455
+ showPostInstallGuide(gen.name, mode);
315
456
  }
316
457
  }
317
458