@hassangameryt/freeflow 0.6.0 → 0.7.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 (136) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +3 -2
  3. package/.codex-plugin/plugin.json +5 -6
  4. package/.cursor-plugin/plugin.json +25 -0
  5. package/README.md +66 -56
  6. package/capabilities/cognitive-routing/SKILL.md +288 -130
  7. package/com.github.copilot/hooks/hooks.json +11 -0
  8. package/command-surface.json +0 -24
  9. package/gemini-extension.json +5 -0
  10. package/hooks/adapters/claude-session-start.mjs +16 -0
  11. package/hooks/adapters/codex-session-start.mjs +16 -0
  12. package/hooks/adapters/copilot-session-start.mjs +13 -0
  13. package/hooks/adapters/cursor-session-start.mjs +13 -0
  14. package/hooks/adapters/gemini-session-start.mjs +15 -0
  15. package/hooks/claude/hooks.json +18 -0
  16. package/hooks/codex/hooks.json +18 -0
  17. package/hooks/cursor/hooks.json +9 -0
  18. package/hooks/freeflow-runtime-context.mjs +3 -650
  19. package/hooks/hooks.json +4 -30
  20. package/hooks/shared/runtime-context.mjs +210 -0
  21. package/hooks/tests/check-host-adapters.test.mjs +82 -0
  22. package/hooks/tests/check-runtime-context-hook.sh +140 -320
  23. package/package.json +20 -4
  24. package/pi-extension/dist/cognitive-routing/commands.js +3 -3
  25. package/pi-extension/dist/cognitive-routing/config.js +16 -20
  26. package/pi-extension/dist/cognitive-routing/controller.js +478 -48
  27. package/pi-extension/dist/cognitive-routing/history.js +12 -0
  28. package/pi-extension/dist/cognitive-routing/host.js +74 -12
  29. package/pi-extension/dist/cognitive-routing/pi-routing-session.js +414 -0
  30. package/pi-extension/dist/cognitive-routing/pi-session-control.js +320 -0
  31. package/pi-extension/dist/cognitive-routing/tool.js +1 -0
  32. package/pi-extension/dist/cognitive-routing/types.js +1 -1
  33. package/pi-extension/dist/index.js +236 -219
  34. package/pi-extension/dist/runtime/runtime-context.js +126 -286
  35. package/pi-extension/dist/settings/settings-ui.js +52 -336
  36. package/pi-extension/src/cognitive-routing/commands.ts +15 -5
  37. package/pi-extension/src/cognitive-routing/config.ts +16 -20
  38. package/pi-extension/src/cognitive-routing/controller.ts +561 -51
  39. package/pi-extension/src/cognitive-routing/history.ts +12 -0
  40. package/pi-extension/src/cognitive-routing/host.ts +110 -16
  41. package/pi-extension/src/cognitive-routing/pi-routing-session.ts +538 -0
  42. package/pi-extension/src/cognitive-routing/pi-session-control.ts +444 -0
  43. package/pi-extension/src/cognitive-routing/tool.ts +1 -0
  44. package/pi-extension/src/cognitive-routing/types.ts +1 -1
  45. package/pi-extension/src/index.ts +249 -239
  46. package/pi-extension/src/runtime/runtime-context.ts +129 -305
  47. package/pi-extension/src/settings/settings-ui.ts +53 -371
  48. package/pi-extension/tests/cognitive-routing/commands.test.js +1 -1
  49. package/pi-extension/tests/cognitive-routing/controller.test.js +69 -40
  50. package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +128 -57
  51. package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +434 -0
  52. package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +174 -0
  53. package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +91 -0
  54. package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +47 -4
  55. package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
  56. package/pi-extension/tests/integration/pi-extension.test.js +430 -2478
  57. package/pi-extension/tests/integration/prompt-architecture.test.js +124 -79
  58. package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
  59. package/plugin.json +33 -0
  60. package/runtime/prompts/cognitive-routing.md +5 -4
  61. package/runtime/prompts/conversation-history.md +1 -1
  62. package/runtime/prompts/core.md +77 -6
  63. package/runtime/prompts/interaction-contract.md +6 -2
  64. package/skills/action-selection/SKILL.md +93 -44
  65. package/skills/action-selection/references/trajectory-stalls.md +71 -0
  66. package/skills/bypass/SKILL.md +109 -39
  67. package/skills/commit-work/SKILL.md +94 -55
  68. package/skills/commit-work/references/git-state-edges.md +94 -0
  69. package/skills/commit-work/references/simple-push.md +92 -0
  70. package/skills/commit-work/references/staging-decisions.md +79 -46
  71. package/skills/decision-gate/SKILL.md +80 -22
  72. package/skills/design-for-depth/SKILL.md +208 -43
  73. package/skills/design-for-depth/references/design-pressure-signals.md +108 -240
  74. package/skills/design-for-depth/references/interface-design-loop.md +77 -97
  75. package/skills/design-for-depth/references/module-and-dependency-design.md +147 -0
  76. package/skills/design-for-depth/references/software-design-philosophy.md +127 -173
  77. package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
  78. package/skills/diagnose-failure/SKILL.md +198 -52
  79. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +19 -5
  80. package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +13 -5
  81. package/skills/discuss/SKILL.md +118 -76
  82. package/skills/discuss/references/discussion-continuity.md +84 -32
  83. package/skills/evaluate-skill/SKILL.md +166 -52
  84. package/skills/evaluate-skill/references/evaluation-definition-schema.md +2 -2
  85. package/skills/evaluate-skill/references/evaluation-design.md +56 -30
  86. package/skills/evaluate-skill/references/execution-and-evidence.md +1 -1
  87. package/skills/evaluate-skill/references/review-and-revision.md +62 -21
  88. package/skills/execute-work/SKILL.md +98 -59
  89. package/skills/execute-work/references/code-practices.md +4 -4
  90. package/skills/execute-work/references/execute-work-edges.md +42 -22
  91. package/skills/review-artifact/SKILL.md +132 -71
  92. package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
  93. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +52 -41
  94. package/skills/review-work/SKILL.md +115 -72
  95. package/skills/review-work/references/adjudicate-work-review.md +97 -0
  96. package/skills/review-work/references/independent-work-reviewer-contract.md +40 -35
  97. package/skills/review-work/references/security-risk-lens.md +17 -15
  98. package/skills/setup-freeflow/SKILL.md +14 -17
  99. package/skills/setup-freeflow/references/activation-contract.md +24 -30
  100. package/skills/setup-freeflow/references/host-setup.md +6 -7
  101. package/skills/simplify-code/SKILL.md +97 -39
  102. package/skills/simplify-code/references/simplification-patterns.md +1 -1
  103. package/skills/tdd/SKILL.md +108 -41
  104. package/skills/tdd/references/test-design.md +1 -1
  105. package/skills/track-work/SKILL.md +133 -300
  106. package/skills/track-work/references/working-record-format.md +515 -0
  107. package/skills/track-work/scripts/lib/document.mjs +713 -0
  108. package/skills/track-work/scripts/lib/format.mjs +166 -0
  109. package/skills/track-work/scripts/lib/store.mjs +233 -0
  110. package/skills/track-work/scripts/lib/transitions.mjs +790 -0
  111. package/skills/track-work/scripts/lib/views.mjs +27 -430
  112. package/skills/track-work/scripts/working-record.mjs +292 -98
  113. package/skills/verify-work/SKILL.md +46 -20
  114. package/skills/verify-work/references/browser-runtime-evidence.md +1 -1
  115. package/skills/verify-work/references/integration-evidence.md +1 -7
  116. package/skills/verify-work/references/performance-evidence.md +1 -1
  117. package/skills/workflow/SKILL.md +110 -80
  118. package/skills/workflow/references/domain-skill-composition.md +24 -18
  119. package/skills/write-skill/SKILL.md +218 -62
  120. package/skills/write-skill/references/activation-boundaries.md +63 -21
  121. package/skills/write-skill/references/agent-first-instructions.md +61 -27
  122. package/skills/write-skill/references/progressive-disclosure.md +91 -41
  123. package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
  124. package/runtime/prompts/skills.md +0 -65
  125. package/skills/mode-contract/SKILL.md +0 -104
  126. package/skills/track-work/scripts/lib/codec.mjs +0 -570
  127. package/skills/track-work/scripts/lib/commands.mjs +0 -568
  128. package/skills/track-work/scripts/lib/contract.mjs +0 -303
  129. package/skills/track-work/scripts/lib/model.mjs +0 -506
  130. package/skills/track-work/scripts/lib/operations.mjs +0 -965
  131. package/skills/track-work/scripts/lib/record-store.mjs +0 -264
  132. package/skills/track-work/scripts/lib/result.mjs +0 -37
  133. package/skills/track-work/scripts/lib/rewrites.mjs +0 -740
  134. package/skills/track-work/scripts/lib/schema.mjs +0 -277
  135. package/skills/track-work/scripts/lib/source-inventory.mjs +0 -162
  136. package/skills/track-work/scripts/lib/workspace.mjs +0 -134
@@ -1,122 +1,316 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { fileURLToPath } from "node:url";
4
- import { resolve } from "node:path";
5
- import { CommittedResultError } from "./lib/record-store.mjs";
6
- import { WorkingRecordError, fail } from "./lib/model.mjs";
7
- import { baseEnvelope, errorItems } from "./lib/result.mjs";
8
- import { executeCommand, readJsonInput } from "./lib/commands.mjs";
3
+ import { rm } from "node:fs/promises";
4
+ import { cwd } from "node:process";
5
+ import { dirname } from "node:path";
6
+ import { canonicalLines, joinLines, slugify, TASK_STATES } from "./lib/format.mjs";
7
+ import { parseDocument, validateDocument } from "./lib/document.mjs";
8
+ import { runTransition } from "./lib/transitions.mjs";
9
+ import {
10
+ createRecordPath,
11
+ displayPath,
12
+ readInput,
13
+ readRecord,
14
+ resolveRecordPath,
15
+ writeInitialAtomically,
16
+ } from "./lib/store.mjs";
17
+ import { renderFull, renderResume } from "./lib/views.mjs";
9
18
 
10
- function parseCliArgs(args) {
11
- const positionals = [];
19
+ function usage() {
20
+ return [
21
+ "Usage:",
22
+ " working-record.mjs init --root <path> --name <task name> [--input <file|->]",
23
+ " working-record.mjs view resume|full --record <record.md>",
24
+ " working-record.mjs validate --record <record.md>",
25
+ " working-record.mjs <slice|checkpoint|decision|task> <operation> ...",
26
+ ].join("\n");
27
+ }
28
+
29
+ const COMMAND_HELP = new Map([
30
+ [
31
+ "slice",
32
+ [
33
+ "Usage: working-record.mjs slice <operation> ...",
34
+ "Operations: slice propose, slice start, slice start-direct, slice pause, slice resume, slice close, slice reopen.",
35
+ "Run working-record.mjs <group> <operation> --help for options and input fields.",
36
+ "Use --input - to read Markdown fragments from stdin.",
37
+ ].join("\n"),
38
+ ],
39
+ [
40
+ "checkpoint",
41
+ [
42
+ "Usage: working-record.mjs checkpoint <operation> ...",
43
+ "Operations: checkpoint propose, checkpoint activate, checkpoint defer, checkpoint resume, checkpoint close.",
44
+ "Run working-record.mjs <group> <operation> --help for options and input fields.",
45
+ "Use --input - to read Markdown fragments from stdin.",
46
+ ].join("\n"),
47
+ ],
48
+ [
49
+ "decision",
50
+ [
51
+ "Usage: working-record.mjs decision <operation> ...",
52
+ "Operations: decision add, decision supersede, decision retire.",
53
+ "Run working-record.mjs <group> <operation> --help for options and input fields.",
54
+ "Use --input - to read Markdown fragments from stdin.",
55
+ ].join("\n"),
56
+ ],
57
+ [
58
+ "task",
59
+ [
60
+ "Usage: working-record.mjs task <operation> ...",
61
+ "Operations: task set-state.",
62
+ "Run working-record.mjs <group> <operation> --help for options and input fields.",
63
+ ].join("\n"),
64
+ ],
65
+ [
66
+ "init",
67
+ "Usage: init --root <path> --name <task name> [--state <state>] [--input <file|->]\nInput: Goal and Next useful action required; the seven Current Context headings are accepted. Use --input - to read Markdown fragments from stdin.",
68
+ ],
69
+ ["view", "Usage: view resume|full --record <record.md>"],
70
+ ["validate", "Usage: validate --record <record.md>"],
71
+ [
72
+ "slice propose",
73
+ "Usage: slice propose --record <record.md> --title <title> --input <file|->\nInput: Intended result required; Type, Expected evidence, and Dependencies optional. Use --input - to read the fragment from stdin.",
74
+ ],
75
+ [
76
+ "slice start",
77
+ "Usage: slice start --record <record.md> --title <proposal title> --next-action <text> --input <file|->\nInput: Authority source, Scope, Expected evidence, Stop condition, and Starting state required. Use --input - to read the fragment from stdin.",
78
+ ],
79
+ [
80
+ "slice start-direct",
81
+ "Usage: slice start-direct --record <record.md> --title <title> --next-action <text> --input <file|->\nInput: Intended result, Authority source, Scope, Expected evidence, Stop condition, and Starting state required; Future Work is unchanged. Use --input - to read the fragment from stdin.",
82
+ ],
83
+ [
84
+ "slice pause",
85
+ "Usage: slice pause --record <record.md> --reason <reason> --resume-when <condition> --next-action <text>",
86
+ ],
87
+ ["slice resume", "Usage: slice resume --record <record.md> --resolution <source> --next-action <text>"],
88
+ [
89
+ "slice close",
90
+ "Usage: slice close --record <record.md> --state <completed|blocked|abandoned> --next-action <text> --input <file|->\nInput: Result, Evidence and limits, and Task effect required. Use --input - to read the fragment from stdin.",
91
+ ],
92
+ [
93
+ "slice reopen",
94
+ "Usage: slice reopen --record <record.md> --id <S-NNN> --next-action <text> --input <file|->\nInput: fresh Authority source, Scope, Expected evidence, Stop condition, and Starting state required. Use --input - to read the fragment from stdin.",
95
+ ],
96
+ [
97
+ "checkpoint propose",
98
+ "Usage: checkpoint propose --record <record.md> --title <title> --input <file|->\nInput: Type, Condition, and Applies to required. Use --input - to read the fragment from stdin.",
99
+ ],
100
+ [
101
+ "checkpoint activate",
102
+ "Usage: checkpoint activate --record <record.md> --title <proposal title> [--next-action <text>]",
103
+ ],
104
+ ["checkpoint defer", "Usage: checkpoint defer --record <record.md> --id <C-NNN> [--next-action <text>]"],
105
+ ["checkpoint resume", "Usage: checkpoint resume --record <record.md> --id <C-NNN> [--next-action <text>]"],
106
+ [
107
+ "checkpoint close",
108
+ "Usage: checkpoint close --record <record.md> --id <C-NNN> --state <completed|cancelled|replaced> [--next-action <text>] --input <file|->\nInput: Result and Task effect required; Evidence optional; Reason required for cancelled or replaced; Replaced by required for replaced. Use --input - to read the fragment from stdin.",
109
+ ],
110
+ [
111
+ "decision add",
112
+ "Usage: decision add --record <record.md> --title <title> --input <file|->\nInput: Decision, Established by, Rationale, Consequences, and Revisit when required; Source references optional. Use --input - to read the fragment from stdin.",
113
+ ],
114
+ [
115
+ "decision supersede",
116
+ "Usage: decision supersede --record <record.md> --id <D-NNN> --title <title> --input <file|->\nInput: Decision, Established by, Rationale, Consequences, and Revisit when required; Source references optional. Use --input - to read the fragment from stdin.",
117
+ ],
118
+ ["decision retire", "Usage: decision retire --record <record.md> --id <D-NNN> --reason <reason>"],
119
+ [
120
+ "task set-state",
121
+ "Usage: task set-state --record <record.md> --state <active|paused|completed|abandoned> --next-action <text>",
122
+ ],
123
+ ]);
124
+
125
+ function commandHelp(command, operation) {
126
+ return `${COMMAND_HELP.get([command, operation].filter(Boolean).join(" ")) ?? COMMAND_HELP.get(command) ?? usage()}\n`;
127
+ }
128
+
129
+ class CliError extends Error {
130
+ constructor(message, exitCode = 1) {
131
+ super(message);
132
+ this.name = "CliError";
133
+ this.exitCode = exitCode;
134
+ }
135
+ }
136
+
137
+ function parseOptions(args) {
12
138
  const options = {};
13
- const flags = new Set(["--dry-run", "--help"]);
139
+ const positionals = [];
14
140
  for (let index = 0; index < args.length; index += 1) {
15
- const argument = args[index];
16
- if (!argument.startsWith("--")) {
17
- positionals.push(argument);
141
+ const token = args[index];
142
+ if (!token.startsWith("--")) {
143
+ positionals.push(token);
18
144
  continue;
19
145
  }
20
- const equals = argument.indexOf("=");
21
- const key = equals >= 0 ? argument.slice(0, equals) : argument;
22
- if (Object.hasOwn(options, key)) fail("duplicate-option", `Option may be supplied once: ${key}`);
23
- if (flags.has(key)) {
24
- options[key] = true;
25
- if (equals >= 0) fail("invalid-option", `${key} does not accept a value`);
146
+ if (options[token] !== undefined) throw new CliError(`Duplicate option: ${token}`);
147
+ if (token === "--help") {
148
+ options[token] = true;
26
149
  continue;
27
150
  }
28
- const value = equals >= 0 ? argument.slice(equals + 1) : args[++index];
29
- if (value === undefined || value.startsWith("--")) fail("missing-option-value", `Option requires a value: ${key}`);
30
- options[key] = value;
151
+ const value = args[index + 1];
152
+ if (value === undefined || value.startsWith("--")) throw new CliError(`Missing value for ${token}`);
153
+ options[token] = value;
154
+ index += 1;
31
155
  }
32
- return { positionals, options };
156
+ return { options, positionals };
33
157
  }
34
- function usage() {
35
- return `Usage: node skills/track-work/scripts/working-record.mjs <command> [options]
36
158
 
37
- Commands:
38
- init --root <repo> --name <short-name> [--input <json-file|->] [--dry-run]
39
- view --record <record.md> --view <resume|discuss|execute|recent|entity|full> [--entity <id-or-title>]
40
- schema --command <init|update|start|block|resume|reopen|close|unlock|migrate|compress|all> [--help]
41
- update --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
42
- start --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
43
- block --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
44
- resume --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
45
- reopen --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
46
- close --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
47
- unlock --record <record.md> --input <json-file|->
48
- migrate --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
49
- compress --record <record.md> --expected-sha <sha256> --input <json-file|-> [--dry-run]
50
- validate --record <record.md>
51
- inspect --record <record.md>
159
+ function allowedOptions(command, operation) {
160
+ const common = new Set(["--root", "--record", "--input", "--help"]);
161
+ const withNextAction = new Set([...common, "--next-action"]);
162
+ if (command === "init") return new Set(["--root", "--name", "--state", "--input", "--help"]);
163
+ if (command === "view") return new Set(["--root", "--record", "--view", "--help"]);
164
+ if (command === "validate") return new Set(["--root", "--record", "--help"]);
165
+ if (command === "slice") {
166
+ if (operation === "propose") return new Set([...common, "--title"]);
167
+ if (operation === "start" || operation === "start-direct") return new Set([...withNextAction, "--title"]);
168
+ if (operation === "pause") return new Set([...withNextAction, "--reason", "--resume-when"]);
169
+ if (operation === "resume") return new Set([...withNextAction, "--resolution"]);
170
+ if (operation === "close") return new Set([...withNextAction, "--state"]);
171
+ if (operation === "reopen") return new Set([...withNextAction, "--id", "--title"]);
172
+ }
173
+ if (command === "checkpoint") {
174
+ if (operation === "propose") return new Set([...common, "--title"]);
175
+ if (operation === "activate") return new Set([...withNextAction, "--title"]);
176
+ if (operation === "defer" || operation === "resume") return new Set([...withNextAction, "--id"]);
177
+ if (operation === "close") return new Set([...withNextAction, "--id", "--state"]);
178
+ }
179
+ if (command === "decision") {
180
+ if (operation === "add") return new Set([...common, "--title"]);
181
+ if (operation === "supersede") return new Set([...common, "--id", "--title"]);
182
+ if (operation === "retire") return new Set(["--root", "--record", "--id", "--reason", "--input", "--help"]);
183
+ }
184
+ if (command === "task" && operation === "set-state")
185
+ return new Set(["--root", "--record", "--state", "--next-action", "--help"]);
186
+ return null;
187
+ }
52
188
 
53
- Views emit bounded Markdown text. Other commands emit one JSON result. Existing-record mutations require the current SHA-256. Use --input - to read semantic JSON from stdin.
54
- `;
189
+ function validateCommandOptions(command, operation, options) {
190
+ const allowed = allowedOptions(command, operation);
191
+ if (!allowed) throw new CliError(`Unknown command: ${command}${operation ? ` ${operation}` : ""}`);
192
+ for (const name of Object.keys(options)) {
193
+ if (!allowed.has(name))
194
+ throw new CliError(`Unknown option ${name} for ${command}${operation ? ` ${operation}` : ""}`);
195
+ }
55
196
  }
56
197
 
57
- export { executeCommand };
198
+ function requireOption(options, name) {
199
+ const value = options[name];
200
+ if (!value) throw new CliError(`Missing required option: ${name}`);
201
+ return value;
202
+ }
58
203
 
59
- async function main() {
60
- const [command, ...args] = process.argv.slice(2);
61
- if (!command || command === "--help" || command === "-h") {
62
- process.stdout.write(usage());
63
- return;
64
- }
65
- const { positionals, options } = parseCliArgs(args);
66
- if (options["--help"]) {
67
- process.stdout.write(usage());
68
- return;
204
+ function rootOption(options) {
205
+ return options["--root"] ?? cwd();
206
+ }
207
+
208
+ function initialContent(skeletonLines, input) {
209
+ if (!input.trim()) return joinLines(skeletonLines, "\n");
210
+ const inputLines = input.replace(/\r\n?/g, "\n").split("\n");
211
+ const targets = new Map();
212
+ const names = [
213
+ "Goal",
214
+ "What defines this task",
215
+ "Settled",
216
+ "Tentative",
217
+ "Open",
218
+ "Current direction",
219
+ "Boundaries",
220
+ "Next useful action",
221
+ ];
222
+ const allowed = new Set(names);
223
+ for (let index = 0; index < inputLines.length; index += 1) {
224
+ const levelThree = /^### (.+?)\s*$/.exec(inputLines[index]);
225
+ if (levelThree) {
226
+ const name = levelThree[1];
227
+ if (!allowed.has(name)) throw new CliError(`Unknown initialization heading: ${name}`);
228
+ if (targets.has(name)) throw new CliError(`Duplicate initialization heading: ${name}`);
229
+ const content = [];
230
+ for (let next = index + 1; next < inputLines.length; next += 1) {
231
+ if (/^### /.test(inputLines[next]) || /^## /.test(inputLines[next])) break;
232
+ content.push(inputLines[next]);
233
+ }
234
+ targets.set(name, content);
235
+ continue;
236
+ }
237
+ if (/^## /.test(inputLines[index])) throw new CliError(`Unknown initialization heading: ${inputLines[index]}`);
69
238
  }
70
- const root = options["--root"] ? resolve(options["--root"]) : process.cwd();
71
- if (positionals.length > 1) fail("invalid-arguments", "Only one positional record or task path is supported");
72
- if (positionals.length === 1 && !options["--record"] && !options["--task"]) options["--record"] = positionals[0];
73
- const input = await readJsonInput(options);
74
- const result = await executeCommand(command, { root, options, input });
75
- if (command === "view" || command === "resume-view") {
76
- process.stdout.write(result.view?.content ?? "");
77
- } else if (command === "schema") {
78
- process.stdout.write(result.content ?? "");
79
- } else {
80
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
239
+ const output = [...skeletonLines];
240
+ for (const name of names) {
241
+ const content = targets.get(name);
242
+ if (!content) continue;
243
+ const headingIndex = output.findIndex((line) => line === `### ${name}`);
244
+ if (headingIndex < 0) continue;
245
+ let end = headingIndex + 1;
246
+ while (end < output.length && !/^### |^## /.test(output[end])) end += 1;
247
+ const trimmed = [...content];
248
+ while (trimmed.length && trimmed[0].trim() === "") trimmed.shift();
249
+ while (trimmed.length && trimmed[trimmed.length - 1].trim() === "") trimmed.pop();
250
+ output.splice(headingIndex + 1, end - headingIndex - 1, "", ...trimmed, "");
81
251
  }
82
- if (result.status === "committed-unconfirmed") process.exitCode = 2;
83
- else if (result.status === "failed") process.exitCode = 1;
252
+ return joinLines(output, "\n");
84
253
  }
85
254
 
86
- if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
255
+ async function initialize(options) {
256
+ const root = rootOption(options);
257
+ const name = requireOption(options, "--name");
258
+ const state = options["--state"] ?? "active";
259
+ if (!TASK_STATES.has(state)) throw new CliError(`Invalid task state: ${state}`);
260
+ const input = await readInput(options["--input"], cwd());
261
+ const text = initialContent(canonicalLines(name, state), input);
262
+ parseDocument(text);
263
+ const created = await createRecordPath(root, name, slugify(name));
87
264
  try {
88
- await main();
265
+ await writeInitialAtomically(root, created.path, text);
89
266
  } catch (error) {
90
- if (error instanceof CommittedResultError) {
91
- process.stdout.write(`${JSON.stringify(error.result, null, 2)}\n`);
92
- process.exitCode = 2;
93
- } else {
94
- const knownError = error instanceof WorkingRecordError;
95
- const command = process.argv[2] ?? null;
96
- if (command === "view" || command === "resume-view") {
97
- process.stdout.write(`Track Work view failed [${error.code ?? "view-failed"}]: ${error.message}\n`);
98
- process.exitCode = error instanceof WorkingRecordError ? error.exitCode : 1;
99
- } else if (command === "schema") {
100
- process.stdout.write(`Track Work schema failed [${error.code ?? "schema-failed"}]: ${error.message}\n`);
101
- process.exitCode = error instanceof WorkingRecordError ? error.exitCode : 1;
102
- } else {
103
- const result = baseEnvelope(command, command, knownError ? error.record : null);
104
- if (!result.record && knownError && error.details?.path) {
105
- result.record = {
106
- path: error.details.path,
107
- confirmation: "unavailable",
108
- sha256: error.details.sha256 ?? null,
109
- schemaVersion: null,
110
- taskState: null,
111
- lastUpdated: null,
112
- currentSlice: null,
113
- unavailable: ["recordProjectionUnavailable"],
114
- };
115
- }
116
- result.errors = errorItems(knownError ? error : new WorkingRecordError("unexpected-error", error.message));
117
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
118
- process.exitCode = error instanceof WorkingRecordError ? error.exitCode : 1;
119
- }
120
- }
267
+ if (error?.exitCode !== 2) await rm(dirname(created.path), { recursive: true, force: true }).catch(() => undefined);
268
+ throw error;
269
+ }
270
+ return `${created.path}\n`;
271
+ }
272
+
273
+ async function readExisting(options) {
274
+ const root = rootOption(options);
275
+ const recordOption = requireOption(options, "--record");
276
+ const loaded = await readRecord(root, resolveRecordPath(root, recordOption));
277
+ return { root, ...loaded };
278
+ }
279
+
280
+ async function runCore(command, rest) {
281
+ const { options, positionals } = parseOptions(rest);
282
+ const operation = positionals[0];
283
+ if (options["--help"]) return commandHelp(command, operation);
284
+ validateCommandOptions(command, operation, options);
285
+ if (command === "init") return initialize(options);
286
+ if (command === "view") {
287
+ if (positionals.length > 1) throw new CliError("View accepts only resume or full");
288
+ const view = positionals[0] ?? options["--view"];
289
+ if (!view || !["resume", "full"].includes(view)) throw new CliError("View must be resume or full");
290
+ const loaded = await readExisting(options);
291
+ if (view === "full") return renderFull(loaded.text);
292
+ return renderResume(loaded.text);
293
+ }
294
+ if (command === "validate") {
295
+ if (positionals.length) throw new CliError("Validate does not accept positional arguments");
296
+ const loaded = await readExisting(options);
297
+ validateDocument(parseDocument(loaded.text));
298
+ return `valid\n${displayPath(loaded.root, loaded.path)}\n`;
299
+ }
300
+ if (positionals.length !== 1) throw new CliError(`Expected one operation for ${command}`);
301
+ const loaded = await readExisting(options);
302
+ const input = await readInput(options["--input"], cwd());
303
+ return runTransition(command, positionals, options, input, loaded);
304
+ }
305
+
306
+ try {
307
+ const [command, ...rest] = process.argv.slice(2);
308
+ if (!command || command === "--help" || command === "help") {
309
+ process.stdout.write(`${usage()}\n`);
310
+ } else {
311
+ process.stdout.write(await runCore(command, rest));
121
312
  }
313
+ } catch (error) {
314
+ process.stderr.write(`Error: ${error.message}\n`);
315
+ process.exitCode = error.exitCode ?? 1;
122
316
  }
@@ -11,7 +11,7 @@ Verification is factual: what ran, what happened, and what that result proves. T
11
11
 
12
12
  ## Name The Claim
13
13
 
14
- State the claim before choosing the check. Include the behavior or property and the boundary where it must hold.
14
+ State the claim before choosing the check. Include the behavior or property and the boundary where it must hold. Keep this compact when both are obvious; do not let an available check silently narrow a broader claim.
15
15
 
16
16
  Claims may concern:
17
17
 
@@ -22,21 +22,21 @@ Claims may concern:
22
22
  - performance or resource bounds;
23
23
  - artifact completeness or repository state.
24
24
 
25
- Do not let an available check silently narrow a broader claim.
26
-
27
25
  ## Choose Evidence That Can Disagree
28
26
 
29
27
  Use the smallest direct evidence that can falsify the claim. Evidence must be fresh for the code, configuration, environment, and artifact being assessed.
30
28
 
31
- Verification inherits the current authority envelope. Existing evidence may be inspected without a new run. Run a new active check only when that envelope covers it directly or as contained verification; otherwise return its purpose, expected evidence, and stop condition to Workflow and wait.
29
+ Verification inherits the current authority envelope. Existing evidence may be inspected without a new run. Run a new active check only when that envelope covers it directly or as contained verification; otherwise return its purpose, expected evidence, and stop condition to [Workflow](../../skills/workflow/SKILL.md) and wait.
30
+
31
+ Verify Work owns the claim and required evidence boundary. When several covered observers can falsify the same claim, or the likely check is broad, use [Action Selection](../../skills/action-selection/SKILL.md) to choose and bound one environment interaction. It returns the observation; Verify Work interprets and classifies support. Skip it when one exact check is already selected.
32
32
 
33
- Verify Work owns the claim and required evidence boundary. When several covered observers can falsify the same claim, or the likely check is broad, use [Action Selection](../action-selection/SKILL.md) to choose and bound one environment interaction. It returns the observation; Verify Work interprets and classifies support. Skip it when one exact check is already selected.
33
+ Before running covered checks concurrently, compare what each may write or remove. Run checks serially when they share generated directories, caches, build outputs, package roots, fixture state, ports, databases, or intentional stale-artifact files. A concurrency-induced red signal is orchestration evidence, not automatically an implementation defect; reproduce it under a non-overlapping or serial schedule before changing production code.
34
34
 
35
35
  Passing tests do not prove behavior they do not exercise. A happy path does not prove failure handling. Source inspection does not prove runtime execution. A helper call does not prove registration, host dispatch, or installed-package behavior.
36
36
 
37
37
  Before selecting or running evidence:
38
38
 
39
- - read [integration evidence](references/integration-evidence.md) when a claim depends on a registered callback or executor, host lifecycle, producer invocation, fallback protocol, installed package, absence counter, or a check that may mutate shared state;
39
+ - read [integration evidence](references/integration-evidence.md) when a claim depends on a registered callback or executor, host lifecycle, producer invocation, fallback protocol, installed package, or absence counter;
40
40
  - read [browser runtime evidence](references/browser-runtime-evidence.md) when a claim depends on rendered UI, browser behavior, accessibility, client networking, console state, visual output, or browser runtime performance;
41
41
  - read [performance evidence](references/performance-evidence.md) when verifying latency, throughput, memory, CPU, bundle, query, rendering, capacity, or resource-regression claims.
42
42
 
@@ -50,25 +50,28 @@ Once the selected check is authorized:
50
50
 
51
51
  1. Run the complete selected check.
52
52
  2. Read the relevant output, exit status, and lower-level evidence that can contradict a summary.
53
- 3. Confirm the intended success or failure path and observing boundary were exercised.
54
- 4. Compare the observation with the exact claim and source requirement.
55
- 5. Preserve contradictory evidence; do not rerun until an unfavorable result disappears.
56
- 6. State unavailable, stale, partial, or reduced-fidelity evidence honestly.
53
+ 3. Confirm the defined assertion and intended success or failure path were exercised.
54
+ 4. Confirm the observing boundary actually matched the claim.
55
+ 5. Compare the observation with the exact claim and source requirement.
56
+ 6. Preserve contradictory evidence; do not rerun until an unfavorable result disappears.
57
+ 7. State unavailable, stale, partial, or reduced-fidelity evidence honestly.
57
58
 
58
59
  Do not convert missing evidence into zero, safe, passed, or probably correct. If the user skips a check, respect that choice and leave the corresponding claim unverified.
59
60
 
60
- Do not change implementation, tests, checks, specs, policies, or acceptance merely to make the signal green. When the cause of a contradiction is unclear, report the contradiction rather than inventing one.
61
+ Do not change implementation, tests, checks, Specs, policies, or acceptance merely to make the signal green. When the cause of a contradiction is unclear, report the contradiction rather than inventing one.
61
62
 
62
63
  ## Classify The Result
63
64
 
64
65
  Keep check execution separate from claim support.
65
66
 
66
- **Check result:**
67
+ **Check result** is relative to the check's defined assertion—not whether the target operation happened to succeed or fail:
67
68
 
68
- - **Passed:** the check completed successfully.
69
- - **Failed:** the check completed and observed a failure.
70
- - **Error:** the check itself did not execute validly.
71
- - **Unavailable:** the required check could not be run.
69
+ - **Passed:** the check executed validly and its defined assertion held.
70
+ - **Failed:** the check executed validly and its defined assertion did not hold.
71
+ - **Error:** the observing mechanism or check execution was invalid.
72
+ - **Unavailable:** the required check could not be attempted safely or reliably.
73
+
74
+ A check can Pass while intentionally observing rejection, failure, rollback, or fail-closed behavior.
72
75
 
73
76
  **Claim result:**
74
77
 
@@ -77,11 +80,34 @@ Keep check execution separate from claim support.
77
80
  - **Inconclusive:** evidence exists but cannot establish or refute the claim at the required boundary.
78
81
  - **Unavailable:** the required evidence cannot currently be obtained safely or reliably.
79
82
 
80
- A passed check may still leave the claim inconclusive. A failed check may expose an implementation defect, an invalid check, an environment problem, or a source conflict; classify only what evidence supports.
83
+ A Passed check may still leave the claim Inconclusive. A Failed check may expose an implementation defect, an invalid expectation, an environment problem, or a source conflict; classify only what evidence supports.
84
+
85
+ When contradictory evidence is unexplained or failure repeats, read [Diagnose Failure](../../skills/diagnose-failure/SKILL.md). When evidence exposes a user-owned decision or source conflict, read [Decision Gate](../../skills/decision-gate/SKILL.md).
86
+
87
+ ## Return Evidence To Review
88
+
89
+ When verification answers a review **Needs evidence** item, preserve the original review-item pointer, claim, required observing boundary, available evidence and prior limit, and why the gap affects review judgment.
90
+
91
+ Return the verification result to the receiving agent for adjudication:
92
+
93
+ - **Supported:** the factual gap may be resolved; do not infer review Pass.
94
+ - **Contradicted:** the finding may be established, invalidated, or expose a source conflict; do not classify the review item here.
95
+ - **Inconclusive:** the review item remains Open when the gap is material.
96
+ - **Unavailable:** the review item remains Open and the observing limitation must remain explicit.
81
97
 
82
- When contradictory evidence is unexplained or failure repeats, read [Diagnose Failure](../diagnose-failure/SKILL.md). When evidence exposes a user-owned decision or source conflict, read [Decision Gate](../decision-gate/SKILL.md).
98
+ Verification does not revise the independent review report, adjudicate findings, authorize correction, or select follow-up review.
99
+
100
+ ## Report Proportionately
101
+
102
+ For one straightforward Supported claim with an obvious check and boundary, use the compact form:
103
+
104
+ ```text
105
+ Claim @ required boundary: Supported ([check result]) by [evidence].
106
+ Proves:
107
+ Does not prove:
108
+ ```
83
109
 
84
- ## Report
110
+ Use the full form when the result is Contradicted, Inconclusive, or Unavailable; several claims or boundaries are involved; evidence conflicts; the claim is consequential; or the result returns to review adjudication:
85
111
 
86
112
  ```text
87
113
  Claim:
@@ -94,4 +120,4 @@ Does not prove:
94
120
  Required next evidence:
95
121
  ```
96
122
 
97
- Omit `Required next evidence` when the claim is fully supported or contradicted. When the result changes or ends the current path, use [Workflow](../workflow/SKILL.md) to choose what follows.
123
+ When returning evidence for adjudication, prepend `Review item:` with the original item pointer. Omit `Required next evidence` when the claim is fully Supported or Contradicted. When the result changes or ends the current path, return it to [Workflow](../../skills/workflow/SKILL.md) to choose what follows.
@@ -52,4 +52,4 @@ Stop or downgrade the claim when:
52
52
  - only a nearby path, screenshot, or mocked page was tested;
53
53
  - browser evidence contradicts tests, specs, or accepted behavior.
54
54
 
55
- Read [Diagnose Failure](../../diagnose-failure/SKILL.md) for unexplained browser failures. Read [Decision Gate](../../decision-gate/SKILL.md) when browser evidence conflicts with accepted behavior or exposes a user-owned decision.
55
+ Read [Diagnose Failure](../../../skills/diagnose-failure/SKILL.md) for unexplained browser failures. Read [Decision Gate](../../../skills/decision-gate/SKILL.md) when browser evidence conflicts with accepted behavior or exposes a user-owned decision.
@@ -1,6 +1,6 @@
1
1
  # Integration Evidence
2
2
 
3
- Read this before selecting or running evidence when a claim depends on a registered callback or executor, host lifecycle, producer invocation, fallback protocol, installed package, absence counter, or a check that may mutate shared state.
3
+ Read this before selecting or running evidence when a claim depends on a registered callback or executor, host lifecycle, producer invocation, fallback protocol, installed package, or absence counter.
4
4
 
5
5
  ## Match The Boundary
6
6
 
@@ -28,12 +28,6 @@ A zero value proves absence only when:
28
28
 
29
29
  Prefer an adversarial disproof: bypass the producer, forge or replay the event, call the helper directly, or resolve code from the checkout instead of the installed root. The proof should fail before downstream work when the claimed boundary was not crossed.
30
30
 
31
- ## Compare Mutation Footprints
32
-
33
- Before running checks concurrently, compare what each check may write or remove. Run checks serially when they share generated directories, caches, build outputs, package roots, fixture state, ports, databases, or intentional stale-artifact files.
34
-
35
- A concurrency-induced red signal is orchestration evidence, not automatically an implementation defect. Reproduce it under a non-overlapping or serial schedule before changing production code.
36
-
37
31
  ## Claim Map
38
32
 
39
33
  For sensitive or proof-bearing claims, record:
@@ -54,4 +54,4 @@ Stop or downgrade the claim when:
54
54
  - only a nearby operation improved;
55
55
  - required production evidence is unavailable.
56
56
 
57
- Read [Diagnose Failure](../../diagnose-failure/SKILL.md) for unexplained regressions. Read [Decision Gate](../../decision-gate/SKILL.md) when the next step depends on a product, SLO, cost, or resource tradeoff owned by the user.
57
+ Read [Diagnose Failure](../../../skills/diagnose-failure/SKILL.md) for unexplained regressions. Read [Decision Gate](../../../skills/decision-gate/SKILL.md) when the next step depends on a product, SLO, cost, or resource tradeoff owned by the user.