@harness-engineering/cli 1.25.6 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/claude-code/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/codex/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/cursor/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/package.json +2 -2
- package/dist/{agents-md-2PYJM2MK.js → agents-md-OPOZA5L7.js} +3 -3
- package/dist/{architecture-VCLB7A23.js → architecture-PMVMO6SF.js} +4 -4
- package/dist/{assess-project-64C6LIKN.js → assess-project-ZW7EKNIT.js} +1 -1
- package/dist/bin/harness-mcp.js +15 -15
- package/dist/bin/harness.js +25 -25
- package/dist/{check-phase-gate-RT6PGEHY.js → check-phase-gate-NTLAU3LO.js} +4 -4
- package/dist/{chunk-JUXFYB2K.js → chunk-4KSKV5MK.js} +1 -1
- package/dist/{chunk-7BAGSY5Q.js → chunk-6SCA4NEZ.js} +1 -1
- package/dist/{chunk-42ZZLMYD.js → chunk-77EZGPSR.js} +1 -1
- package/dist/{chunk-CBZECDCW.js → chunk-7JNZXJKY.js} +5 -5
- package/dist/{chunk-43VBX44J.js → chunk-CAS3TS4Y.js} +110 -92
- package/dist/{chunk-FL6A72LV.js → chunk-EXTWTJRF.js} +1 -1
- package/dist/{chunk-XLO4AXXM.js → chunk-FI3D6D7U.js} +9 -9
- package/dist/{chunk-ZAKUCM7O.js → chunk-G6SYTGOH.js} +2 -2
- package/dist/{chunk-RKZW3FDF.js → chunk-HAOBHL3W.js} +1 -1
- package/dist/{chunk-4YEBV2FT.js → chunk-IFHAUFJX.js} +2 -2
- package/dist/{chunk-XMEEYMGE.js → chunk-J3O64D2A.js} +1 -1
- package/dist/{chunk-WEOGCL7B.js → chunk-JBJ4AVE4.js} +3 -3
- package/dist/{chunk-VELT5VAG.js → chunk-JWSVLC4I.js} +1 -1
- package/dist/{chunk-BUJOMC3O.js → chunk-JZ6GORAK.js} +38 -2
- package/dist/{chunk-JQCS75DY.js → chunk-KFE2X7LG.js} +4 -4
- package/dist/{chunk-U2OMWI7Z.js → chunk-KSFUJT5B.js} +1 -1
- package/dist/{chunk-Y5JA4J2M.js → chunk-KXIAHHHP.js} +2 -2
- package/dist/{chunk-R2BI5UPK.js → chunk-NIOB6FTG.js} +1 -1
- package/dist/{chunk-X2JJ3CPG.js → chunk-NVGQO4VM.js} +8 -8
- package/dist/{chunk-EY6F2QXW.js → chunk-QYSWNPXZ.js} +1 -1
- package/dist/{chunk-SZZ5UQL7.js → chunk-RNAGPTKF.js} +6 -6
- package/dist/{chunk-KJC4SE7C.js → chunk-UBRD5FH4.js} +9 -9
- package/dist/{chunk-RDQGCHKD.js → chunk-VV2PJT4K.js} +3358 -227
- package/dist/{chunk-SMY35HJM.js → chunk-Z2JORLRT.js} +1 -1
- package/dist/{chunk-R7P2FMJT.js → chunk-ZBQ3ZY75.js} +436 -284
- package/dist/{ci-workflow-SZL3KVUK.js → ci-workflow-H52EMCL6.js} +3 -3
- package/dist/{dist-GRW3X2ZQ.js → dist-PGQ32ZI7.js} +41 -1
- package/dist/{dist-T3DGV5UN.js → dist-TG63OKA5.js} +2 -2
- package/dist/{docs-WDLJORLK.js → docs-GP4VUSIB.js} +4 -4
- package/dist/{engine-2YWYRCKK.js → engine-KQG5RVXX.js} +3 -3
- package/dist/{entropy-PJGTOORX.js → entropy-RXESIYKC.js} +3 -3
- package/dist/{feedback-M5KCJKL2.js → feedback-HS7ZYXOU.js} +1 -1
- package/dist/{generate-agent-definitions-MFDW6LZT.js → generate-agent-definitions-I4B7CVOB.js} +4 -4
- package/dist/{graph-loader-QMKXT454.js → graph-loader-TIVI6NQ7.js} +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +25 -25
- package/dist/{loader-6O52FYHE.js → loader-CWAH6B4H.js} +3 -3
- package/dist/{mcp-GGNFWKVC.js → mcp-KHK5KYER.js} +15 -15
- package/dist/{performance-337U5URQ.js → performance-WDW5WS3J.js} +4 -4
- package/dist/{review-pipeline-DB5RD4SN.js → review-pipeline-QOZGWCTY.js} +3 -3
- package/dist/{runtime-B74EN2WD.js → runtime-SFEFRPLX.js} +3 -3
- package/dist/{scan-DXQUHGTT.js → scan-IJ7EYTF7.js} +1 -1
- package/dist/{security-3AYN6FVU.js → security-2K7UUK6T.js} +1 -1
- package/dist/{validate-35CD7VWN.js → validate-HXM6DXRZ.js} +4 -4
- package/dist/{validate-cross-check-LJKXBQYH.js → validate-cross-check-ULQLEOME.js} +3 -3
- package/package.json +9 -9
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Harness Knowledge Pipeline
|
|
2
|
+
|
|
3
|
+
> 4-phase knowledge extraction, reconciliation, drift detection, and remediation with convergence loop. Keeps the business knowledge graph current and identifies coverage gaps.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- When you want a full knowledge health check: extract signals, detect drift, find gaps
|
|
8
|
+
- After adding new code, connectors, or diagram files that contain business knowledge
|
|
9
|
+
- As a periodic hygiene check to ensure the knowledge graph reflects the codebase
|
|
10
|
+
- When `--drift-check` is needed in CI to gate on knowledge freshness
|
|
11
|
+
- NOT for manually authoring knowledge files (write to `docs/knowledge/` directly)
|
|
12
|
+
- NOT for ingesting a single source (use `ingest_source` MCP tool directly)
|
|
13
|
+
- NOT for graph queries or exploration (use `ask_graph` or `query_graph`)
|
|
14
|
+
|
|
15
|
+
## Process
|
|
16
|
+
|
|
17
|
+
1. **EXTRACT:** Run code signal extractors, diagram parsers, BusinessKnowledgeIngestor, and KnowledgeLinker against the project
|
|
18
|
+
2. **RECONCILE:** Build pre-extraction snapshot (current graph state) and post-extraction snapshot, then run StructuralDriftDetector
|
|
19
|
+
3. **DETECT:** Partition findings by classification (new/stale/drifted/contradicting), generate gap report
|
|
20
|
+
4. **REMEDIATE (only with `--fix`):** Apply safe remediations, convergence loop up to 5 iterations
|
|
21
|
+
|
|
22
|
+
## Iron Law
|
|
23
|
+
|
|
24
|
+
**Auto-remediate stale findings only. Prompt for drifted and contradicting.** Never auto-resolve a `contradicting` finding — the human must decide which source is authoritative.
|
|
25
|
+
|
|
26
|
+
## Flags
|
|
27
|
+
|
|
28
|
+
| Flag | Effect |
|
|
29
|
+
| ----------------- | ---------------------------------------------------------------- |
|
|
30
|
+
| `--fix` | Enable convergence-based auto-remediation (default: detect-only) |
|
|
31
|
+
| `--ci` | Non-interactive: apply safe fixes only, report everything else |
|
|
32
|
+
| `--domain <name>` | Limit pipeline to specific knowledge domain |
|
|
33
|
+
|
|
34
|
+
## Shared Context Object
|
|
35
|
+
|
|
36
|
+
All phases read from and write to a shared `KnowledgePipelineContext`:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface KnowledgePipelineContext {
|
|
40
|
+
extractionSnapshot: KnowledgeSnapshot;
|
|
41
|
+
currentSnapshot: KnowledgeSnapshot;
|
|
42
|
+
driftResult: DriftResult;
|
|
43
|
+
gapReport: GapReport;
|
|
44
|
+
remediationsApplied: string[];
|
|
45
|
+
iteration: number;
|
|
46
|
+
verdict: 'pass' | 'warn' | 'fail';
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Phase 1: EXTRACT
|
|
53
|
+
|
|
54
|
+
Extract business knowledge from all available sources into a fresh snapshot.
|
|
55
|
+
|
|
56
|
+
1. **Code Signal Extractors:** Run `ExtractionRunner` against the project directory.
|
|
57
|
+
- Test description extractor
|
|
58
|
+
- Enum/constant extractor
|
|
59
|
+
- Validation rule extractor
|
|
60
|
+
- API path extractor
|
|
61
|
+
- Output goes to `.harness/knowledge/extracted/`
|
|
62
|
+
|
|
63
|
+
2. **Diagram Parsers:** Run `DiagramParser.ingest()` for diagram-as-code files.
|
|
64
|
+
- Scans for `.mmd`, `.mermaid`, `.d2`, `.puml`, `.plantuml` files
|
|
65
|
+
- Extracts entities and relationships into `business_concept` nodes
|
|
66
|
+
|
|
67
|
+
3. **Connector Sync** (if configured): Trigger connector sync for Jira, Slack, Confluence.
|
|
68
|
+
- Only runs if connectors are configured in `harness.config.json`
|
|
69
|
+
- Skip silently if no connectors
|
|
70
|
+
|
|
71
|
+
4. **Build Fresh Snapshot:** Collect all extraction results into a `KnowledgeSnapshot`.
|
|
72
|
+
- Each entry has: `id`, `type`, `contentHash`, `source`, `name`
|
|
73
|
+
|
|
74
|
+
**Output:** `context.extractionSnapshot` populated.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Phase 2: RECONCILE
|
|
79
|
+
|
|
80
|
+
Compare the fresh extraction against the current graph state.
|
|
81
|
+
|
|
82
|
+
1. **Build Current Snapshot:** Read all `business_*` nodes from GraphStore.
|
|
83
|
+
- Map each node to a `KnowledgeSnapshotEntry`
|
|
84
|
+
- Use node ID as entry ID, compute contentHash from node content
|
|
85
|
+
|
|
86
|
+
2. **Run Drift Detection:** Call `StructuralDriftDetector.detect(current, fresh)`.
|
|
87
|
+
- Produces `DriftResult` with findings classified as `new`, `drifted`, `stale`, `contradicting`
|
|
88
|
+
- Produces `driftScore` (0.0 - 1.0)
|
|
89
|
+
|
|
90
|
+
**Output:** `context.currentSnapshot` and `context.driftResult` populated.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Phase 3: DETECT
|
|
95
|
+
|
|
96
|
+
Partition drift findings and classify safety.
|
|
97
|
+
|
|
98
|
+
1. **Partition by classification:**
|
|
99
|
+
|
|
100
|
+
| Classification | Severity | Safety | Action |
|
|
101
|
+
| --------------- | -------- | ------------- | ------------------------- |
|
|
102
|
+
| `new` | low | safe | Stage automatically |
|
|
103
|
+
| `stale` | high | probably-safe | Auto-remove (source gone) |
|
|
104
|
+
| `drifted` | medium | probably-safe | Prompt for confirmation |
|
|
105
|
+
| `contradicting` | critical | unsafe | Never auto-resolve |
|
|
106
|
+
|
|
107
|
+
2. **Generate Drift Report:** Present findings grouped by classification:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
KNOWLEDGE PIPELINE -- Drift Detection
|
|
111
|
+
|
|
112
|
+
Drift Score: 0.23 (12 findings / 52 entries)
|
|
113
|
+
|
|
114
|
+
NEW (4 findings, safe):
|
|
115
|
+
- business_rule:payments:refund-window [extractor]
|
|
116
|
+
- business_concept:auth:session-timeout [diagram]
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
STALE (3 findings, probably-safe):
|
|
120
|
+
- business_fact:billing:old-rate-limit [extractor] — source file deleted
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
DRIFTED (4 findings, requires confirmation):
|
|
124
|
+
- business_rule:checkout:tax-calculation [extractor] — content changed
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
CONTRADICTING (1 finding, requires human decision):
|
|
128
|
+
- business_term:Settlement SLA — extractor says 24h, linker says 48h
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
3. **Generate Gap Report:** Run `KnowledgeStagingAggregator.generateGapReport()`.
|
|
132
|
+
- Lists domains with entry counts
|
|
133
|
+
- Write to `.harness/knowledge/gaps.md`
|
|
134
|
+
|
|
135
|
+
**Output:** Drift report and gap report written. `context.gapReport` populated.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Phase 4: REMEDIATE (only with `--fix`)
|
|
140
|
+
|
|
141
|
+
Apply safe fixes and converge.
|
|
142
|
+
|
|
143
|
+
1. **Stage `new` findings:** Write to `.harness/knowledge/staged/pipeline-staged.jsonl` via `KnowledgeStagingAggregator`.
|
|
144
|
+
|
|
145
|
+
2. **Auto-remove `stale` findings:** Remove nodes from graph where source file no longer exists.
|
|
146
|
+
- Log each removal
|
|
147
|
+
|
|
148
|
+
3. **Present `drifted` findings:** Ask the human to confirm each update.
|
|
149
|
+
- In `--ci` mode: skip, report as unresolved
|
|
150
|
+
- If confirmed: update the graph node with fresh content
|
|
151
|
+
|
|
152
|
+
4. **Surface `contradicting` findings:** Never auto-resolve.
|
|
153
|
+
- Present both sources and ask the human which is authoritative
|
|
154
|
+
- In `--ci` mode: report as unresolved
|
|
155
|
+
|
|
156
|
+
5. **Convergence Check:** After remediation:
|
|
157
|
+
- Re-run EXTRACT + RECONCILE + DETECT
|
|
158
|
+
- Count remaining findings
|
|
159
|
+
- If `newCount >= previousCount`: STOP (converged or no progress)
|
|
160
|
+
- If `newCount < previousCount`: continue (max 5 iterations)
|
|
161
|
+
|
|
162
|
+
### Convergence Loop
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
maxIterations = 5
|
|
166
|
+
previousCount = findings.length
|
|
167
|
+
|
|
168
|
+
while iteration < maxIterations:
|
|
169
|
+
1. Apply safe remediations (new → stage, stale → remove)
|
|
170
|
+
2. Present probably-safe remediations (skip in --ci)
|
|
171
|
+
3. Log unsafe findings (never auto-apply)
|
|
172
|
+
4. Re-run EXTRACT + RECONCILE + DETECT
|
|
173
|
+
5. newCount = remaining findings
|
|
174
|
+
6. if newCount >= previousCount: STOP (converged)
|
|
175
|
+
7. previousCount = newCount; iteration++
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Verdict Rules
|
|
181
|
+
|
|
182
|
+
After all phases complete, compute verdict:
|
|
183
|
+
|
|
184
|
+
| Verdict | Condition |
|
|
185
|
+
| ------- | ------------------------------------------------- |
|
|
186
|
+
| `pass` | Zero unresolved findings after pipeline |
|
|
187
|
+
| `warn` | Only `new` findings remain (low severity) |
|
|
188
|
+
| `fail` | Any `contradicting`, `stale`, or `drifted` remain |
|
|
189
|
+
|
|
190
|
+
Present verdict summary:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
KNOWLEDGE PIPELINE -- Verdict: WARN
|
|
194
|
+
|
|
195
|
+
Findings: 2 new (staged), 0 stale, 0 drifted, 0 contradicting
|
|
196
|
+
Gap Report: 3 domains, 12 total entries
|
|
197
|
+
Drift Score: 0.04
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Harness Integration
|
|
201
|
+
|
|
202
|
+
- **`ingest_source`** -- MCP tool for ingesting diagram sources (`source: 'diagrams'`)
|
|
203
|
+
- **`ExtractionRunner`** -- Code signal extraction from `@harness-engineering/graph`
|
|
204
|
+
- **`DiagramParser`** -- Diagram-as-code parsing from `@harness-engineering/graph`
|
|
205
|
+
- **`StructuralDriftDetector`** -- Drift detection from `@harness-engineering/graph`
|
|
206
|
+
- **`KnowledgeStagingAggregator`** -- Staging and gap reporting from `@harness-engineering/graph`
|
|
207
|
+
- **`harness validate`** -- Run after remediation to verify project health
|
|
208
|
+
|
|
209
|
+
## Success Criteria
|
|
210
|
+
|
|
211
|
+
1. All 4 phases execute in sequence (EXTRACT, RECONCILE, DETECT, REMEDIATE)
|
|
212
|
+
2. Drift detection correctly classifies findings into 4 categories
|
|
213
|
+
3. Auto-remediation only applies to safe/probably-safe findings
|
|
214
|
+
4. Contradicting findings are never auto-resolved
|
|
215
|
+
5. Convergence loop terminates when finding count stops decreasing (max 5 iterations)
|
|
216
|
+
6. Gap report lists domains with entry counts
|
|
217
|
+
7. Verdict accurately reflects remaining finding state
|
|
218
|
+
8. `--ci` mode is fully non-interactive
|
|
219
|
+
|
|
220
|
+
## Examples
|
|
221
|
+
|
|
222
|
+
### Example: Running detect-only pipeline
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
$ harness knowledge-pipeline
|
|
226
|
+
|
|
227
|
+
KNOWLEDGE PIPELINE -- Verdict: WARN
|
|
228
|
+
|
|
229
|
+
Drift Score: 0.12
|
|
230
|
+
Findings: 3 new, 0 stale, 0 drifted, 0 contradicting
|
|
231
|
+
Extraction: 12 code signals, 5 diagrams, 2 linker facts, 4 business knowledge
|
|
232
|
+
Gaps: 2 domains, 16 total entries
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Example: Running with fix mode
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
$ harness knowledge-pipeline --fix
|
|
239
|
+
|
|
240
|
+
KNOWLEDGE PIPELINE -- Verdict: PASS
|
|
241
|
+
|
|
242
|
+
Drift Score: 0.00
|
|
243
|
+
Findings: 0 new, 0 stale, 0 drifted, 0 contradicting
|
|
244
|
+
Extraction: 12 code signals, 5 diagrams, 2 linker facts, 4 business knowledge
|
|
245
|
+
Gaps: 2 domains, 19 total entries
|
|
246
|
+
Convergence: 2 iterations
|
|
247
|
+
Remediations: 3 applied
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Example: CI gate mode
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
$ harness knowledge-pipeline --ci --drift-check
|
|
254
|
+
# Exits 1 if unresolved drift exists
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Rationalizations to Reject
|
|
258
|
+
|
|
259
|
+
| Rationalization | Reality |
|
|
260
|
+
| ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
261
|
+
| "The contradicting findings have an obvious resolution, so I can auto-fix them" | The Iron Law: contradicting findings require human decision. Different sources may have different authority levels that only the human understands. |
|
|
262
|
+
| "Drift score is low (0.05), so I can skip the DETECT phase and go straight to PASS" | Every finding must be classified regardless of drift score. A low score with one critical contradiction is still a FAIL. |
|
|
263
|
+
| "The stale entries might come back if the source is restored, so I should keep them" | Stale means the source is gone now. If it comes back, the next extraction will find it as NEW. Keeping stale entries pollutes the graph. |
|
|
264
|
+
| "I can run the convergence loop more than 5 times to get to zero findings" | The 5-iteration cap is a safety bound. If findings aren't decreasing, more iterations won't help — the remaining issues need human intervention. |
|
|
265
|
+
|
|
266
|
+
## Gates
|
|
267
|
+
|
|
268
|
+
- **No auto-resolution of contradicting findings.** EVER. Present both sources, ask the human.
|
|
269
|
+
- **No skipping DETECT.** Even in `--fix` mode, DETECT must run before REMEDIATE.
|
|
270
|
+
- **No convergence beyond 5 iterations.** If findings aren't decreasing, stop and report.
|
|
271
|
+
- **No REMEDIATE without `--fix`.** Default mode is detect-and-report only.
|
|
272
|
+
|
|
273
|
+
## Escalation
|
|
274
|
+
|
|
275
|
+
- **When no graph is available:** Run extractors and diagram parsers only. Skip reconciliation (no current snapshot). Report extraction results as gap analysis.
|
|
276
|
+
- **When connectors fail:** Log the error, continue with available sources. Note which connectors were skipped in the report.
|
|
277
|
+
- **When convergence stalls at iteration 1:** All remaining findings require human intervention. Present them and stop.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: harness-knowledge-pipeline
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: 4-phase knowledge extraction, reconciliation, drift detection, and remediation with convergence loop
|
|
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
|
+
- Edit
|
|
18
|
+
- Glob
|
|
19
|
+
- Grep
|
|
20
|
+
cli:
|
|
21
|
+
command: harness skill run harness-knowledge-pipeline
|
|
22
|
+
args:
|
|
23
|
+
- name: path
|
|
24
|
+
description: Project root path
|
|
25
|
+
required: false
|
|
26
|
+
- name: fix
|
|
27
|
+
description: Enable auto-remediation of safe findings (default detect-only)
|
|
28
|
+
required: false
|
|
29
|
+
- name: ci
|
|
30
|
+
description: Non-interactive mode, skip probably-safe fixes
|
|
31
|
+
required: false
|
|
32
|
+
- name: domain
|
|
33
|
+
description: Limit pipeline to specific knowledge domain
|
|
34
|
+
required: false
|
|
35
|
+
mcp:
|
|
36
|
+
tool: run_skill
|
|
37
|
+
input:
|
|
38
|
+
skill: harness-knowledge-pipeline
|
|
39
|
+
path: string
|
|
40
|
+
type: rigid
|
|
41
|
+
tier: 2
|
|
42
|
+
phases:
|
|
43
|
+
- name: extract
|
|
44
|
+
description: Run code signal extractors, diagram parsers, and connector sync
|
|
45
|
+
required: true
|
|
46
|
+
- name: reconcile
|
|
47
|
+
description: Build snapshots and run structural drift detection
|
|
48
|
+
required: true
|
|
49
|
+
- name: detect
|
|
50
|
+
description: Partition findings by severity and safety classification
|
|
51
|
+
required: true
|
|
52
|
+
- name: remediate
|
|
53
|
+
description: Apply safe fixes, prompt for unsafe, convergence loop
|
|
54
|
+
required: false
|
|
55
|
+
state:
|
|
56
|
+
persistent: false
|
|
57
|
+
files:
|
|
58
|
+
- .harness/knowledge/staged/pipeline-staged.jsonl
|
|
59
|
+
- .harness/knowledge/gaps.md
|
|
60
|
+
depends_on: []
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Harness Knowledge Pipeline
|
|
2
|
+
|
|
3
|
+
> 4-phase knowledge extraction, reconciliation, drift detection, and remediation with convergence loop. Keeps the business knowledge graph current and identifies coverage gaps.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- When you want a full knowledge health check: extract signals, detect drift, find gaps
|
|
8
|
+
- After adding new code, connectors, or diagram files that contain business knowledge
|
|
9
|
+
- As a periodic hygiene check to ensure the knowledge graph reflects the codebase
|
|
10
|
+
- When `--drift-check` is needed in CI to gate on knowledge freshness
|
|
11
|
+
- NOT for manually authoring knowledge files (write to `docs/knowledge/` directly)
|
|
12
|
+
- NOT for ingesting a single source (use `ingest_source` MCP tool directly)
|
|
13
|
+
- NOT for graph queries or exploration (use `ask_graph` or `query_graph`)
|
|
14
|
+
|
|
15
|
+
## Process
|
|
16
|
+
|
|
17
|
+
1. **EXTRACT:** Run code signal extractors, diagram parsers, BusinessKnowledgeIngestor, and KnowledgeLinker against the project
|
|
18
|
+
2. **RECONCILE:** Build pre-extraction snapshot (current graph state) and post-extraction snapshot, then run StructuralDriftDetector
|
|
19
|
+
3. **DETECT:** Partition findings by classification (new/stale/drifted/contradicting), generate gap report
|
|
20
|
+
4. **REMEDIATE (only with `--fix`):** Apply safe remediations, convergence loop up to 5 iterations
|
|
21
|
+
|
|
22
|
+
## Iron Law
|
|
23
|
+
|
|
24
|
+
**Auto-remediate stale findings only. Prompt for drifted and contradicting.** Never auto-resolve a `contradicting` finding — the human must decide which source is authoritative.
|
|
25
|
+
|
|
26
|
+
## Flags
|
|
27
|
+
|
|
28
|
+
| Flag | Effect |
|
|
29
|
+
| ----------------- | ---------------------------------------------------------------- |
|
|
30
|
+
| `--fix` | Enable convergence-based auto-remediation (default: detect-only) |
|
|
31
|
+
| `--ci` | Non-interactive: apply safe fixes only, report everything else |
|
|
32
|
+
| `--domain <name>` | Limit pipeline to specific knowledge domain |
|
|
33
|
+
|
|
34
|
+
## Shared Context Object
|
|
35
|
+
|
|
36
|
+
All phases read from and write to a shared `KnowledgePipelineContext`:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface KnowledgePipelineContext {
|
|
40
|
+
extractionSnapshot: KnowledgeSnapshot;
|
|
41
|
+
currentSnapshot: KnowledgeSnapshot;
|
|
42
|
+
driftResult: DriftResult;
|
|
43
|
+
gapReport: GapReport;
|
|
44
|
+
remediationsApplied: string[];
|
|
45
|
+
iteration: number;
|
|
46
|
+
verdict: 'pass' | 'warn' | 'fail';
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Phase 1: EXTRACT
|
|
53
|
+
|
|
54
|
+
Extract business knowledge from all available sources into a fresh snapshot.
|
|
55
|
+
|
|
56
|
+
1. **Code Signal Extractors:** Run `ExtractionRunner` against the project directory.
|
|
57
|
+
- Test description extractor
|
|
58
|
+
- Enum/constant extractor
|
|
59
|
+
- Validation rule extractor
|
|
60
|
+
- API path extractor
|
|
61
|
+
- Output goes to `.harness/knowledge/extracted/`
|
|
62
|
+
|
|
63
|
+
2. **Diagram Parsers:** Run `DiagramParser.ingest()` for diagram-as-code files.
|
|
64
|
+
- Scans for `.mmd`, `.mermaid`, `.d2`, `.puml`, `.plantuml` files
|
|
65
|
+
- Extracts entities and relationships into `business_concept` nodes
|
|
66
|
+
|
|
67
|
+
3. **Connector Sync** (if configured): Trigger connector sync for Jira, Slack, Confluence.
|
|
68
|
+
- Only runs if connectors are configured in `harness.config.json`
|
|
69
|
+
- Skip silently if no connectors
|
|
70
|
+
|
|
71
|
+
4. **Build Fresh Snapshot:** Collect all extraction results into a `KnowledgeSnapshot`.
|
|
72
|
+
- Each entry has: `id`, `type`, `contentHash`, `source`, `name`
|
|
73
|
+
|
|
74
|
+
**Output:** `context.extractionSnapshot` populated.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Phase 2: RECONCILE
|
|
79
|
+
|
|
80
|
+
Compare the fresh extraction against the current graph state.
|
|
81
|
+
|
|
82
|
+
1. **Build Current Snapshot:** Read all `business_*` nodes from GraphStore.
|
|
83
|
+
- Map each node to a `KnowledgeSnapshotEntry`
|
|
84
|
+
- Use node ID as entry ID, compute contentHash from node content
|
|
85
|
+
|
|
86
|
+
2. **Run Drift Detection:** Call `StructuralDriftDetector.detect(current, fresh)`.
|
|
87
|
+
- Produces `DriftResult` with findings classified as `new`, `drifted`, `stale`, `contradicting`
|
|
88
|
+
- Produces `driftScore` (0.0 - 1.0)
|
|
89
|
+
|
|
90
|
+
**Output:** `context.currentSnapshot` and `context.driftResult` populated.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Phase 3: DETECT
|
|
95
|
+
|
|
96
|
+
Partition drift findings and classify safety.
|
|
97
|
+
|
|
98
|
+
1. **Partition by classification:**
|
|
99
|
+
|
|
100
|
+
| Classification | Severity | Safety | Action |
|
|
101
|
+
| --------------- | -------- | ------------- | ------------------------- |
|
|
102
|
+
| `new` | low | safe | Stage automatically |
|
|
103
|
+
| `stale` | high | probably-safe | Auto-remove (source gone) |
|
|
104
|
+
| `drifted` | medium | probably-safe | Prompt for confirmation |
|
|
105
|
+
| `contradicting` | critical | unsafe | Never auto-resolve |
|
|
106
|
+
|
|
107
|
+
2. **Generate Drift Report:** Present findings grouped by classification:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
KNOWLEDGE PIPELINE -- Drift Detection
|
|
111
|
+
|
|
112
|
+
Drift Score: 0.23 (12 findings / 52 entries)
|
|
113
|
+
|
|
114
|
+
NEW (4 findings, safe):
|
|
115
|
+
- business_rule:payments:refund-window [extractor]
|
|
116
|
+
- business_concept:auth:session-timeout [diagram]
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
STALE (3 findings, probably-safe):
|
|
120
|
+
- business_fact:billing:old-rate-limit [extractor] — source file deleted
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
DRIFTED (4 findings, requires confirmation):
|
|
124
|
+
- business_rule:checkout:tax-calculation [extractor] — content changed
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
CONTRADICTING (1 finding, requires human decision):
|
|
128
|
+
- business_term:Settlement SLA — extractor says 24h, linker says 48h
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
3. **Generate Gap Report:** Run `KnowledgeStagingAggregator.generateGapReport()`.
|
|
132
|
+
- Lists domains with entry counts
|
|
133
|
+
- Write to `.harness/knowledge/gaps.md`
|
|
134
|
+
|
|
135
|
+
**Output:** Drift report and gap report written. `context.gapReport` populated.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Phase 4: REMEDIATE (only with `--fix`)
|
|
140
|
+
|
|
141
|
+
Apply safe fixes and converge.
|
|
142
|
+
|
|
143
|
+
1. **Stage `new` findings:** Write to `.harness/knowledge/staged/pipeline-staged.jsonl` via `KnowledgeStagingAggregator`.
|
|
144
|
+
|
|
145
|
+
2. **Auto-remove `stale` findings:** Remove nodes from graph where source file no longer exists.
|
|
146
|
+
- Log each removal
|
|
147
|
+
|
|
148
|
+
3. **Present `drifted` findings:** Ask the human to confirm each update.
|
|
149
|
+
- In `--ci` mode: skip, report as unresolved
|
|
150
|
+
- If confirmed: update the graph node with fresh content
|
|
151
|
+
|
|
152
|
+
4. **Surface `contradicting` findings:** Never auto-resolve.
|
|
153
|
+
- Present both sources and ask the human which is authoritative
|
|
154
|
+
- In `--ci` mode: report as unresolved
|
|
155
|
+
|
|
156
|
+
5. **Convergence Check:** After remediation:
|
|
157
|
+
- Re-run EXTRACT + RECONCILE + DETECT
|
|
158
|
+
- Count remaining findings
|
|
159
|
+
- If `newCount >= previousCount`: STOP (converged or no progress)
|
|
160
|
+
- If `newCount < previousCount`: continue (max 5 iterations)
|
|
161
|
+
|
|
162
|
+
### Convergence Loop
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
maxIterations = 5
|
|
166
|
+
previousCount = findings.length
|
|
167
|
+
|
|
168
|
+
while iteration < maxIterations:
|
|
169
|
+
1. Apply safe remediations (new → stage, stale → remove)
|
|
170
|
+
2. Present probably-safe remediations (skip in --ci)
|
|
171
|
+
3. Log unsafe findings (never auto-apply)
|
|
172
|
+
4. Re-run EXTRACT + RECONCILE + DETECT
|
|
173
|
+
5. newCount = remaining findings
|
|
174
|
+
6. if newCount >= previousCount: STOP (converged)
|
|
175
|
+
7. previousCount = newCount; iteration++
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Verdict Rules
|
|
181
|
+
|
|
182
|
+
After all phases complete, compute verdict:
|
|
183
|
+
|
|
184
|
+
| Verdict | Condition |
|
|
185
|
+
| ------- | ------------------------------------------------- |
|
|
186
|
+
| `pass` | Zero unresolved findings after pipeline |
|
|
187
|
+
| `warn` | Only `new` findings remain (low severity) |
|
|
188
|
+
| `fail` | Any `contradicting`, `stale`, or `drifted` remain |
|
|
189
|
+
|
|
190
|
+
Present verdict summary:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
KNOWLEDGE PIPELINE -- Verdict: WARN
|
|
194
|
+
|
|
195
|
+
Findings: 2 new (staged), 0 stale, 0 drifted, 0 contradicting
|
|
196
|
+
Gap Report: 3 domains, 12 total entries
|
|
197
|
+
Drift Score: 0.04
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Harness Integration
|
|
201
|
+
|
|
202
|
+
- **`ingest_source`** -- MCP tool for ingesting diagram sources (`source: 'diagrams'`)
|
|
203
|
+
- **`ExtractionRunner`** -- Code signal extraction from `@harness-engineering/graph`
|
|
204
|
+
- **`DiagramParser`** -- Diagram-as-code parsing from `@harness-engineering/graph`
|
|
205
|
+
- **`StructuralDriftDetector`** -- Drift detection from `@harness-engineering/graph`
|
|
206
|
+
- **`KnowledgeStagingAggregator`** -- Staging and gap reporting from `@harness-engineering/graph`
|
|
207
|
+
- **`harness validate`** -- Run after remediation to verify project health
|
|
208
|
+
|
|
209
|
+
## Success Criteria
|
|
210
|
+
|
|
211
|
+
1. All 4 phases execute in sequence (EXTRACT, RECONCILE, DETECT, REMEDIATE)
|
|
212
|
+
2. Drift detection correctly classifies findings into 4 categories
|
|
213
|
+
3. Auto-remediation only applies to safe/probably-safe findings
|
|
214
|
+
4. Contradicting findings are never auto-resolved
|
|
215
|
+
5. Convergence loop terminates when finding count stops decreasing (max 5 iterations)
|
|
216
|
+
6. Gap report lists domains with entry counts
|
|
217
|
+
7. Verdict accurately reflects remaining finding state
|
|
218
|
+
8. `--ci` mode is fully non-interactive
|
|
219
|
+
|
|
220
|
+
## Examples
|
|
221
|
+
|
|
222
|
+
### Example: Running detect-only pipeline
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
$ harness knowledge-pipeline
|
|
226
|
+
|
|
227
|
+
KNOWLEDGE PIPELINE -- Verdict: WARN
|
|
228
|
+
|
|
229
|
+
Drift Score: 0.12
|
|
230
|
+
Findings: 3 new, 0 stale, 0 drifted, 0 contradicting
|
|
231
|
+
Extraction: 12 code signals, 5 diagrams, 2 linker facts, 4 business knowledge
|
|
232
|
+
Gaps: 2 domains, 16 total entries
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Example: Running with fix mode
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
$ harness knowledge-pipeline --fix
|
|
239
|
+
|
|
240
|
+
KNOWLEDGE PIPELINE -- Verdict: PASS
|
|
241
|
+
|
|
242
|
+
Drift Score: 0.00
|
|
243
|
+
Findings: 0 new, 0 stale, 0 drifted, 0 contradicting
|
|
244
|
+
Extraction: 12 code signals, 5 diagrams, 2 linker facts, 4 business knowledge
|
|
245
|
+
Gaps: 2 domains, 19 total entries
|
|
246
|
+
Convergence: 2 iterations
|
|
247
|
+
Remediations: 3 applied
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Example: CI gate mode
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
$ harness knowledge-pipeline --ci --drift-check
|
|
254
|
+
# Exits 1 if unresolved drift exists
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Rationalizations to Reject
|
|
258
|
+
|
|
259
|
+
| Rationalization | Reality |
|
|
260
|
+
| ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
261
|
+
| "The contradicting findings have an obvious resolution, so I can auto-fix them" | The Iron Law: contradicting findings require human decision. Different sources may have different authority levels that only the human understands. |
|
|
262
|
+
| "Drift score is low (0.05), so I can skip the DETECT phase and go straight to PASS" | Every finding must be classified regardless of drift score. A low score with one critical contradiction is still a FAIL. |
|
|
263
|
+
| "The stale entries might come back if the source is restored, so I should keep them" | Stale means the source is gone now. If it comes back, the next extraction will find it as NEW. Keeping stale entries pollutes the graph. |
|
|
264
|
+
| "I can run the convergence loop more than 5 times to get to zero findings" | The 5-iteration cap is a safety bound. If findings aren't decreasing, more iterations won't help — the remaining issues need human intervention. |
|
|
265
|
+
|
|
266
|
+
## Gates
|
|
267
|
+
|
|
268
|
+
- **No auto-resolution of contradicting findings.** EVER. Present both sources, ask the human.
|
|
269
|
+
- **No skipping DETECT.** Even in `--fix` mode, DETECT must run before REMEDIATE.
|
|
270
|
+
- **No convergence beyond 5 iterations.** If findings aren't decreasing, stop and report.
|
|
271
|
+
- **No REMEDIATE without `--fix`.** Default mode is detect-and-report only.
|
|
272
|
+
|
|
273
|
+
## Escalation
|
|
274
|
+
|
|
275
|
+
- **When no graph is available:** Run extractors and diagram parsers only. Skip reconciliation (no current snapshot). Report extraction results as gap analysis.
|
|
276
|
+
- **When connectors fail:** Log the error, continue with available sources. Note which connectors were skipped in the report.
|
|
277
|
+
- **When convergence stalls at iteration 1:** All remaining findings require human intervention. Present them and stop.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: harness-knowledge-pipeline
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: 4-phase knowledge extraction, reconciliation, drift detection, and remediation with convergence loop
|
|
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
|
+
- Edit
|
|
18
|
+
- Glob
|
|
19
|
+
- Grep
|
|
20
|
+
cli:
|
|
21
|
+
command: harness skill run harness-knowledge-pipeline
|
|
22
|
+
args:
|
|
23
|
+
- name: path
|
|
24
|
+
description: Project root path
|
|
25
|
+
required: false
|
|
26
|
+
- name: fix
|
|
27
|
+
description: Enable auto-remediation of safe findings (default detect-only)
|
|
28
|
+
required: false
|
|
29
|
+
- name: ci
|
|
30
|
+
description: Non-interactive mode, skip probably-safe fixes
|
|
31
|
+
required: false
|
|
32
|
+
- name: domain
|
|
33
|
+
description: Limit pipeline to specific knowledge domain
|
|
34
|
+
required: false
|
|
35
|
+
mcp:
|
|
36
|
+
tool: run_skill
|
|
37
|
+
input:
|
|
38
|
+
skill: harness-knowledge-pipeline
|
|
39
|
+
path: string
|
|
40
|
+
type: rigid
|
|
41
|
+
tier: 2
|
|
42
|
+
phases:
|
|
43
|
+
- name: extract
|
|
44
|
+
description: Run code signal extractors, diagram parsers, and connector sync
|
|
45
|
+
required: true
|
|
46
|
+
- name: reconcile
|
|
47
|
+
description: Build snapshots and run structural drift detection
|
|
48
|
+
required: true
|
|
49
|
+
- name: detect
|
|
50
|
+
description: Partition findings by severity and safety classification
|
|
51
|
+
required: true
|
|
52
|
+
- name: remediate
|
|
53
|
+
description: Apply safe fixes, prompt for unsafe, convergence loop
|
|
54
|
+
required: false
|
|
55
|
+
state:
|
|
56
|
+
persistent: false
|
|
57
|
+
files:
|
|
58
|
+
- .harness/knowledge/staged/pipeline-staged.jsonl
|
|
59
|
+
- .harness/knowledge/gaps.md
|
|
60
|
+
depends_on: []
|