@harness-engineering/cli 1.7.0 → 1.8.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 (187) hide show
  1. package/dist/agents/personas/documentation-maintainer.yaml +3 -1
  2. package/dist/agents/personas/performance-guardian.yaml +23 -0
  3. package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
  4. package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
  5. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
  6. package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
  7. package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +48 -1
  8. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
  9. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +7 -0
  10. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +11 -3
  11. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +81 -11
  12. package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
  13. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
  14. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
  15. package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
  16. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
  17. package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
  18. package/dist/agents/skills/claude-code/harness-docs-pipeline/SKILL.md +460 -0
  19. package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
  20. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
  21. package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
  22. package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
  23. package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
  24. package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
  25. package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
  26. package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
  27. package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
  28. package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
  29. package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +35 -6
  30. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +17 -1
  31. package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
  32. package/dist/agents/skills/claude-code/harness-perf/SKILL.md +37 -8
  33. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
  34. package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
  35. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +59 -5
  36. package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
  37. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +16 -0
  38. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +561 -0
  39. package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
  40. package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
  41. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
  42. package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
  43. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
  44. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
  45. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
  46. package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
  47. package/dist/agents/skills/claude-code/harness-verify/SKILL.md +11 -0
  48. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
  49. package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
  50. package/dist/agents/skills/gemini-cli/add-harness-component/SKILL.md +192 -0
  51. package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +32 -0
  52. package/dist/agents/skills/gemini-cli/align-documentation/SKILL.md +213 -0
  53. package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +31 -0
  54. package/dist/agents/skills/gemini-cli/check-mechanical-constraints/SKILL.md +191 -0
  55. package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +32 -0
  56. package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +245 -0
  57. package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +33 -0
  58. package/dist/agents/skills/gemini-cli/detect-doc-drift/SKILL.md +179 -0
  59. package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +30 -0
  60. package/dist/agents/skills/gemini-cli/enforce-architecture/SKILL.md +240 -0
  61. package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +34 -0
  62. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +7 -0
  63. package/dist/agents/skills/gemini-cli/harness-architecture-advisor/SKILL.md +397 -0
  64. package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +48 -0
  65. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +11 -3
  66. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +317 -0
  67. package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +49 -0
  68. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +681 -0
  69. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +45 -0
  70. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
  71. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
  72. package/dist/agents/skills/gemini-cli/harness-debugging/SKILL.md +366 -0
  73. package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +47 -0
  74. package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
  75. package/dist/agents/skills/gemini-cli/harness-diagnostics/SKILL.md +318 -0
  76. package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +50 -0
  77. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
  78. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
  79. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +382 -0
  80. package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +51 -0
  81. package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +268 -0
  82. package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +31 -0
  83. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
  84. package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
  85. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
  86. package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
  87. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
  88. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
  89. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
  90. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +35 -6
  91. package/dist/agents/skills/gemini-cli/harness-integrity/SKILL.md +167 -0
  92. package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +47 -0
  93. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
  94. package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +288 -0
  95. package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +30 -0
  96. package/dist/agents/skills/gemini-cli/harness-parallel-agents/SKILL.md +171 -0
  97. package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +33 -0
  98. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
  99. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  100. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
  101. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +389 -0
  102. package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +49 -0
  103. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +262 -0
  104. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +33 -0
  105. package/dist/agents/skills/gemini-cli/harness-refactoring/SKILL.md +169 -0
  106. package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +33 -0
  107. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +16 -0
  108. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +561 -0
  109. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
  110. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
  111. package/dist/agents/skills/gemini-cli/harness-skill-authoring/SKILL.md +292 -0
  112. package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +32 -0
  113. package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
  114. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
  115. package/dist/agents/skills/gemini-cli/harness-state-management/SKILL.md +309 -0
  116. package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +32 -0
  117. package/dist/agents/skills/gemini-cli/harness-tdd/SKILL.md +177 -0
  118. package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +48 -0
  119. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
  120. package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +328 -0
  121. package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +42 -0
  122. package/dist/agents/skills/gemini-cli/harness-verify/SKILL.md +159 -0
  123. package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +40 -0
  124. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +224 -0
  125. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +31 -0
  126. package/dist/agents/skills/gemini-cli/validate-context-engineering/SKILL.md +150 -0
  127. package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +31 -0
  128. package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
  129. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
  130. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
  131. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
  132. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
  133. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
  134. package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
  135. package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
  136. package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
  137. package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
  138. package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
  139. package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
  140. package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
  141. package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
  142. package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
  143. package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
  144. package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
  145. package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
  146. package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
  147. package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
  148. package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
  149. package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
  150. package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
  151. package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
  152. package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
  153. package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
  154. package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
  155. package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
  156. package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
  157. package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
  158. package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
  159. package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
  160. package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
  161. package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
  162. package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
  163. package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
  164. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
  165. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
  166. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
  167. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
  168. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
  169. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
  170. package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
  171. package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
  172. package/dist/bin/harness.js +64 -4
  173. package/dist/{chunk-GA6GN5J2.js → chunk-E2RTDBMG.js} +2263 -41
  174. package/dist/{chunk-FFIX3QVG.js → chunk-KJANDVVC.js} +141 -49
  175. package/dist/{chunk-4WUGOJQ7.js → chunk-RT2LYQHF.js} +1 -1
  176. package/dist/{dist-C4J67MPP.js → dist-CCM3L3UE.js} +95 -1
  177. package/dist/{dist-N4D4QWFV.js → dist-K6KTTN3I.js} +4 -4
  178. package/dist/index.d.ts +187 -7
  179. package/dist/index.js +7 -3
  180. package/dist/validate-cross-check-ZGKFQY57.js +7 -0
  181. package/package.json +9 -9
  182. package/dist/agents/skills/node_modules/.bin/glob +0 -17
  183. package/dist/agents/skills/node_modules/.bin/vitest +0 -17
  184. package/dist/agents/skills/node_modules/.bin/yaml +0 -17
  185. package/dist/templates/advanced/docs/specs/.gitkeep +0 -0
  186. package/dist/templates/intermediate/docs/specs/.gitkeep +0 -0
  187. package/dist/validate-cross-check-WGXQ7K62.js +0 -7
@@ -0,0 +1,389 @@
1
+ # Harness Planning
2
+
3
+ > Implementation planning with atomic tasks, goal-backward must-haves, and complete executable instructions. Every task fits in one context window.
4
+
5
+ ## When to Use
6
+
7
+ - After a design spec is approved (output of harness-brainstorming) and implementation needs to be planned
8
+ - When starting a new feature or project that needs structured task decomposition
9
+ - When `on_new_feature` or `on_project_init` triggers fire and the work is non-trivial
10
+ - When resuming a stalled project that needs a fresh plan
11
+ - NOT when the task is small enough to implement directly (under 15 minutes, single file — just do it)
12
+ - NOT when you need to explore the problem space first (use harness-brainstorming)
13
+ - NOT when a plan already exists and needs execution (use harness-execution)
14
+
15
+ ## Process
16
+
17
+ ### Iron Law
18
+
19
+ **Every task in the plan must be completable in one context window (2-5 minutes). If a task is larger, split it.**
20
+
21
+ A plan with vague tasks like "add validation" or "implement the service" is not a plan — it is a wish list. Every task must contain exact file paths, exact commands, and complete code snippets.
22
+
23
+ ---
24
+
25
+ ### Phase 1: SCOPE — Derive Must-Haves from Goals
26
+
27
+ Work backward from the goal. Do not start with "what should we build?" Start with "what must be true when we are done?"
28
+
29
+ 1. **State the goal.** One sentence. What does the system do when this plan is complete?
30
+
31
+ 2. **Derive observable truths.** What can be observed (by running a command, opening a browser, reading a file) that proves the goal is met? These are your acceptance criteria. Be specific:
32
+ - BAD: "The API handles errors"
33
+ - GOOD: "GET /api/users/nonexistent returns 404 with `{ error: 'User not found' }` body"
34
+
35
+ 3. **Derive required artifacts.** For each observable truth, what files must exist? What functions must be implemented? What tests must pass? List exact file paths.
36
+
37
+ 4. **Identify key links.** How do the artifacts connect? What imports what? What calls what? What data flows where? Draw the dependency graph mentally.
38
+
39
+ 5. **Apply YAGNI.** For every artifact, ask: "Is this required for an observable truth?" If not, cut it.
40
+
41
+ When scope is ambiguous and requires clarification, use `emit_interaction`:
42
+
43
+ ```json
44
+ emit_interaction({
45
+ path: "<project-root>",
46
+ type: "question",
47
+ question: {
48
+ text: "The spec mentions X but does not define behavior for Y. Should we:",
49
+ options: ["A) Include Y in this plan", "B) Defer Y to a follow-up plan", "C) Update the spec first"]
50
+ }
51
+ })
52
+ ```
53
+
54
+ #### EARS Requirement Patterns
55
+
56
+ When writing observable truths and acceptance criteria, use EARS (Easy Approach to Requirements Syntax) sentence patterns. These patterns eliminate ambiguity by forcing a consistent grammatical structure.
57
+
58
+ | Pattern | Template | Use When |
59
+ | ---------------- | -------------------------------------------------------- | ------------------------------------------------- |
60
+ | **Ubiquitous** | The system shall [behavior]. | Behavior that always applies, unconditionally |
61
+ | **Event-driven** | When [trigger], the system shall [response]. | Behavior triggered by a specific event |
62
+ | **State-driven** | While [state], the system shall [behavior]. | Behavior that applies only during a certain state |
63
+ | **Optional** | Where [feature is enabled], the system shall [behavior]. | Behavior gated by a configuration or feature flag |
64
+ | **Unwanted** | If [condition], then the system shall not [behavior]. | Explicitly preventing undesirable behavior |
65
+
66
+ **Worked Examples:**
67
+
68
+ 1. **Ubiquitous:** "The system shall return JSON responses with `Content-Type: application/json` header."
69
+ 2. **Event-driven:** "When a user submits an invalid form, the system shall display field-level error messages within 200ms."
70
+ 3. **State-driven:** "While the database connection is unavailable, the system shall serve cached responses and log reconnection attempts."
71
+ 4. **Optional:** "Where rate limiting is enabled, the system shall reject requests exceeding 100/minute per API key with HTTP 429."
72
+ 5. **Unwanted:** "If the request body exceeds 10MB, then the system shall not attempt to parse it — return HTTP 413 immediately."
73
+
74
+ **When to use EARS:** Apply these patterns when writing observable truths in Phase 1. Not every criterion needs an EARS pattern — use them when the requirement is behavioral (not structural). File existence checks ("src/types/user.ts exists with User interface") do not need EARS framing.
75
+
76
+ ### Graph-Enhanced Context (when available)
77
+
78
+ When a knowledge graph exists at `.harness/graph/`, use graph queries for faster, more accurate context:
79
+
80
+ - `query_graph` — discover module dependencies for realistic task decomposition
81
+ - `get_impact` — estimate which modules a feature touches and their dependencies
82
+
83
+ Enables accurate effort estimation and task sequencing. Fall back to file-based commands if no graph is available.
84
+
85
+ ---
86
+
87
+ ### Phase 2: DECOMPOSE — Map File Structure and Create Tasks
88
+
89
+ When presenting the task breakdown, use progress markers:
90
+
91
+ ```
92
+ **[Phase 2/4]** DECOMPOSE — mapping file structure and creating tasks
93
+ ```
94
+
95
+ 1. **Map the file structure first.** Before writing any tasks, list every file that will be created or modified. This is where decomposition decisions are locked. Example:
96
+
97
+ ```
98
+ CREATE src/services/notification-service.ts
99
+ CREATE src/services/notification-service.test.ts
100
+ MODIFY src/services/index.ts (add export)
101
+ CREATE src/types/notification.ts
102
+ MODIFY src/api/routes/users.ts (add notification trigger)
103
+ ```
104
+
105
+ 2. **Decompose into atomic tasks.** Each task must:
106
+ - Be completable in 2-5 minutes
107
+ - Fit in a single context window
108
+ - Have a clear, testable outcome
109
+ - Follow TDD: write test, fail, implement, pass, commit
110
+ - Produce one atomic commit
111
+
112
+ 3. **Write complete instructions for each task.** Not summaries — complete executable instructions:
113
+ - **Exact file paths** to create or modify
114
+ - **Exact code** to write (not "add validation logic" — write the actual validation code)
115
+ - **Exact test commands** to run (e.g., `npx vitest run src/services/notification-service.test.ts`)
116
+ - **Exact commit message** to use
117
+ - **`harness validate`** as the final step
118
+
119
+ 4. **Include checkpoints.** Mark tasks that require human verification, decisions, or actions:
120
+ - `[checkpoint:human-verify]` — Pause, show result, wait for confirmation
121
+ - `[checkpoint:decision]` — Pause, present options, wait for choice
122
+ - `[checkpoint:human-action]` — Pause, instruct human on what they need to do
123
+
124
+ ---
125
+
126
+ ### Phase 3: SEQUENCE — Order Tasks and Identify Dependencies
127
+
128
+ 1. **Order by dependency.** Types before implementations. Implementations before integrations. Tests alongside their implementations (same task, TDD style).
129
+
130
+ 2. **Identify parallel opportunities.** Tasks that touch different subsystems with no shared state can be marked as parallelizable (for harness-parallel-agents).
131
+
132
+ 3. **Number tasks sequentially.** Use `Task 1`, `Task 2`, etc. Dependencies reference task numbers: "Depends on: Task 3."
133
+
134
+ 4. **Estimate total time.** Each task is 2-5 minutes. Sum them. If the total exceeds the available time, identify a milestone boundary where the plan can be paused with a working system.
135
+
136
+ ---
137
+
138
+ ### Phase 4: VALIDATE — Review and Finalize the Plan
139
+
140
+ 1. **Verify completeness.** Every observable truth from Phase 1 must be achievable by completing the tasks. Trace each truth to the specific task(s) that deliver it.
141
+
142
+ 2. **Verify task sizing.** Read each task. Could an agent complete it in one context window without needing to explore or make decisions? If not, split it.
143
+
144
+ 3. **Verify TDD compliance.** Every task that produces code must include a test step. No task should say "write tests later."
145
+
146
+ 4. **Run `harness validate`** to verify project health before writing the plan.
147
+
148
+ 5. **Check failures log.** Read `.harness/failures.md` before finalizing. If planned approaches match known failures, flag them with warnings.
149
+
150
+ 6. **Run soundness review.** After the plan passes completeness verification, invoke `harness-soundness-review --mode plan` against the draft. Do not proceed to write the plan until the soundness review converges with no remaining issues.
151
+
152
+ 7. **Write the plan to `docs/plans/`.** Use naming convention: `YYYY-MM-DD-<feature-name>-plan.md`. If the directory does not exist, create it.
153
+
154
+ 8. **Write handoff.** Save `.harness/handoff.json` with the following structure:
155
+
156
+ ```json
157
+ {
158
+ "fromSkill": "harness-planning",
159
+ "phase": "VALIDATE",
160
+ "summary": "<one-sentence description of what was planned>",
161
+ "completed": [],
162
+ "pending": ["<task 1>", "<task 2>", "..."],
163
+ "concerns": ["<any concerns or risks identified>"],
164
+ "decisions": ["<key decisions made during planning>"],
165
+ "contextKeywords": ["<domain-relevant keywords>"]
166
+ }
167
+ ```
168
+
169
+ 9. **Request plan sign-off:**
170
+
171
+ ```json
172
+ emit_interaction({
173
+ path: "<project-root>",
174
+ type: "confirmation",
175
+ confirmation: {
176
+ text: "Approve plan at <plan-file-path>?",
177
+ context: "<task count> tasks, <estimated time> minutes. <one-sentence summary>"
178
+ }
179
+ })
180
+ ```
181
+
182
+ 10. **Suggest transition to execution.** After the human approves the plan:
183
+
184
+ Call `emit_interaction`:
185
+
186
+ ```json
187
+ {
188
+ "type": "transition",
189
+ "transition": {
190
+ "completedPhase": "planning",
191
+ "suggestedNext": "execution",
192
+ "reason": "Plan approved with all tasks defined",
193
+ "artifacts": ["<plan file path>"],
194
+ "requiresConfirmation": true,
195
+ "summary": "<Plan title> -- <N> tasks, <N> checkpoints. Estimated <time>."
196
+ }
197
+ }
198
+ ```
199
+
200
+ If the user confirms: invoke harness-execution with the plan path.
201
+ If the user declines: stop. The handoff is already written for future invocation.
202
+
203
+ ---
204
+
205
+ ### Plan Document Structure
206
+
207
+ ````markdown
208
+ # Plan: <Feature Name>
209
+
210
+ **Date:** YYYY-MM-DD
211
+ **Spec:** docs/changes/<feature>/proposal.md (if applicable)
212
+ **Estimated tasks:** N
213
+ **Estimated time:** N minutes
214
+
215
+ ## Goal
216
+
217
+ One sentence.
218
+
219
+ ## Observable Truths (Acceptance Criteria)
220
+
221
+ 1. [observable truth]
222
+ 2. [observable truth]
223
+
224
+ ## File Map
225
+
226
+ - CREATE path/to/file.ts
227
+ - MODIFY path/to/other-file.ts
228
+
229
+ ## Tasks
230
+
231
+ ### Task 1: <descriptive name>
232
+
233
+ **Depends on:** none
234
+ **Files:** path/to/file.ts, path/to/file.test.ts
235
+
236
+ 1. Create test file `path/to/file.test.ts`:
237
+ ```typescript
238
+ // exact test code
239
+ ```
240
+ ````
241
+
242
+ 2. Run test: `npx vitest run path/to/file.test.ts`
243
+ 3. Observe failure: [expected failure message]
244
+ 4. Create implementation `path/to/file.ts`:
245
+ ```typescript
246
+ // exact implementation code
247
+ ```
248
+ 5. Run test: `npx vitest run path/to/file.test.ts`
249
+ 6. Observe: all tests pass
250
+ 7. Run: `harness validate`
251
+ 8. Commit: `feat(scope): descriptive message`
252
+
253
+ ### Task 2: <descriptive name>
254
+
255
+ [checkpoint:human-verify]
256
+ ...
257
+
258
+ ````
259
+
260
+ ## Harness Integration
261
+
262
+ - **`harness validate`** — Run during Phase 4 (before writing the plan) and included as a step in every task.
263
+ - **`harness check-deps`** — Referenced in tasks that add imports or create new modules. Ensures dependency boundaries are respected.
264
+ - **Plan location** — Plans go to `docs/plans/`. Follow the naming convention: `YYYY-MM-DD-<feature-name>-plan.md`.
265
+ - **Handoff to harness-execution** — Once the plan is approved, invoke harness-execution to begin task-by-task implementation.
266
+ - **Task commands** — Every task includes exact harness CLI commands to run (e.g., `harness validate`, `harness check-deps`).
267
+ - **`emit_interaction`** -- Call at the end of Phase 4 to suggest transitioning to harness-execution. Uses confirmed transition (waits for user approval).
268
+
269
+ ## Change Specifications
270
+
271
+ When planning changes to existing functionality (not greenfield), express requirements as deltas from the current documented behavior. Use these markers:
272
+
273
+ - **[ADDED]** — New behavior that does not exist today
274
+ - **[MODIFIED]** — Existing behavior that changes
275
+ - **[REMOVED]** — Existing behavior that goes away
276
+
277
+ **Example:**
278
+ ```markdown
279
+ ## Changes to User Authentication
280
+
281
+ - [ADDED] Support OAuth2 refresh tokens with 7-day expiry
282
+ - [MODIFIED] Login endpoint returns `refreshToken` field alongside existing `accessToken`
283
+ - [MODIFIED] Token validation middleware accepts both JWT and OAuth2 tokens
284
+ - [REMOVED] Legacy API key authentication (deprecated in v2.1)
285
+ ````
286
+
287
+ This is not mandatory for greenfield features. Only apply when modifying existing documented behavior.
288
+
289
+ When `docs/changes/` exists in the project, produce `docs/changes/<feature>/delta.md` alongside the task plan. This keeps the change intent separate from the full spec and makes review easier.
290
+
291
+ ## Success Criteria
292
+
293
+ - A plan document exists in `docs/plans/` with all required sections
294
+ - Every task is completable in 2-5 minutes (one context window)
295
+ - Every task includes exact file paths, exact code, and exact commands
296
+ - Every code-producing task follows TDD: test first, fail, implement, pass
297
+ - Observable truths trace to specific tasks that deliver them
298
+ - File map lists every file to be created or modified
299
+ - Checkpoints are marked where human input is required
300
+ - `harness validate` passes before the plan is written
301
+ - `harness validate` is included as a step in every task
302
+ - The human has reviewed and approved the plan
303
+
304
+ ## Examples
305
+
306
+ ### Example: Planning a User Notification Feature
307
+
308
+ **Goal:** Users receive email and in-app notifications when their account is modified.
309
+
310
+ **Observable Truths:**
311
+
312
+ 1. `POST /api/users/:id` with changed fields triggers a notification record in the database
313
+ 2. `GET /api/notifications?userId=:id` returns the notification with type, message, and timestamp
314
+ 3. Notification email is sent via the existing email utility (verified by mock in test)
315
+ 4. `npx vitest run src/services/notification-service.test.ts` passes with 8+ tests
316
+ 5. `harness validate` passes
317
+
318
+ **File Map:**
319
+
320
+ ```
321
+ CREATE src/types/notification.ts
322
+ CREATE src/services/notification-service.ts
323
+ CREATE src/services/notification-service.test.ts
324
+ MODIFY src/services/index.ts
325
+ MODIFY src/api/routes/users.ts
326
+ MODIFY src/api/routes/users.test.ts
327
+ ```
328
+
329
+ **Task 1: Define notification types**
330
+
331
+ ```
332
+ Files: src/types/notification.ts
333
+ 1. Create src/types/notification.ts:
334
+ export interface Notification {
335
+ id: string;
336
+ userId: string;
337
+ type: 'account_modified';
338
+ message: string;
339
+ read: boolean;
340
+ createdAt: Date;
341
+ expiresAt: Date;
342
+ }
343
+ 2. Run: harness validate
344
+ 3. Commit: "feat(notifications): define Notification type"
345
+ ```
346
+
347
+ **Task 2: Create notification service with create method (TDD)**
348
+
349
+ ```
350
+ Files: src/services/notification-service.ts, src/services/notification-service.test.ts
351
+ 1. Write test: create notification returns Notification object with correct fields
352
+ 2. Run test — observe: NotificationService is not defined
353
+ 3. Implement: NotificationService.create() stores and returns notification
354
+ 4. Run test — observe: pass
355
+ 5. Run: harness validate
356
+ 6. Commit: "feat(notifications): add NotificationService.create"
357
+ ```
358
+
359
+ **Task 3: Add list and expiry methods (TDD)**
360
+
361
+ ```
362
+ [checkpoint:human-verify] — verify Task 2 output before continuing
363
+ Files: src/services/notification-service.ts, src/services/notification-service.test.ts
364
+ 1. Write tests: list by userId, filter expired
365
+ 2. Run tests — observe failures
366
+ 3. Implement: list() and isExpired() methods
367
+ 4. Run tests — observe: pass
368
+ 5. Run: harness validate, harness check-deps
369
+ 6. Commit: "feat(notifications): add list and expiry to NotificationService"
370
+ ```
371
+
372
+ ## Gates
373
+
374
+ These are hard stops. Violating any gate means the process has broken down.
375
+
376
+ - **No vague tasks.** "Implement the service" is not a task. Every task must have exact file paths, exact code, and exact commands. If you cannot write the code in the plan, you do not understand the task well enough to plan it.
377
+ - **No tasks larger than one context window.** If a task requires exploring the codebase, making design decisions, or touching more than 3 files, it is too large. Split it.
378
+ - **No skipping TDD in tasks.** Every task that produces code must start with writing a test. "Add tests later" is not allowed in a plan. If tests cannot be written first, the design is unclear — go back to brainstorming.
379
+ - **No plan without observable truths.** The plan must start with goal-backward acceptance criteria. If you cannot state what is observable when the plan is complete, you do not understand the goal.
380
+ - **No implementation during planning.** The plan is a document, not code. Do not "just start Task 1 while we are here." Write the plan, get approval, then use harness-execution.
381
+ - **File map must be complete.** Every file that will be created or modified must appear in the file map. Discovering new files during execution means the plan was incomplete.
382
+
383
+ ## Escalation
384
+
385
+ - **When you cannot write exact code for a task:** The design is underspecified. Go back to the spec (or brainstorm if no spec exists). Do not write a vague task as a placeholder.
386
+ - **When task count exceeds 20:** The project may be too large for a single plan. Consider splitting into multiple plans with clear milestone boundaries.
387
+ - **When dependencies form a cycle:** The decomposition is wrong. Re-examine the file map and find a way to break the cycle (usually by extracting a shared type or interface).
388
+ - **When you discover the spec is missing information during planning:** Do not fill in the gaps yourself. Escalate: "The spec does not define behavior for [scenario]. This blocks Task N. We need to update the spec before continuing the plan."
389
+ - **When estimated time exceeds available time:** Identify a milestone boundary where the plan can be paused with a working system. Propose delivering the plan in phases, each phase producing a usable increment.
@@ -0,0 +1,49 @@
1
+ name: harness-planning
2
+ version: "1.0.0"
3
+ description: Structured project planning with harness constraints and validation
4
+ cognitive_mode: constructive-architect
5
+ triggers:
6
+ - manual
7
+ - on_new_feature
8
+ - on_project_init
9
+ platforms:
10
+ - claude-code
11
+ - gemini-cli
12
+ tools:
13
+ - Bash
14
+ - Read
15
+ - Write
16
+ - Edit
17
+ - Glob
18
+ - emit_interaction
19
+ cli:
20
+ command: harness skill run harness-planning
21
+ args:
22
+ - name: path
23
+ description: Project root path
24
+ required: false
25
+ mcp:
26
+ tool: run_skill
27
+ input:
28
+ skill: harness-planning
29
+ path: string
30
+ type: rigid
31
+ phases:
32
+ - name: scope
33
+ description: Define goals and constraints
34
+ required: true
35
+ - name: decompose
36
+ description: Break work into tasks
37
+ required: true
38
+ - name: sequence
39
+ description: Order tasks and identify dependencies
40
+ required: true
41
+ - name: validate
42
+ description: Run harness checks on the plan
43
+ required: true
44
+ state:
45
+ persistent: false
46
+ files: []
47
+ depends_on:
48
+ - harness-verification
49
+ - harness-soundness-review
@@ -0,0 +1,262 @@
1
+ # Harness Pre-Commit Review
2
+
3
+ > Lightweight pre-commit quality gate — mechanical checks first, AI review second. Fast feedback before code leaves your machine.
4
+
5
+ ## When to Use
6
+
7
+ - Before committing code (manual invocation or git pre-commit hook)
8
+ - As a quick sanity check before pushing to a branch
9
+ - When you want fast feedback without a full code review cycle
10
+ - NOT as a replacement for full peer review (use `harness-code-review` for that)
11
+ - NOT for commits that only update documentation or configuration (fast path skips AI review)
12
+
13
+ ## Principle: Deterministic First
14
+
15
+ This skill follows the Deterministic-vs-LLM Responsibility Split principle. Mechanical checks run first and must pass before any AI review occurs. If a linter or type checker can catch the problem, the LLM should not be the one finding it.
16
+
17
+ ## Process
18
+
19
+ ### Phase 1: Mechanical Checks
20
+
21
+ Run all deterministic checks against staged changes. These are binary pass/fail — no judgment required.
22
+
23
+ #### 1. Detect Available Check Commands
24
+
25
+ ```bash
26
+ # Check for project-specific commands
27
+ cat package.json 2>/dev/null | grep -E '"(lint|typecheck|test)"'
28
+ cat Makefile 2>/dev/null | grep -E '^(lint|typecheck|test):'
29
+ ```
30
+
31
+ #### 2. Run Checks in Order
32
+
33
+ Run whichever of these are available in the project:
34
+
35
+ ```bash
36
+ # Lint (fastest — run first)
37
+ pnpm lint 2>&1 || npm run lint 2>&1 || make lint 2>&1
38
+
39
+ # Type check
40
+ pnpm typecheck 2>&1 || npx tsc --noEmit 2>&1 || make typecheck 2>&1
41
+
42
+ # Tests (slowest — run last)
43
+ pnpm test 2>&1 || npm test 2>&1 || make test 2>&1
44
+ ```
45
+
46
+ #### 3. Gate Decision
47
+
48
+ - **Any check fails:** STOP. Report the failure. Do not proceed to AI review. The author must fix mechanical issues first.
49
+ - **All checks pass:** Proceed to Phase 2.
50
+
51
+ **Output format for failures:**
52
+
53
+ ```
54
+ Pre-Commit Check: FAIL
55
+
56
+ Mechanical Checks:
57
+ - Lint: FAIL — 3 errors (see output above)
58
+ - Types: PASS
59
+ - Tests: NOT RUN (blocked by lint failure)
60
+
61
+ Action: Fix lint errors before committing.
62
+ ```
63
+
64
+ ### Graph Freshness Check
65
+
66
+ If a knowledge graph exists at `.harness/graph/` and code files have changed since the last scan, run `harness scan` before proceeding. The AI review phase uses graph-enhanced MCP tools (impact analysis, harness checks) that return stale results with an outdated graph.
67
+
68
+ If no graph exists, skip this step — the tools fall back to non-graph behavior.
69
+
70
+ ### Phase 2: Classify Changes
71
+
72
+ Determine whether AI review is needed based on what changed.
73
+
74
+ ```bash
75
+ # Get list of staged files
76
+ git diff --cached --name-only
77
+
78
+ # Check if only docs/config files changed
79
+ git diff --cached --name-only | grep -v -E '\.(md|yml|yaml|json|toml|ini|cfg|conf|env|env\..*)$' | wc -l
80
+ ```
81
+
82
+ #### Fast Path: Skip AI Review
83
+
84
+ If ALL staged files match these patterns, skip AI review and approve:
85
+
86
+ - `*.md` (documentation)
87
+ - `*.yml`, `*.yaml` (configuration)
88
+ - `*.json` (configuration — unless in `src/`)
89
+ - `*.toml`, `*.ini`, `*.cfg` (configuration)
90
+ - `.env*` (environment — but warn about secrets)
91
+ - `LICENSE`, `CODEOWNERS`, `.gitignore`
92
+
93
+ **Output for fast path:**
94
+
95
+ ```
96
+ Pre-Commit Check: PASS (fast path)
97
+
98
+ Mechanical Checks:
99
+ - Lint: PASS
100
+ - Types: PASS
101
+ - Tests: PASS (12/12)
102
+
103
+ AI Review: SKIPPED (docs/config only)
104
+ ```
105
+
106
+ #### Standard Path: Proceed to AI Review
107
+
108
+ If any staged file contains code changes, proceed to Phase 3.
109
+
110
+ ### Phase 3: Security Scan
111
+
112
+ Run the built-in security scanner against staged files. This is a mechanical check — no AI judgment involved.
113
+
114
+ ```bash
115
+ # Get list of staged source files
116
+ git diff --cached --name-only --diff-filter=d | grep -E '\.(ts|tsx|js|jsx|go|py)$'
117
+ ```
118
+
119
+ Use the `run_security_scan` MCP tool or invoke the scanner on the staged files. Report any findings:
120
+
121
+ - **Error findings (blocking):** Hardcoded secrets, eval/injection, weak crypto — these block the commit just like lint failures.
122
+ - **Warning/info findings (advisory):** CORS wildcards, HTTP URLs, disabled TLS — reported but do not block.
123
+
124
+ Include security scan results in the report output:
125
+
126
+ ```
127
+ Security Scan: [PASS/WARN/FAIL] (N errors, N warnings)
128
+ ```
129
+
130
+ If no source files are staged, skip the security scan.
131
+
132
+ ### Phase 4: AI Review (Lightweight)
133
+
134
+ Perform a focused, lightweight review of staged changes. This is NOT a full code review — it catches obvious issues only.
135
+
136
+ #### 1. Get the Staged Diff
137
+
138
+ ```bash
139
+ git diff --cached
140
+ ```
141
+
142
+ #### 2. Quick Review Checklist
143
+
144
+ Review the staged diff for these high-signal issues only:
145
+
146
+ - **Obvious bugs:** null dereference, infinite loops, off-by-one errors, resource leaks
147
+ - **Security issues:** hardcoded secrets, SQL injection, path traversal, unvalidated input (complements the mechanical scan with semantic analysis — e.g., tracing user input across function boundaries)
148
+ - **Broken imports:** references to files/modules that do not exist
149
+ - **Debug artifacts:** console.log, debugger statements, TODO/FIXME without issue reference
150
+ - **Type mismatches:** function called with wrong argument types (if visible in diff)
151
+
152
+ Do NOT review for:
153
+
154
+ - Style (that is the linter's job)
155
+ - Architecture (that is the full review's job)
156
+ - Test completeness (that is the full review's job)
157
+ - Naming preferences (subjective and noisy at this stage)
158
+
159
+ #### 3. Report
160
+
161
+ **If no issues found:**
162
+
163
+ ```
164
+ Pre-Commit Check: PASS
165
+
166
+ Mechanical Checks:
167
+ - Lint: PASS
168
+ - Types: PASS
169
+ - Tests: PASS (12/12)
170
+ - Security Scan: PASS (0 errors, 0 warnings)
171
+
172
+ AI Review: PASS (no issues found)
173
+ ```
174
+
175
+ **If issues found:**
176
+
177
+ ```
178
+ Pre-Commit Check: WARN
179
+
180
+ Mechanical Checks:
181
+ - Lint: PASS
182
+ - Types: PASS
183
+ - Tests: PASS (12/12)
184
+ - Security Scan: WARN (0 errors, 1 warning)
185
+ - [SEC-NET-001] src/cors.ts:5 — CORS wildcard origin
186
+
187
+ AI Review: 2 observations
188
+ 1. [file:line] Possible null dereference — `user.email` accessed without null check after `findUser()` which can return null.
189
+ 2. [file:line] Debug artifact — `console.log('debug:', payload)` appears to be left from debugging.
190
+
191
+ Action: Review observations above. Commit anyway if intentional, or fix first.
192
+ ```
193
+
194
+ ## Git Hook Installation
195
+
196
+ To use as an automatic pre-commit hook, add to `.git/hooks/pre-commit` or configure via your git hooks manager (husky, lefthook, etc.):
197
+
198
+ ```bash
199
+ #!/bin/bash
200
+ # .git/hooks/pre-commit
201
+ harness skill run harness-pre-commit-review
202
+ exit_code=$?
203
+ if [ $exit_code -ne 0 ]; then
204
+ echo "Pre-commit review failed. Fix issues before committing."
205
+ exit 1
206
+ fi
207
+ ```
208
+
209
+ **Note:** AI review observations (WARN) do not block the commit — only mechanical check failures (FAIL) block. The author decides whether to address AI observations.
210
+
211
+ ## Gates
212
+
213
+ - **Mechanical checks must pass before AI review.** Do not run AI review if lint/typecheck/tests fail.
214
+ - **Fast path is mandatory.** If only docs/config changed, skip AI review — do not waste tokens.
215
+ - **AI review is advisory only.** Observations do not block the commit. Only mechanical failures block.
216
+
217
+ ## Harness Integration
218
+
219
+ - Follows Principle 7 (Deterministic-vs-LLM Split) — mechanical checks first, AI review second
220
+ - Reads `.harness/review-learnings.md` for calibration (if present)
221
+ - Complements harness-code-review (full review) — use pre-commit for quick checks, code-review for thorough analysis
222
+
223
+ ## Success Criteria
224
+
225
+ - [ ] Mechanical checks ran and produced clear pass/fail results
226
+ - [ ] Fast path correctly identified docs/config-only changes
227
+ - [ ] AI review focused on high-signal issues only (no style nits)
228
+ - [ ] Report follows the structured format exactly
229
+
230
+ ## Examples
231
+
232
+ ### Example: Clean Commit
233
+
234
+ ```
235
+ Pre-Commit Check: PASS
236
+
237
+ Mechanical Checks:
238
+ - Lint: PASS
239
+ - Types: PASS
240
+ - Tests: PASS (12/12)
241
+
242
+ AI Review: PASS (no issues found)
243
+ ```
244
+
245
+ ### Example: Docs-Only Fast Path
246
+
247
+ ```
248
+ Pre-Commit Check: PASS (fast path)
249
+
250
+ Mechanical Checks:
251
+ - Lint: PASS
252
+ - Types: PASS
253
+ - Tests: PASS (12/12)
254
+
255
+ AI Review: SKIPPED (docs/config only)
256
+ ```
257
+
258
+ ## Escalation
259
+
260
+ - **Mechanical checks fail:** Fix the issues. Do not bypass the hook.
261
+ - **AI review finds a potential issue you disagree with:** Commit anyway — AI review observations are advisory, not blocking. If the observation is consistently wrong, add it to `.harness/review-learnings.md` under Noise / False Positives.
262
+ - **Hook is too slow:** If the full test suite is slow, configure the project to run only affected tests in pre-commit. The full suite runs in CI.