frontend-harness 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +27 -25
  2. package/dist/cli/index.js +8 -2
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/runtime/builtin-skills.js +6 -13
  5. package/dist/runtime/builtin-skills.js.map +1 -1
  6. package/dist/runtime/command-taxonomy.d.ts +1 -0
  7. package/dist/runtime/command-taxonomy.js +6 -2
  8. package/dist/runtime/command-taxonomy.js.map +1 -1
  9. package/dist/runtime/common/naming.js +16 -1
  10. package/dist/runtime/common/naming.js.map +1 -1
  11. package/dist/runtime/context.js +2 -2
  12. package/dist/runtime/context.js.map +1 -1
  13. package/dist/runtime/graph.js +5 -1
  14. package/dist/runtime/graph.js.map +1 -1
  15. package/dist/runtime/knowledge.js +12 -6
  16. package/dist/runtime/knowledge.js.map +1 -1
  17. package/dist/runtime/plan/component-resolver.js +88 -31
  18. package/dist/runtime/plan/component-resolver.js.map +1 -1
  19. package/dist/runtime/plan/guidance.js +8 -4
  20. package/dist/runtime/plan/guidance.js.map +1 -1
  21. package/dist/runtime/plan/proposal.js +4 -0
  22. package/dist/runtime/plan/proposal.js.map +1 -1
  23. package/dist/runtime/plan/workflow.js +45 -51
  24. package/dist/runtime/plan/workflow.js.map +1 -1
  25. package/dist/runtime/plan.js +101 -9
  26. package/dist/runtime/plan.js.map +1 -1
  27. package/dist/runtime/policy-provenance.js +2 -2
  28. package/dist/runtime/policy-provenance.js.map +1 -1
  29. package/dist/runtime/protocol-init.js +16 -15
  30. package/dist/runtime/protocol-init.js.map +1 -1
  31. package/dist/runtime/repair-packet.js +4 -3
  32. package/dist/runtime/repair-packet.js.map +1 -1
  33. package/dist/runtime/scaffold/vue-template.js +1 -1
  34. package/dist/runtime/scaffold/vue-template.js.map +1 -1
  35. package/dist/runtime/state-explain.js +2 -1
  36. package/dist/runtime/state-explain.js.map +1 -1
  37. package/dist/runtime/state.d.ts +10 -0
  38. package/dist/runtime/state.js +86 -18
  39. package/dist/runtime/state.js.map +1 -1
  40. package/dist/runtime/ui-restoration.d.ts +3 -2
  41. package/dist/runtime/ui-restoration.js +100 -26
  42. package/dist/runtime/ui-restoration.js.map +1 -1
  43. package/dist/runtime/units.js +25 -3
  44. package/dist/runtime/units.js.map +1 -1
  45. package/dist/runtime/verify.js +269 -3
  46. package/dist/runtime/verify.js.map +1 -1
  47. package/dist/schemas/types.d.ts +2 -0
  48. package/docs/DIRECTION.md +1 -1
  49. package/package.json +3 -5
  50. package/AGENTS.md +0 -60
  51. package/CLAUDE.md +0 -60
  52. package/dist/runtime/common/parsing.d.ts +0 -11
  53. package/dist/runtime/common/parsing.js +0 -30
  54. package/dist/runtime/common/parsing.js.map +0 -1
  55. package/dist/runtime/project-discovery.d.ts +0 -17
  56. package/dist/runtime/project-discovery.js +0 -174
  57. package/dist/runtime/project-discovery.js.map +0 -1
  58. package/dist/runtime/skills.d.ts +0 -19
  59. package/dist/runtime/skills.js +0 -230
  60. package/dist/runtime/skills.js.map +0 -1
  61. package/dist/runtime/verification-commands.d.ts +0 -11
  62. package/dist/runtime/verification-commands.js +0 -93
  63. package/dist/runtime/verification-commands.js.map +0 -1
  64. package/dist/storage/json.d.ts +0 -5
  65. package/dist/storage/json.js +0 -29
  66. package/dist/storage/json.js.map +0 -1
  67. package/dist/storage/paths.d.ts +0 -3
  68. package/dist/storage/paths.js +0 -9
  69. package/dist/storage/paths.js.map +0 -1
@@ -1,18 +1,87 @@
1
1
  import { lines } from "./common/text.js";
2
- export const UI_RESTORATION_CONSTRAINTS = [
3
- "Treat imported MCP/Stitch/Figma/HTML output as source material, not project-ready code.",
4
- "Normalize generated UI into project components, naming, state, routing, and styling conventions.",
5
- "Split substantial restored screens into page orchestration, typed data fixtures, view configuration, calculations, and focused presentational components.",
6
- "Represent mock/domain data with named object fields instead of long positional factory arguments.",
7
- "Derive progress, summary values, badges, disabled states, and totals from source data or explicit workflow state instead of duplicating static literals.",
8
- "Preserve PRD terminology in visible labels and record stable domain wording in project knowledge when PRD input is provided.",
9
- "Implement expected interactions for the affected workflow, or mark unsupported interactions as explicit assumptions in the handoff evidence.",
10
- "Use reusable design tokens for colors, spacing, layout metrics, and status semantics instead of one-off page-only constants.",
11
- "Keep design input, PRD summary, component boundary notes, and visual verification evidence as durable project artifacts when a design source is provided.",
12
- "Replace visible placeholder labels for icons or visual primitives with real project icons, components, or CSS shapes.",
13
- "Cross-check visible state consistency across selected steps, progress labels, percentages, bars, badges, disabled states, and summary counts.",
14
- "Keep generated build output such as dist/ out of lint and typecheck scopes."
2
+ const UI_RESTORATION_RULES = [
3
+ {
4
+ section: "Source Material",
5
+ constraint: "Treat imported MCP/Pixso/Figma/Stitch/HTML output as source material, not project-ready code.",
6
+ guidance: "Treat MCP, Pixso, Figma, Stitch, or exported HTML as reference material and rewrite it into project code."
7
+ },
8
+ {
9
+ section: "Source Material",
10
+ constraint: "When both design structure data and screenshots exist, use design structure data for hierarchy, text, dimensions, tokens, and component boundaries; use screenshots for final visual verification.",
11
+ guidance: "Prefer DST or structured design data for hierarchy, text, dimensions, tokens, and component boundaries; use screenshots to verify final rendered appearance, alignment, overflow, and visual state."
12
+ },
13
+ {
14
+ section: "Project Conventions",
15
+ constraint: "Normalize generated UI into project components, naming, state, routing, and styling conventions.",
16
+ guidance: "Preserve the target project's component API, naming, routing, state, style, UI-library, icon, and layout conventions."
17
+ },
18
+ {
19
+ section: "Source Structure",
20
+ constraint: "Split substantial restored screens into page orchestration, typed data fixtures, view configuration, calculations, and focused presentational components.",
21
+ guidance: "Keep page files thin; move types, data fixtures, view configuration, calculations, and repeated sections into feature modules or focused components."
22
+ },
23
+ {
24
+ section: "Source Structure",
25
+ constraint: "Represent mock/domain data with named object fields instead of long positional factory arguments.",
26
+ guidance: "Use named object fixtures for domain rows; avoid long positional factory arguments in generated examples."
27
+ },
28
+ {
29
+ section: "State And Interactions",
30
+ constraint: "Derive progress, summary values, badges, disabled states, and totals from source data or explicit workflow state instead of duplicating static literals.",
31
+ guidance: "Derive summary values, progress text, percentages, bars, badges, and disabled states from the same source state."
32
+ },
33
+ {
34
+ section: "State And Interactions",
35
+ constraint: "Preserve PRD terminology in visible labels and record stable domain wording in source-linked project knowledge when PRD input is provided.",
36
+ guidance: "Preserve PRD terminology in visible labels and capture stable domain wording in project knowledge with source_paths and coverage when PRD input is available."
37
+ },
38
+ {
39
+ section: "State And Interactions",
40
+ constraint: "Implement expected interactions for the affected workflow, or mark unsupported interactions as explicit assumptions in the handoff evidence.",
41
+ guidance: "Implement or explicitly defer expected interactions for the affected workflow, such as filtering, selection, editing, navigation, dialogs, or bulk actions when applicable."
42
+ },
43
+ {
44
+ section: "Styling",
45
+ constraint: "Use reusable design tokens for colors, spacing, layout metrics, and status semantics instead of one-off page-only constants.",
46
+ guidance: "Use reusable design tokens for colors, spacing, status colors, and layout metrics instead of page-only literals."
47
+ },
48
+ {
49
+ section: "Required Artifacts",
50
+ constraint: "Keep design input, PRD summary, component boundary notes, and visual verification evidence as durable project artifacts when a design source is provided.",
51
+ guidance: "Keep design input, PRD summary, component boundary notes, and visual verification screenshots or notes as project artifacts when a design source exists."
52
+ },
53
+ {
54
+ section: "Project Conventions",
55
+ constraint: "Replace visible placeholder labels for icons or visual primitives with real project icons, components, or CSS shapes.",
56
+ guidance: "Replace visible placeholder labels for icons or visual primitives with real project icons, components, or CSS shapes."
57
+ },
58
+ {
59
+ section: "Accessibility",
60
+ constraint: "Preserve accessibility semantics for controls, forms, dialogs, tables, keyboard navigation, focus order, and icon-only actions.",
61
+ guidance: "Use semantic HTML and project UI-library accessibility behavior for controls, forms, dialogs, tables, keyboard navigation, focus order, and icon-only actions."
62
+ },
63
+ {
64
+ section: "Localization",
65
+ constraint: "Keep visible copy, dates, numbers, directionality, and terminology compatible with the project's i18n and localization conventions.",
66
+ guidance: "Follow project i18n conventions for visible copy, dates, numbers, directionality, and terminology instead of hard-coding locale-specific formatting."
67
+ },
68
+ {
69
+ section: "Styling",
70
+ constraint: "Use project theme tokens for light/dark mode, status colors, typography, density, and responsive breakpoints instead of one-off visual constants.",
71
+ guidance: "Use project theme tokens for light/dark mode, status colors, typography, density, and responsive breakpoints instead of page-only constants."
72
+ },
73
+ {
74
+ section: "Verification",
75
+ constraint: "Cross-check visible state consistency across selected steps, progress labels, percentages, bars, badges, disabled states, and summary counts.",
76
+ guidance: "Verify visible state consistency across selected steps, progress labels, percentages, bars, badges, disabled states, and summary counts."
77
+ },
78
+ {
79
+ section: "Verification",
80
+ constraint: "Keep generated build output such as dist/ out of lint and typecheck scopes.",
81
+ guidance: "Keep generated build output such as dist/ out of lint and typecheck scopes."
82
+ }
15
83
  ];
84
+ export const UI_RESTORATION_CONSTRAINTS = UI_RESTORATION_RULES.map((rule) => rule.constraint);
16
85
  export const UI_RESTORATION_VERIFICATION_FOCUS = [
17
86
  "typecheck",
18
87
  "component behavior",
@@ -20,19 +89,24 @@ export const UI_RESTORATION_VERIFICATION_FOCUS = [
20
89
  "responsive rendering",
21
90
  "visual regressions when UI source is provided"
22
91
  ];
23
- export const UI_RESTORATION_GUIDANCE = [
24
- "Keep page files thin; move types, data fixtures, view configuration, calculations, and repeated sections into feature modules or focused components.",
25
- "Use named object fixtures for domain rows; avoid long positional factory arguments in generated examples.",
26
- "Derive summary values, progress text, percentages, bars, badges, and disabled states from the same source state.",
27
- "Preserve PRD terminology in visible labels and capture stable domain wording in project knowledge when PRD input is available.",
28
- "Implement or explicitly defer expected interactions for the affected workflow, such as filtering, selection, editing, navigation, dialogs, or bulk actions when applicable.",
29
- "Use reusable design tokens for colors, spacing, status colors, and layout metrics instead of page-only literals.",
30
- "Keep design input, PRD summary, component boundary notes, and visual verification screenshots or notes as project artifacts when a design source exists.",
31
- "Replace visible placeholder labels for icons or visual primitives with real project icons, components, or CSS shapes.",
32
- "Verify visible state consistency across selected steps, progress labels, percentages, bars, badges, disabled states, and summary counts.",
33
- "Keep generated build output such as dist/ out of lint and typecheck scopes."
34
- ];
92
+ export const UI_RESTORATION_GUIDANCE = UI_RESTORATION_RULES.map((rule) => rule.guidance);
93
+ export function renderUiImplementationSkillBullets() {
94
+ return UI_RESTORATION_GUIDANCE.map((item) => `- ${item}`).join("\n");
95
+ }
35
96
  export function renderUiRestorationChecklist() {
36
- return lines("# UI Restoration Checklist", "", "Use this checklist when converting design files, screenshots, exported HTML, or generated UI into project code.", "", "## Required Artifacts", "", "- Save or reference the design input used for implementation.", "- Keep a concise PRD summary with domain terminology and acceptance rules when product requirements are available.", "- Record the component boundary plan before implementation.", "- Keep visual verification evidence such as screenshots, browser notes, or viewport checks.", "", "## Source Structure", "", "- Keep route/page entry files as orchestration only.", "- Put feature code under the project-standard feature/module location.", "- Split substantial screens into types, data fixtures, view configuration, calculations, and focused components when the screen has repeated sections, workflows, editable data, dialogs, or dense state.", "- Use named object fixtures for mock/domain rows instead of long positional factory arguments.", "", "## State And Interactions", "", "- Derive summary values, progress labels, percentages, progress bars, badges, disabled states, and totals from the same source state.", "- Preserve PRD wording in visible labels.", "- Implement expected interactions for the affected workflow, or document deferred interactions explicitly.", "", "## Styling", "", "- Reuse project design tokens for colors, spacing, status colors, and layout sizing.", "- Keep generated build output such as `dist/` out of lint and typecheck scopes.");
97
+ return lines("# UI Restoration Checklist", "", "Use this checklist when converting design files, screenshots, exported HTML, or generated UI into project code.", "", ...renderChecklistSections());
98
+ }
99
+ function renderChecklistSections() {
100
+ const output = [];
101
+ for (const section of checklistSections()) {
102
+ output.push(`## ${section}`, "");
103
+ output.push(...UI_RESTORATION_RULES.map((rule) => rule.section === section ? `- ${rule.guidance}` : "").filter(Boolean));
104
+ output.push("");
105
+ }
106
+ output.pop();
107
+ return output;
108
+ }
109
+ function checklistSections() {
110
+ return [...new Set(UI_RESTORATION_RULES.map((rule) => rule.section))];
37
111
  }
38
112
  //# sourceMappingURL=ui-restoration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-restoration.js","sourceRoot":"","sources":["../../src/runtime/ui-restoration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,yFAAyF;IACzF,kGAAkG;IAClG,2JAA2J;IAC3J,mGAAmG;IACnG,0JAA0J;IAC1J,8HAA8H;IAC9H,8IAA8I;IAC9I,8HAA8H;IAC9H,2JAA2J;IAC3J,uHAAuH;IACvH,+IAA+I;IAC/I,6EAA6E;CACrE,CAAC;AAEX,MAAM,CAAC,MAAM,iCAAiC,GAAG;IAC/C,WAAW;IACX,oBAAoB;IACpB,4BAA4B;IAC5B,sBAAsB;IACtB,+CAA+C;CACvC,CAAC;AAEX,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,sJAAsJ;IACtJ,2GAA2G;IAC3G,kHAAkH;IAClH,gIAAgI;IAChI,6KAA6K;IAC7K,kHAAkH;IAClH,0JAA0J;IAC1J,uHAAuH;IACvH,0IAA0I;IAC1I,6EAA6E;CACrE,CAAC;AAEX,MAAM,UAAU,4BAA4B;IAC1C,OAAO,KAAK,CACV,4BAA4B,EAC5B,EAAE,EACF,iHAAiH,EACjH,EAAE,EACF,uBAAuB,EACvB,EAAE,EACF,+DAA+D,EAC/D,oHAAoH,EACpH,6DAA6D,EAC7D,6FAA6F,EAC7F,EAAE,EACF,qBAAqB,EACrB,EAAE,EACF,sDAAsD,EACtD,wEAAwE,EACxE,2MAA2M,EAC3M,gGAAgG,EAChG,EAAE,EACF,2BAA2B,EAC3B,EAAE,EACF,uIAAuI,EACvI,2CAA2C,EAC3C,4GAA4G,EAC5G,EAAE,EACF,YAAY,EACZ,EAAE,EACF,sFAAsF,EACtF,iFAAiF,CAClF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ui-restoration.js","sourceRoot":"","sources":["../../src/runtime/ui-restoration.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { relativeHarnessPath } from "../storage/paths.js";
4
+ import { projectScriptCommand } from "./command-taxonomy.js";
5
+ import { UI_RESTORATION_VERIFICATION_FOCUS } from "./ui-restoration.js";
4
6
  import { discoverVerificationCommands, defaultVerificationCommandNames } from "./verification-commands.js";
5
7
  const policyVerificationNames = [
6
8
  "targeted test",
@@ -11,6 +13,7 @@ const policyVerificationNames = [
11
13
  "documentation review",
12
14
  "review findings"
13
15
  ];
16
+ const policyEvidenceNames = UI_RESTORATION_VERIFICATION_FOCUS.filter((focus) => focus !== "typecheck");
14
17
  export function checkExecutionUnits(projectRoot) {
15
18
  const artifactPath = relativeHarnessPath("execution-units", "latest.json");
16
19
  const fullPath = path.join(projectRoot, artifactPath);
@@ -21,7 +24,7 @@ export function checkExecutionUnits(projectRoot) {
21
24
  unitCount: 0,
22
25
  independentUnitIds: [],
23
26
  errors: [],
24
- warnings: ["Run frontend-harness plan before checking execution units."]
27
+ warnings: [`Run ${projectScriptCommand("frontend-harness plan --json \"<task>\"")} before checking execution units.`]
25
28
  };
26
29
  }
27
30
  const errors = [];
@@ -33,6 +36,7 @@ export function checkExecutionUnits(projectRoot) {
33
36
  .filter((command) => command.command)
34
37
  .map((command) => command.name)
35
38
  ]);
39
+ const knownEvidenceNames = new Set(policyEvidenceNames);
36
40
  const artifact = readArtifact(fullPath, errors);
37
41
  const units = getUnits(artifact, errors);
38
42
  const ids = new Set();
@@ -57,7 +61,7 @@ export function checkExecutionUnits(projectRoot) {
57
61
  if (!isRecord(unit)) {
58
62
  continue;
59
63
  }
60
- validateUnit(unit, index, ids, knownVerificationNames, errors);
64
+ validateUnit(unit, index, ids, knownVerificationNames, knownEvidenceNames, errors);
61
65
  }
62
66
  validateDependencyCycles(units, errors);
63
67
  return {
@@ -123,10 +127,11 @@ function getUnits(artifact, errors) {
123
127
  }
124
128
  return artifact["units"];
125
129
  }
126
- function validateUnit(unit, index, ids, knownVerificationNames, errors) {
130
+ function validateUnit(unit, index, ids, knownVerificationNames, knownEvidenceNames, errors) {
127
131
  validateFile(unit, index, errors);
128
132
  validateTask(unit, index, errors);
129
133
  validateVerification(unit, index, knownVerificationNames, errors);
134
+ validateVerificationEvidence(unit, index, knownEvidenceNames, errors);
130
135
  validateDependsOn(unit, index, ids, errors);
131
136
  validateParallelGroup(unit, index, errors);
132
137
  }
@@ -162,6 +167,20 @@ function validateVerification(unit, index, knownVerificationNames, errors) {
162
167
  }
163
168
  }
164
169
  }
170
+ function validateVerificationEvidence(unit, index, knownEvidenceNames, errors) {
171
+ if (unit.verificationEvidence === undefined) {
172
+ return;
173
+ }
174
+ if (!Array.isArray(unit.verificationEvidence)) {
175
+ errors.push(`units[${index}].verificationEvidence must be an array when present.`);
176
+ return;
177
+ }
178
+ for (const [evidenceIndex, evidence] of unit.verificationEvidence.entries()) {
179
+ if (typeof evidence !== "string" || !knownEvidenceNames.has(evidence)) {
180
+ errors.push(`units[${index}].verificationEvidence[${evidenceIndex}] must be one of: ${[...knownEvidenceNames].join(", ")}.`);
181
+ }
182
+ }
183
+ }
165
184
  function validateDependsOn(unit, index, ids, errors) {
166
185
  if (!Array.isArray(unit.dependsOn)) {
167
186
  errors.push(`units[${index}].dependsOn must be an array.`);
@@ -208,6 +227,9 @@ function isProjectRelativeSourcePath(file) {
208
227
  if (normalized.startsWith("/") || /^[a-zA-Z]:\//.test(normalized)) {
209
228
  return false;
210
229
  }
230
+ if (normalized === ".frontend-harness/knowledge" || normalized.startsWith(".frontend-harness/knowledge/")) {
231
+ return true;
232
+ }
211
233
  const firstSegment = normalized.split("/")[0];
212
234
  return firstSegment !== ".frontend-harness";
213
235
  }
@@ -1 +1 @@
1
- {"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/runtime/units.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,4BAA4B,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAsB3G,MAAM,uBAAuB,GAAG;IAC9B,eAAe;IACf,iBAAiB;IACjB,8BAA8B;IAC9B,0BAA0B;IAC1B,kBAAkB;IAClB,sBAAsB;IACtB,iBAAiB;CAClB,CAAC;AACF,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,MAAM,YAAY,GAAG,mBAAmB,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,gBAAgB;YACxB,YAAY;YACZ,SAAS,EAAE,CAAC;YACZ,kBAAkB,EAAE,EAAE;YACtB,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,CAAC,4DAA4D,CAAC;SACzE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAS;QAC7C,GAAG,+BAA+B;QAClC,GAAG,uBAAuB;QAC1B,GAAG,4BAA4B,CAAC,WAAW,CAAC;aACzC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;aACpC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KAClC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,sBAAsB,CAAC,CAAC;YAClD,SAAS;QACX,CAAC;QACD,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChB,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,gCAAgC,WAAW,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,SAAS;QACX,CAAC;QACD,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IACD,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAExC,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;QAC/C,YAAY;QACZ,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,kBAAkB,EAAE,sBAAsB,CAAC,KAAK,CAAC;QACjD,MAAM;QACN,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAgB,EAAE,MAAgB;IAClE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;YAC3F,SAAS;QACX,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAwB,EAAE,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC;IACxH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,SAAS,KAAK,CAAC,EAAU,EAAE,SAAmB;QAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,MAAM,CAAC,IAAI,CAAC,6CAA6C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChF,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjB,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,MAAgB;IACtD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAY,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,8CAA8C,OAAO,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,QAAiB,EAAE,MAAgB;IACnD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;QAC/D,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB,EAAE,KAAa,EAAE,GAAgB,EAAE,sBAAmC,EAAE,MAAgB;IAC7H,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAClE,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5C,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,IAAiB,EAAE,KAAa,EAAE,MAAgB;IACpE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,kCAAkC,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB,EAAE,KAAa,EAAE,MAAgB;IACtE,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,mDAAmD,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IACD,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,4EAA4E,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB,EAAE,KAAa,EAAE,MAAgB;IACtE,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,oCAAoC,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAiB,EAAE,KAAa,EAAE,sBAAmC,EAAE,MAAgB;IACnH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,mEAAmE,CAAC,CAAC;QAC/F,OAAO;IACT,CAAC;IAED,KAAK,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5E,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,kBAAkB,iBAAiB,qBAAqB,CAAC,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/H,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAiB,EAAE,KAAa,EAAE,GAAgB,EAAE,MAAgB;IAC7F,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,+BAA+B,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,KAAK,MAAM,CAAC,eAAe,EAAE,UAAU,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QACrE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,eAAe,eAAe,gCAAgC,CAAC,CAAC;YAC1F,SAAS;QACX,CAAC;QACD,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,eAAe,eAAe,mCAAmC,CAAC,CAAC;YAC7F,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,eAAe,eAAe,iCAAiC,UAAU,GAAG,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAiB,EAAE,KAAa,EAAE,MAAgB;IAC/E,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO;IACT,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,qDAAqD,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAgB;IAC9C,OAAO,KAAK;SACT,MAAM,CAAC,QAAQ,CAAC;SAChB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;SACpF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACzB,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAY;IAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAClE,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,YAAY,KAAK,mBAAmB,CAAC;AAC9C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/runtime/units.ts"],"names":[],"mappings":"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"}
@@ -4,13 +4,110 @@ import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { harnessPath } from "../storage/paths.js";
6
6
  import { ensureDir, readJson, writeJson, writeText } from "../storage/json.js";
7
- import { updateVerificationState } from "./state.js";
7
+ import { checkStateContract, loadState, updateVerificationState } from "./state.js";
8
+ import { checkKnowledgeCoverage } from "./knowledge.js";
8
9
  import { discoverVerificationCommands } from "./verification-commands.js";
9
10
  import { createRepairPacket } from "./repair-packet.js";
11
+ import { projectScriptCommand } from "./command-taxonomy.js";
10
12
  const MAX_NODE_E_SCRIPT_LENGTH = 200;
11
13
  export function runVerification(projectRoot, options) {
12
14
  const commands = resolveCommands(projectRoot, options);
13
15
  const startedFromFailed = readPreviousStatus(projectRoot) === "failed";
16
+ const stateContract = checkStateContract(projectRoot);
17
+ if (stateContract.status === "failed") {
18
+ const relativeLogPath = `.frontend-harness/logs/harness-contract-${new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z")}.log`;
19
+ writeText(path.join(projectRoot, relativeLogPath), [
20
+ "Harness execution contract failed before project verification.",
21
+ "",
22
+ "## Errors",
23
+ ...stateContract.errors.map((error) => `- ${error}`),
24
+ "",
25
+ "## Warnings",
26
+ ...(stateContract.warnings.length ? stateContract.warnings.map((warning) => `- ${warning}`) : ["- none"]),
27
+ "",
28
+ "## Expected execution-unit files",
29
+ ...(stateContract.expectedFiles.length ? stateContract.expectedFiles.map((file) => `- ${file}`) : ["- none"]),
30
+ "",
31
+ "## Recorded changed files",
32
+ ...(stateContract.changedFiles.length ? stateContract.changedFiles.map((file) => `- ${file}`) : ["- none"])
33
+ ].join("\n"));
34
+ const result = {
35
+ status: "failed",
36
+ results: [
37
+ {
38
+ name: "harness-contract",
39
+ command: "frontend-harness state check --json",
40
+ source: "none",
41
+ status: "failed",
42
+ exitCode: 1,
43
+ durationMs: 0,
44
+ logPath: relativeLogPath
45
+ }
46
+ ],
47
+ retryGuidance: {
48
+ summary: "recorded changed files do not cover the planned execution units",
49
+ failedCommands: ["frontend-harness state check --json"],
50
+ logs: [relativeLogPath],
51
+ nextAgentInstruction: [
52
+ "Read .frontend-harness/plans/latest.json and .frontend-harness/execution-units/latest.json.",
53
+ "Record every planned execution-unit file that was edited.",
54
+ "If the implementation boundary changed, rerun planning before verification.",
55
+ `Then rerun ${projectScriptCommand("frontend-harness verify --json")}.`
56
+ ].join(" ")
57
+ }
58
+ };
59
+ writeResult(projectRoot, result);
60
+ updateVerificationState(projectRoot, "failed", startedFromFailed);
61
+ createRepairPacket(projectRoot, { verification: result });
62
+ return result;
63
+ }
64
+ const state = loadState(projectRoot);
65
+ if (state.task?.inputs?.prd) {
66
+ const coverage = checkKnowledgeCoverage(projectRoot);
67
+ if (coverage.status !== "passed") {
68
+ const relativeLogPath = `.frontend-harness/logs/knowledge-coverage-${new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z")}.log`;
69
+ writeText(path.join(projectRoot, relativeLogPath), [
70
+ "PRD traceability failed before project verification.",
71
+ "",
72
+ `PRD input: ${state.task.inputs.prd}`,
73
+ `coverage status: ${coverage.status}`,
74
+ "",
75
+ "## Errors",
76
+ ...(coverage.errors.length ? coverage.errors.map((error) => `- ${error}`) : ["- none"]),
77
+ "",
78
+ "## Warnings",
79
+ ...(coverage.warnings.length ? coverage.warnings.map((warning) => `- ${warning}`) : ["- none"])
80
+ ].join("\n"));
81
+ const result = {
82
+ status: "failed",
83
+ results: [
84
+ {
85
+ name: "knowledge-coverage",
86
+ command: "frontend-harness knowledge coverage --json",
87
+ source: "none",
88
+ status: "failed",
89
+ exitCode: 1,
90
+ durationMs: 0,
91
+ logPath: relativeLogPath
92
+ }
93
+ ],
94
+ retryGuidance: {
95
+ summary: "PRD-derived knowledge is missing source traceability",
96
+ failedCommands: ["frontend-harness knowledge coverage --json"],
97
+ logs: [relativeLogPath],
98
+ nextAgentInstruction: [
99
+ "Distill PRD acceptance rules into .frontend-harness/knowledge cards.",
100
+ "Each active PRD card must include source_paths and coverage for the referenced PRD section.",
101
+ `Then rerun ${projectScriptCommand("frontend-harness verify --json")}.`
102
+ ].join(" ")
103
+ }
104
+ };
105
+ writeResult(projectRoot, result);
106
+ updateVerificationState(projectRoot, "failed", startedFromFailed);
107
+ createRepairPacket(projectRoot, { verification: result });
108
+ return result;
109
+ }
110
+ }
14
111
  if (commands.length === 0) {
15
112
  const result = {
16
113
  status: "not_configured",
@@ -31,6 +128,50 @@ export function runVerification(projectRoot, options) {
31
128
  updateVerificationState(projectRoot, "not_configured", startedFromFailed);
32
129
  return result;
33
130
  }
131
+ const evidenceGate = checkVerificationEvidence(projectRoot);
132
+ if (evidenceGate.status === "failed") {
133
+ const relativeLogPath = `.frontend-harness/logs/evidence-gate-${new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z")}.log`;
134
+ writeText(path.join(projectRoot, relativeLogPath), [
135
+ "Verification evidence gate failed before project verification.",
136
+ "",
137
+ "## Evidence manifest",
138
+ evidenceGate.manifestPath,
139
+ "",
140
+ "## Required evidence",
141
+ ...evidenceGate.requiredEvidence.map((evidence) => `- ${evidence.unitId}: ${evidence.kind}`),
142
+ "",
143
+ "## Errors",
144
+ ...evidenceGate.errors.map((error) => `- ${error}`)
145
+ ].join("\n"));
146
+ const result = {
147
+ status: "failed",
148
+ results: [
149
+ {
150
+ name: "evidence-gate",
151
+ command: "frontend-harness verify --json",
152
+ source: "none",
153
+ status: "failed",
154
+ exitCode: 1,
155
+ durationMs: 0,
156
+ logPath: relativeLogPath
157
+ }
158
+ ],
159
+ retryGuidance: {
160
+ summary: "required verification evidence artifacts are missing or stale",
161
+ failedCommands: ["frontend-harness verify --json"],
162
+ logs: [relativeLogPath],
163
+ nextAgentInstruction: [
164
+ "Create .frontend-harness/verification/evidence.json with entries for every required unit evidence kind.",
165
+ "Each entry must include unitId, kind, artifactPaths, and a createdAt timestamp, and every artifact path must exist under .frontend-harness/.",
166
+ `Then rerun ${projectScriptCommand("frontend-harness verify --json")}.`
167
+ ].join(" ")
168
+ }
169
+ };
170
+ writeResult(projectRoot, result);
171
+ updateVerificationState(projectRoot, "failed", startedFromFailed);
172
+ createRepairPacket(projectRoot, { verification: result });
173
+ return result;
174
+ }
34
175
  const results = commands.map(({ name, source, command }) => runCommand(projectRoot, name, source, command));
35
176
  const failed = results.filter((result) => result.status === "failed" || result.status === "error");
36
177
  const status = failed.length > 0 ? "failed" : "passed";
@@ -45,8 +186,8 @@ export function runVerification(projectRoot, options) {
45
186
  nextAgentInstruction: [
46
187
  "Read .frontend-harness/verification/latest.json and the failed command logs.",
47
188
  "Patch the relevant project files without changing generated harness artifacts.",
48
- "Record newly changed files with frontend-harness state record-change <file>.",
49
- "Rerun frontend-harness verify --json until verification passes."
189
+ `Record newly changed files with ${projectScriptCommand("frontend-harness state record-change <file>")}.`,
190
+ `Rerun ${projectScriptCommand("frontend-harness verify --json")} until verification passes.`
50
191
  ].join(" ")
51
192
  }
52
193
  : null
@@ -58,6 +199,131 @@ export function runVerification(projectRoot, options) {
58
199
  }
59
200
  return result;
60
201
  }
202
+ function checkVerificationEvidence(projectRoot) {
203
+ const state = loadState(projectRoot);
204
+ const manifestPath = ".frontend-harness/verification/evidence.json";
205
+ const requiredEvidence = state.units.flatMap((unit) => [...new Set(unit.verificationEvidence ?? [])]
206
+ .map(evidenceArtifactKind)
207
+ .filter((kind) => Boolean(kind))
208
+ .map((kind) => ({ unitId: unit.id, kind })));
209
+ if (requiredEvidence.length === 0) {
210
+ return {
211
+ status: "passed",
212
+ manifestPath,
213
+ requiredEvidence,
214
+ errors: []
215
+ };
216
+ }
217
+ const manifest = readEvidenceManifest(projectRoot, manifestPath);
218
+ if (!manifest.ok) {
219
+ return {
220
+ status: "failed",
221
+ manifestPath,
222
+ requiredEvidence,
223
+ errors: [manifest.error]
224
+ };
225
+ }
226
+ const entries = manifest.entries;
227
+ const errors = validateEvidenceEntries(projectRoot, requiredEvidence, entries);
228
+ return {
229
+ status: errors.length ? "failed" : "passed",
230
+ manifestPath,
231
+ requiredEvidence,
232
+ errors
233
+ };
234
+ }
235
+ function evidenceArtifactKind(evidence) {
236
+ const normalized = evidence.toLowerCase();
237
+ if (normalized.includes("component behavior")) {
238
+ return "component-behavior";
239
+ }
240
+ if (normalized.includes("interaction")) {
241
+ return "interaction-smoke";
242
+ }
243
+ if (normalized.includes("responsive")) {
244
+ return "responsive-rendering";
245
+ }
246
+ if (normalized.includes("visual")) {
247
+ return "visual-regression";
248
+ }
249
+ return null;
250
+ }
251
+ function readEvidenceManifest(projectRoot, relativePath) {
252
+ const fullPath = path.join(projectRoot, relativePath);
253
+ if (!fs.existsSync(fullPath)) {
254
+ return { ok: false, error: `Missing evidence manifest: ${relativePath}.` };
255
+ }
256
+ let parsed;
257
+ try {
258
+ parsed = readJson(fullPath);
259
+ }
260
+ catch (error) {
261
+ return { ok: false, error: `Evidence manifest is not valid JSON: ${error instanceof Error ? error.message : String(error)}.` };
262
+ }
263
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
264
+ return { ok: false, error: "Evidence manifest root must be an object." };
265
+ }
266
+ const entries = parsed["entries"];
267
+ if (!Array.isArray(entries)) {
268
+ return { ok: false, error: "Evidence manifest must contain an entries array." };
269
+ }
270
+ return { ok: true, entries: entries.flatMap(parseEvidenceEntry) };
271
+ }
272
+ function parseEvidenceEntry(value) {
273
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
274
+ return [];
275
+ }
276
+ const entry = value;
277
+ const unitId = entry["unitId"];
278
+ const kind = entry["kind"];
279
+ const artifactPaths = entry["artifactPaths"];
280
+ const createdAt = entry["createdAt"];
281
+ if (typeof unitId !== "string"
282
+ || typeof kind !== "string"
283
+ || !Array.isArray(artifactPaths)
284
+ || artifactPaths.some((artifactPath) => typeof artifactPath !== "string")
285
+ || typeof createdAt !== "string") {
286
+ return [];
287
+ }
288
+ return [{
289
+ unitId,
290
+ kind,
291
+ artifactPaths: artifactPaths,
292
+ createdAt
293
+ }];
294
+ }
295
+ function validateEvidenceEntries(projectRoot, requiredEvidence, entries) {
296
+ const errors = [];
297
+ for (const required of requiredEvidence) {
298
+ const entry = entries.find((candidate) => candidate.unitId === required.unitId && candidate.kind === required.kind);
299
+ if (!entry) {
300
+ errors.push(`Missing evidence entry for ${required.unitId}: ${required.kind}.`);
301
+ continue;
302
+ }
303
+ if (!/^\d{4}-\d{2}-\d{2}T/.test(entry.createdAt)) {
304
+ errors.push(`Evidence entry for ${required.unitId}: ${required.kind} must include an ISO createdAt timestamp.`);
305
+ }
306
+ if (entry.artifactPaths.length === 0) {
307
+ errors.push(`Evidence entry for ${required.unitId}: ${required.kind} must include at least one artifact path.`);
308
+ continue;
309
+ }
310
+ for (const artifactPath of entry.artifactPaths) {
311
+ validateEvidenceArtifactPath(projectRoot, artifactPath, `${required.unitId}: ${required.kind}`, errors);
312
+ }
313
+ }
314
+ return errors;
315
+ }
316
+ function validateEvidenceArtifactPath(projectRoot, artifactPath, label, errors) {
317
+ const normalized = path.posix.normalize(artifactPath.replace(/\\/g, "/"));
318
+ if (!normalized.startsWith(".frontend-harness/") || normalized.includes("..") || path.isAbsolute(artifactPath)) {
319
+ errors.push(`Evidence artifact for ${label} must be a project-relative path under .frontend-harness/: ${artifactPath}.`);
320
+ return;
321
+ }
322
+ const fullPath = path.join(projectRoot, normalized);
323
+ if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isFile()) {
324
+ errors.push(`Evidence artifact for ${label} does not exist: ${artifactPath}.`);
325
+ }
326
+ }
61
327
  function resolveCommands(projectRoot, options) {
62
328
  return discoverVerificationCommands(projectRoot, options)
63
329
  .flatMap((entry) => entry.command ? [{ name: entry.name, source: entry.source, command: entry.command }] : []);