frontend-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/AGENTS.md +48 -0
  2. package/CLAUDE.md +48 -0
  3. package/README.md +262 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +380 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/runtime/builtin-skills.d.ts +6 -0
  8. package/dist/runtime/builtin-skills.js +269 -0
  9. package/dist/runtime/builtin-skills.js.map +1 -0
  10. package/dist/runtime/clean.d.ts +11 -0
  11. package/dist/runtime/clean.js +85 -0
  12. package/dist/runtime/clean.js.map +1 -0
  13. package/dist/runtime/command-taxonomy.d.ts +12 -0
  14. package/dist/runtime/command-taxonomy.js +72 -0
  15. package/dist/runtime/command-taxonomy.js.map +1 -0
  16. package/dist/runtime/context.d.ts +71 -0
  17. package/dist/runtime/context.js +153 -0
  18. package/dist/runtime/context.js.map +1 -0
  19. package/dist/runtime/graph.d.ts +12 -0
  20. package/dist/runtime/graph.js +211 -0
  21. package/dist/runtime/graph.js.map +1 -0
  22. package/dist/runtime/knowledge.d.ts +48 -0
  23. package/dist/runtime/knowledge.js +383 -0
  24. package/dist/runtime/knowledge.js.map +1 -0
  25. package/dist/runtime/plan.d.ts +18 -0
  26. package/dist/runtime/plan.js +571 -0
  27. package/dist/runtime/plan.js.map +1 -0
  28. package/dist/runtime/policy-provenance.d.ts +17 -0
  29. package/dist/runtime/policy-provenance.js +195 -0
  30. package/dist/runtime/policy-provenance.js.map +1 -0
  31. package/dist/runtime/project-discovery.d.ts +17 -0
  32. package/dist/runtime/project-discovery.js +166 -0
  33. package/dist/runtime/project-discovery.js.map +1 -0
  34. package/dist/runtime/project-paths.d.ts +6 -0
  35. package/dist/runtime/project-paths.js +47 -0
  36. package/dist/runtime/project-paths.js.map +1 -0
  37. package/dist/runtime/protocol-init.d.ts +50 -0
  38. package/dist/runtime/protocol-init.js +256 -0
  39. package/dist/runtime/protocol-init.js.map +1 -0
  40. package/dist/runtime/repair-decision.d.ts +3 -0
  41. package/dist/runtime/repair-decision.js +195 -0
  42. package/dist/runtime/repair-decision.js.map +1 -0
  43. package/dist/runtime/repair-packet.d.ts +7 -0
  44. package/dist/runtime/repair-packet.js +159 -0
  45. package/dist/runtime/repair-packet.js.map +1 -0
  46. package/dist/runtime/skills.d.ts +19 -0
  47. package/dist/runtime/skills.js +230 -0
  48. package/dist/runtime/skills.js.map +1 -0
  49. package/dist/runtime/state-explain.d.ts +2 -0
  50. package/dist/runtime/state-explain.js +106 -0
  51. package/dist/runtime/state-explain.js.map +1 -0
  52. package/dist/runtime/state.d.ts +10 -0
  53. package/dist/runtime/state.js +237 -0
  54. package/dist/runtime/state.js.map +1 -0
  55. package/dist/runtime/units.d.ts +10 -0
  56. package/dist/runtime/units.js +181 -0
  57. package/dist/runtime/units.js.map +1 -0
  58. package/dist/runtime/verification-commands.d.ts +11 -0
  59. package/dist/runtime/verification-commands.js +89 -0
  60. package/dist/runtime/verification-commands.js.map +1 -0
  61. package/dist/runtime/verify.d.ts +7 -0
  62. package/dist/runtime/verify.js +192 -0
  63. package/dist/runtime/verify.js.map +1 -0
  64. package/dist/schemas/types.d.ts +244 -0
  65. package/dist/schemas/types.js +2 -0
  66. package/dist/schemas/types.js.map +1 -0
  67. package/dist/schemas/validation.d.ts +2 -0
  68. package/dist/schemas/validation.js +21 -0
  69. package/dist/schemas/validation.js.map +1 -0
  70. package/dist/storage/json.d.ts +5 -0
  71. package/dist/storage/json.js +24 -0
  72. package/dist/storage/json.js.map +1 -0
  73. package/dist/storage/paths.d.ts +3 -0
  74. package/dist/storage/paths.js +9 -0
  75. package/dist/storage/paths.js.map +1 -0
  76. package/docs/DIRECTION.md +67 -0
  77. package/package.json +35 -0
@@ -0,0 +1,244 @@
1
+ export type HarnessStatus = "idle" | "planned" | "awaiting_agent_edit" | "verifying" | "passed" | "failed" | "blocked";
2
+ export type VerificationStatus = "not_run" | "not_configured" | "passed" | "failed" | "error";
3
+ export interface TaskUnderstanding {
4
+ intent: string;
5
+ scope: string;
6
+ constraints: string[];
7
+ frontendWorkflow?: FrontendWorkflowPolicy;
8
+ inputs?: {
9
+ prd?: string;
10
+ ui?: string;
11
+ agentDecision?: string;
12
+ };
13
+ reasoningMode?: "deterministic" | "agent_assisted";
14
+ policyProvenance?: PolicyProvenance;
15
+ agentDecision?: {
16
+ summary?: string | null;
17
+ artifactPath?: string | null;
18
+ contractVersion?: 1 | null;
19
+ intentSuggestion?: string | null;
20
+ constraintHints?: string[];
21
+ componentHints?: AgentDecisionComponentHint[];
22
+ };
23
+ }
24
+ export type FrontendWorkflowKind = "ui_implementation" | "prd_knowledge" | "api_integration" | "frontend_test" | "bug_fix" | "requirement_change";
25
+ export interface FrontendWorkflowPolicy {
26
+ kind: FrontendWorkflowKind;
27
+ summary: string;
28
+ requiredKnowledgeActions: string[];
29
+ implementationConstraints: string[];
30
+ verificationFocus: string[];
31
+ }
32
+ export interface PolicyProvenance {
33
+ selectedSkills: string[];
34
+ skillPaths: string[];
35
+ skillRoutes: SkillRouteCandidate[];
36
+ knowledgeReferences: string[];
37
+ knowledgeSha256: Record<string, string>;
38
+ selectionReason: string;
39
+ }
40
+ export interface SkillRouteCandidate {
41
+ name: string;
42
+ path: string;
43
+ score: number;
44
+ source: "metadata" | "workflow" | "keyword";
45
+ reasons: string[];
46
+ }
47
+ export interface AgentDecisionComponentHint {
48
+ name?: string;
49
+ responsibility?: string;
50
+ }
51
+ export interface AgentPlanningDecision {
52
+ contractVersion?: 1;
53
+ intentSuggestion?: string;
54
+ constraintHints?: string[];
55
+ componentHints?: AgentDecisionComponentHint[];
56
+ }
57
+ export interface AgentPlanningDecisionEnvelope {
58
+ contractVersion: 1;
59
+ decision: AgentPlanningDecision;
60
+ }
61
+ export interface AgentDecisionCheckResult {
62
+ status: "passed" | "failed";
63
+ artifactPath: string;
64
+ contractVersion: 1 | null;
65
+ decision: AgentPlanningDecision | null;
66
+ errors: string[];
67
+ }
68
+ export interface PlanningDecisionSummary {
69
+ artifactPath: string | null;
70
+ contractVersion: 1 | null;
71
+ intentSuggestion: string | null;
72
+ constraintHints: string[];
73
+ componentHints: AgentDecisionComponentHint[];
74
+ }
75
+ export interface ComponentItem {
76
+ name: string;
77
+ file: string;
78
+ responsibility: string;
79
+ status: "new" | "existing" | "unknown";
80
+ }
81
+ export interface ExecutionUnit {
82
+ id: string;
83
+ file: string;
84
+ task: string;
85
+ verification: string[];
86
+ dependsOn: string[];
87
+ parallelGroup: string | null;
88
+ }
89
+ export type ExecutionGuidanceAction = "inspect_plan" | "edit_files" | "record_changes" | "verify" | "fix_failed_verification";
90
+ export interface ExecutionGuidanceStep {
91
+ order: number;
92
+ action: ExecutionGuidanceAction;
93
+ description: string;
94
+ command: string | null;
95
+ condition: string | null;
96
+ }
97
+ export type StateNextAction = "plan" | "edit" | "verify" | "fix" | "configure_verification" | "done" | "blocked";
98
+ export interface StateNextResult {
99
+ action: StateNextAction;
100
+ reason: string;
101
+ command: string | null;
102
+ stateStatus: HarnessStatus;
103
+ verificationStatus: VerificationStatus;
104
+ changedFiles: string[];
105
+ guidance: string[];
106
+ artifacts: string[];
107
+ checks: string[];
108
+ stopCondition: string;
109
+ }
110
+ export interface StateExplainResult {
111
+ contractVersion: 1;
112
+ createdAt: string;
113
+ nextAction: StateNextResult;
114
+ summary: string;
115
+ rationale: string[];
116
+ requiredArtifacts: string[];
117
+ repairPacket: {
118
+ path: string;
119
+ markdownPath: string;
120
+ available: boolean;
121
+ };
122
+ repairDecision: {
123
+ path: string;
124
+ available: boolean;
125
+ sourceArtifactPath: string | null;
126
+ repairPacketArtifactPath: string | null;
127
+ repairPacketSha256: string | null;
128
+ verificationArtifactPath: string | null;
129
+ verificationSha256: string | null;
130
+ };
131
+ recommendedCommands: string[];
132
+ stopCondition: string;
133
+ }
134
+ export interface ComponentGraphNode {
135
+ id: string;
136
+ component: string;
137
+ file: string;
138
+ executionUnitId: string;
139
+ }
140
+ export interface ComponentGraphEdge {
141
+ from: string;
142
+ to: string;
143
+ type: "depends_on";
144
+ source: "execution_unit_depends_on";
145
+ }
146
+ export interface ComponentGraphArtifact {
147
+ nodes: ComponentGraphNode[];
148
+ edges: ComponentGraphEdge[];
149
+ }
150
+ export interface HarnessState {
151
+ version: 1;
152
+ status: HarnessStatus;
153
+ task: TaskUnderstanding | null;
154
+ components: ComponentItem[];
155
+ units: ExecutionUnit[];
156
+ changedFiles: string[];
157
+ verification: {
158
+ status: VerificationStatus;
159
+ latestResultPath: string | null;
160
+ };
161
+ errors: string[];
162
+ retryCount: number;
163
+ blockers: string[];
164
+ updatedAt: string;
165
+ }
166
+ export interface VerificationCommandResult {
167
+ name: string;
168
+ command: string | null;
169
+ source: "flag" | "config" | "package" | "none";
170
+ status: VerificationStatus;
171
+ exitCode: number | null;
172
+ durationMs: number;
173
+ logPath: string | null;
174
+ }
175
+ export interface VerificationResult {
176
+ status: VerificationStatus;
177
+ results: VerificationCommandResult[];
178
+ retryGuidance: null | {
179
+ summary: string;
180
+ failedCommands: string[];
181
+ logs: string[];
182
+ nextAgentInstruction: string;
183
+ };
184
+ }
185
+ export interface RepairPacketArtifact {
186
+ contractVersion: 1;
187
+ createdAt: string;
188
+ status: "ready" | "not_applicable";
189
+ stateStatus: HarnessStatus;
190
+ verificationStatus: VerificationStatus;
191
+ nextAction: StateNextResult;
192
+ artifacts: {
193
+ verification: string;
194
+ repairPacket: string;
195
+ repairPacketMarkdown: string;
196
+ };
197
+ changedFiles: string[];
198
+ failedCommands: Array<{
199
+ name: string;
200
+ command: string | null;
201
+ status: VerificationStatus;
202
+ exitCode: number | null;
203
+ logPath: string | null;
204
+ logExcerpt: string | null;
205
+ logSha256: string | null;
206
+ logSizeBytes: number | null;
207
+ excerptStartByte: number | null;
208
+ excerptEndByte: number | null;
209
+ excerptTruncated: boolean;
210
+ }>;
211
+ retryGuidance: VerificationResult["retryGuidance"];
212
+ instructions: string[];
213
+ }
214
+ export interface RepairDecision {
215
+ intent: string;
216
+ hypothesis: string;
217
+ targetFiles: string[];
218
+ verificationFocus: string[];
219
+ }
220
+ export interface RepairDecisionEnvelope {
221
+ contractVersion: 1;
222
+ decision: RepairDecision;
223
+ }
224
+ export interface RepairDecisionCheckResult {
225
+ status: "passed" | "failed";
226
+ artifactPath: string;
227
+ acceptedArtifactPath: string | null;
228
+ contractVersion: 1 | null;
229
+ decision: RepairDecision | null;
230
+ errors: string[];
231
+ }
232
+ export interface RepairDecisionSummary {
233
+ artifactPath: string;
234
+ sourceArtifactPath: string;
235
+ repairPacketArtifactPath: string | null;
236
+ repairPacketSha256: string | null;
237
+ verificationArtifactPath: string | null;
238
+ verificationSha256: string | null;
239
+ contractVersion: 1;
240
+ intent: string;
241
+ hypothesis: string;
242
+ targetFiles: string[];
243
+ verificationFocus: string[];
244
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schemas/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import type { HarnessState } from "./types.js";
2
+ export declare function isHarnessState(value: unknown): value is HarnessState;
@@ -0,0 +1,21 @@
1
+ export function isHarnessState(value) {
2
+ if (!isRecord(value)) {
3
+ return false;
4
+ }
5
+ const verification = value["verification"];
6
+ return value["version"] === 1
7
+ && typeof value["status"] === "string"
8
+ && Array.isArray(value["components"])
9
+ && Array.isArray(value["units"])
10
+ && Array.isArray(value["changedFiles"])
11
+ && isRecord(verification)
12
+ && typeof verification["status"] === "string"
13
+ && Array.isArray(value["errors"])
14
+ && typeof value["retryCount"] === "number"
15
+ && Array.isArray(value["blockers"])
16
+ && typeof value["updatedAt"] === "string";
17
+ }
18
+ function isRecord(value) {
19
+ return typeof value === "object" && value !== null;
20
+ }
21
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/schemas/validation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC;WACxB,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,QAAQ;WACnC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;WAClC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;WAC7B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;WACpC,QAAQ,CAAC,YAAY,CAAC;WACtB,OAAO,YAAY,CAAC,QAAQ,CAAC,KAAK,QAAQ;WAC1C,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;WAC9B,OAAO,KAAK,CAAC,YAAY,CAAC,KAAK,QAAQ;WACvC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;WAChC,OAAO,KAAK,CAAC,WAAW,CAAC,KAAK,QAAQ,CAAC;AAC9C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function ensureDir(dir: string): void;
2
+ export declare function writeJson(filePath: string, value: unknown): void;
3
+ export declare function writeJsonExclusive(filePath: string, value: unknown): void;
4
+ export declare function readJson<T>(filePath: string): T | null;
5
+ export declare function writeText(filePath: string, value: string): void;
@@ -0,0 +1,24 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ export function ensureDir(dir) {
4
+ fs.mkdirSync(dir, { recursive: true });
5
+ }
6
+ export function writeJson(filePath, value) {
7
+ ensureDir(path.dirname(filePath));
8
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
9
+ }
10
+ export function writeJsonExclusive(filePath, value) {
11
+ ensureDir(path.dirname(filePath));
12
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
13
+ }
14
+ export function readJson(filePath) {
15
+ if (!fs.existsSync(filePath)) {
16
+ return null;
17
+ }
18
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
19
+ }
20
+ export function writeText(filePath, value) {
21
+ ensureDir(path.dirname(filePath));
22
+ fs.writeFileSync(filePath, value, "utf8");
23
+ }
24
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/storage/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAc;IACxD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,KAAc;IACjE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,QAAgB;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAM,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAa;IACvD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const HARNESS_DIR = ".frontend-harness";
2
+ export declare function harnessPath(projectRoot: string, ...parts: string[]): string;
3
+ export declare function relativeHarnessPath(...parts: string[]): string;
@@ -0,0 +1,9 @@
1
+ import path from "node:path";
2
+ export const HARNESS_DIR = ".frontend-harness";
3
+ export function harnessPath(projectRoot, ...parts) {
4
+ return path.join(projectRoot, HARNESS_DIR, ...parts);
5
+ }
6
+ export function relativeHarnessPath(...parts) {
7
+ return path.posix.join(HARNESS_DIR, ...parts);
8
+ }
9
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAE/C,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,GAAG,KAAe;IACjE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAG,KAAe;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,67 @@
1
+ # frontend-harness Direction
2
+
3
+ `frontend-harness` is a project-level Execution Policy Layer for frontend AI-assisted development.
4
+
5
+ The package should make Codex and Claude Code more predictable inside a frontend repository without replacing their runtime capabilities.
6
+
7
+ ## Product Surface
8
+
9
+ The primary product surface is protocol injection:
10
+
11
+ ```text
12
+ npm install frontend-harness --save-dev
13
+ npx frontend-harness init
14
+ ```
15
+
16
+ After that, team members work normally in Codex or Claude Code. The injected `AGENTS.md` and `CLAUDE.md` protocol tells the agent to use the harness loop.
17
+
18
+ ## Policy Loop
19
+
20
+ The stable loop is:
21
+
22
+ ```text
23
+ context -> plan -> implement -> record-change -> verify -> repair -> done
24
+ ```
25
+
26
+ The CLI should keep these steps deterministic and evidence-backed.
27
+
28
+ `plan --json` should classify the frontend workflow before implementation. The first stable workflow policy classes are:
29
+
30
+ - `ui_implementation`: hand-written UI or generated UI adaptation from MCP/Stitch/Figma/HTML.
31
+ - `prd_knowledge`: PRD digestion into durable project knowledge.
32
+ - `api_integration`: Swagger/API-backed frontend data integration.
33
+ - `frontend_test`: E2E or integration testing.
34
+ - `bug_fix`: scoped bug repair with regression evidence.
35
+ - `requirement_change`: implementation plus knowledge/test synchronization for changed requirements.
36
+
37
+ These classes are policy metadata, not skill routing and not runtime scheduling.
38
+
39
+ ## Boundaries
40
+
41
+ `frontend-harness` owns:
42
+
43
+ - project context isolation
44
+ - frontend workflow protocol
45
+ - verification standards
46
+ - state continuity
47
+ - repair evidence
48
+ - project-local knowledge and skills
49
+
50
+ Codex and Claude Code own:
51
+
52
+ - agent loop
53
+ - tool execution
54
+ - permissions
55
+ - retries
56
+ - subagents
57
+ - skill loading
58
+ - runtime orchestration
59
+
60
+ ## Directional Decisions
61
+
62
+ - Human-facing commands stay minimal: `init` and `protocol check`.
63
+ - Agent-facing commands stay stable: `context`, `plan`, `state record-change`, `verify`, `repair packet`, and `state next`.
64
+ - Low-level launcher lifecycle commands are removed from the product direction.
65
+ - Phase planning documents are no longer the product documentation model.
66
+ - README is the product entry point.
67
+ - This direction document is the durable project compass.
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "frontend-harness",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": [
6
+ "dist",
7
+ "docs",
8
+ "AGENTS.md",
9
+ "CLAUDE.md",
10
+ "README.md"
11
+ ],
12
+ "bin": {
13
+ "frontend-harness": "./dist/cli/index.js"
14
+ },
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "exports": {
19
+ ".": "./dist/cli/index.js"
20
+ },
21
+ "scripts": {
22
+ "clean": "rm -rf dist",
23
+ "build": "npm run clean && tsc",
24
+ "harness": "node dist/cli/index.js",
25
+ "prepare": "npm run build",
26
+ "smoke:phase9": "node scripts/smoke-phase9.mjs",
27
+ "verify": "npm test && npm run typecheck && npm run build && npm run smoke:phase9",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "npm run build && node --test tests/*.test.mjs"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.10.0",
33
+ "typescript": "^5.7.0"
34
+ }
35
+ }