> Orchestrator composing 4 documentation skills into a sequential pipeline with convergence-based remediation, producing a qualitative documentation health report.
Installs into .claude/skills of the current project.
Are you the author of Harness Docs Pipeline?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/intense-visions-harness-docs-pipeline)
# Harness Docs Pipeline
> Orchestrator composing 4 documentation skills into a sequential pipeline with convergence-based remediation, producing a qualitative documentation health report.
## When to Use
- When you want a single-command documentation health check across drift, coverage, links, and freshness
- After major refactoring that may have caused widespread documentation drift
- As a periodic hygiene check (weekly or per-sprint)
- When onboarding a new project that has no AGENTS.md (bootstrap mode)
- When `on_doc_check` triggers fire
- NOT for fixing a single known drift issue (use align-documentation directly)
- NOT for generating AGENTS.md from scratch when you know you have a graph (use harness-knowledge-mapper directly)
- NOT for validating a single file's context (use validate-context-engineering directly)
## Relationship to Sub-Skills
| Skill | Pipeline Phase | Role |
| ---------------------------- | -------------- | ------------------------------------------- |
| detect-doc-drift | DETECT | Find drift between code and docs |
| align-documentation | FIX | Apply fixes for drift findings |
| validate-context-engineering | AUDIT | Find gaps in documentation coverage |
| harness-knowledge-mapper | FILL | Generate/regenerate AGENTS.md and fill gaps |
This orchestrator delegates to sub-skills — it never reimplements their logic. Each sub-skill retains full standalone functionality.
## Iron Law
**The pipeline delegates, never reimplements.** If you find yourself writing drift detection logic, fix application logic, or gap analysis logic inside the pipeline, STOP. Delegate to the dedicated sub-skill.
**Safe fixes are silent, unsafe fixes surface.** Never apply a fix classified as `unsafe` without explicit user approval. Never prompt the user for a fix classified as `safe`.
## Flags
| Flag | Effect |
| -------------- | ----------------------------------------------------------------- |
| `--fix` | Enable convergence-based auto-fix (default: detect + report only) |
| `--no-freshen` | Skip graph staleness check |
| `--bootstrap` | Force AGENTS.md regeneration even if one exists |
| `--ci` | Non-interactive: apply safe fixes only, report everything else |
## Shared Context Object
All phases read from and write to a shared `DocPipelineContext`:
```typescript
interface DocPipelineContext {
// Pipeline state
graphAvailable: boolean;
agentsMdExists: boolean;
bootstrapped: boolean; // true if AGENTS.md was created this run
// Phase outputs
driftFindings: DriftFinding[];
fixesApplied: DocFix[];
gapFindings: GapFinding[];
fillsApplied: DocFix[];
exclusions: Set<string>; // finding IDs already addressed
// Health verdict
verdict: 'pass' | 'warn' | 'fail';
summary: string;
}
interface DriftFinding {
id: string;
file: string;
line?: number;
driftType: 'renamed' | 'new-code' | 'deleted-code' | 'changed-behavior' | 'moved-code';
priority: 'critical' | 'high' | 'medium' | 'low';
staleText: string;
codeChange: string;
suggestedFix: string;
fixSafety: 'safe' | 'probably-safe' | 'unsafe';
}
interface GapFinding {
id: string;
file?: string;
gapType: 'undocumented' | 'broken-link' | 'stale-section' | 'missing-context';
priority: 'critical' | 'high' | 'medium' | 'low';
description: string;
suggestedFix: string;
fixSafety: 'safe' | 'probably-safe' | 'unsafe';
}
interface DocFix {
findingId: string;
file: string;
oldText: string;
newText: string;
safety: 'safe' | 'probably-safe';
verified: boolean; // harness check-docs passed after applying
}
```
The context is passed to sub-skills via `handoff.json` with a `pipeline` field. Sub-skills check for this field; if absent, they run in standalone mode.
## Process
### Phase 1: FRESHEN — Graph Freshness and AGENTS.md Bootstrap
**Skip this phase if `--no-freshen` flag is set.**
1. **Check graph existence.** Look for `.harness/graph/` directory.
- If exists: set `context.graphAvailable = true`
- If not: set `context.graphAvailable = false`, log notice: "No knowledge graph available. Pipeline will use static analysis fallbacks. Run `harness scan` for richer results."
2. **Check graph staleness** (only if graph exists).
- Count commits since last graph update: `git rev-list --count HEAD ^$(cat .harness/graph/.last-scan-commit 2>/dev/null || echo HEAD)`
- If >10 commits behind: run `harness scan` to refresh
- If <=10 commits: proceed with current graph
3. **Check AGENTS.md existence.**
- If exists and `--bootstrap` not set: set `context.agentsMdExists = true`, proceed to DETECT
- If exists and `--bootstrap` set: proceed to step 4 (regenerate)
- If not exists: proceed to step 4
4. **Bootstrap AGENTS.md.**
**If graph available:**
- Invoke `harness-knowledge-mapper` to generate AGENTS.md
- Set `context.bootstrapped = true`
- Set `context.agentsMdExists = true`
**If no graph (directory structure fallback):**
- Glob source directories: `src/*/`, `packages/*/`, `lib/*/`
- Read `package.json` for project name and description
- Identify entry points: files matching `src/index.*`, `main` field in package.json
- List top-level modules: each immediate subdirectory of `src/` (or `packages/`) with its directory name as the module name
- Generate minimal AGENTS.md:
```markdown
# AGENTS.md
> Generated from directory structure. Run `harness scan` for richer output.
## Project
<name from package.json> — <description from package.json>
## Entry Points
- <each identified entry point>
## Modules
- **<dir-name>/** — <inferred from directory name>
```
- Set `context.bootstrapped = true`
- Set `context.agentsMdExists = true`
5. Proceed to DETECT phase.
### Phase 2: DETECT — Find Documentation Drift
1. **Write pipeline context to handoff.json.** Set the `pipeline` field in `.harness/handoff.json` with the current `DocPipelineContext` so detect-doc-drift can read it.
2. **Invoke detect-doc-drift.** Run the skill's full process:
- Phase 1 (Scan): `harness check-docs` and `harness cleanup --type drift`
- Phase 2 (Identify): Classify each finding into drift types
- Phase 3 (Prioritize): Rank by impact (Critical > High > Medium > Low)
- Phase 4 (Report): Structured output
3. **Populate context with DriftFinding objects.** For each finding from detect-doc-drift, create a `DriftFinding` with:
- `id`: deterministic hash of `file + line + driftType` (for dedup tracking)
- `driftType`: map to one of `renamed`, `new-code`, `deleted-code`, `changed-behavior`, `moved-code`
- `priority`: map to `critical`, `high`, `medium`, `low`
- `fixSafety`: classify using the safety table below
4. **Store findings.** Set `context.driftFindings = <all DriftFinding objects>`.
5. **If `--fix` flag is not set:** Skip to AUDIT phase (Phase 4).
### Fix Safety Classification
| Category | Safe (apply silently) | Probably safe (present diff) | Unsafe (surface to user) |
| --------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| **Drift fixes** | Update file path where rename is unambiguous; fix import reference | Rewrite description for simple rename/parameter change; update code examples | Rewrite behavioral explanations; remove sections for deleted code |
| **Gap fills** | Add entry for new file with obvious single-purpose name | Add entry for new file requiring description; update AGENTS.md section ordering | Write documentation for complex modules; create new doc pages |
| **Link fixes** | Redirect broken link where target is unambiguous | Redirect when multiple candidates exist (present options) | Remove link when target no longer exists |
### Phase 3: FIX — Convergence-Based Drift Remediation
**This phase runs only when `--fix` flag is set.**
#### Convergence Loop
```
previousCount = context.driftFindings.length
maxIterations = 5
while iteration < maxIterations:
1. Partition findings by safety
2. Apply safe fixes → verify → record
3. Present probably-safe fixes → apply approved → verify → record
4. Surface unsafe fixes to user (no auto-apply)
5. Re-run detect-doc-drift
6. newCount = remaining findings
7. if newCount >= previousCount: STOP (converged)
8. previousCount = newCount
9. iteration++
```
#### Step-by-step
1. **Partition findings by fixSafety.**
- `safeFixes`: findings where `fixSafety === 'safe'`
- `probablySafeFixes`: findings where `fixSafety === 'probably-safe'`
- `unsafeFixes`: findings where `fixSafety === 'unsafe'`
2. **Apply safe fixes silently.**
- Write pipeline context to handoff.json with `pipeline.fixBatch = safeFixes`
- Invoke align-documentation to apply the fixes
- Run `harness check-docs` after the batch
- If check passes: record each fix as a `DocFix` with `verified: true` in `context.fixesApplied`
- If check fails: revert the batch (`git checkout -- <files>`), record fixes as `verified: false`
- Add fixed finding IDs to `context.exclusions`
3. **Present probably-safe fixes** (skip in `--ci` mode).
- For each fix, show the diff (oldText vs newText) to the user
- Apply user-approved fixes
- Run `harness check-docs` after the batch
- Same verify/revert logic as safe fixes
- Add fixed finding IDs to `context.exclusions`
4. **Surface unsafe fixes.**
- List each unsafe finding with its `suggestedFix` text
- Do not apply — user must handle manually
- In `--ci` mode: log to report, do not prompt
5. **Re-run detect-doc-drift** to check for cascading issues revealed by fixes.
- If new finding count < previous count: loop back to step 1
- If new finding count >= previous count: stop (converged or no progress)
- If max iterations reached: stop
6. **Record remaining unfixed findings** for the REPORT phase.
### Phase 4: AUDIT — Find Documentation Gaps
1. **Write pipeline context to handoff.json.** Update the `pipeline` field with the current `DocPipelineContext` (including `exclusions` from FIX phase).
2. **Invoke validate-context-engineering.** Run the skill's full process:
- Phase 1 (Audit): `harness validate` and `harness check-docs`
- Phase 2 (Detect Gaps): Classify into undocumented, broken-link, stale-section, missing-context
- Phase 3 (Suggest Updates): Generate specific suggestions
- Phase 4 (Apply): Deferred to FILL phase
3. **Populate context with GapFinding objects.** For each finding, create a `GapFinding` with:
- `id`: deterministic hash of `file + gapType + description`
- `gapType`: map to `undocumented`, `broken-link`, `stale-section`, `missing-context`
- `priority`: map to `critical`, `high`, `medium`, `low`
- `fixSafety`: classify using the safety table from DETECT phase
4. **Dedup against FIX phase.** Remove any `GapFinding` whose `id` appears in `context.exclusions`. This prevents double-counting items already fixed in the FIX phase.
5. **Store findings.** Set `context.gapFindings = <deduplicated GapFinding objects>`.
6. **If `--fix` flag is not set:** Skip to REPORT phase (Phase 6).
### Phase 5: FILL — Convergence-Based Gap Remediation
**This phase runs only when `--fix` flag is set.**
1. **Check if AGENTS.md needs regeneration.** If `context.bootstrapped === true` and gap findings include AGENTS.md coverage issues, invoke harness-knowledge-mapper (if graph available) or the directory-structure fallback to improve AGENTS.md quality.
2. **Run convergence loop** (same pattern as FIX phase):
```
previousCount = context.gapFindings.length
maxIterations = 5
while iteration < maxIterations:
1. Partition findings by safety
2. Apply safe fills → verify → record
3. Present probably-safe fills → apply approved → verify → record
4. Surface unsafe fills to user
5. Re-run validate-context-engineering
6. newCount = remaining gaps (after dedup against exclusions)
7. if newCount >= previousCount: STOP (converged)
8. previousCount = newCount
9. iteration++
```
3. **Apply safe fills silently.**
- For `broken-link` with unambiguous target: redirect the link
- For `undocumented` with obvious single-purpose name: add minimal entry
- Run `harness check-docs` after each batch
- Record in `context.fillsApplied`
- Add filled finding IDs to `context.exclusions`
4. **Present probably-safe fills** (skip in `--ci` mode).
- Show diff for: new file entries requiring description, AGENTS.md section reordering
- Apply approved fills, verify, record
5. **Surface unsafe fills.**
- Documentation for complex modules, new doc pages
- Log for report, do not apply
6. **Record remaining unfilled gaps** for the REPORT phase.
### Phase 6: REPORT — Synthesize Health Verdict
1. **Run final `harness check-docs`** to establish the post-pipeline state.
2. **Compute verdict.**
**FAIL if any of:**
- Any critical drift findings remain unfixed
- `harness check-docs` fails after all fix attempts
- AGENTS.md does not exist and bootstrap failed
**WARN if any of:**
- High-priority drift or gap findings remain (user-deferred)
- > 30% of source modules are undocumented
- Graph not available (reduced accuracy notice)
**PASS if:**
- No critical or high findings remaining
- `harness check-docs` passes
- AGENTS.md exists and covers >70% of modules
3. **Generate per-category breakdown:**
| Category | Metric |
| --------- | -------------------------------------- |
| Accuracy | Drift findings remaining (by priority) |
| Coverage | Undocumented modules remaining |
| Links | Broken references remaining |
| Freshness | Graph staleness status |
4. **List actions taken:**
- Auto-fixes applied (safe): count and file list
- User-approved fixes (probably-safe): count and file list
- Findings deferred to user (unsafe): count and details
- AGENTS.md bootstrapped: yes/no and method (graph or directory structure)
5. **Set context verdict and summary.** Write `context.verdict` and `context.summary`.
6. **Output report** to console. Format:
```
=== Documentation Health Report ===
Verdict: PASS | WARN | FAIL
Accuracy: N drift findings remaining (0 critical, 0 high, N medium, N low)
Coverage: N/M modules documented (N%)
Links: N broken references remaining
Freshness: Graph current | Graph stale (N commits behind) | No graph
Actions:
- N safe fixes applied silently
- N probably-safe fixes applied (user-approved)
- N unsafe findings deferred to user
- AGENTS.md bootstrapped from <graph|directory structure>
Remaining findings:
[list of unfixed findings with priority and suggested action]
```
## Harness Integration
- **`harness check-docs`** — Run in DETECT, after each fix batch in FIX/FILL, and in REPORT for final state
- **`harness cleanup --type drift`** — Used by detect-doc-drift during DETECT phase
- **`harness scan`** — Used in FRESHEN to refresh stale graph
- **`harness validate`** — Run as final step in each task to verify project health
## Success Criteria
- `harness-docs-pipeline` runs all 4 sub-skills in the right order with shared context
- FIX and FILL phases iterate until converged; cascading fixes are caught
- Safe fixes are applied silently; unsafe changes surface to user
- `harness check-docs` runs after every fix batch; failed fixes are reverted
- Bootstrap handles cold start (no AGENTS.md) with graph path and directory structure fallback
- Standalone skills work independently exactly as today when invoked without pipeline context
- Entire pipeline runs without graph using static analysis fallbacks
- PASS/WARN/FAIL report includes per-category breakdown and specific remaining findings
- Drift fixes in FIX phase are excluded from AUDIT findings (no double-counting)
## Rationalizations to Reject
These are common rationalizations that sound reasonable but lead to incorrect results. When you catch yourself thinking any of these, stop and follow the documented process instead.
| Rationalization | Why It Is Wrong |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| "The drift finding is marked unsafe but the fix is obvious, so I will apply it silently" | Never apply a fix classified as unsafe without explicit user approval. The Iron Law: safe fixes are silent, unsafe fixes surface. |
| "The convergence loop reduced findings from 8 to 6, but the remaining ones are hard -- I will keep iterating" | If a convergence iteration does not reduce the finding count, stop immediately. Continuing without progress wastes iterations. |
| "I can write the drift detection logic directly instead of delegating to detect-doc-drift" | The pipeline delegates, never reimplements. Each sub-skill retains full standalone functionality. |
| "The graph is not available so the pipeline results will be unreliable" | The entire pipeline runs without a graph using static analysis fallbacks. Reduced accuracy is noted in the report, not used as an excuse to skip. |
## Examples
### Example: Full pipeline run with fixes
```
Input: --fix flag set, graph available, AGENTS.md exists
1. FRESHEN — Graph exists, 3 commits behind (< 10, skip refresh)
AGENTS.md exists, no bootstrap needed
2. DETECT — detect-doc-drift found 8 findings:
2 critical (deleted file still referenced)
3 high (renamed functions)
2 medium (stale descriptions)
1 low (formatting)
3. FIX — Iteration 1:
3 safe fixes applied (renamed file paths)
2 probably-safe presented, 2 approved
2 unsafe surfaced to user
harness check-docs: pass
Re-detect: 1 new finding (cascading rename)
Iteration 2:
1 safe fix applied
Re-detect: 0 new findings — converged
4. AUDIT — validate-context-engineering found 5 gaps
2 already in exclusions (fixed in FIX) → 3 remaining
5. FILL — 1 safe fill (broken link redirect)
1 probably-safe (new module entry) → approved
1 unsafe (complex module docs) → deferred
Re-audit: converged
6. REPORT — Verdict: WARN
Accuracy: 2 drift findings remaining (0 critical, 0 high, 1 medium, 1 low)
Coverage: 12/14 modules documented (86%)
Links: 0 broken references
Freshness: Graph current
```
### Example: CI mode (non-interactive)
```
Input: --fix --ci flags set, no graph
1. FRESHEN — No graph (notice logged), AGENTS.md exists
2. DETECT — 4 findings (1 critical, 2 high, 1 medium)
3. FIX — 2 safe fixes applied silently
probably-safe and unsafe: logged to report (no prompts)
4. AUDIT — 2 gaps (1 deduped) → 1 remaining
5. FILL — 0 safe fills, 1 probably-safe logged to report
6. REPORT — Verdict: FAIL (1 critical finding remains)
```
### Example: Bootstrap from directory structure
```
Input: --bootstrap flag set, no graph, no AGENTS.md
1. FRESHEN — No graph, no AGENTS.md
Fallback bootstrap: glob src/*, read package.json
Generated minimal AGENTS.md (32 lines)
context.bootstrapped = true
2. DETECT — 0 drift findings (fresh AGENTS.md, no stale refs)
3. AUDIT — 6 gaps (4 undocumented modules, 2 missing context)
4. REPORT — Verdict: WARN (>30% modules undocumented, no graph)
```
## Gates
- **No fix without verification.** Every fix batch must be followed by `harness check-docs`. If check fails, revert the batch.
- **No unsafe auto-apply.** Fixes classified as `unsafe` are never applied without explicit user approval. In `--ci` mode, they are logged but never applied.
- **No reimplementation of sub-skill logic.** The pipeline delegates to sub-skills. If the DETECT phase is writing drift detection code, the plan is wrong.
- **No convergence without progress.** If a convergence loop iteration does not reduce the finding count, stop immediately. Do not retry.
- **Max 5 iterations per convergence loop.** Hard cap to prevent runaway loops.
## Escalation
- **When findings exceed 50:** Focus on critical and high priority only. Defer medium and low to a follow-up run.
- **When bootstrap produces low-quality AGENTS.md:** This is expected without a graph. Log a notice recommending `harness scan` and accept the reduced quality for the current run.
- **When convergence loop does not converge within 5 iterations:** Stop the loop, log remaining findings, and proceed to the next phase. The report will reflect the unconverged state.
- **When a sub-skill fails:** Log the failure, skip the phase, and continue the pipeline. The report will note the skipped phase with a WARN or FAIL verdict.
- **When `harness check-docs` is unavailable:** Fall back to file existence checks and link validation via grep. Log a notice about reduced verification accuracy.