coding-agent-harness 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.en-US.md +14 -0
  3. package/README.md +111 -86
  4. package/README.zh-CN.md +270 -0
  5. package/SKILL.md +116 -189
  6. package/docs-release/README.md +72 -5
  7. package/docs-release/architecture/overview.md +286 -28
  8. package/docs-release/architecture/overview.zh-CN.md +288 -0
  9. package/docs-release/assets/dashboard-overview-en.png +0 -0
  10. package/docs-release/assets/harness-architecture.svg +163 -0
  11. package/docs-release/assets/harness-workflow.svg +64 -0
  12. package/docs-release/guides/agent-installation.en-US.md +214 -0
  13. package/docs-release/guides/agent-installation.md +123 -26
  14. package/docs-release/guides/document-audience-and-surfaces.en-US.md +112 -0
  15. package/docs-release/guides/document-audience-and-surfaces.md +112 -0
  16. package/docs-release/guides/full-legacy-migration-subagent-strategy.md +334 -0
  17. package/docs-release/guides/full-legacy-migration-subagent-strategy.zh-CN.md +334 -0
  18. package/docs-release/guides/legacy-migration-agent-prompt.md +384 -0
  19. package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +361 -0
  20. package/docs-release/guides/migration-playbook.en-US.md +325 -0
  21. package/docs-release/guides/migration-playbook.md +329 -0
  22. package/docs-release/guides/parent-control-repository-pattern.en-US.md +252 -0
  23. package/docs-release/guides/parent-control-repository-pattern.md +252 -0
  24. package/docs-release/guides/repository-operating-models.en-US.md +196 -0
  25. package/docs-release/guides/repository-operating-models.md +196 -0
  26. package/docs-release/intl/README.md +15 -0
  27. package/docs-release/intl/de-DE.md +18 -0
  28. package/docs-release/intl/en-US.md +18 -0
  29. package/docs-release/intl/es-ES.md +18 -0
  30. package/docs-release/intl/fr-FR.md +18 -0
  31. package/docs-release/intl/ja-JP.md +18 -0
  32. package/docs-release/intl/ko-KR.md +18 -0
  33. package/docs-release/intl/zh-CN.md +18 -0
  34. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/brief.md +13 -0
  35. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/lesson_candidates.md +24 -0
  36. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/progress.md +1 -1
  37. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/task_plan.md +4 -2
  38. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/{visual_roadmap.md → visual_map.md} +9 -1
  39. package/package.json +3 -1
  40. package/references/agents-md-pattern.md +3 -3
  41. package/references/docs-directory-standard.md +47 -3
  42. package/references/external-source-intake-standard.md +75 -0
  43. package/references/harness-ledger.md +5 -3
  44. package/references/legacy-12-phase-bootstrap.md +41 -0
  45. package/references/lessons-governance.md +23 -6
  46. package/references/planning-loop.md +41 -3
  47. package/references/project-onboarding-audit.md +10 -0
  48. package/references/repo-governance-standard.md +2 -0
  49. package/references/testing-standard.md +50 -0
  50. package/references/walkthrough-closeout.md +6 -5
  51. package/scripts/check-harness.mjs +76 -35
  52. package/scripts/harness.mjs +303 -12
  53. package/scripts/lib/capability-registry.mjs +533 -0
  54. package/scripts/lib/check-profiles.mjs +510 -0
  55. package/scripts/lib/core-shared.mjs +186 -0
  56. package/scripts/lib/dashboard-data.mjs +389 -0
  57. package/scripts/lib/dashboard-workbench.mjs +217 -0
  58. package/scripts/lib/dashboard-writer.mjs +93 -2
  59. package/scripts/lib/harness-core.mjs +10 -1318
  60. package/scripts/lib/lesson-maintenance.mjs +145 -0
  61. package/scripts/lib/markdown-utils.mjs +158 -0
  62. package/scripts/lib/migration-planner.mjs +478 -0
  63. package/scripts/lib/migration-support.mjs +312 -0
  64. package/scripts/lib/task-lifecycle.mjs +755 -0
  65. package/scripts/lib/task-scanner.mjs +682 -0
  66. package/scripts/smoke-dashboard.mjs +22 -0
  67. package/scripts/test-harness.mjs +926 -14
  68. package/templates/AGENTS.md.template +41 -30
  69. package/templates/architecture/Architecture-SSoT.md +21 -0
  70. package/templates/architecture/README.md +49 -0
  71. package/templates/architecture/critical-flows.md +22 -0
  72. package/templates/architecture/local-repo-context.md +20 -0
  73. package/templates/architecture/service-catalog.md +17 -0
  74. package/templates/architecture/services/service-template.md +31 -0
  75. package/templates/architecture/system-map.md +22 -0
  76. package/templates/dashboard/assets/app-src/00-state.js +41 -0
  77. package/templates/dashboard/assets/app-src/10-router.js +76 -0
  78. package/templates/dashboard/assets/app-src/20-overview.js +235 -0
  79. package/templates/dashboard/assets/app-src/30-tasks.js +563 -0
  80. package/templates/dashboard/assets/app-src/40-modules.js +58 -0
  81. package/templates/dashboard/assets/app-src/45-review.js +128 -0
  82. package/templates/dashboard/assets/app-src/50-migration.js +169 -0
  83. package/templates/dashboard/assets/app-src/60-shared.js +61 -0
  84. package/templates/dashboard/assets/app-src/90-bindings.js +382 -0
  85. package/templates/dashboard/assets/app.css +2575 -310
  86. package/templates/dashboard/assets/app.js +1498 -307
  87. package/templates/dashboard/assets/app.manifest.json +11 -0
  88. package/templates/dashboard/assets/i18n.js +429 -44
  89. package/templates/dashboard/assets/mermaid-renderer.js +58 -8
  90. package/templates/development/README.md +52 -0
  91. package/templates/development/codebase-map.md +11 -0
  92. package/templates/development/cross-repo-debugging.md +18 -0
  93. package/templates/development/external-context/service-template.md +33 -0
  94. package/templates/development/external-source-packs/README.md +24 -0
  95. package/templates/development/external-source-packs/digest-template.md +28 -0
  96. package/templates/development/local-setup.md +16 -0
  97. package/templates/development/stubs-and-mocks.md +11 -0
  98. package/templates/integrations/README.md +40 -0
  99. package/templates/integrations/api-contract.md +42 -0
  100. package/templates/integrations/event-contract.md +46 -0
  101. package/templates/integrations/third-party/vendor-template.md +42 -0
  102. package/templates/integrations/webhook-contract.md +41 -0
  103. package/templates/planning/brief.md +32 -0
  104. package/templates/planning/lesson_candidates.md +58 -0
  105. package/templates/planning/long-running-task-contract.md +7 -0
  106. package/templates/planning/module_brief.md +25 -0
  107. package/templates/planning/module_session_prompt.md +6 -0
  108. package/templates/planning/task_plan.md +7 -5
  109. package/templates/planning/{visual_roadmap.md → visual_map.md} +24 -2
  110. package/templates/reference/docs-library-standard.md +31 -0
  111. package/templates/reference/execution-workflow-standard.md +4 -2
  112. package/templates/reference/external-source-intake-standard.md +82 -0
  113. package/templates/reference/harness-ledger-standard.md +1 -0
  114. package/templates/reference/repo-governance-standard.md +6 -4
  115. package/templates/reference/walkthrough-standard.md +2 -1
  116. package/templates/walkthrough/walkthrough-template.md +2 -2
  117. package/templates-zh-CN/AGENTS.md.template +69 -70
  118. package/templates-zh-CN/architecture/Architecture-SSoT.md +21 -0
  119. package/templates-zh-CN/architecture/README.md +51 -0
  120. package/templates-zh-CN/architecture/critical-flows.md +24 -0
  121. package/templates-zh-CN/architecture/local-repo-context.md +20 -0
  122. package/templates-zh-CN/architecture/service-catalog.md +17 -0
  123. package/templates-zh-CN/architecture/services/service-template.md +31 -0
  124. package/templates-zh-CN/architecture/system-map.md +22 -0
  125. package/templates-zh-CN/development/README.md +54 -0
  126. package/templates-zh-CN/development/codebase-map.md +11 -0
  127. package/templates-zh-CN/development/cross-repo-debugging.md +18 -0
  128. package/templates-zh-CN/development/external-context/service-template.md +33 -0
  129. package/templates-zh-CN/development/external-source-packs/README.md +24 -0
  130. package/templates-zh-CN/development/external-source-packs/digest-template.md +28 -0
  131. package/templates-zh-CN/development/local-setup.md +16 -0
  132. package/templates-zh-CN/development/stubs-and-mocks.md +11 -0
  133. package/templates-zh-CN/integrations/README.md +42 -0
  134. package/templates-zh-CN/integrations/api-contract.md +42 -0
  135. package/templates-zh-CN/integrations/event-contract.md +46 -0
  136. package/templates-zh-CN/integrations/third-party/vendor-template.md +42 -0
  137. package/templates-zh-CN/integrations/webhook-contract.md +41 -0
  138. package/templates-zh-CN/planning/brief.md +32 -0
  139. package/templates-zh-CN/planning/lesson_candidates.md +58 -0
  140. package/templates-zh-CN/planning/long-running-task-contract.md +1 -1
  141. package/templates-zh-CN/planning/module_brief.md +25 -0
  142. package/templates-zh-CN/planning/module_plan.md +2 -2
  143. package/templates-zh-CN/planning/module_session_prompt.md +4 -3
  144. package/templates-zh-CN/planning/task_plan.md +10 -4
  145. package/templates-zh-CN/planning/{visual_roadmap.md → visual_map.md} +21 -2
  146. package/templates-zh-CN/reference/docs-library-standard.md +35 -0
  147. package/templates-zh-CN/reference/execution-workflow-standard.md +9 -2
  148. package/templates-zh-CN/reference/external-source-intake-standard.md +82 -0
  149. package/templates-zh-CN/reference/harness-ledger-standard.md +5 -2
  150. package/templates-zh-CN/reference/repo-governance-standard.md +2 -0
  151. package/templates-zh-CN/reference/walkthrough-standard.md +4 -4
  152. package/templates-zh-CN/walkthrough/Closeout-SSoT.md +2 -2
  153. package/templates-zh-CN/walkthrough/walkthrough-template.md +2 -2
  154. package/templates-zh-CN/dashboard/assets/app.css +0 -399
  155. package/templates-zh-CN/dashboard/assets/app.js +0 -435
  156. package/templates-zh-CN/dashboard/assets/i18n.js +0 -47
  157. package/templates-zh-CN/dashboard/assets/markdown-reader.js +0 -116
  158. package/templates-zh-CN/dashboard/assets/mermaid-renderer.js +0 -59
  159. package/templates-zh-CN/dashboard/index.html +0 -18
@@ -0,0 +1,235 @@
1
+ function overview() {
2
+ return `<div class="dashboard-grid">
3
+ <main class="dashboard-main stack">
4
+ ${flowPanel()}
5
+ ${activeTaskBriefs()}
6
+ ${migrationSummaryPanel()}
7
+ </main>
8
+ <aside class="dashboard-sidebar stack">
9
+ ${statusStrip()}
10
+ ${ledgerPanel()}
11
+ ${healthPanel()}
12
+ ${lessonPanel()}
13
+ </aside>
14
+ </div>`;
15
+ }
16
+
17
+ function statusStrip() {
18
+ const status = bundle.status?.checkState?.status || "unknown";
19
+ const failures = bundle.status?.checkState?.failures || 0;
20
+ const warnings = bundle.status?.checkState?.warnings || 0;
21
+ const tasks = bundle.status?.tasks || [];
22
+ const summary = bundle.status?.summary || {};
23
+ const visual = summary.visualMapCoverage || {};
24
+ const withBrief = tasks.filter((task) => task.briefSource === "standalone").length;
25
+ return `<section class="status-card-group">
26
+ <div class="status-primary ${status}">
27
+ <span>${t("readiness")}</span>
28
+ <strong>${label(status)}</strong>
29
+ <p>${nextActionText()}</p>
30
+ </div>
31
+ <div class="metrics-grid">
32
+ ${metric(t("tasks"), tasks.length)}
33
+ ${metric(t("briefCoverage"), `${withBrief}/${tasks.length}`)}
34
+ ${metric(t("visualMapCoverage"), `${visual.canonical || 0}/${summary.visualMapRequiredCount || tasks.length}`)}
35
+ ${metric(t("fullCutover"), summary.fullCutoverEligible ? t("ready") : t("notReady"))}
36
+ ${metric(t("legacyVisualOnly"), summary.legacyVisualOnlyCount || 0)}
37
+ ${metric(t("weakBrief"), summary.weakBriefCount || 0)}
38
+ ${metric(t("blockers"), failures)}
39
+ ${metric(t("advice"), warnings)}
40
+ </div>
41
+ </section>`;
42
+ }
43
+
44
+ function metric(labelText, value) {
45
+ return `<div class="metric"><span>${escapeHtml(labelText)}</span><strong>${escapeHtml(value)}</strong></div>`;
46
+ }
47
+
48
+ function nextActionText() {
49
+ const failures = bundle.status?.checkState?.failures || 0;
50
+ if (failures > 0) return t("resolveBlockers");
51
+ const missingBriefs = (bundle.status?.tasks || []).filter((task) => task.briefSource !== "standalone").length;
52
+ if (missingBriefs > 0) return `${missingBriefs} ${t("missingBriefs")}`;
53
+ const warnings = bundle.status?.checkState?.warnings || 0;
54
+ if (warnings > 0) return t("reviewAdvice");
55
+ return t("noBlockers");
56
+ }
57
+
58
+ function flowPanel() {
59
+ const tasks = bundle.status?.tasks || [];
60
+ const total = tasks.length;
61
+ if (total === 0) return "";
62
+ const active = tasks.filter((task) => isActiveTaskState(task.state)).length;
63
+ const done = tasks.filter((task) => !isActiveTaskState(task.state) && (task.state === "done" || task.completion === 100)).length;
64
+ const planned = Math.max(0, total - done - active);
65
+ const pct = (n) => total > 0 ? Math.round((n / total) * 100) : 0;
66
+ return `<section class="flow-panel">
67
+ <div class="section-head">
68
+ <div>
69
+ <p class="eyebrow">${t("firstLook")}</p>
70
+ <h2>${t("projectProgress")}</h2>
71
+ </div>
72
+ <span class="subtle">${done}/${total} ${t("completed")}</span>
73
+ </div>
74
+ <div class="progress-bar-container">
75
+ <div class="progress-bar">
76
+ ${done > 0 ? `<div class="progress-segment done" style="width:${pct(done)}%" title="${t("done")}: ${done}"></div>` : ""}
77
+ ${active > 0 ? `<div class="progress-segment active" style="width:${pct(active)}%" title="${t("active")}: ${active}"></div>` : ""}
78
+ ${planned > 0 ? `<div class="progress-segment planned" style="width:${pct(planned)}%" title="${t("planned")}: ${planned}"></div>` : ""}
79
+ </div>
80
+ <div class="progress-legend">
81
+ <span class="legend-item"><span class="legend-dot done"></span>${t("done")} ${done}</span>
82
+ <span class="legend-item"><span class="legend-dot active"></span>${t("active")} ${active}</span>
83
+ <span class="legend-item"><span class="legend-dot planned"></span>${t("planned")} ${planned}</span>
84
+ </div>
85
+ </div>
86
+ ${usesAggregateFlow() ? migrationRunwayBreakdown() : ""}
87
+ </section>`;
88
+ }
89
+
90
+ function projectMermaid() {
91
+ if (usesAggregateFlow()) return migrationAggregateMermaid();
92
+ const graph = bundle.graph || { nodes: [], edges: [] };
93
+ const preferredTypes = graph.nodes?.some((node) => node.type === "module") ? ["module", "step"] : ["task", "phase"];
94
+ const nodes = (graph.nodes || [])
95
+ .filter((node) => preferredTypes.includes(node.type))
96
+ .filter((node) => node.type !== "phase" || ["in_progress", "review", "blocked", "done"].includes(node.state))
97
+ .slice(0, 28);
98
+ if (nodes.length < 2) return mermaidFromBriefs();
99
+ const nodeIds = new Set(nodes.map((node) => node.id));
100
+ const lines = ["flowchart LR"];
101
+ let edgeCount = 0;
102
+ for (const edge of graph.edges || []) {
103
+ if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) continue;
104
+ lines.push(` ${mermaidId(edge.from)}["${mermaidLabel(edge.from)}"] --> ${mermaidId(edge.to)}["${mermaidLabel(edge.to)}"]`);
105
+ edgeCount += 1;
106
+ if (edgeCount >= 34) break;
107
+ }
108
+ if (edgeCount === 0) {
109
+ for (let index = 1; index < nodes.length; index += 1) {
110
+ lines.push(` ${mermaidId(nodes[index - 1].id)}["${mermaidLabel(nodes[index - 1].id)}"] --> ${mermaidId(nodes[index].id)}["${mermaidLabel(nodes[index].id)}"]`);
111
+ }
112
+ }
113
+ return lines.join("\n");
114
+ }
115
+
116
+ function usesAggregateFlow() {
117
+ const graph = bundle.graph || { nodes: [], edges: [] };
118
+ const taskCount = (bundle.status?.tasks || []).length;
119
+ const taskNodes = (graph.nodes || []).filter((node) => node.type === "task").length;
120
+ const usefulEdges = (graph.edges || []).filter((edge) => ["depends_on", "current_step"].includes(edge.type)).length;
121
+ return taskCount > 80 || taskNodes > 80 || ((graph.nodes || []).length > 80 && usefulEdges < 6);
122
+ }
123
+
124
+ function migrationAggregateMermaid() {
125
+ const tasks = bundle.status?.tasks || [];
126
+ const warnings = warningQueue();
127
+ const activeContracts = warnings.filter((warning) => warning.phase === "active-task-contracts").length;
128
+ const moduleCount = new Set(tasks.map(taskModuleKey)).size;
129
+ const reviewWarnings = warnings.filter((warning) => ["review-evidence", "strict-cutover"].includes(warning.phase)).length;
130
+ const lines = [
131
+ "flowchart LR",
132
+ ` baseline["${t("runwayBaseline")}\\n${tasks.length} ${t("tasks")}"] --> triage["${t("runwayTriage")}\\n${warnings.length} ${t("warnings")}"]`,
133
+ ` triage --> contracts["${t("runwayContracts")}\\n${activeContracts} ${t("items")}"]`,
134
+ ` contracts --> modules["${t("runwayModules")}\\n${moduleCount} ${t("groups")}"]`,
135
+ ` modules --> cutover["${t("runwayCutover")}\\n${reviewWarnings} ${t("items")}"]`,
136
+ ];
137
+ return lines.join("\n");
138
+ }
139
+
140
+ function migrationRunwayBreakdown() {
141
+ const tasks = bundle.status?.tasks || [];
142
+ const warnings = warningQueue();
143
+ const phases = [
144
+ ["baseline", t("runwayBaseline"), tasks.length, t("tasks"), "#/tasks"],
145
+ ["triage", t("runwayTriage"), warnings.length, t("warnings"), "#/"],
146
+ ["active-task-contracts", t("runwayContracts"), warnings.filter((warning) => warning.phase === "active-task-contracts").length, t("items"), "#/"],
147
+ ["module-classification", t("runwayModules"), new Set(tasks.map(taskModuleKey)).size, t("groups"), "#/tasks"],
148
+ ["strict-cutover", t("runwayCutover"), warnings.filter((warning) => warning.phase === "strict-cutover").length, t("items"), "#/"],
149
+ ];
150
+ return `<div class="runway-breakdown">
151
+ ${phases.map(([phase, title, count, unit, href]) => `<a href="${href}" data-runway-phase="${escapeAttr(phase)}"><strong>${escapeHtml(title)}</strong><span>${count} ${escapeHtml(unit)}</span></a>`).join("")}
152
+ </div>`;
153
+ }
154
+
155
+ function mermaidFromBriefs() {
156
+ const brief = activeTasks().map((task) => taskDocument(task, "brief.md")).find((doc) => doc?.content?.includes("```mermaid"));
157
+ const match = brief?.content.match(/```mermaid\s*([\s\S]*?)```/i);
158
+ return match ? match[1].trim() : "";
159
+ }
160
+
161
+ function graphSummary() {
162
+ const graph = bundle.graph || { nodes: [], edges: [] };
163
+ if (usesAggregateFlow()) return `${t("aggregateMigrationView")} · ${(bundle.status?.tasks || []).length} ${t("tasks")}`;
164
+ return `${graph.nodes?.length || 0} ${t("nodes")} · ${graph.edges?.length || 0} ${t("edges")}`;
165
+ }
166
+
167
+ function activeTaskBriefs() {
168
+ const tasks = activeTasks().slice(0, 8);
169
+ return `<section class="task-briefs">
170
+ <div class="section-head">
171
+ <div>
172
+ <p class="eyebrow">${t("currentWork")}</p>
173
+ <h2>${t("activeBriefs")}</h2>
174
+ </div>
175
+ <a href="#/tasks">${t("openTaskIndex")}</a>
176
+ </div>
177
+ <div class="brief-grid">${tasks.map((task) => taskBriefCard(task, { compact: false })).join("") || emptyState(t("noActiveTasks"))}</div>
178
+ </section>`;
179
+ }
180
+
181
+ function activeTasks() {
182
+ const tasks = bundle.status?.tasks || [];
183
+ const active = tasks.filter((task) => isActiveTaskState(task.state) || ["planned", "not_started"].includes(task.state));
184
+ if (active.length > 0) return active;
185
+ return tasks.filter((task) => task.briefSource === "standalone").slice(0, 6);
186
+ }
187
+
188
+ function isActiveTaskState(state) {
189
+ return ["active", "in_progress", "review", "blocked", "reopened", "current-evidence"].includes(state);
190
+ }
191
+
192
+ function taskBriefCard(task, { compact = true } = {}) {
193
+ const doc = taskDocument(task, "brief.md");
194
+ const summaryText = doc ? getBriefSummary(doc.content) : t("missingBriefExplain");
195
+ return `<article class="brief-card ${compact ? "compact" : ""}">
196
+ <div class="card-head">
197
+ <div>
198
+ <a href="#/tasks/${encodeURIComponent(task.id)}">${escapeHtml(task.title)}</a>
199
+ <p>${escapeHtml(task.id)}</p>
200
+ </div>
201
+ ${tag(task.state)}
202
+ </div>
203
+ ${progressBar(task.completion)}
204
+ <div class="brief-content">
205
+ <p class="brief-teaser">${escapeHtml(summaryText)}</p>
206
+ </div>
207
+ <div class="card-actions">
208
+ <button class="btn-drawer-trigger" data-open-drawer="${escapeAttr(task.id)}">${t("viewDetails")}</button>
209
+ </div>
210
+ </article>`;
211
+ }
212
+
213
+ function getBriefSummary(content) {
214
+ if (!content) return "";
215
+ let text = content
216
+ .replace(/#+\s+/g, "")
217
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
218
+ .replace(/[*_`]/g, "")
219
+ .replace(/-\s+/g, "")
220
+ .replace(/>\s+/g, "")
221
+ .replaceAll("\n", " ")
222
+ .replace(/\s+/g, " ")
223
+ .trim();
224
+ if (text.length > 140) text = text.slice(0, 137) + "...";
225
+ return text;
226
+ }
227
+
228
+ function generatedBrief(task) {
229
+ const phaseText = (task.phases || []).slice(0, 6).map((phase) => `<li><strong>${escapeHtml(phase.id)}</strong> ${escapeHtml(phase.output || phase.state)} · ${phase.completion}%</li>`).join("");
230
+ return `<div class="missing-brief">
231
+ <strong>${t("visibilityBriefMissing")}</strong>
232
+ <p>${t("missingBriefExplain")}</p>
233
+ <ul>${phaseText || `<li>${t("noPhaseData")}</li>`}</ul>
234
+ </div>`;
235
+ }