@harness-engineering/cli 1.26.0 → 1.26.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.
Files changed (179) hide show
  1. package/dist/agents/skills/README.md +1 -0
  2. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +33 -5
  3. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +6 -0
  4. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +25 -1
  5. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +22 -6
  6. package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +2 -1
  7. package/dist/agents/skills/claude-code/initialize-test-suite-project/SKILL.md +415 -0
  8. package/dist/agents/skills/claude-code/initialize-test-suite-project/skill.yaml +35 -0
  9. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +33 -5
  10. package/dist/agents/skills/codex/harness-execution/SKILL.md +6 -0
  11. package/dist/agents/skills/codex/harness-planning/SKILL.md +25 -1
  12. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +22 -6
  13. package/dist/agents/skills/codex/initialize-harness-project/skill.yaml +2 -1
  14. package/dist/agents/skills/codex/initialize-test-suite-project/SKILL.md +415 -0
  15. package/dist/agents/skills/codex/initialize-test-suite-project/skill.yaml +35 -0
  16. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +33 -5
  17. package/dist/agents/skills/cursor/harness-execution/SKILL.md +6 -0
  18. package/dist/agents/skills/cursor/harness-planning/SKILL.md +25 -1
  19. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +22 -6
  20. package/dist/agents/skills/cursor/initialize-harness-project/skill.yaml +2 -1
  21. package/dist/agents/skills/cursor/initialize-test-suite-project/SKILL.md +415 -0
  22. package/dist/agents/skills/cursor/initialize-test-suite-project/skill.yaml +35 -0
  23. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +33 -5
  24. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +6 -0
  25. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +25 -1
  26. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +22 -6
  27. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +2 -1
  28. package/dist/agents/skills/gemini-cli/initialize-test-suite-project/SKILL.md +415 -0
  29. package/dist/agents/skills/gemini-cli/initialize-test-suite-project/skill.yaml +35 -0
  30. package/dist/agents/skills/tests/initialize-test-suite-project.test.ts +152 -0
  31. package/dist/{agents-md-OPOZA5L7.js → agents-md-VI3HLR7E.js} +3 -3
  32. package/dist/{architecture-PMVMO6SF.js → architecture-ZDDKEVID.js} +4 -4
  33. package/dist/{assess-project-ZW7EKNIT.js → assess-project-Y6W7YDUA.js} +1 -1
  34. package/dist/bin/harness-mcp.js +16 -15
  35. package/dist/bin/harness.js +27 -27
  36. package/dist/{check-phase-gate-NTLAU3LO.js → check-phase-gate-CXR3VM22.js} +4 -4
  37. package/dist/{chunk-CAS3TS4Y.js → chunk-2BPPS6YQ.js} +793 -94
  38. package/dist/{chunk-VV2PJT4K.js → chunk-2FPUPRCY.js} +777 -598
  39. package/dist/{chunk-IFHAUFJX.js → chunk-3AMQYWGT.js} +2 -2
  40. package/dist/{chunk-FI3D6D7U.js → chunk-56A6OXVA.js} +9 -9
  41. package/dist/{chunk-QYSWNPXZ.js → chunk-7GY6WNEI.js} +1 -1
  42. package/dist/{chunk-ZBQ3ZY75.js → chunk-AMRC4FU2.js} +44 -41
  43. package/dist/{chunk-JZ6GORAK.js → chunk-B66LRB5M.js} +1 -1
  44. package/dist/{chunk-KFE2X7LG.js → chunk-BK4DJIIY.js} +4 -4
  45. package/dist/{chunk-G6SYTGOH.js → chunk-DBIX3X4H.js} +2 -2
  46. package/dist/{chunk-KXIAHHHP.js → chunk-FUND5WJR.js} +2 -2
  47. package/dist/{chunk-JWSVLC4I.js → chunk-JV4Y2U5F.js} +1 -1
  48. package/dist/{chunk-RNAGPTKF.js → chunk-K56DTX7G.js} +6 -6
  49. package/dist/{chunk-EXTWTJRF.js → chunk-N6B6RKQQ.js} +1 -1
  50. package/dist/{chunk-JBJ4AVE4.js → chunk-NY7DTZ6K.js} +3 -3
  51. package/dist/{chunk-Z2JORLRT.js → chunk-OLW7BJ5N.js} +1 -1
  52. package/dist/{chunk-HAOBHL3W.js → chunk-ORNEK65Y.js} +1 -1
  53. package/dist/{chunk-7JNZXJKY.js → chunk-PNNFCVW4.js} +5 -5
  54. package/dist/{chunk-NIOB6FTG.js → chunk-Q3ZLVMQM.js} +1 -1
  55. package/dist/{chunk-NVGQO4VM.js → chunk-RAVD7QLY.js} +8 -8
  56. package/dist/{chunk-J3O64D2A.js → chunk-TSVYBDDE.js} +1 -1
  57. package/dist/{chunk-KSFUJT5B.js → chunk-TY2ESLVL.js} +1 -1
  58. package/dist/{chunk-4KSKV5MK.js → chunk-VKS3F46M.js} +1 -1
  59. package/dist/{chunk-UBRD5FH4.js → chunk-WZ7UHPT3.js} +9 -9
  60. package/dist/{chunk-77EZGPSR.js → chunk-YC4EYIER.js} +8 -2
  61. package/dist/{chunk-6SCA4NEZ.js → chunk-ZN6ROTYP.js} +1 -1
  62. package/dist/{ci-workflow-H52EMCL6.js → ci-workflow-EW37KVPS.js} +3 -3
  63. package/dist/{create-skill-6QWJHQYS.js → create-skill-4T5CBSJ2.js} +2 -2
  64. package/dist/{dist-TG63OKA5.js → dist-CJDGASPP.js} +2 -2
  65. package/dist/{dist-PGQ32ZI7.js → dist-NCNAXUFD.js} +1 -1
  66. package/dist/{docs-GP4VUSIB.js → docs-4XI2FQW2.js} +4 -4
  67. package/dist/{engine-KQG5RVXX.js → engine-4L4CDTHU.js} +3 -3
  68. package/dist/{entropy-RXESIYKC.js → entropy-PBYSIQYS.js} +3 -3
  69. package/dist/{feedback-HS7ZYXOU.js → feedback-OTIFW5MK.js} +1 -1
  70. package/dist/{generate-agent-definitions-I4B7CVOB.js → generate-agent-definitions-CZGUXIIN.js} +4 -4
  71. package/dist/{graph-loader-TIVI6NQ7.js → graph-loader-RDXSEBD7.js} +1 -1
  72. package/dist/index.js +27 -27
  73. package/dist/{loader-CWAH6B4H.js → loader-UZOXCWFC.js} +3 -3
  74. package/dist/{mcp-KHK5KYER.js → mcp-GWVVV6LH.js} +16 -15
  75. package/dist/{performance-WDW5WS3J.js → performance-5UQPP3XX.js} +4 -4
  76. package/dist/{review-pipeline-QOZGWCTY.js → review-pipeline-65V4EO6O.js} +3 -3
  77. package/dist/{runtime-SFEFRPLX.js → runtime-PXX7HNB3.js} +3 -3
  78. package/dist/{scan-IJ7EYTF7.js → scan-WM7XDUF7.js} +1 -1
  79. package/dist/{security-2K7UUK6T.js → security-CAYDRZIZ.js} +1 -1
  80. package/dist/{validate-HXM6DXRZ.js → validate-CWGXR7QM.js} +4 -4
  81. package/dist/{validate-cross-check-ULQLEOME.js → validate-cross-check-BKCNLZYG.js} +3 -3
  82. package/package.json +4 -4
  83. package/dist/agents/commands/claude-code/harness/harness.md +0 -36
  84. package/dist/agents/commands/codex/AGENTS.md +0 -39
  85. package/dist/agents/commands/codex/harness/add-harness-component/SKILL.md +0 -204
  86. package/dist/agents/commands/codex/harness/add-harness-component/agents/openai.yaml +0 -3
  87. package/dist/agents/commands/codex/harness/cleanup-dead-code/SKILL.md +0 -257
  88. package/dist/agents/commands/codex/harness/cleanup-dead-code/agents/openai.yaml +0 -3
  89. package/dist/agents/commands/codex/harness/detect-doc-drift/SKILL.md +0 -191
  90. package/dist/agents/commands/codex/harness/detect-doc-drift/agents/openai.yaml +0 -3
  91. package/dist/agents/commands/codex/harness/enforce-architecture/SKILL.md +0 -289
  92. package/dist/agents/commands/codex/harness/enforce-architecture/agents/openai.yaml +0 -3
  93. package/dist/agents/commands/codex/harness/harness-architecture-advisor/SKILL.md +0 -442
  94. package/dist/agents/commands/codex/harness/harness-architecture-advisor/agents/openai.yaml +0 -3
  95. package/dist/agents/commands/codex/harness/harness-autopilot/SKILL.md +0 -929
  96. package/dist/agents/commands/codex/harness/harness-autopilot/agents/openai.yaml +0 -3
  97. package/dist/agents/commands/codex/harness/harness-brainstorming/SKILL.md +0 -418
  98. package/dist/agents/commands/codex/harness/harness-brainstorming/agents/openai.yaml +0 -3
  99. package/dist/agents/commands/codex/harness/harness-code-review/SKILL.md +0 -850
  100. package/dist/agents/commands/codex/harness/harness-code-review/agents/openai.yaml +0 -3
  101. package/dist/agents/commands/codex/harness/harness-codebase-cleanup/SKILL.md +0 -236
  102. package/dist/agents/commands/codex/harness/harness-codebase-cleanup/agents/openai.yaml +0 -3
  103. package/dist/agents/commands/codex/harness/harness-debugging/SKILL.md +0 -378
  104. package/dist/agents/commands/codex/harness/harness-debugging/agents/openai.yaml +0 -3
  105. package/dist/agents/commands/codex/harness/harness-dependency-health/SKILL.md +0 -190
  106. package/dist/agents/commands/codex/harness/harness-dependency-health/agents/openai.yaml +0 -3
  107. package/dist/agents/commands/codex/harness/harness-docs-pipeline/SKILL.md +0 -472
  108. package/dist/agents/commands/codex/harness/harness-docs-pipeline/agents/openai.yaml +0 -3
  109. package/dist/agents/commands/codex/harness/harness-execution/SKILL.md +0 -522
  110. package/dist/agents/commands/codex/harness/harness-execution/agents/openai.yaml +0 -3
  111. package/dist/agents/commands/codex/harness/harness-hotspot-detector/SKILL.md +0 -172
  112. package/dist/agents/commands/codex/harness/harness-hotspot-detector/agents/openai.yaml +0 -3
  113. package/dist/agents/commands/codex/harness/harness-impact-analysis/SKILL.md +0 -195
  114. package/dist/agents/commands/codex/harness/harness-impact-analysis/agents/openai.yaml +0 -3
  115. package/dist/agents/commands/codex/harness/harness-integrity/SKILL.md +0 -178
  116. package/dist/agents/commands/codex/harness/harness-integrity/agents/openai.yaml +0 -3
  117. package/dist/agents/commands/codex/harness/harness-onboarding/SKILL.md +0 -299
  118. package/dist/agents/commands/codex/harness/harness-onboarding/agents/openai.yaml +0 -3
  119. package/dist/agents/commands/codex/harness/harness-perf/SKILL.md +0 -272
  120. package/dist/agents/commands/codex/harness/harness-perf/agents/openai.yaml +0 -3
  121. package/dist/agents/commands/codex/harness/harness-planning/SKILL.md +0 -592
  122. package/dist/agents/commands/codex/harness/harness-planning/agents/openai.yaml +0 -3
  123. package/dist/agents/commands/codex/harness/harness-refactoring/SKILL.md +0 -181
  124. package/dist/agents/commands/codex/harness/harness-refactoring/agents/openai.yaml +0 -3
  125. package/dist/agents/commands/codex/harness/harness-release-readiness/SKILL.md +0 -701
  126. package/dist/agents/commands/codex/harness/harness-release-readiness/agents/openai.yaml +0 -3
  127. package/dist/agents/commands/codex/harness/harness-roadmap/SKILL.md +0 -607
  128. package/dist/agents/commands/codex/harness/harness-roadmap/agents/openai.yaml +0 -3
  129. package/dist/agents/commands/codex/harness/harness-security-scan/SKILL.md +0 -147
  130. package/dist/agents/commands/codex/harness/harness-security-scan/agents/openai.yaml +0 -3
  131. package/dist/agents/commands/codex/harness/harness-skill-authoring/SKILL.md +0 -314
  132. package/dist/agents/commands/codex/harness/harness-skill-authoring/agents/openai.yaml +0 -3
  133. package/dist/agents/commands/codex/harness/harness-soundness-review/SKILL.md +0 -1280
  134. package/dist/agents/commands/codex/harness/harness-soundness-review/agents/openai.yaml +0 -3
  135. package/dist/agents/commands/codex/harness/harness-supply-chain-audit/SKILL.md +0 -255
  136. package/dist/agents/commands/codex/harness/harness-supply-chain-audit/agents/openai.yaml +0 -3
  137. package/dist/agents/commands/codex/harness/harness-tdd/SKILL.md +0 -189
  138. package/dist/agents/commands/codex/harness/harness-tdd/agents/openai.yaml +0 -3
  139. package/dist/agents/commands/codex/harness/harness-test-advisor/SKILL.md +0 -171
  140. package/dist/agents/commands/codex/harness/harness-test-advisor/agents/openai.yaml +0 -3
  141. package/dist/agents/commands/codex/harness/harness-verification/SKILL.md +0 -433
  142. package/dist/agents/commands/codex/harness/harness-verification/agents/openai.yaml +0 -3
  143. package/dist/agents/commands/codex/harness/harness-verify/SKILL.md +0 -170
  144. package/dist/agents/commands/codex/harness/harness-verify/agents/openai.yaml +0 -3
  145. package/dist/agents/commands/codex/harness/initialize-harness-project/SKILL.md +0 -244
  146. package/dist/agents/commands/codex/harness/initialize-harness-project/agents/openai.yaml +0 -3
  147. package/dist/agents/commands/cursor/harness/add-harness-component.mdc +0 -200
  148. package/dist/agents/commands/cursor/harness/cleanup-dead-code.mdc +0 -253
  149. package/dist/agents/commands/cursor/harness/detect-doc-drift.mdc +0 -187
  150. package/dist/agents/commands/cursor/harness/enforce-architecture.mdc +0 -304
  151. package/dist/agents/commands/cursor/harness/harness-architecture-advisor.mdc +0 -457
  152. package/dist/agents/commands/cursor/harness/harness-autopilot.mdc +0 -924
  153. package/dist/agents/commands/cursor/harness/harness-brainstorming.mdc +0 -414
  154. package/dist/agents/commands/cursor/harness/harness-code-review.mdc +0 -865
  155. package/dist/agents/commands/cursor/harness/harness-codebase-cleanup.mdc +0 -232
  156. package/dist/agents/commands/cursor/harness/harness-debugging.mdc +0 -374
  157. package/dist/agents/commands/cursor/harness/harness-dependency-health.mdc +0 -187
  158. package/dist/agents/commands/cursor/harness/harness-docs-pipeline.mdc +0 -468
  159. package/dist/agents/commands/cursor/harness/harness-execution.mdc +0 -518
  160. package/dist/agents/commands/cursor/harness/harness-hotspot-detector.mdc +0 -169
  161. package/dist/agents/commands/cursor/harness/harness-impact-analysis.mdc +0 -192
  162. package/dist/agents/commands/cursor/harness/harness-integrity.mdc +0 -175
  163. package/dist/agents/commands/cursor/harness/harness-onboarding.mdc +0 -296
  164. package/dist/agents/commands/cursor/harness/harness-perf.mdc +0 -268
  165. package/dist/agents/commands/cursor/harness/harness-planning.mdc +0 -587
  166. package/dist/agents/commands/cursor/harness/harness-refactoring.mdc +0 -177
  167. package/dist/agents/commands/cursor/harness/harness-release-readiness.mdc +0 -697
  168. package/dist/agents/commands/cursor/harness/harness-roadmap.mdc +0 -603
  169. package/dist/agents/commands/cursor/harness/harness-security-scan.mdc +0 -162
  170. package/dist/agents/commands/cursor/harness/harness-skill-authoring.mdc +0 -300
  171. package/dist/agents/commands/cursor/harness/harness-soundness-review.mdc +0 -1275
  172. package/dist/agents/commands/cursor/harness/harness-supply-chain-audit.mdc +0 -252
  173. package/dist/agents/commands/cursor/harness/harness-tdd.mdc +0 -185
  174. package/dist/agents/commands/cursor/harness/harness-test-advisor.mdc +0 -168
  175. package/dist/agents/commands/cursor/harness/harness-verification.mdc +0 -429
  176. package/dist/agents/commands/cursor/harness/harness-verify.mdc +0 -167
  177. package/dist/agents/commands/cursor/harness/initialize-harness-project.mdc +0 -240
  178. package/dist/agents/commands/gemini-cli/harness/harness.toml +0 -277
  179. package/dist/{chunk-RRHUCDRD.js → chunk-ZP5E7YET.js} +3 -3
@@ -0,0 +1,35 @@
1
+ name: initialize-test-suite-project
2
+ version: "1.0.0"
3
+ description: Scaffold or migrate a test-suite project (API, E2E/UI, or shared library) with test-suite-specific layer models, tags, reporter stack, and custom report
4
+ stability: static
5
+ cognitive_mode: constructive-architect
6
+ triggers:
7
+ - manual
8
+ platforms:
9
+ - claude-code
10
+ - gemini-cli
11
+ - cursor
12
+ - codex
13
+ tools:
14
+ - Bash
15
+ - Read
16
+ - Write
17
+ - Glob
18
+ cli:
19
+ command: harness skill run initialize-test-suite-project
20
+ args:
21
+ - name: path
22
+ description: Project root path
23
+ required: false
24
+ mcp:
25
+ tool: run_skill
26
+ input:
27
+ skill: initialize-test-suite-project
28
+ path: string
29
+ type: flexible
30
+ tier: 1
31
+ state:
32
+ persistent: false
33
+ files: []
34
+ depends_on:
35
+ - initialize-harness-project
@@ -114,9 +114,31 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
114
114
 
115
115
  3. **Write the spec** to `docs/changes/<feature>/proposal.md`.
116
116
 
117
- 4. **Run `harness validate`** to verify proper placement and project health.
117
+ 4. **Run skill advisor scan.** After writing the spec, extract signals from its content and scan the skill index for relevant skills. Write results to `docs/changes/<feature>/SKILLS.md` alongside the spec.
118
118
 
119
- 5. **Request sign-off via `emit_interaction`:**
119
+ Use the `advise_skills` MCP tool:
120
+
121
+ ```json
122
+ advise_skills({
123
+ "path": "<project-root>",
124
+ "specPath": "docs/changes/<feature>/proposal.md"
125
+ })
126
+ ```
127
+
128
+ Announce findings in a brief summary (skip announcement in `--fast` mode):
129
+
130
+ ```
131
+ Skill Advisor: Found N relevant skills for '<feature>'
132
+ Apply: N (skill-a, skill-b, ...)
133
+ Reference: N | Consider: N
134
+ Full list: docs/changes/<feature>/SKILLS.md
135
+ ```
136
+
137
+ In `--thorough` mode, show the full skill list for human review before proceeding.
138
+
139
+ 5. **Run `harness validate`** to verify proper placement and project health.
140
+
141
+ 6. **Request sign-off via `emit_interaction`:**
120
142
 
121
143
  ```json
122
144
  emit_interaction({
@@ -133,14 +155,14 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
133
155
 
134
156
  The human must explicitly approve before this skill is complete.
135
157
 
136
- 6. **Add feature to roadmap.** If `docs/roadmap.md` exists:
158
+ 7. **Add feature to roadmap.** If `docs/roadmap.md` exists:
137
159
  - Derive feature name from the spec title (the H1 heading).
138
160
  - Call `manage_roadmap` with action `add`, `status: "planned"`, `milestone: "Current Work"`, and the spec path.
139
161
  - If the feature already exists, skip silently.
140
162
  - If `manage_roadmap` is unavailable, fall back to `parseRoadmap`/`serializeRoadmap` from core. Warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored."
141
163
  - If no roadmap exists, skip silently.
142
164
 
143
- 7. **Write handoff and suggest transition.** After approval:
165
+ 8. **Write handoff and suggest transition.** After approval:
144
166
 
145
167
  Write handoff to the session-scoped path when a session slug is known, otherwise fall back to the global path:
146
168
  - Session-scoped (preferred): `.harness/sessions/<session-slug>/handoff.json`
@@ -155,7 +177,13 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
155
177
  "summary": "<1-sentence summary>",
156
178
  "artifacts": ["<spec path>"],
157
179
  "decisions": [{ "what": "<decision>", "why": "<rationale>" }],
158
- "contextKeywords": ["<keywords from Phase 2>"]
180
+ "contextKeywords": ["<keywords from Phase 2>"],
181
+ "recommendedSkills": {
182
+ "apply": ["<skill-names>"],
183
+ "reference": ["<skill-names>"],
184
+ "consider": ["<skill-names>"],
185
+ "skillsPath": "docs/changes/<feature>/SKILLS.md"
186
+ }
159
187
  }
160
188
  ```
161
189
 
@@ -96,6 +96,12 @@ For each task, starting from current position:
96
96
 
97
97
  1. **Read task instructions completely** before writing any code.
98
98
 
99
+ 1b. **Load skill context for annotated tasks.** If the task has a `**Skills:**` annotation:
100
+
101
+ - For `apply` tier skills: note the skill name in the task context. The skill may provide patterns or approaches to follow during implementation.
102
+ - For `reference` tier skills (type: `knowledge`): load the skill's SKILL.md content as supplementary context. Cap at 3 reference skills per task to manage context budget.
103
+ - Use the skill content to inform implementation decisions but follow the plan's exact instructions as written. Skill context provides background knowledge, not overriding instructions.
104
+
99
105
  2. **Follow instructions exactly.** The plan contains exact file paths, code, and commands. Execute as written.
100
106
 
101
107
  3. **TDD rhythm:**
@@ -54,6 +54,21 @@ When no arguments are provided (standalone invocation), discover spec from conte
54
54
  Work backward from the goal. Start with "what must be true when we are done?"
55
55
 
56
56
  1. **State the goal.** One sentence. What does the system do when this plan is complete?
57
+
58
+ 1b. **Load skill recommendations.** After loading the spec, check for skill recommendations:
59
+
60
+ - If `docs/changes/<feature>/SKILLS.md` exists alongside the spec: parse the Apply and Reference tiers. These inform task annotation in Phase 2.
61
+ - If SKILLS.md is missing but a spec exists: run the advisor inline using `advise_skills` MCP tool to generate SKILLS.md.
62
+ - If neither SKILLS.md nor a spec exists: emit a one-line note:
63
+
64
+ ```
65
+ Note: No skill recommendations found. Run the advisor to discover
66
+ relevant design, framework, and knowledge skills:
67
+ harness advise-skills --spec-path <path>
68
+ ```
69
+
70
+ Store the parsed skill list for use in Phase 2 task annotation.
71
+
57
72
  2. **Derive observable truths.** What can be observed (running a command, opening a browser, reading a file) that proves the goal is met? Be specific:
58
73
  - BAD: "The API handles errors"
59
74
  - GOOD: "GET /api/users/nonexistent returns 404 with `{ error: 'User not found' }` body"
@@ -190,7 +205,16 @@ Report progress: `**[Phase 2/4]** DECOMPOSE — mapping file structure and creat
190
205
  - **Exact commit message**
191
206
  - **`harness validate`** as the final step
192
207
 
193
- 5. **Include checkpoints.** Mark tasks requiring human input:
208
+ 5. **Skill annotations.** If skill recommendations were loaded in Phase 1, annotate each task with relevant skills from the Apply and Reference tiers:
209
+
210
+ ```
211
+ ### Task 3: Implement dark mode toggle
212
+ **Skills:** `design-dark-mode` (apply), `a11y-color-contrast` (reference)
213
+ ```
214
+
215
+ Match skills to tasks based on keyword and domain overlap between the task description and the skill's purpose/keywords. Only annotate when the match is relevant to the specific task.
216
+
217
+ 6. **Include checkpoints.** Mark tasks requiring human input:
194
218
  - `[checkpoint:human-verify]` — Pause, show result, wait for confirmation
195
219
  - `[checkpoint:decision]` — Pause, present options, wait for choice
196
220
  - `[checkpoint:human-action]` — Pause, instruct human on required action
@@ -29,6 +29,17 @@
29
29
 
30
30
  4. **Recommend the target adoption level.** For new projects, start with basic unless the team has harness experience. For existing projects, recommend one level up from current. Present the recommendation and wait for confirmation.
31
31
 
32
+ 5. **Classify the project shape — product/service or test-suite?** Check these signals; if any match, the project is a test suite and the rest of this skill's flow changes:
33
+ - Repo or package name matches `*test*`, `*-e2e*`, `*-qa*`, `*-automation*`
34
+ - `package.json` has `@playwright/test`, `cypress`, `webdriverio`, `mocha`, or `testcafe` as a direct dep
35
+ - Top-level `tests/`, `e2e/`, `specs/`, or `playwright/` directories are the primary source tree
36
+ - Config files like `playwright.config.*`, `cypress.config.*`, `wdio.conf.*`
37
+ - No production runtime — build output consumed only by other test repos (shared library)
38
+
39
+ **If a test suite:** complete Phase 2 (scaffolding) here, then dispatch to `initialize-test-suite-project` for Phase 3 configuration and Phase 4 verification, then return here for Phase 4 step 4+ (knowledge graph, roadmap nudge, final commit). The test-suite skill owns archetype selection, layer variants, tags, reporters, and the custom report.
40
+
41
+ **If a product/service:** continue with the rest of this skill as written.
42
+
32
43
  ### Phase 2: SCAFFOLD — Generate Project Structure
33
44
 
34
45
  1. **Run `harness init` with the appropriate flags:**
@@ -72,6 +83,8 @@
72
83
  - **No:** Set `i18n.enabled: false` in `harness.config.json`. The `harness-i18n-process` skill will still fire gentle prompts for unconfigured projects when features touch user-facing strings.
73
84
  - **Not sure yet:** Skip i18n configuration entirely. Do not set `i18n.enabled`. The project can enable i18n later by running `harness-i18n-workflow` directly.
74
85
 
86
+ 6. **Test-suite projects only — dispatch to `initialize-test-suite-project`.** If Phase 1 step 5 classified this as a test suite, invoke `initialize-test-suite-project` now and let it own archetype selection, shared-library decision, layer variants (A self-contained vs B consumer), ESLint flat-config fix, tag taxonomy, reporter stack, custom report, and the "prove the guards fire" verification. Return here for Phase 4 step 4+ (knowledge graph, roadmap, commit). Product and service projects skip this step entirely.
87
+
75
88
  ### Phase 4: VALIDATE — Confirm Everything Works
76
89
 
77
90
  1. **Run `harness validate`** to verify the full configuration. This checks:
@@ -107,6 +120,7 @@ This creates the `.harness/graph/` directory and populates it with the project's
107
120
  - **`harness validate`** — Verify the full project configuration is valid and complete.
108
121
  - **`harness check-deps`** — Verify dependency constraints match the actual codebase (intermediate and above).
109
122
  - **`harness-i18n-workflow configure` + `harness-i18n-workflow scaffold`** — Invoked during Phase 3 if the project will support multiple languages. Sets up i18n configuration and translation file structure.
123
+ - **`initialize-test-suite-project`** — Sub-skill. Invoked during Phase 3 step 6 when Phase 1 step 5 classified the project as a test suite. Owns archetype selection, shared-library vs in-repo decision, layer variants, tag taxonomy, reporter stack, custom report, and "prove the guards fire" verification.
110
124
  - **Roadmap nudge** — After successful initialization, inform the user about `/harness:roadmap --create` for setting up project-level feature tracking. Informational only; does not create the roadmap.
111
125
 
112
126
  ## Success Criteria
@@ -120,15 +134,17 @@ This creates the `.harness/graph/` directory and populates it with the project's
120
134
  - The adoption level matches what was agreed upon with the human
121
135
  - All generated files are committed in a single atomic commit
122
136
  - i18n configuration is set if the human chose to enable it during init
137
+ - For test suites: `initialize-test-suite-project` ran to completion and its Success Criteria are also met
123
138
 
124
139
  ## Rationalizations to Reject
125
140
 
126
- | Rationalization | Why It Is Wrong |
127
- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
128
- | "The generated AGENTS.md template looks fine -- no need to customize it" | Phase 3 says do not blindly accept generated content. Without project-specific descriptions, agents receive generic instructions. |
129
- | "We should start at the advanced level since we want full coverage" | The skill recommends basic for new projects. Each level builds on the previous. Jumping to advanced creates misconfigured rules. |
130
- | "I will skip the i18n question to keep setup fast" | Phase 3 requires asking about i18n and recording the decision. Skipping creates ambiguity about whether the omission was intentional. |
131
- | "Validation passed, so the project is ready" | Phase 4 includes harness check-deps for intermediate+ projects and knowledge graph initialization. Validation alone is not sufficient. |
141
+ | Rationalization | Why It Is Wrong |
142
+ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
143
+ | "The generated AGENTS.md template looks fine -- no need to customize it" | Phase 3 says do not blindly accept generated content. Without project-specific descriptions, agents receive generic instructions. |
144
+ | "We should start at the advanced level since we want full coverage" | The skill recommends basic for new projects. Each level builds on the previous. Jumping to advanced creates misconfigured rules. |
145
+ | "I will skip the i18n question to keep setup fast" | Phase 3 requires asking about i18n and recording the decision. Skipping creates ambiguity about whether the omission was intentional. |
146
+ | "Validation passed, so the project is ready" | Phase 4 includes harness check-deps for intermediate+ projects and knowledge graph initialization. Validation alone is not sufficient. |
147
+ | "This is a test suite, we'll configure layers in this skill" | Phase 3 step 6 dispatches to `initialize-test-suite-project` for archetype selection, layer variants, and the rest. Do not inline test-suite-specific configuration here — the sub-skill owns it and carries the gotchas. |
132
148
 
133
149
  ## Examples
134
150
 
@@ -32,4 +32,5 @@ tier: 1
32
32
  state:
33
33
  persistent: false
34
34
  files: []
35
- depends_on: []
35
+ depends_on:
36
+ - initialize-test-suite-project
@@ -0,0 +1,415 @@
1
+ # Initialize Test Suite Project
2
+
3
+ > Scaffold or migrate a test-suite project — API, E2E/UI, or shared test library. Owns test-suite-specific archetype selection, shared-library vs in-repo scaffolding decision, layer variants, tag taxonomy, reporter stack, and custom report. Cross-cutting concerns (adoption level, personas, AGENTS.md base template, i18n, knowledge graph, roadmap nudge, final commit) delegate to `initialize-harness-project`.
4
+
5
+ ## When to Use
6
+
7
+ - Initializing a new test-suite project (you already know it is a test suite)
8
+ - Migrating an existing test-suite project to the next adoption level
9
+ - When `initialize-harness-project`'s Phase 1 classification step hands off here
10
+ - NOT when the project is a product or service (use `initialize-harness-project`)
11
+ - NOT when adding a single spec, domain, or fixture to an already-configured test suite (use `add-harness-component`)
12
+
13
+ ## Composition with `initialize-harness-project`
14
+
15
+ This skill owns only the _test-suite-specific_ pieces. The generic harness flow belongs to the parent skill. Two invocation patterns:
16
+
17
+ 1. **Parent dispatches here.** The user runs `initialize-harness-project`; its Phase 1 step 5 classifies the project as a test suite and dispatches to this skill. Run the parent's Phase 2 (scaffolding) first, then this skill's full flow, then return to the parent for Phase 4 wrap-up (knowledge graph, roadmap, commit).
18
+
19
+ 2. **Direct invocation.** The user knows up front it's a test suite and invokes this skill directly. Run the parent's Phase 1 (assess state), Phase 2 (`harness init`), and Phase 3 steps 1–2 and 5 (personas, AGENTS.md base, i18n) inline or by invoking the parent explicitly, then apply this skill's Phase 1–4, then hand back to the parent's Phase 4 steps 4–5.
20
+
21
+ Either way, what this skill owns: archetype selection, shared-library vs scaffold decision, layer-model variants A/B, ESLint flat-config fix, test-framework delegation, env and secrets, auth abstraction, schema validation, fixtures isolation, mocking support, tag-driven organization, reporters, the custom report, CI integration, and "prove the guards fire" verification.
22
+
23
+ ## Process
24
+
25
+ ### Phase 1: CLASSIFY — Pick the Archetype
26
+
27
+ Before scaffolding, classify the project and record in the assessment.
28
+
29
+ **Test-suite signals** (at least one must apply — re-check even if dispatched from the parent):
30
+
31
+ - Repo or package name matches `*test*`, `*-e2e*`, `*-qa*`, `*-automation*`
32
+ - `package.json` has `@playwright/test`, `cypress`, `webdriverio`, `mocha`, or `testcafe` as a direct dep (frameworks that are _only_ test-related — presence of `vitest`/`jest` alone is not enough)
33
+ - Top-level `tests/`, `e2e/`, `specs/`, or `playwright/` directories are the primary source tree, not an adjunct to `src/`
34
+ - Config files like `playwright.config.*`, `cypress.config.*`, `wdio.conf.*`
35
+ - No production runtime — build output is consumed only by other test repos (shared library)
36
+
37
+ **Archetypes:**
38
+
39
+ - **API test suite** — exercises HTTP APIs end-to-end (e.g. Playwright API tests)
40
+ - **E2E / UI suite** — browser-driven tests (Playwright, Cypress, WebdriverIO)
41
+ - **Shared test library** — API clients, Page Object Models, fixtures, or test users consumed by the above; no tests in-repo
42
+
43
+ ### Phase 2: DECIDE — Shared Library or Scaffold In-Repo?
44
+
45
+ For **API** and **E2E/UI** suites, check whether a shared library already exists — typically a team-specific `@<org>/<team>-testing-api-library` for API clients, or an equivalent for Page Object Models. If one exists, consuming it is strongly preferred: one client implementation shared by all test suites is the contract source of truth and avoids drift. Only scaffold an in-repo `src/api/` or `src/page-objects/` tree if no shared library exists or the suite has a genuinely different contract.
46
+
47
+ For **Shared test library** archetypes, this phase is trivial — you _are_ the shared library; scaffold in-repo.
48
+
49
+ Record the decision in AGENTS.md. It determines which layer-model variant applies in Phase 3 step 2.
50
+
51
+ ### Phase 3: CONFIGURE — Test-Suite Shape
52
+
53
+ Apply these steps before running validation. Record decisions in AGENTS.md as you go.
54
+
55
+ 1. **Pick a domain layout.** Independent of whether clients are in-repo or imported, domains drive the folder layout:
56
+ - **Self-contained suite:** one folder per API domain, feature area, or user flow under `src/api/` or `src/page-objects/`, each exposing a manager/client class (API suites) or Page Object Model (UI suites) that takes an HTTP client or browser context in its constructor. A single composition module wires everything together.
57
+ - **Shared-library consumer:** no per-domain folders in `src/`. Instead, a thin `config/` adapter wraps the shared library's entry point (e.g. exposes `{api, user}` on the Playwright test fixture). Tests are still organized by domain — see step 10 — but the domain folders live under `tests/<domain>/`, not `src/api/<domain>/`.
58
+
59
+ Document the chosen layout in AGENTS.md with a directory tree.
60
+
61
+ 2. **Define the layer model.** Two variants — pick the one matching Phase 2.
62
+
63
+ **Variant A — self-contained test suite.** Record in `harness.config.json`:
64
+ - `utils` → helpers, date/string/id utilities (no internal deps)
65
+ - `composition` → single wiring module (e.g. `managers.ts`) → allowed to import every layer below
66
+ - `common` → shared DTOs, enums, error types → `utils`
67
+ - `config` → HTTP client, auth service, environment loader → `utils`, `common`
68
+ - `api` / `domains` / `page-objects` → per-domain managers or POMs → `utils`, `common`, `config`
69
+ - `fixtures` → deterministic seed data, factories, builders → `utils`, `common`, `config`
70
+ - `specs` → top layer; imports composition + fixtures; nothing imports specs
71
+
72
+ Forbid (same-layer rules, enforced via `forbiddenImports`):
73
+ - A domain/POM importing a sibling domain/POM (domains are peers, not hierarchical)
74
+ - `fixtures` importing specs
75
+ - Specs importing each other (tests must be independently runnable in any order)
76
+
77
+ **Variant B — shared-library consumer.** No `common`, no `api` layer — those live in the shared library. Record in `harness.config.json`:
78
+ - `utils` → helpers with no internal deps
79
+ - `config` → thin adapter wrapping the shared library (e.g. builds the `Managers` from the shared lib + current env), token handler, constants → `utils`
80
+ - `fixtures` → Playwright test fixtures that expose `{api, user, ...}` to specs → `utils`, `config`
81
+ - `specs` → top layer; imports `fixtures` → `utils`, `config`, `fixtures`
82
+
83
+ Forbid:
84
+ - Specs bypassing `fixtures` and instantiating the shared library directly — always go through the fixture so auth, base URL, and teardown are consistent
85
+ - `fixtures` importing specs
86
+ - Any layer importing the shared library from outside `config` (forces single adapter point, keeps upgrades localized)
87
+
88
+ **Layer-ordering gotcha — `harness check-deps` and `@harness-engineering/eslint-plugin` both use first-match-wins layer resolution.** Put more-specific patterns _before_ more-general ones in the `layers` array. For Variant A, `composition` (pattern `src/config/managers.ts`) must come before `config` (pattern `src/config/**`), otherwise `managers.ts` is classified as `config` and every `api` import becomes a layer violation. Do not rely on per-layer `excludePatterns` — the CLI and the ESLint plugin both drop that field.
89
+
90
+ **`forbiddenImports` gotcha — no `exceptPaths` support.** The ESLint plugin schema for `forbiddenImports` only accepts `from`, `disallow`, `message` — any other keys (including `exceptPaths`) are silently stripped. Do not write `from: src/config/**, disallow: [src/api/**], exceptPaths: [src/config/managers.ts]` and expect it to work. Use layer ordering (above) to carve out the composition file; reserve `forbiddenImports` for same-layer rules like sibling-domain isolation that the layer graph cannot express.
91
+
92
+ 3. **Wire up the ESLint flat config so the forbidden-imports rule actually runs.** `harness init` scaffolds `eslint.config.mjs` that spreads `harnessPlugin.configs.recommended` but does not declare a `files:` glob or a TypeScript parser. Under ESLint 9 flat config this means every `.ts` file is ignored and the rule never fires. Replace the scaffolded config with an explicit block: `files: ['src/**/*.ts', 'tests/**/*.ts']`, `languageOptions: { parser: tsParser, parserOptions: { ecmaVersion: 'latest', sourceType: 'module' } }`, `plugins: { '@harness-engineering': harnessPlugin }`, and the three `'error'` rules (`no-layer-violation`, `no-forbidden-imports`, `no-circular-deps`). Add `@typescript-eslint/parser` to devDependencies. Verify by running `npx eslint 'src/**/*.ts'` and seeing it actually report errors on a deliberately bad file.
93
+
94
+ 4. **Pick the test framework(s) and delegate detailed setup to the right skill.** Do not configure the framework here — just record the choice in AGENTS.md and point the human at the follow-up skill:
95
+ - Playwright (API or E2E) → `test-playwright-setup` then `test-playwright-patterns`
96
+ - Vitest → `test-vitest-config`
97
+ - Contract tests → `api-contract-testing` and `test-contract-testing`
98
+ - Mocking (MSW, route interception) → `test-msw-pattern`, `test-mock-patterns`
99
+ - Fixtures / factories → `test-factory-patterns`, `harness-test-data`
100
+ - For shared libraries that are _consumed_ by tests but contain none themselves, skip framework setup entirely — record this in AGENTS.md under "Gotchas" so agents do not try to add Vitest later.
101
+
102
+ 5. **Environment and secret handling.** Require a committed `.env.example` listing every variable the suite reads (API base URLs, OAuth client IDs, registry tokens, feature flags). Actual `.env*` files must be gitignored. For multi-environment suites, encode environments as `.env.dev`, `.env.stage`, `.env.prod` and document in AGENTS.md how the runner selects one (env var, CLI flag, or config). Never commit real credentials even as examples — use placeholders like `REPLACE_ME`.
103
+
104
+ 6. **Authentication abstraction.** Record in AGENTS.md: token source (OAuth client-credentials, CIAM, basic auth, session cookie), caching strategy (in-memory, file, Redis), and how test users or parent/child scopes are resolved. If a shared test-user library exists (typically `@<org>/<team>-testing-user-library` or similar), link it and forbid inlining user credentials in specs.
105
+
106
+ 7. **Schema / contract validation.** Decide whether request and response DTOs are validated at runtime (zod, ajv, io-ts) or only compile-time. Intermediate and above should validate at runtime for contract-drift detection. If adopting zod, reference `zod-schema-definition`.
107
+
108
+ 8. **Fixtures and test-data isolation.** Document the per-test isolation strategy in AGENTS.md: unique IDs per run (UUID suffixes, timestamps), teardown hooks, no shared mutable state between specs. Forbid hard-coded production record IDs in fixtures.
109
+
110
+ 9. **Mocking support (shared libraries and API clients).** If the project will be consumed by FE or UI test suites that need to mock upstream responses, expose mock response builders (e.g. `buildMockResponse`, `buildMockErrorResponse`) and document the override API in AGENTS.md so consumer projects know the contract.
111
+
112
+ 10. **Test organization: tags over folders.** Do _not_ split specs into `tests/smoke/`, `tests/regression/`, etc. Organize specs by domain / feature area (`tests/<domain>/<feature>.spec.ts`) and filter run shape with tags. This matches how Playwright (and most modern runners) expect grep-based filtering to work, and avoids moving a spec file whenever its coverage tier changes.
113
+
114
+ Record the tag taxonomy in AGENTS.md. Baseline for a Playwright API suite:
115
+ - `@smoke` — fast subset; PR gate. Applied per-test or per-describe.
116
+ - Untagged = regression. "Full suite" is just `playwright test` with no grep.
117
+ - **Quarantine tags (never run):** `@known-failure`, `@wip`, `@blocked`, `@archived`. Exclude these globally via `grepInvert` in `playwright.config.ts`:
118
+ ```ts
119
+ grepInvert: [/@known-failure/, /@wip/, /@blocked/, /@archived/],
120
+ ```
121
+
122
+ Filter commands (bake into `package.json` scripts, not ad-hoc CI yaml):
123
+ - `npm run smoke` → `playwright test --grep @smoke`
124
+ - `npm run exhaustive` → `playwright test` (full regression, quarantine excluded)
125
+ - `npm run list` → `playwright test --list` (sanity check after tag edits)
126
+
127
+ **Reporters.** Configure `playwright.config.ts` with the stack that feeds both human and machine consumers:
128
+
129
+ ```ts
130
+ reporter: [
131
+ ['html', {outputFolder: './test-results/html-test-results', open: 'never'}],
132
+ ['list'],
133
+ ['github'],
134
+ ['json', {outputFile: 'test-results/json-results/results.json'}],
135
+ ],
136
+ ```
137
+
138
+ The `json` reporter is the input to the custom report in step 11. The `github` reporter produces annotations on PRs; `list` is for local stdout; `html` is for deep-dive failure triage.
139
+
140
+ 11. **Custom report (enriched HTML + Slack + history).** Playwright's stock HTML report is fine for a single run but does not track trends, categorize failures, or know which tests are quarantined. Scaffold a `scripts/generate-reports.ts` that reads the JSON reporter output (`test-results/json-results/results.json`) and emits an enriched report. Modeled on reference implementations running in production test suites, it should produce:
141
+ - **Failure categorization:** bucket each failure into one of `schema | auth | server | client | timeout | network | other` based on the error message. Surfaces whether a red run is an API regression (schema) vs. infrastructure (timeout/network) vs. test-data problem (auth).
142
+ - **Per-area health:** group by domain folder (first path segment under `tests/`), report pass rate and failing titles per area. Tells you which surface of the product is drifting.
143
+ - **Delta vs history:** append each run to a JSONL ledger keyed by commit. Report new failures since last run and failures since last green — not just "X failed" but "X started failing at commit Y."
144
+ - **Quarantine ledger:** scan for `@known-failure`-tagged tests, track age since first seen in a JSON ledger, flag tests quarantined longer than 14 days.
145
+ - **Slack summary:** short markdown block with pass rate, new failures, and a link to the HTML report. Optional but cheap once the categorization exists.
146
+ - **Environment + git context:** node version, base URL, commit SHA, branch, commit message — so a report opened later tells you where and when it ran.
147
+
148
+ Wire the script into `package.json`:
149
+
150
+ ```json
151
+ {
152
+ "scripts": {
153
+ "generate-custom-reports": "npx ts-node scripts/generate-reports.ts",
154
+ "show-custom-report": "open test-results/reports/test-report.html"
155
+ }
156
+ }
157
+ ```
158
+
159
+ Do not block CI on the custom report — run it as a post-step and upload the output as an artifact. If categorization throws on an unexpected error shape, the exit code should be non-fatal.
160
+
161
+ 12. **CI integration.** For intermediate+: PR pipeline runs `npm run smoke` (tag-filtered, not folder-filtered); main merges trigger `npm run exhaustive`; nightly runs `npm run exhaustive` plus a quarantine audit (step 11) reporting quarantined-too-long tests. Record the flake policy (max retries, quarantine threshold) in `harness.config.json` so agents do not silently raise retries to hide flakes.
162
+
163
+ ### Phase 4: VALIDATE — Prove the Guards Fire
164
+
165
+ Run the three gates on the clean tree:
166
+
167
+ ```bash
168
+ harness validate
169
+ harness check-deps
170
+ npx eslint 'src/**/*.ts' 'tests/**/*.ts'
171
+ ```
172
+
173
+ All three must pass before proceeding.
174
+
175
+ **Clean-tree passing is necessary but not sufficient.** All three tools can pass while the rules are silently misconfigured (layer ordering wrong, ESLint files glob missing, forbidden-imports schema fields dropped). Before handing back to `initialize-harness-project` for wrap-up:
176
+
177
+ - Insert one deliberate forbidden import — a sibling-domain import is the easiest (e.g. `src/api/users/users-manager.ts` importing `../auth/auth-manager`). Run `npx eslint <file>` and confirm it reports the violation.
178
+ - Insert one deliberate cross-layer import (e.g. `src/utils/foo.ts` importing from `src/api/users/`). Run `harness check-deps` and confirm it reports the violation.
179
+ - Revert both edits. Confirm the clean tree is green on all three gates.
180
+
181
+ After verification passes, return to `initialize-harness-project`'s Phase 4 for:
182
+
183
+ - `harness scan` (knowledge graph)
184
+ - Roadmap nudge
185
+ - Final commit
186
+
187
+ ## Harness Integration
188
+
189
+ - **`initialize-harness-project`** — parent skill. Owns adoption-level selection, `harness init` invocation, persona configuration, AGENTS.md base template, i18n decision, knowledge-graph build, roadmap nudge, final commit.
190
+ - **`harness validate`** — verifies `harness.config.json` schema, AGENTS.md, layers, persona config.
191
+ - **`harness check-deps`** — verifies layer-graph dependency constraints at the file level.
192
+ - **`@harness-engineering/eslint-plugin`** — enforces `forbiddenImports` (same-layer rules) and surfaces layer-graph violations at lint time.
193
+ - **Follow-up test skills** — `test-playwright-setup`, `test-playwright-patterns`, `test-vitest-config`, `test-msw-pattern`, `test-mock-patterns`, `test-factory-patterns`, `harness-test-data`, `api-contract-testing`, `test-contract-testing`.
194
+ - **Related libraries** — `zod-schema-definition` (runtime DTO validation).
195
+
196
+ ## Success Criteria
197
+
198
+ - Archetype is recorded in AGENTS.md (API / E2E-UI / Shared library)
199
+ - Shared-library decision is recorded in AGENTS.md
200
+ - Layer model matches the chosen variant (A self-contained or B shared-library consumer) from Phase 3 step 2
201
+ - Layer ordering puts `composition` before `config` (Variant A only)
202
+ - `forbiddenImports` uses only `{from, disallow, message}` — no silently-dropped `exceptPaths`
203
+ - `eslint.config.mjs` declares an explicit `files:` glob and imports a TypeScript parser
204
+ - `.env.example` is present with `REPLACE_ME` placeholders
205
+ - No real secrets are committed (real `.env*` gitignored)
206
+ - Test framework choice and tag taxonomy (including `@smoke` + quarantine tags) are recorded in AGENTS.md
207
+ - Specs are organized `tests/<domain>/<feature>.spec.ts` — no `tests/smoke/` or `tests/regression/` folders
208
+ - `playwright.config.ts` declares html + list + github + json reporters and `grepInvert` for quarantine tags
209
+ - `scripts/generate-reports.ts` exists and is wired to `npm run generate-custom-reports`
210
+ - All three Phase 4 gates pass on the clean tree
211
+ - "Prove the guards fire" step completed — deliberate violations were caught and reverted
212
+ - Control returned to `initialize-harness-project` for knowledge-graph build and final commit
213
+
214
+ ## Rationalizations to Reject
215
+
216
+ | Rationalization | Why It Is Wrong |
217
+ | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
218
+ | "This is a test suite, so strict layer constraints are overkill" | Test suites benefit _more_ from layer constraints than product code — peer-domain imports and spec coupling are the top sources of flaky, hard-to-maintain suites. |
219
+ | "We can commit a real `.env` for convenience, CI will ignore it" | Phase 3 step 5 forbids committing real credentials. A leaked `.env` in a test repo leaks the same secrets as a product repo. Use `.env.example` with placeholders. |
220
+ | "Tests don't need tags — we'll run everything every time" | Without a `@smoke` tag the PR pipeline grows to 30+ minutes and drives developers to skip CI. Record a tag taxonomy in Phase 3 step 10 even if enforcement comes later. |
221
+ | "We'll split specs into `tests/smoke/` and `tests/regression/` for filtering" | Folder-based filtering forces a file move every time a spec's tier changes. Modern runners (Playwright, Vitest, Cypress) expect `--grep @tag`. Keep `tests/<domain>/<feature>.spec.ts` flat and tag per-test. |
222
+ | "We'll add schema validation later once the client stabilizes" | Runtime DTO validation is the primary contract-drift detector for API test suites. Adding it after tests exist means updating every spec. Decide in Phase 3 step 7. |
223
+ | "We'll copy the API client code into this test suite for convenience" | If a shared API client library already exists, consume it — do not fork. Forked clients drift immediately; the shared library is the contract source of truth. Only scaffold in-repo clients if no shared library exists. See Phase 2. |
224
+ | "Playwright's built-in HTML report is enough" | The built-in report shows a single run. It does not categorize failures (schema vs auth vs timeout), does not track regressions by commit, and does not surface tests quarantined for weeks. Scaffold `scripts/generate-reports.ts` per Phase 3 step 11. |
225
+ | "All three gates passed, so we're done" | Clean-tree passing can co-exist with silently-misconfigured rules (layer ordering wrong, eslint glob missing, forbidden-imports fields dropped). Phase 4 requires deliberately inserting a violation and confirming the tool catches it. |
226
+
227
+ ## Examples
228
+
229
+ ### Example: Initializing a Shared API Test Library (Intermediate)
230
+
231
+ **CLASSIFY:**
232
+
233
+ ```
234
+ Human: "New repo. It's a shared TypeScript HTTP client for our API test suites — consumed by Playwright API tests and also used to mock responses in FE tests. No tests live in this repo."
235
+ package.json has no Playwright/Vitest as direct deps (shared library, not a test runner).
236
+ Archetype: Shared test library.
237
+ ```
238
+
239
+ **DECIDE (Phase 2):**
240
+
241
+ ```
242
+ This is the shared library itself — scaffold in-repo. Phase 2 is trivial.
243
+ ```
244
+
245
+ **SCAFFOLD (delegated to `initialize-harness-project`):**
246
+
247
+ ```bash
248
+ harness init --level intermediate --language typescript
249
+ ```
250
+
251
+ **CONFIGURE (Phase 3):**
252
+
253
+ ```text
254
+ Domain layout: one folder per API domain under src/api/ (challenges, rewards,
255
+ user, oauth, ...). Each domain exposes <domain>-manager.ts taking HttpClient
256
+ in its constructor. Single composition module src/config/managers.ts wires
257
+ every domain from one HttpClient.
258
+
259
+ Layer model (Variant A, harness.config.json):
260
+ utils → src/utils/** (no internal deps)
261
+ composition → src/config/managers.ts → utils, common, config, api
262
+ common → src/api/common/** → utils
263
+ config → src/config/** → utils, common
264
+ api → src/api/** → utils, common, config
265
+
266
+ Layer ordering: composition BEFORE config (first-match-wins).
267
+
268
+ Forbidden (forbiddenImports):
269
+ - any src/api/<domain> importing a sibling src/api/<domain>
270
+ - src/api/common importing config or sibling domains
271
+
272
+ Framework: none in-repo (shared library). Gotcha recorded in AGENTS.md so
273
+ future agents don't scaffold Vitest.
274
+
275
+ Env: .env.example committed with GITHUB_ACCESS_TOKEN placeholder (registry
276
+ auth only). No runtime env vars — consumers pass config explicitly.
277
+
278
+ Auth: OAuth client-credentials with pluggable TokenStorage interface; parent
279
+ vs child scope resolution documented in docs/auth-flow.md. Link to
280
+ a shared test-user library for test-user data.
281
+
282
+ Schema validation: zod at runtime for all response DTOs. Reference
283
+ zod-schema-definition skill for future domain additions.
284
+
285
+ Mocking: expose buildMockResponse / buildMockSuccessResponse /
286
+ buildMockErrorResponse from src/config/mock-response.ts so FE test repos
287
+ can override per spec. Document override contract in docs/mock-response.md.
288
+ ```
289
+
290
+ **VALIDATE (Phase 4):**
291
+
292
+ ```bash
293
+ harness validate # Pass
294
+ harness check-deps # Pass — no sibling-domain violations
295
+ npx eslint 'src/**/*.ts' # Pass
296
+
297
+ # Prove the guards fire: insert a sibling-domain import, eslint reports it, revert.
298
+
299
+ # Hand back to initialize-harness-project:
300
+ harness scan # Builds .harness/graph/
301
+ git commit -m "feat: initialize harness project at intermediate level for shared API test library"
302
+ ```
303
+
304
+ ### Example: Playwright API Test Suite Consuming a Shared Library (Intermediate)
305
+
306
+ **CLASSIFY:**
307
+
308
+ ```
309
+ Human: "New repo. Playwright API tests for one of our backend services. A shared API client library already exists at @<org>/<team>-testing-api-library and a shared test-user library at @<org>/<team>-testing-user-library."
310
+ package.json will have @playwright/test as a direct dep → test suite signal.
311
+ Archetype: API test suite.
312
+ ```
313
+
314
+ **DECIDE (Phase 2):**
315
+
316
+ ```
317
+ Shared library exists → consume it. Layer variant B (shared-library consumer).
318
+ Do NOT scaffold src/api/. Record decision in AGENTS.md.
319
+ ```
320
+
321
+ **SCAFFOLD (delegated to `initialize-harness-project`):**
322
+
323
+ ```bash
324
+ harness init --level intermediate --language typescript
325
+ # Scaffolded output is a starting point — replace generic layers and eslint config.
326
+ ```
327
+
328
+ **CONFIGURE (Phase 3, Variant B):**
329
+
330
+ ```text
331
+ Dependencies: @<org>/<team>-testing-api-library, @<org>/<team>-testing-user-library,
332
+ @playwright/test, dotenv, zod.
333
+
334
+ Directory layout (no src/api/, no src/page-objects/):
335
+ config/
336
+ api-adapter.ts # Builds Managers from the shared library + env vars
337
+ api-client.ts # Fetcher wrapping Playwright's APIRequestContext
338
+ token-handler.ts # OAuth + test-user token resolution
339
+ constants.ts # TEST_ARTIFACTS_DIR, URLs, etc.
340
+ fixtures/
341
+ test-fixture.ts # Playwright fixture exposing {api, user}
342
+ test-no-init-auth-fixture.ts # Fixture for 401/auth-failure tests
343
+ expects.ts # expectOkResponse, expectUnauthorized, ...
344
+ tests/
345
+ challenges/
346
+ create.spec.ts
347
+ checkin.spec.ts
348
+ ...
349
+ oauth/
350
+ login.spec.ts
351
+ user-profile/
352
+ ...
353
+ global.setup.ts
354
+ global.teardown.ts
355
+ scripts/
356
+ generate-reports.ts
357
+ playwright.config.ts
358
+ .env.example
359
+ harness.config.json
360
+ AGENTS.md
361
+
362
+ Layer model (Variant B, harness.config.json):
363
+ utils → src/utils/** (no internal deps)
364
+ config → config/** → utils
365
+ fixtures → fixtures/** → utils, config
366
+ specs → tests/** → utils, config, fixtures
367
+
368
+ Forbidden (same-layer or cross-cutting):
369
+ - tests/** importing @<org>/<team>-testing-api-library directly
370
+ (must go through fixtures → config adapter)
371
+ - fixtures/** importing tests/**
372
+ - Specs importing each other
373
+
374
+ Tags (playwright.config.ts):
375
+ grepInvert: [/@known-failure/, /@wip/, /@blocked/, /@archived/]
376
+ Tag @smoke on PR-gate specs; untagged = regression.
377
+
378
+ Reporters (playwright.config.ts):
379
+ ['html', {outputFolder: './test-results/html-test-results', open: 'never'}],
380
+ ['list'],
381
+ ['github'],
382
+ ['json', {outputFile: 'test-results/json-results/results.json'}],
383
+
384
+ Custom report (scripts/generate-reports.ts):
385
+ Reads test-results/json-results/results.json. Emits HTML + Slack with:
386
+ failure categorization, per-area health, delta vs history, quarantine ledger.
387
+ Wired to `npm run generate-custom-reports` / `npm run show-custom-report`.
388
+
389
+ package.json scripts:
390
+ smoke: playwright test --grep @smoke
391
+ exhaustive: playwright test
392
+ list: playwright test --list
393
+ generate-custom-reports: npx ts-node scripts/generate-reports.ts
394
+ show-custom-report: open test-results/reports/test-report.html
395
+
396
+ .env.example: API_BASE_URL, OAUTH_TOKEN_URL, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET,
397
+ TEST_USER_POOL_URL, TEST_USER_POOL_TOKEN. Real .env is gitignored.
398
+ ```
399
+
400
+ **VALIDATE (Phase 4):**
401
+
402
+ ```bash
403
+ harness validate # Pass
404
+ harness check-deps # Pass
405
+ npm run lint # Pass
406
+ npm run smoke # Sanity: runs only @smoke-tagged specs
407
+
408
+ # Prove the forbidden-imports rule fires:
409
+ # temporarily add an import of @<org>/<team>-testing-api-library to a spec
410
+ npx eslint tests/challenges/create.spec.ts # Should report violation
411
+ # revert, confirm green
412
+
413
+ # Hand back to initialize-harness-project:
414
+ git commit -m "feat: initialize harness project at intermediate level for Playwright API suite"
415
+ ```