coding-agent-harness 1.0.2 → 1.0.5
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/CHANGELOG.md +32 -0
- package/CONTRIBUTING.md +98 -0
- package/LICENSE +661 -21
- package/LICENSE-EXCEPTION.md +37 -0
- package/README.md +244 -87
- package/README.zh-CN.md +77 -35
- package/SKILL.md +32 -24
- package/docs-release/README.md +9 -5
- package/docs-release/architecture/overview.md +17 -5
- package/docs-release/architecture/overview.zh-CN.md +9 -5
- package/docs-release/architecture/system-explainer/01-system-overview.md +217 -0
- package/docs-release/architecture/system-explainer/02-module-dependency.md +257 -0
- package/docs-release/architecture/system-explainer/03-task-lifecycle.md +304 -0
- package/docs-release/architecture/system-explainer/04-check-and-governance.md +239 -0
- package/docs-release/architecture/system-explainer/05-data-flow.md +276 -0
- package/docs-release/architecture/system-explainer/06-preset-and-migration.md +303 -0
- package/docs-release/architecture/system-explainer/README.md +67 -0
- package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +226 -0
- package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +263 -0
- package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +319 -0
- package/docs-release/architecture/system-explainer/en-US/04-check-and-governance.md +250 -0
- package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +290 -0
- package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +323 -0
- package/docs-release/architecture/system-explainer/en-US/README.md +70 -0
- package/docs-release/assets/dashboard-overview.png +0 -0
- package/docs-release/guides/agent-installation.en-US.md +39 -15
- package/docs-release/guides/agent-installation.md +43 -16
- package/docs-release/guides/contributing.md +100 -0
- package/docs-release/guides/contributing.zh-CN.md +99 -0
- package/docs-release/guides/document-audience-and-surfaces.en-US.md +3 -2
- package/docs-release/guides/document-audience-and-surfaces.md +3 -2
- package/docs-release/guides/full-legacy-migration-subagent-strategy.md +2 -2
- package/docs-release/guides/full-legacy-migration-subagent-strategy.zh-CN.md +2 -2
- package/docs-release/guides/legacy-migration-agent-prompt.md +0 -11
- package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +0 -11
- package/docs-release/guides/migration-playbook.en-US.md +14 -15
- package/docs-release/guides/migration-playbook.md +14 -15
- package/docs-release/guides/parent-control-repository-pattern.en-US.md +7 -5
- package/docs-release/guides/parent-control-repository-pattern.md +7 -5
- package/docs-release/guides/preset-development.md +238 -0
- package/docs-release/guides/repository-operating-models.en-US.md +5 -4
- package/docs-release/guides/repository-operating-models.md +5 -4
- package/docs-release/guides/task-state-machine.en-US.md +224 -0
- package/docs-release/guides/task-state-machine.md +231 -0
- package/docs-release/intl/en-US.md +1 -1
- package/docs-release/intl/zh-CN.md +1 -1
- package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/INDEX.md +60 -0
- package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/findings.md +7 -0
- package/package.json +10 -4
- package/presets/legacy-migration/checks/preset-check.mjs +3 -0
- package/presets/legacy-migration/preset.yaml +134 -0
- package/presets/legacy-migration/scripts/plan-work-queue.mjs +4 -0
- package/presets/legacy-migration/scripts/scaffold-task-contracts.mjs +4 -0
- package/presets/legacy-migration/templates/execution_strategy.append.md +18 -0
- package/presets/legacy-migration/templates/findings.seed.md +17 -0
- package/presets/legacy-migration/templates/review.seed.md +12 -0
- package/presets/legacy-migration/templates/task_plan.append.md +9 -0
- package/presets/legacy-migration/templates/visual_map.append.md +12 -0
- package/presets/legacy-migration/workbench/dashboard-panels.yaml +2 -0
- package/presets/legacy-migration/workbench/migration-queue.schema.json +23 -0
- package/presets/lesson-sedimentation/preset.yaml +23 -0
- package/presets/lesson-sedimentation/templates/prompt.md +23 -0
- package/presets/module/preset.yaml +25 -0
- package/presets/module/templates/execution_strategy.append.md +8 -0
- package/presets/module/templates/task_plan.append.md +17 -0
- package/presets/standard-task/preset.yaml +31 -0
- package/presets/standard-task/templates/task_plan.append.md +7 -0
- package/references/adversarial-review-standard.md +2 -2
- package/references/agents-md-pattern.md +2 -2
- package/references/delivery-operating-model-standard.md +3 -3
- package/references/docs-directory-standard.md +6 -7
- package/references/harness-ledger.md +53 -96
- package/references/lessons-governance.md +88 -93
- package/references/module-parallel-standard.md +14 -14
- package/references/planning-loop.md +12 -6
- package/references/pull-request-standard.md +118 -0
- package/references/repo-governance-standard.md +11 -2
- package/references/review-routing-standard.md +7 -1
- package/references/ssot-governance.md +67 -59
- package/references/taskr-gap-analysis.md +600 -0
- package/references/walkthrough-closeout.md +7 -7
- package/scripts/check-harness.mjs +40 -301
- package/scripts/commands/dashboard-command.mjs +67 -0
- package/scripts/commands/migration-command.mjs +126 -0
- package/scripts/commands/preset-command.mjs +73 -0
- package/scripts/commands/task-command.mjs +328 -0
- package/scripts/harness.mjs +59 -260
- package/scripts/lib/capability-registry.mjs +82 -28
- package/scripts/lib/check-module-parallel.mjs +230 -0
- package/scripts/lib/check-profiles.mjs +90 -228
- package/scripts/lib/check-task-contracts.mjs +55 -0
- package/scripts/lib/core-shared.mjs +65 -2
- package/scripts/lib/dashboard-data.mjs +155 -24
- package/scripts/lib/dashboard-workbench.mjs +131 -12
- package/scripts/lib/dashboard-writer.mjs +20 -4
- package/scripts/lib/git-status-summary.mjs +46 -0
- package/scripts/lib/governance-index-generator.mjs +174 -0
- package/scripts/lib/governance-sync.mjs +611 -0
- package/scripts/lib/governance-table-boundary.mjs +175 -0
- package/scripts/lib/harness-core.mjs +6 -0
- package/scripts/lib/lesson-maintenance.mjs +36 -29
- package/scripts/lib/markdown-utils.mjs +33 -0
- package/scripts/lib/migration-planner.mjs +4 -6
- package/scripts/lib/migration-support.mjs +1 -1
- package/scripts/lib/phase-kind.mjs +50 -0
- package/scripts/lib/preset-audit-contracts.mjs +37 -0
- package/scripts/lib/preset-engine.mjs +494 -0
- package/scripts/lib/preset-registry.mjs +776 -0
- package/scripts/lib/preset-resource-contracts.mjs +83 -0
- package/scripts/lib/review-confirm-git-gate.mjs +248 -0
- package/scripts/lib/status-builder.mjs +88 -0
- package/scripts/lib/status-dashboard-renderer.mjs +105 -0
- package/scripts/lib/subagent-authorization-audit.mjs +196 -0
- package/scripts/lib/task-audit-metadata.mjs +385 -0
- package/scripts/lib/task-audit-migration.mjs +350 -0
- package/scripts/lib/task-completion-consistency.mjs +26 -0
- package/scripts/lib/task-index.mjs +93 -0
- package/scripts/lib/task-lesson-candidates.mjs +242 -0
- package/scripts/lib/task-lesson-sedimentation.mjs +326 -0
- package/scripts/lib/task-lifecycle/create-task-helpers.mjs +67 -0
- package/scripts/lib/task-lifecycle/phase-sync.mjs +88 -0
- package/scripts/lib/task-lifecycle/review-confirm.mjs +112 -0
- package/scripts/lib/task-lifecycle/review-gates.mjs +73 -0
- package/scripts/lib/task-lifecycle/review-submission.mjs +63 -0
- package/scripts/lib/task-lifecycle/scaffold-provenance.mjs +49 -0
- package/scripts/lib/task-lifecycle/template-files.mjs +53 -0
- package/scripts/lib/task-lifecycle/text-utils.mjs +24 -0
- package/scripts/lib/task-lifecycle.mjs +338 -477
- package/scripts/lib/task-metadata.mjs +118 -0
- package/scripts/lib/task-review-model.mjs +455 -0
- package/scripts/lib/task-scanner.mjs +193 -372
- package/scripts/lib/task-tombstone-commands.mjs +140 -0
- package/scripts/postinstall.mjs +14 -0
- package/skills/preset-creator/SKILL.md +179 -0
- package/skills/preset-creator/references/complex-task-skeleton/README.md +31 -0
- package/skills/preset-creator/references/complex-task-skeleton/artifacts/INDEX.md +12 -0
- package/skills/preset-creator/references/complex-task-skeleton/brief.md +43 -0
- package/skills/preset-creator/references/complex-task-skeleton/execution_strategy.md +71 -0
- package/skills/preset-creator/references/complex-task-skeleton/findings.md +24 -0
- package/skills/preset-creator/references/complex-task-skeleton/lesson_candidates.md +70 -0
- package/skills/preset-creator/references/complex-task-skeleton/long-running-task-contract.md +76 -0
- package/skills/preset-creator/references/complex-task-skeleton/progress.md +33 -0
- package/skills/preset-creator/references/complex-task-skeleton/references/INDEX.md +13 -0
- package/skills/preset-creator/references/complex-task-skeleton/review.md +107 -0
- package/skills/preset-creator/references/complex-task-skeleton/task_plan.md +111 -0
- package/skills/preset-creator/references/complex-task-skeleton/visual_map.md +50 -0
- package/skills/preset-creator/references/preset-package-skeleton.md +296 -0
- package/templates/AGENTS.md.template +24 -18
- package/templates/dashboard/assets/app-src/00-state.js +13 -0
- package/templates/dashboard/assets/app-src/10-router.js +5 -1
- package/templates/dashboard/assets/app-src/20-overview.js +18 -8
- package/templates/dashboard/assets/app-src/30-tasks.js +92 -246
- package/templates/dashboard/assets/app-src/35-task-detail.js +286 -0
- package/templates/dashboard/assets/app-src/45-review.js +241 -22
- package/templates/dashboard/assets/app-src/50-migration.js +24 -10
- package/templates/dashboard/assets/app-src/55-presets.js +375 -0
- package/templates/dashboard/assets/app-src/60-shared.js +3 -1
- package/templates/dashboard/assets/app-src/90-bindings.js +302 -29
- package/templates/dashboard/assets/app.css +1501 -376
- package/templates/dashboard/assets/app.css.manifest.json +10 -0
- package/templates/dashboard/assets/app.js +1240 -101
- package/templates/dashboard/assets/app.manifest.json +2 -0
- package/templates/dashboard/assets/css-src/00-foundation.css +346 -0
- package/templates/dashboard/assets/css-src/10-panels-flow.css +236 -0
- package/templates/dashboard/assets/css-src/20-briefs-controls.css +398 -0
- package/templates/dashboard/assets/css-src/30-task-index.css +739 -0
- package/templates/dashboard/assets/css-src/35-review-workspace.css +507 -0
- package/templates/dashboard/assets/css-src/40-detail-modules-migration.css +489 -0
- package/templates/dashboard/assets/css-src/45-presets.css +516 -0
- package/templates/dashboard/assets/css-src/50-responsive-overrides.css +551 -0
- package/templates/dashboard/assets/i18n.js +263 -23
- package/templates/ledger/Harness-Ledger.md +13 -25
- package/templates/lessons/lesson-arch-process-change.md +1 -1
- package/templates/lessons/lesson-new-doc.md +1 -1
- package/templates/lessons/lesson-ref-change.md +1 -1
- package/templates/planning/INDEX.md +87 -0
- package/templates/planning/brief.md +1 -1
- package/templates/planning/execution_strategy.md +31 -0
- package/templates/planning/lesson_candidates.md +18 -6
- package/templates/planning/module_session_prompt.md +1 -0
- package/templates/planning/optional/artifacts/INDEX.md +3 -3
- package/templates/planning/optional/references/INDEX.md +3 -3
- package/templates/planning/review.md +41 -0
- package/templates/planning/task_plan.md +5 -21
- package/templates/planning/visual_map.md +13 -9
- package/templates/planning/visual_map.simple.md +52 -0
- package/templates/reference/execution-workflow-standard.md +31 -3
- package/templates/reference/pull-request-standard.md +80 -0
- package/templates/reference/repo-governance-standard.md +7 -6
- package/templates/reference/review-routing-standard.md +6 -0
- package/templates/reference/walkthrough-standard.md +2 -1
- package/templates/verifier/verifier-output.md +1 -1
- package/templates-zh-CN/AGENTS.md.template +25 -19
- package/templates-zh-CN/ledger/Harness-Ledger.md +17 -40
- package/templates-zh-CN/planning/INDEX.md +87 -0
- package/templates-zh-CN/planning/brief.md +1 -1
- package/templates-zh-CN/planning/execution_strategy.md +30 -0
- package/templates-zh-CN/planning/lesson_candidates.md +18 -6
- package/templates-zh-CN/planning/module_session_prompt.md +1 -0
- package/templates-zh-CN/planning/review.md +41 -1
- package/templates-zh-CN/planning/task_plan.md +4 -44
- package/templates-zh-CN/planning/visual_map.md +14 -7
- package/templates-zh-CN/planning/visual_map.simple.md +48 -0
- package/templates-zh-CN/reference/adversarial-review-standard.md +1 -1
- package/templates-zh-CN/reference/docs-library-standard.md +1 -1
- package/templates-zh-CN/reference/execution-workflow-standard.md +33 -7
- package/templates-zh-CN/reference/harness-ledger-standard.md +2 -2
- package/templates-zh-CN/reference/pull-request-standard.md +106 -0
- package/templates-zh-CN/reference/repo-governance-standard.md +4 -3
- package/templates-zh-CN/reference/review-routing-standard.md +8 -1
- package/templates-zh-CN/reference/walkthrough-standard.md +3 -2
- package/templates-zh-CN/walkthrough/Closeout-SSoT.md +1 -1
- package/docs-release/assets/dashboard-overview-en.png +0 -0
- package/scripts/smoke-dashboard.mjs +0 -92
- package/scripts/test-harness.mjs +0 -1395
- package/templates/ssot/Feature-SSoT.md +0 -43
- package/templates/ssot/Lessons-SSoT.md +0 -44
- package/templates-zh-CN/ssot/Feature-SSoT.md +0 -49
- package/templates-zh-CN/ssot/Lessons-SSoT.md +0 -49
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# 05 — Data Flow: From Markdown to Dashboard
|
|
2
|
+
|
|
3
|
+
## Level 0 — Where data starts and ends
|
|
4
|
+
|
|
5
|
+
```mermaid
|
|
6
|
+
flowchart LR
|
|
7
|
+
A["📄 Markdown files\n(source files under docs/)"]
|
|
8
|
+
B["⚙️ Scanner\n(parse + validate)"]
|
|
9
|
+
C["📊 Dashboard\n(HTML + JSON)"]
|
|
10
|
+
|
|
11
|
+
A -->|"read"| B -->|"generate"| C
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
All data comes from Markdown files — no database, no external services.
|
|
15
|
+
Every run re-reads from the filesystem from scratch, caching no intermediate state.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Level 1 — Which files are data sources
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart TD
|
|
23
|
+
Sources["Data source files"]
|
|
24
|
+
|
|
25
|
+
Sources --> TP["task_plan.md\nBudget / title / metadata / Preset info\nTask Contract marker"]
|
|
26
|
+
Sources --> PR["progress.md\nCurrent state / operation log"]
|
|
27
|
+
Sources --> VM["visual_map.md\nPhase list / completion / evidence status"]
|
|
28
|
+
Sources --> RV["review.md\nFindings table / human confirmation block"]
|
|
29
|
+
Sources --> BR["brief.md\nTask summary"]
|
|
30
|
+
Sources --> LC["lesson_candidates.md\nLesson candidates / decision state"]
|
|
31
|
+
Sources --> HL["Harness-Ledger.md\nGlobal ledger (all tasks summarized)"]
|
|
32
|
+
Sources --> ES["execution_strategy.md\nSubagent authorization state"]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Level 2 — How the Scanner processes these files
|
|
38
|
+
|
|
39
|
+
The Scanner layer (`task-scanner.mjs` + `task-review-model.mjs`) parses raw Markdown
|
|
40
|
+
into structured objects.
|
|
41
|
+
|
|
42
|
+
### collectTasks() discovery flow
|
|
43
|
+
|
|
44
|
+
```mermaid
|
|
45
|
+
flowchart TD
|
|
46
|
+
CT["collectTasks()"]
|
|
47
|
+
|
|
48
|
+
CT --> Discover["listTaskPlanPaths()\nScans two root directories:\n09-PLANNING/TASKS/\n09-PLANNING/MODULES/\nFilters out template and archive directories"]
|
|
49
|
+
|
|
50
|
+
Discover --> ReadFiles["For each task directory, reads 9 files:\ntask_plan / brief / progress\nreview / visual_map\nexecution_strategy\nlesson_candidates / findings / context"]
|
|
51
|
+
|
|
52
|
+
ReadFiles --> Parse["Parse each file"]
|
|
53
|
+
|
|
54
|
+
Parse --> P1["parseTaskBudget()\nExtract budget from task_plan.md"]
|
|
55
|
+
Parse --> P2["parseTaskState()\nExtract state from progress.md"]
|
|
56
|
+
Parse --> P3["parsePhases()\nExtract phase list from visual_map.md"]
|
|
57
|
+
Parse --> P4["parseAgentReviewSubmission()\nExtract Agent submission state from review.md"]
|
|
58
|
+
Parse --> P5["parseReviewConfirmation()\nExtract human confirmation block from review.md"]
|
|
59
|
+
Parse --> P6["parseLessonCandidateStatus()\nExtract decision state from lesson_candidates.md"]
|
|
60
|
+
Parse --> P7["parseTaskTombstone()\nExtract soft-delete state from task_plan.md"]
|
|
61
|
+
|
|
62
|
+
P1 & P2 & P3 & P4 & P5 & P6 & P7 --> Derive["Derivation (pure functions)"]
|
|
63
|
+
|
|
64
|
+
Derive --> LS["deriveLifecycleState()\nDerive lifecycleState from combined inputs"]
|
|
65
|
+
Derive --> QS["deriveTaskQueues()\nDetermine which queues the task belongs to"]
|
|
66
|
+
Derive --> RQS["deriveReviewQueueState()\nDerive reviewQueueState"]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### parseTaskState() format
|
|
70
|
+
|
|
71
|
+
Extracts state from the first line after the `## Current Status` or `## Status` heading
|
|
72
|
+
in `progress.md`:
|
|
73
|
+
|
|
74
|
+
```markdown
|
|
75
|
+
## Current Status
|
|
76
|
+
|
|
77
|
+
in_progress
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Supports Chinese aliases (`进行中` → `in_progress`). Falls back to legacy table parsing
|
|
81
|
+
mode if the format doesn't match expectations.
|
|
82
|
+
|
|
83
|
+
### parsePhases() table format
|
|
84
|
+
|
|
85
|
+
Finds the table with a `Phase ID` column header in `visual_map.md` and extracts 9 fields:
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
| Phase ID | Depends On | State | Completion | Output | Required Evidence | Evidence Status | Blocking Risk | Owner / Handoff |
|
|
89
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
90
|
+
| P1 | — | done | 100 | ... | E-001 | present | low | coordinator |
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The dependency field supports multiple values separated by commas, semicolons, or `&`.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Level 2 — What buildStatus() assembles from Scanner results
|
|
98
|
+
|
|
99
|
+
```mermaid
|
|
100
|
+
flowchart TD
|
|
101
|
+
BS["buildStatus()"]
|
|
102
|
+
|
|
103
|
+
BS --> Tasks["tasks[]\nComplete structured data for each task\n(see field list below)"]
|
|
104
|
+
BS --> Failures["failures[]\nHard failure list"]
|
|
105
|
+
BS --> Warnings["warnings[]\nSoft warning list"]
|
|
106
|
+
BS --> Caps["capabilities[]\nCapability registry state"]
|
|
107
|
+
BS --> Git["git\nGit status summary (dirty files etc.)"]
|
|
108
|
+
BS --> Summary["summary\nbriefCoverage / visualMapCoverage\nfullCutoverEligible and other aggregate metrics"]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Complete fields of a task object**:
|
|
112
|
+
|
|
113
|
+
| Field | Meaning |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `path` | Relative path |
|
|
116
|
+
| `title` | Task title |
|
|
117
|
+
| `state` | Task state (`in_progress / done / ...`) |
|
|
118
|
+
| `stateSource` | State source (`valid / invalid`) |
|
|
119
|
+
| `budget` | Budget level (`simple / standard / complex`) |
|
|
120
|
+
| `lifecycleState` | Derived lifecycle state |
|
|
121
|
+
| `reviewQueueState` | Review queue state |
|
|
122
|
+
| `taskQueues[]` | List of queues the task belongs to |
|
|
123
|
+
| `phases[]` | Phase list (with id / state / completion / evidenceStatus) |
|
|
124
|
+
| `closeoutStatus` | Closeout status |
|
|
125
|
+
| `tombstone` | Soft-delete information |
|
|
126
|
+
| `briefSource` | Brief source (`standalone / missing / ...`) |
|
|
127
|
+
| `visualMapSource` | Visual map source (`canonical / legacy / missing`) |
|
|
128
|
+
| `taskPreset` | Preset ID used |
|
|
129
|
+
| `presetVersion` | Preset version |
|
|
130
|
+
| `handoffs` | Handoff information array |
|
|
131
|
+
| `lessonCandidateDecisionComplete` | Whether Lesson decision is complete |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Level 3 — What buildDashboardBundle() adds on top of status
|
|
136
|
+
|
|
137
|
+
`buildDashboardBundle()` calls `buildStatus()` then additionally collects four types of data:
|
|
138
|
+
|
|
139
|
+
```mermaid
|
|
140
|
+
flowchart TD
|
|
141
|
+
Bundle["buildDashboardBundle()"]
|
|
142
|
+
|
|
143
|
+
Bundle --> Status["status\n(from buildStatus)"]
|
|
144
|
+
Bundle --> Documents["documents[]\nContent of all Markdown documents\nEach document: id / path / title / type / content"]
|
|
145
|
+
Bundle --> Tables["tables[]\nMarkdown tables extracted from documents\nEach table: column definitions + row data"]
|
|
146
|
+
Bundle --> Graph["graph\nTask dependency graph\nnodes (tasks/phases/modules/steps)\nedges (dependency/containment/handoff relationships)"]
|
|
147
|
+
Bundle --> Adoption["adoption\nMigration adoption state analysis\n(warnings categorized with priority and fix suggestions)"]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### documents collection scope
|
|
151
|
+
|
|
152
|
+
Which files `collectMarkdownDocuments()` collects:
|
|
153
|
+
|
|
154
|
+
```mermaid
|
|
155
|
+
flowchart TD
|
|
156
|
+
Collect["collectMarkdownDocuments()"]
|
|
157
|
+
|
|
158
|
+
Collect --> Fixed["Fixed paths (collected when they exist)\nHarness-Ledger.md\n09-PLANNING/Module-Registry.md\n05-TEST-QA/Regression-SSoT.md\n10-WALKTHROUGH/Closeout-SSoT.md"]
|
|
159
|
+
|
|
160
|
+
Collect --> Walkthrough["All .md files under 10-WALKTHROUGH/\n(excluding _archive/ and files starting with _)"]
|
|
161
|
+
|
|
162
|
+
Collect --> TaskDocs["Under each task directory:\nbrief / task_plan / execution_strategy\nvisual_map / lesson_candidates\nprogress / review / findings\nreferences/INDEX.md / artifacts/INDEX.md"]
|
|
163
|
+
|
|
164
|
+
Collect --> ModuleDocs["Under 09-PLANNING/MODULES/:\nmodule_plan.md for each module\nbrief.md for each module"]
|
|
165
|
+
|
|
166
|
+
Collect --> Lessons["All .md files under 01-GOVERNANCE/lessons/"]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
After collection, uniformly filters out `_archive/`, `_task-template/`, and
|
|
170
|
+
`_optional-structures/` paths.
|
|
171
|
+
|
|
172
|
+
### graph data structure
|
|
173
|
+
|
|
174
|
+
The graph contains two types of elements:
|
|
175
|
+
|
|
176
|
+
- **nodes**: task nodes, phase nodes, module nodes, step nodes
|
|
177
|
+
- **edges**: dependency relationships (phase → phase), containment relationships (task → phase),
|
|
178
|
+
handoff relationships (step → step)
|
|
179
|
+
|
|
180
|
+
If the source node of a dependency doesn't exist, a virtual node of type
|
|
181
|
+
`external-dependency` is created.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Level 2 — Two Dashboard generation modes
|
|
186
|
+
|
|
187
|
+
```mermaid
|
|
188
|
+
flowchart LR
|
|
189
|
+
subgraph "Static mode (read-only snapshot)"
|
|
190
|
+
SC["harness dashboard\n--out-dir ./out"]
|
|
191
|
+
SC --> SH["index.html\n(all resources inlined)"]
|
|
192
|
+
SC --> SJ["dashboard-data.json\n(for external tools to read)"]
|
|
193
|
+
SC --> SF["status.json / tables.json\ndocuments.json / graph.json\nadoption.json"]
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
subgraph "Dynamic mode (Workbench)"
|
|
197
|
+
DC["harness dev"]
|
|
198
|
+
DC --> HTTP["Local HTTP server\nlocalhost:PORT"]
|
|
199
|
+
DC --> Watch["File watching\nPolling mode, checks every 1 second\nRegenerates after 250ms delay on change"]
|
|
200
|
+
HTTP --> Browser["Live browser view\nSupports review-confirm and other write operations"]
|
|
201
|
+
end
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Key boundary**: The static Dashboard is read-only and cannot trigger any write operations.
|
|
205
|
+
Only `harness dev` (Workbench mode) can execute write operations like `review-confirm`
|
|
206
|
+
and `task-start`.
|
|
207
|
+
|
|
208
|
+
### Dashboard HTML generation
|
|
209
|
+
|
|
210
|
+
Dashboard HTML is generated via string concatenation (no template engine).
|
|
211
|
+
`app.js` is obtained via manifest or direct read — if a manifest exists, it reads and
|
|
212
|
+
concatenates multiple source files in order (modular source code under `app-src/`).
|
|
213
|
+
|
|
214
|
+
`<` in the payload is escaped to `<` to prevent HTML injection.
|
|
215
|
+
|
|
216
|
+
### File watching implementation
|
|
217
|
+
|
|
218
|
+
`dashboard-workbench.mjs` file watching uses **polling mode** (`startPollingWatch()`):
|
|
219
|
+
- Checks the latest modification time (mtime) of the directory tree every 1000ms
|
|
220
|
+
- When a change is detected, triggers regeneration after a 250ms delay (debounce)
|
|
221
|
+
- Watch scope: the entire `target.docsRoot`, excluding `.git`, `node_modules`, `tmp`
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Level 3 — Core capabilities of markdown-utils.mjs
|
|
226
|
+
|
|
227
|
+
The technical foundation that lets the whole system derive state from Markdown files is
|
|
228
|
+
the table parsing capability provided by `markdown-utils.mjs`:
|
|
229
|
+
|
|
230
|
+
| Function | Purpose |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| `markdownTableRows()` | Extract all table rows |
|
|
233
|
+
| `parseAllMarkdownTables()` | Parse all tables in a document, return array of structured objects |
|
|
234
|
+
| `splitMarkdownRow()` | Split row cells (handles escaped pipe characters and code blocks) |
|
|
235
|
+
| `tableAfterHeading()` | Locate the table after a specific heading |
|
|
236
|
+
| `getCell()` | Get a cell by column name (supports multiple aliases) |
|
|
237
|
+
| `splitList()` | Split comma/semicolon/plus-separated lists |
|
|
238
|
+
| `splitDependencies()` | Split dependencies, filtering out `none/n/a` placeholders |
|
|
239
|
+
|
|
240
|
+
**Pipe characters inside code blocks**: `splitMarkdownRow()` tracks code block state —
|
|
241
|
+
`|` inside code blocks is not treated as a column separator and the original content is preserved.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Level 2 — Design decisions
|
|
246
|
+
|
|
247
|
+
### Why Dashboard is plain HTML + vanilla JS, not React/Vite
|
|
248
|
+
|
|
249
|
+
harness is distributed via `npx`. Introducing React/Vite would mean users pull in large
|
|
250
|
+
build dependencies on every run, breaking the zero-dependency portability. Static HTML can
|
|
251
|
+
be opened directly from `file://` and shared as a CI evidence snapshot without any runtime.
|
|
252
|
+
|
|
253
|
+
The vanilla JS components in app-src (`DashboardShell`, `SidebarNav`, `TableView`, etc.)
|
|
254
|
+
are concatenated in order via manifest. Each file is < 600 lines, git-diff readable,
|
|
255
|
+
no webpack/esbuild needed.
|
|
256
|
+
|
|
257
|
+
### Why the static Dashboard is read-only
|
|
258
|
+
|
|
259
|
+
The static Dashboard's role is "shareable evidence snapshot" — it can be generated by CI,
|
|
260
|
+
opened offline, and sent to external reviewers. In these scenarios, write operations have
|
|
261
|
+
no security boundary (no CSRF/Origin/Host validation). Write operations can only be
|
|
262
|
+
executed in Workbench mode, because the Workbench server binds to `127.0.0.1` and has
|
|
263
|
+
a complete security validation chain.
|
|
264
|
+
|
|
265
|
+
### Why `harness dev` and `harness dashboard` are two separate commands
|
|
266
|
+
|
|
267
|
+
`harness dashboard` generates a static read-only snapshot (suitable for CI, migration
|
|
268
|
+
reports, offline evidence). `harness dev` starts a local dynamic Workbench server with
|
|
269
|
+
file watching, auto-refresh, and review-confirm write operations. The boundary is:
|
|
270
|
+
**static snapshots can be shared; the dynamic Workbench is local-only**.
|
|
271
|
+
|
|
272
|
+
### Why file watching uses polling instead of fs.watch
|
|
273
|
+
|
|
274
|
+
`fs.watch` has known missed-event issues on macOS for deep directory trees, and harness's
|
|
275
|
+
docs directory structure is a multi-level nested Markdown file tree. The polling approach
|
|
276
|
+
is simple to implement, has predictable behavior, and doesn't introduce third-party
|
|
277
|
+
dependencies like chokidar (consistent with the zero-dependency principle).
|
|
278
|
+
1-second polling + 250ms debounce is sufficient for human editing scenarios.
|
|
279
|
+
|
|
280
|
+
### Why not introduce SQLite or a JSON database
|
|
281
|
+
|
|
282
|
+
Introducing JSON/SQLite without a clear authority boundary would create drift between
|
|
283
|
+
Markdown, JSON, and SQLite as three separate facts. Git review is friendly to Markdown/JSON
|
|
284
|
+
diffs but not to SQLite diffs. Current scale is "hundreds of tasks" — generated JSON +
|
|
285
|
+
indexed in-memory filtering is sufficient.
|
|
286
|
+
|
|
287
|
+
The decision: Markdown is the single source of truth, generated JSON index is a
|
|
288
|
+
regenerable cache, and SQLite is only considered when task count and query complexity
|
|
289
|
+
exceed what JSON can handle — and even then, only as a regenerable query cache, never
|
|
290
|
+
hand-written, never as an authoritative source of truth.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# 06 — Preset System and Migration Engine
|
|
2
|
+
|
|
3
|
+
## Level 0 — Two independent subsystems
|
|
4
|
+
|
|
5
|
+
This document covers two related but independent subsystems:
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
flowchart LR
|
|
9
|
+
A["Preset system\nReusable task method packages\n(injected at new-task time)"]
|
|
10
|
+
B["Migration engine\nOnboarding legacy projects to harness\n(migrate-* commands)"]
|
|
11
|
+
|
|
12
|
+
A -->|"legacy-migration Preset\nis the migration engine's dedicated Preset"| B
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Their relationship: the migration engine has a dedicated Preset (`legacy-migration`), but
|
|
16
|
+
the Preset system itself is general-purpose — any type of task can have its own Preset.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Part 1 — Preset System
|
|
21
|
+
|
|
22
|
+
### Level 1 — What is a Preset
|
|
23
|
+
|
|
24
|
+
A Preset is a **reusable task method package** that bundles everything a specific type of
|
|
25
|
+
task needs:
|
|
26
|
+
- Template append content (appended on top of standard templates)
|
|
27
|
+
- Execution scripts (run during plan / scaffold phases)
|
|
28
|
+
- Check scripts (validate Preset compliance)
|
|
29
|
+
- Resource declarations (reference files, artifacts, required reads)
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
flowchart TD
|
|
33
|
+
Preset["Preset package\npresets/<id>/"]
|
|
34
|
+
|
|
35
|
+
Preset --> Manifest["preset.yaml\nPackage manifest (required)"]
|
|
36
|
+
Preset --> Templates["templates/\nTemplate append files"]
|
|
37
|
+
Preset --> Scripts["scripts/\nPlan / scaffold scripts"]
|
|
38
|
+
Preset --> Checks["checks/\nCheck scripts"]
|
|
39
|
+
Preset --> Workbench["workbench/\nDashboard panel definitions (optional)"]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Level 1 — Layered discovery: three search layers
|
|
43
|
+
|
|
44
|
+
Presets are searched in **project → user → builtin** order, with **first-match-wins** for
|
|
45
|
+
same-named Presets:
|
|
46
|
+
|
|
47
|
+
```mermaid
|
|
48
|
+
flowchart LR
|
|
49
|
+
P["project layer\n<target>/.coding-agent-harness/presets/\n(highest priority)"]
|
|
50
|
+
U["user layer\n~/.coding-agent-harness/presets/\n(second priority)"]
|
|
51
|
+
B["builtin layer\npackage/presets/\n(lowest priority)"]
|
|
52
|
+
|
|
53
|
+
P -->|"continue if not found"| U -->|"continue if not found"| B
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This design allows:
|
|
57
|
+
- **Project-level override**: put a same-named Preset in the project to override the builtin version
|
|
58
|
+
- **User-level override**: put a Preset in the home directory to apply to all projects
|
|
59
|
+
- **Builtin fallback**: Presets bundled with the package serve as the default implementation
|
|
60
|
+
|
|
61
|
+
`harness preset install --project <preset-id>` installs a Preset to the project layer;
|
|
62
|
+
`harness preset uninstall --project <preset-id>` removes it from the project layer
|
|
63
|
+
(doesn't affect user and builtin layers).
|
|
64
|
+
|
|
65
|
+
### Level 2 — preset.yaml structure
|
|
66
|
+
|
|
67
|
+
```mermaid
|
|
68
|
+
flowchart TD
|
|
69
|
+
YAML["preset.yaml"]
|
|
70
|
+
|
|
71
|
+
YAML --> Meta["Basic info\nid / version / purpose\ncompatibleBudgets / localeSupport"]
|
|
72
|
+
YAML --> Task["task config\nkind / requiresFromSession\nprojectLevelOnly"]
|
|
73
|
+
YAML --> EP["entrypoints\n(see below)"]
|
|
74
|
+
YAML --> WS["writeScopes\nRestrict write paths (security boundary)"]
|
|
75
|
+
YAML --> Resources["resources\nreferences / artifacts / context.requiredReads"]
|
|
76
|
+
YAML --> Audit["audit\nmanifestRequired: true\nevidenceFiles[]"]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Level 3 — Entrypoint type system
|
|
80
|
+
|
|
81
|
+
Each entrypoint has two dimensions: **name** (when it triggers) and **type** (how it executes):
|
|
82
|
+
|
|
83
|
+
```mermaid
|
|
84
|
+
flowchart LR
|
|
85
|
+
subgraph "Name (when it triggers)"
|
|
86
|
+
N1["newTask\nWhen harness new-task --preset X is run"]
|
|
87
|
+
N2["plan\nMigration plan phase"]
|
|
88
|
+
N3["scaffold\nBulk completion phase"]
|
|
89
|
+
N4["check\nValidation phase"]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
subgraph "Type (how it executes)"
|
|
93
|
+
T1["template\nAppend template content to task files"]
|
|
94
|
+
T2["script\nRun a Node.js script"]
|
|
95
|
+
T3["check\nRun a check script"]
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Differences between the three execution types:
|
|
100
|
+
- **template**: Renders a template file and appends the result to task files
|
|
101
|
+
(`task_plan.md`, `execution_strategy.md`, etc.)
|
|
102
|
+
- **script**: Executes a Node.js script that can read/write the filesystem;
|
|
103
|
+
returns results as audit evidence
|
|
104
|
+
- **check**: Executes a check script that validates Preset application completeness;
|
|
105
|
+
blocks task creation on failure
|
|
106
|
+
|
|
107
|
+
Each entrypoint also declares `writes` (allowed write path globs) and `reads`
|
|
108
|
+
(allowed read path globs).
|
|
109
|
+
|
|
110
|
+
### Level 3 — writeScopes security boundary
|
|
111
|
+
|
|
112
|
+
`writeScopes` is a path allowlist that restricts Presets to only writing to declared directories.
|
|
113
|
+
`assertPresetWriteScope()` checks whether the relative path matches any scope on every file write.
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
writeScopes:
|
|
117
|
+
tasks:
|
|
118
|
+
path: docs/09-PLANNING/TASKS/**
|
|
119
|
+
access: write
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Supports `path/**` wildcards for a directory and all its subdirectories.
|
|
123
|
+
Relative paths must be normalized (no `../`, no absolute paths) to prevent path traversal attacks.
|
|
124
|
+
|
|
125
|
+
### Level 2 — Preset lifecycle
|
|
126
|
+
|
|
127
|
+
```mermaid
|
|
128
|
+
sequenceDiagram
|
|
129
|
+
participant User
|
|
130
|
+
participant CLI as harness CLI
|
|
131
|
+
participant Registry as preset-registry.mjs
|
|
132
|
+
participant Engine as preset-engine.mjs
|
|
133
|
+
participant TaskDir as Task directory
|
|
134
|
+
|
|
135
|
+
User->>CLI: harness new-task my-task --preset legacy-migration --from-session session.json
|
|
136
|
+
CLI->>Registry: listPresetPackages()\n(layered discovery, first-match-wins)
|
|
137
|
+
Registry-->>CLI: Preset object (with manifest + path)
|
|
138
|
+
CLI->>TaskDir: Create standard task scaffold (brief / task_plan / visual_map etc.)
|
|
139
|
+
CLI->>Engine: executeEntrypoint("newTask", preset, taskDir)
|
|
140
|
+
Engine->>TaskDir: Append Preset template content to task files
|
|
141
|
+
CLI->>TaskDir: Write Preset metadata to task_plan.md
|
|
142
|
+
CLI->>TaskDir: Generate evidence bundle (preset-manifest.json / preset-audit.json)
|
|
143
|
+
CLI-->>User: Task creation complete
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Level 1 — Currently available Presets
|
|
147
|
+
|
|
148
|
+
| Preset ID | Purpose | Compatible Budget | Special requirements |
|
|
149
|
+
| --- | --- | --- | --- |
|
|
150
|
+
| `legacy-migration` | Migrate legacy harness projects to v1.0 | complex | Requires `--from-session session.json` |
|
|
151
|
+
| `lesson-sedimentation` | Lesson sedimentation tasks | standard, complex | None |
|
|
152
|
+
| `module` | Module parallel work tasks | standard, complex | Requires `--module <module-id>` |
|
|
153
|
+
| `standard-task` | Standard task method | standard, complex | None |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Part 2 — Migration Engine
|
|
158
|
+
|
|
159
|
+
### Level 1 — Three phases of migration
|
|
160
|
+
|
|
161
|
+
```mermaid
|
|
162
|
+
flowchart LR
|
|
163
|
+
A["① migrate-plan\nAnalyze gaps\nGenerate action queue"] --> B["② migrate-run\nExecute migration actions\nWrite session record"] --> C["③ migrate-verify\nVerify migration results\nCompare against baseline"]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Level 2 — What migrate-plan does
|
|
167
|
+
|
|
168
|
+
`buildMigrationPlan()` identifies 6 types of gaps:
|
|
169
|
+
|
|
170
|
+
```mermaid
|
|
171
|
+
flowchart TD
|
|
172
|
+
Plan["harness migrate-plan"]
|
|
173
|
+
|
|
174
|
+
Plan --> Scan["Scan target repo\nbuildStatus (non-strict mode)"]
|
|
175
|
+
Scan --> Detect["Detect existing capabilities\nreadCapabilityRegistry()"]
|
|
176
|
+
Detect --> Gaps["Identify gaps (6 types)"]
|
|
177
|
+
|
|
178
|
+
Gaps --> TaskActions["taskActions\nActive tasks missing execution_strategy.md\nor visual_map.md"]
|
|
179
|
+
Gaps --> ReviewActions["reviewActions\nMissing review fields\n(Reviewer Identity etc.)"]
|
|
180
|
+
Gaps --> LegacyActions["legacyActions\nMissing required reference files"]
|
|
181
|
+
Gaps --> LegacyResiduals["legacyResiduals\nContract gaps in historical tasks\n(should not be auto-migrated)"]
|
|
182
|
+
Gaps --> WeakBriefs["weakBriefTasks\nbrief.md quality below threshold"]
|
|
183
|
+
Gaps --> UnknownClass["unknownClassificationTasks\nTask classification unclear"]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Action queue format**: Each taskAction contains `taskId`, `path`, `files[]`, `commands[]`,
|
|
187
|
+
and an `action` description. `commands[]` is a list of harness CLI commands that can be
|
|
188
|
+
executed directly.
|
|
189
|
+
|
|
190
|
+
### Level 2 — Two modes of migrate-verify
|
|
191
|
+
|
|
192
|
+
```mermaid
|
|
193
|
+
flowchart TD
|
|
194
|
+
Verify["harness migrate-verify session.json"]
|
|
195
|
+
|
|
196
|
+
Verify --> Normal["Normal mode\nRe-run checks\nReport failures / warnings"]
|
|
197
|
+
|
|
198
|
+
Verify --> FullCutover["--full-cutover mode\nStrictest validation (8 conditions)"]
|
|
199
|
+
|
|
200
|
+
FullCutover --> C1{"session.result == complete?"}
|
|
201
|
+
C1 -->|"no"| F1["FAIL"]
|
|
202
|
+
C1 -->|"yes"| C2{"No strictDeferred?"}
|
|
203
|
+
C2 -->|"no"| F2["FAIL"]
|
|
204
|
+
C2 -->|"yes"| C3{"All counters == 0?\n(warnings / taskActions\nreviewSchemaGaps / legacyResiduals etc.)"}
|
|
205
|
+
C3 -->|"no"| F3["FAIL (list non-zero counters)"]
|
|
206
|
+
C3 -->|"yes"| C4{"fullCutoverEligible == true?"}
|
|
207
|
+
C4 -->|"no"| F4["FAIL"]
|
|
208
|
+
C4 -->|"yes"| P1["PASS (full cutover ready)"]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`--full-cutover` is the final acceptance criteria for migration completion: all 8 conditions
|
|
212
|
+
must be satisfied to pass.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Part 3 — Capability Registry
|
|
217
|
+
|
|
218
|
+
### Level 1 — Capability dependency graph
|
|
219
|
+
|
|
220
|
+
```mermaid
|
|
221
|
+
flowchart TD
|
|
222
|
+
Core["core\n(required, foundation for all other capabilities)"]
|
|
223
|
+
|
|
224
|
+
Core --> ModParallel["module-parallel\nModule registry + parallel work"]
|
|
225
|
+
Core --> AdvReview["adversarial-review\nAdversarial review reports\n(alias: review-contract)"]
|
|
226
|
+
Core --> LongRunning["long-running-task\nLong-running task contracts"]
|
|
227
|
+
Core --> Dashboard["dashboard\nLocal HTML Dashboard"]
|
|
228
|
+
Core --> SafeAdoption["safe-adoption\nSmooth onboarding for legacy projects"]
|
|
229
|
+
|
|
230
|
+
ModParallel --> SubagentWorker["subagent-worker\nCommit-backed worker handoff protocol"]
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Level 2 — selectWhen for each capability
|
|
234
|
+
|
|
235
|
+
| Capability | When to enable |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| `core` | Always — this is the required foundation |
|
|
238
|
+
| `module-parallel` | When the project has 2+ independent modules needing parallel ownership |
|
|
239
|
+
| `subagent-worker` | When code-change subagents need to work in isolated worktrees and commit handoffs |
|
|
240
|
+
| `adversarial-review` | When release, architecture, security, data, or policy risks require independent review artifacts |
|
|
241
|
+
| `long-running-task` | When Agents may run across multiple loops without per-step user confirmation |
|
|
242
|
+
| `dashboard` | When local read-only state visualization is needed |
|
|
243
|
+
| `safe-adoption` | When onboarding v1.0 into an existing harness project without rewriting history |
|
|
244
|
+
|
|
245
|
+
### Level 2 — Preset resource declarations (resources)
|
|
246
|
+
|
|
247
|
+
Presets can declare three types of resources. These are auto-generated at task creation
|
|
248
|
+
time and validated by the checker:
|
|
249
|
+
|
|
250
|
+
| Resource type | Meaning | Validation |
|
|
251
|
+
| --- | --- | --- |
|
|
252
|
+
| `resources.references` | Reference files provided by the Preset | File exists + indexed in `references/INDEX.md` + required reads declared in `task_plan.md` |
|
|
253
|
+
| `resources.artifacts` | Artifacts generated by the Preset | File exists + indexed in `artifacts/INDEX.md` |
|
|
254
|
+
| `context.requiredReads` | Reference file IDs that must be read | Recorded in both indexes |
|
|
255
|
+
|
|
256
|
+
This is a **three-layer validation chain**: file exists → indexed in index table →
|
|
257
|
+
required reads declared in task_plan.md. Any missing layer produces a failure.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Part 4 — Design decisions
|
|
262
|
+
|
|
263
|
+
### Why Presets weren't there from the start
|
|
264
|
+
|
|
265
|
+
The Preset system evolved from the need "migrating legacy projects is too complex". Initially
|
|
266
|
+
there was only `new-task --budget complex` with no Preset concept. When users raised the
|
|
267
|
+
legacy project migration need, the initial proposal was to invent a new "Ultra" task level.
|
|
268
|
+
|
|
269
|
+
Research found the problem wasn't that Complex was insufficient — it was "without Presets,
|
|
270
|
+
every Agent has to figure out how to structure the migration process from scratch". Three
|
|
271
|
+
independent subagent adversarial reviews all pointed to the same conclusion: Preset is the
|
|
272
|
+
right abstraction, Ultra is over-engineering.
|
|
273
|
+
|
|
274
|
+
Reasons for rejecting Ultra:
|
|
275
|
+
1. Ultra would introduce a second task system, breaking the consistency of simple/standard/complex
|
|
276
|
+
2. The root cause wasn't that Complex couldn't handle it, but that there was no pre-filled scaffold
|
|
277
|
+
3. Preset is a general abstraction, not just for migration — any type of task can have its own Preset
|
|
278
|
+
|
|
279
|
+
### Why Preset manifests use YAML
|
|
280
|
+
|
|
281
|
+
YAML was chosen for readability — Preset manifests need to be written and reviewed by humans,
|
|
282
|
+
and YAML has fewer quotes and brackets than JSON. A lightweight custom parser (`parseSimpleYaml()`)
|
|
283
|
+
was written instead of introducing `js-yaml` to maintain zero dependencies. JS format was
|
|
284
|
+
ruled out because Presets need to be cross-tool auditable and can't be executable code.
|
|
285
|
+
|
|
286
|
+
### Why layered discovery (project/user/builtin)
|
|
287
|
+
|
|
288
|
+
Layered discovery was introduced two days after the Preset system itself. Initially it only
|
|
289
|
+
read from the package's fixed `presets/` path. The core problem layered design solves:
|
|
290
|
+
- Different projects can have their own private Presets (project layer)
|
|
291
|
+
- Users can install Presets shared across projects (user layer)
|
|
292
|
+
- Package bundled Presets serve as fallback, usable without installation (builtin layer)
|
|
293
|
+
|
|
294
|
+
Priority order (project > user > builtin) ensures project-level customization can override
|
|
295
|
+
global defaults.
|
|
296
|
+
|
|
297
|
+
### Why migration is split into three phases instead of one step
|
|
298
|
+
|
|
299
|
+
The core consideration is "can't auto-migrate" — Presets only scaffold structure, they don't
|
|
300
|
+
automatically modify historical docs, auto-stage, or auto-commit. Before actually writing to
|
|
301
|
+
the target repo, users still need to confirm the write scope and migration depth.
|
|
302
|
+
|
|
303
|
+
- `migrate-plan`: read-only analysis, no side effects
|
|
304
|
+
- `migrate-run`: write execution, requires user confirmation
|
|
305
|
+
- `migrate-verify`: post-hoc verification, confirms migration results
|
|
306
|
+
|
|
307
|
+
Three separate steps give users a confirmation opportunity at every node with side effects.
|
|
308
|
+
|
|
309
|
+
### Why full-cutover verification is so strict
|
|
310
|
+
|
|
311
|
+
`full-cutover` is an irreversible declaration — once migration is declared complete,
|
|
312
|
+
subsequent Agents won't treat this project as a migration target anymore. A more lenient
|
|
313
|
+
approach (only checking strict pass) was rejected because real-world project validation
|
|
314
|
+
(471 tasks) proved that even with a strict pass, weak briefs or legacy-only visual maps
|
|
315
|
+
could still remain.
|
|
316
|
+
|
|
317
|
+
### writeScopes security boundary
|
|
318
|
+
|
|
319
|
+
writeScopes and the Preset system were introduced simultaneously — it wasn't a security
|
|
320
|
+
hardening added later. Presets are third-party installable packages, and without write
|
|
321
|
+
scope restrictions, a malicious or buggy Preset could overwrite arbitrary files. The
|
|
322
|
+
runtime enforces path checks, rejecting paths starting with `../` and absolute paths
|
|
323
|
+
(path traversal protection).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Coding Agent Harness — Architecture Explainer
|
|
2
|
+
|
|
3
|
+
This set of documents helps you understand the system architecture of `coding-agent-harness`.
|
|
4
|
+
Whether you want to contribute code, integrate it into your own project, or just figure out
|
|
5
|
+
"how does this thing actually work" — this is the best place to start.
|
|
6
|
+
|
|
7
|
+
Each document uses a **top-down, layer-by-layer** approach: it gives you a big picture first
|
|
8
|
+
to build an overall mental model, then dives into each module. You can stop at any layer —
|
|
9
|
+
you don't need to read every detail.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Why these docs exist
|
|
14
|
+
|
|
15
|
+
The `coding-agent-harness` codebase itself isn't complex, but its **design intent** isn't
|
|
16
|
+
easy to read directly from the code.
|
|
17
|
+
|
|
18
|
+
For example:
|
|
19
|
+
- Why is state stored in Markdown files instead of a database?
|
|
20
|
+
- Why are there three check profiles instead of one?
|
|
21
|
+
- What's the difference between `governance-sync` and `governance rebuild`, and why are they separate?
|
|
22
|
+
- Why must `review-confirm` be a manual operation — why can't it be automated?
|
|
23
|
+
|
|
24
|
+
The answers to these questions are scattered across design decisions, historical evolution,
|
|
25
|
+
and operating standards. These docs bring them together so you can understand the system's
|
|
26
|
+
"why" without digging through git log.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reading order
|
|
31
|
+
|
|
32
|
+
Reading in order works best, about 15-25 minutes per doc:
|
|
33
|
+
|
|
34
|
+
| File | Topic | What you'll understand |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| [01-system-overview.md](01-system-overview.md) | System overview | What this is, what problem it solves, what the four main blocks do |
|
|
37
|
+
| [02-module-dependency.md](02-module-dependency.md) | Code modules | How the CLI dispatches, how the 30+ modules in lib/ are layered, dependency relationships |
|
|
38
|
+
| [03-task-lifecycle.md](03-task-lifecycle.md) | Task lifecycle | The full flow of a task from creation to closeout, gates, and the queue system |
|
|
39
|
+
| [04-check-and-governance.md](04-check-and-governance.md) | Check system | Three profiles, what each of the 9 validators checks, how governance indexes are rebuilt |
|
|
40
|
+
| [05-data-flow.md](05-data-flow.md) | Data flow | How Markdown files become a Dashboard, the boundary between two generation modes |
|
|
41
|
+
| [06-preset-and-migration.md](06-preset-and-migration.md) | Preset and migration | Preset package structure and entrypoint type system, three phases of legacy project migration |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Document conventions
|
|
46
|
+
|
|
47
|
+
Each file uses `Level 0 / 1 / 2 / 3` to mark depth:
|
|
48
|
+
|
|
49
|
+
- **Level 0**: Highest level, 3-5 big blocks, builds overall understanding (required reading)
|
|
50
|
+
- **Level 1**: Expands the blocks, shows sub-modules (recommended)
|
|
51
|
+
- **Level 2**: Dives into sub-modules, explains internal logic (read as needed)
|
|
52
|
+
- **Level 3**: Most detailed, function-level flows (reference use)
|
|
53
|
+
|
|
54
|
+
You can stop at Level 1 and go deeper only when you need to.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick lookup
|
|
59
|
+
|
|
60
|
+
If you have a specific question, jump directly to the relevant file:
|
|
61
|
+
|
|
62
|
+
| I want to know… | Go to |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| What problem this system solves | [01 — System overview](01-system-overview.md) |
|
|
65
|
+
| What `harness check` validates | [04 — Check system](04-check-and-governance.md) |
|
|
66
|
+
| What a task's `review` state means | [03 — Task lifecycle](03-task-lifecycle.md) |
|
|
67
|
+
| Where Dashboard data comes from | [05 — Data flow](05-data-flow.md) |
|
|
68
|
+
| How to write a Preset | [06 — Preset and migration](06-preset-and-migration.md) |
|
|
69
|
+
| What a module in the code does | [02 — Code modules](02-module-dependency.md) |
|
|
70
|
+
| How to migrate a legacy project | [06 — Preset and migration](06-preset-and-migration.md) |
|
|
Binary file
|