forge-workflow 0.1.0-beta.5 → 0.1.0-beta.7

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 (268) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +48 -0
  3. package/CLAUDE.md +0 -12
  4. package/CODING_STANDARDS.md +72 -0
  5. package/bin/forge.js +12 -1
  6. package/docs/guides/MIGRATION.md +3 -3
  7. package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +4 -0
  8. package/docs/reference/INSTALL.md +4 -0
  9. package/docs/reference/LEGACY_CLAIM_REPAIR.md +112 -0
  10. package/docs/reference/RELEASE.md +4 -4
  11. package/docs/reference/github-accounts.md +134 -0
  12. package/docs/reference/shepherd.md +63 -13
  13. package/lib/adapters/pr-state-adapter.js +15 -2
  14. package/lib/base-remote.js +138 -0
  15. package/lib/beta5-compatibility-evidence.js +1093 -0
  16. package/lib/bun-lockfile-proof.js +413 -0
  17. package/lib/bun-workflow-pins.js +461 -0
  18. package/lib/capabilities/index.js +9 -0
  19. package/lib/capabilities/model.js +141 -0
  20. package/lib/capabilities/probes.js +347 -0
  21. package/lib/codex-skills.js +2 -2
  22. package/lib/commands/_manifest.js +1 -0
  23. package/lib/commands/_registry.js +48 -18
  24. package/lib/commands/clean.js +57 -1
  25. package/lib/commands/doctor.js +37 -6
  26. package/lib/commands/gate.js +197 -27
  27. package/lib/commands/github.js +215 -0
  28. package/lib/commands/hooks.js +54 -6
  29. package/lib/commands/memory.js +66 -2
  30. package/lib/commands/merge.js +720 -73
  31. package/lib/commands/plan.js +33 -2
  32. package/lib/commands/pr.js +2 -0
  33. package/lib/commands/preflight.js +10 -2
  34. package/lib/commands/push.js +120 -9
  35. package/lib/commands/recall.js +95 -61
  36. package/lib/commands/release.js +23 -2
  37. package/lib/commands/remember.js +28 -4
  38. package/lib/commands/serve.js +26 -9
  39. package/lib/commands/setup.js +132 -4
  40. package/lib/commands/shepherd.js +578 -72
  41. package/lib/commands/ship.js +15 -69
  42. package/lib/commands/skill.js +8 -0
  43. package/lib/commands/team.js +47 -8
  44. package/lib/commands/test.js +163 -4
  45. package/lib/commands/validate.js +78 -22
  46. package/lib/commands/worktree.js +155 -19
  47. package/lib/fixtures/beta5-corpus/v1/README.md +9 -0
  48. package/lib/fixtures/beta5-corpus/v1/contract/command-contract.json +26 -0
  49. package/lib/fixtures/beta5-corpus/v1/contract/package-contract.json +13 -0
  50. package/lib/fixtures/beta5-corpus/v1/contract/workflow-stage-matrix.json +8 -0
  51. package/lib/fixtures/beta5-corpus/v1/manifest.json +25 -0
  52. package/lib/fixtures/beta5-corpus/v1/state/comments.jsonl +1 -0
  53. package/lib/fixtures/beta5-corpus/v1/state/config.yaml +6 -0
  54. package/lib/fixtures/beta5-corpus/v1/state/dependencies.jsonl +1 -0
  55. package/lib/fixtures/beta5-corpus/v1/state/issues.jsonl +2 -0
  56. package/lib/fixtures/beta5-corpus/v1/state/kernel.sql +20 -0
  57. package/lib/forge-issues.js +78 -0
  58. package/lib/gate-events.js +98 -10
  59. package/lib/github-context.js +308 -0
  60. package/lib/global-flags.js +1 -0
  61. package/lib/hook-renderer.js +29 -1
  62. package/lib/issue-render.js +19 -0
  63. package/lib/kernel/broker.js +723 -31
  64. package/lib/kernel/claim-reconciler.js +238 -0
  65. package/lib/kernel/lease-enforcer.js +9 -4
  66. package/lib/kernel/legacy-claim-repair.js +442 -0
  67. package/lib/kernel/live-claim-projection.js +26 -0
  68. package/lib/kernel/migrations.js +118 -3
  69. package/lib/kernel/readiness-model.js +184 -12
  70. package/lib/kernel/schema.js +49 -1
  71. package/lib/kernel/sqlite-driver.js +3322 -183
  72. package/lib/kernel/taxonomy-validator.js +4 -1
  73. package/lib/kernel/windows-private-acl.js +239 -0
  74. package/lib/memory/hygiene.js +191 -0
  75. package/lib/memory/router.js +94 -27
  76. package/lib/memory/usage-evidence.js +4 -0
  77. package/lib/memory-digest.js +59 -0
  78. package/lib/merge-rules.js +135 -17
  79. package/lib/npm-publish-workflow.js +233 -40
  80. package/lib/package-root.js +2 -0
  81. package/lib/pr-monitor/auto-actions.js +169 -28
  82. package/lib/pr-monitor/differ.js +110 -4
  83. package/lib/pr-monitor/events.js +0 -0
  84. package/lib/pr-monitor/flow-monitor.js +1424 -0
  85. package/lib/pr-monitor/gather.js +251 -44
  86. package/lib/pr-monitor/journal.js +0 -37
  87. package/lib/pr-monitor/monitor.js +117 -10
  88. package/lib/pr-monitor/process-identity.js +117 -0
  89. package/lib/pr-monitor/reconcile-executor.js +1101 -625
  90. package/lib/pr-monitor/reconcile.js +0 -0
  91. package/lib/pr-monitor/render-summary.js +121 -24
  92. package/lib/pr-monitor/review-preflight.js +269 -0
  93. package/lib/pr-monitor/shepherd-lease.js +28 -19
  94. package/lib/pr-monitor/verdict.js +438 -0
  95. package/lib/pr-monitor/watch-lifecycle.js +144 -38
  96. package/lib/pr-monitor/watch-owner.js +1414 -0
  97. package/lib/pr-monitor/watch.js +129 -58
  98. package/lib/pr-shepherd.js +17 -3
  99. package/lib/project-memory.js +145 -3
  100. package/lib/protected-state-authority.js +799 -4
  101. package/lib/protected-state-surfaces.js +181 -3
  102. package/lib/release-readiness.js +2 -3
  103. package/lib/review-adapter.js +65 -0
  104. package/lib/skills-sync.js +65 -32
  105. package/lib/validation/risk-manifest.js +339 -0
  106. package/lib/validation-receipt.js +190 -0
  107. package/lib/workflow/enforce-stage.js +44 -0
  108. package/lib/workflow/plan-authority.js +225 -0
  109. package/node_modules/@forge/contracts/compatibility-matrix.v1.json +1 -0
  110. package/node_modules/@forge/contracts/contract-baseline.v1.json +134 -0
  111. package/node_modules/@forge/contracts/fixtures/v1/canonical-hash.json +1 -0
  112. package/node_modules/@forge/contracts/fixtures/v1/contract-inputs.v1.json +71 -0
  113. package/node_modules/@forge/contracts/fixtures/v1/feedback-secret-reject.json +1 -0
  114. package/node_modules/@forge/contracts/fixtures/v1/identity-conflict.json +1 -0
  115. package/node_modules/@forge/contracts/fixtures/v1/malformed-envelope-inputs.v1.json +16 -0
  116. package/node_modules/@forge/contracts/fixtures/v1/malformed-missing-required.json +1 -0
  117. package/node_modules/@forge/contracts/fixtures/v1/monitor-bounds-reject.json +1 -0
  118. package/node_modules/@forge/contracts/fixtures/v1/monitor-receipt-privacy-reject.json +1 -0
  119. package/node_modules/@forge/contracts/fixtures/v1/not-executed-receipt.json +1 -0
  120. package/node_modules/@forge/contracts/fixtures/v1/privacy-redaction.json +1 -0
  121. package/node_modules/@forge/contracts/fixtures/v1/retry-identical.json +1 -0
  122. package/node_modules/@forge/contracts/fixtures/v1/stale-authority-reject.json +1 -0
  123. package/node_modules/@forge/contracts/fixtures/v1/structured-error-privacy-reject.json +1 -0
  124. package/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-live-reject.json +1 -0
  125. package/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-test-reject.json +1 -0
  126. package/node_modules/@forge/contracts/fixtures/v1/unknown-advisory-roundtrip.json +1 -0
  127. package/node_modules/@forge/contracts/fixtures/v1/unknown-consequential-reject.json +1 -0
  128. package/node_modules/@forge/contracts/fixtures/v1/valid-full.json +1 -0
  129. package/node_modules/@forge/contracts/fixtures/v1/valid-minimal.json +1 -0
  130. package/node_modules/@forge/contracts/fixtures/v1/wrong-capability-digest.json +1 -0
  131. package/node_modules/@forge/contracts/index.js +32 -0
  132. package/node_modules/@forge/contracts/package.json +35 -0
  133. package/node_modules/@forge/contracts/schemas/v1/capability-manifest.schema.json +1 -0
  134. package/node_modules/@forge/contracts/schemas/v1/claim-request.schema.json +1 -0
  135. package/node_modules/@forge/contracts/schemas/v1/context-packet.schema.json +1 -0
  136. package/node_modules/@forge/contracts/schemas/v1/delivery-receipt.schema.json +1 -0
  137. package/node_modules/@forge/contracts/schemas/v1/feedback-report.schema.json +1 -0
  138. package/node_modules/@forge/contracts/schemas/v1/lease-receipt.schema.json +1 -0
  139. package/node_modules/@forge/contracts/schemas/v1/monitor-event.schema.json +1 -0
  140. package/node_modules/@forge/contracts/schemas/v1/monitor-receipt.schema.json +1 -0
  141. package/node_modules/@forge/contracts/schemas/v1/run-receipt.schema.json +1 -0
  142. package/node_modules/@forge/contracts/schemas/v1/structured-error.schema.json +1 -0
  143. package/node_modules/@forge/contracts/schemas/v1/work-packet.schema.json +1 -0
  144. package/node_modules/@forge/contracts/src/baseline.js +23 -0
  145. package/node_modules/@forge/contracts/src/canonical.js +151 -0
  146. package/node_modules/@forge/contracts/src/definitions.js +176 -0
  147. package/node_modules/@forge/contracts/src/identity.js +42 -0
  148. package/node_modules/@forge/contracts/src/schema.js +72 -0
  149. package/node_modules/@forge/contracts/src/validate.js +305 -0
  150. package/node_modules/@forge/flow/index.js +114 -0
  151. package/node_modules/@forge/flow/package.json +34 -0
  152. package/node_modules/@forge/flow/src/bounded-loop.js +415 -0
  153. package/node_modules/@forge/flow/src/efficiency-supervisor.js +89 -0
  154. package/node_modules/@forge/flow/src/executor.js +279 -0
  155. package/node_modules/@forge/flow/src/monitor-durability.js +419 -0
  156. package/node_modules/@forge/flow/src/monitor-runtime.js +460 -0
  157. package/node_modules/@forge/flow/src/process-lifecycle.js +469 -0
  158. package/node_modules/@forge/flow/src/skill-runtime.js +343 -0
  159. package/node_modules/@forge/memory/index.js +331 -0
  160. package/node_modules/@forge/memory/package.json +34 -0
  161. package/node_modules/@forge/memory/src/authority-provider.js +67 -0
  162. package/node_modules/@forge/memory/src/backend-registry.js +166 -0
  163. package/node_modules/@forge/memory/src/feedback-intake.js +243 -0
  164. package/node_modules/@forge/memory/src/pr-lifecycle-authority.js +946 -0
  165. package/node_modules/@forge/memory/src/usage-evidence.js +205 -0
  166. package/package.json +16 -4
  167. package/packages/flow/node_modules/@forge/contracts/compatibility-matrix.v1.json +1 -0
  168. package/packages/flow/node_modules/@forge/contracts/contract-baseline.v1.json +134 -0
  169. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/canonical-hash.json +1 -0
  170. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/contract-inputs.v1.json +71 -0
  171. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/feedback-secret-reject.json +1 -0
  172. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/identity-conflict.json +1 -0
  173. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/malformed-envelope-inputs.v1.json +16 -0
  174. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/malformed-missing-required.json +1 -0
  175. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/monitor-bounds-reject.json +1 -0
  176. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/monitor-receipt-privacy-reject.json +1 -0
  177. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/not-executed-receipt.json +1 -0
  178. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/privacy-redaction.json +1 -0
  179. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/retry-identical.json +1 -0
  180. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/stale-authority-reject.json +1 -0
  181. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/structured-error-privacy-reject.json +1 -0
  182. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-live-reject.json +1 -0
  183. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-test-reject.json +1 -0
  184. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/unknown-advisory-roundtrip.json +1 -0
  185. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/unknown-consequential-reject.json +1 -0
  186. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/valid-full.json +1 -0
  187. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/valid-minimal.json +1 -0
  188. package/packages/flow/node_modules/@forge/contracts/fixtures/v1/wrong-capability-digest.json +1 -0
  189. package/packages/flow/node_modules/@forge/contracts/index.js +32 -0
  190. package/packages/flow/node_modules/@forge/contracts/package.json +35 -0
  191. package/packages/flow/node_modules/@forge/contracts/schemas/v1/capability-manifest.schema.json +1 -0
  192. package/packages/flow/node_modules/@forge/contracts/schemas/v1/claim-request.schema.json +1 -0
  193. package/packages/flow/node_modules/@forge/contracts/schemas/v1/context-packet.schema.json +1 -0
  194. package/packages/flow/node_modules/@forge/contracts/schemas/v1/delivery-receipt.schema.json +1 -0
  195. package/packages/flow/node_modules/@forge/contracts/schemas/v1/feedback-report.schema.json +1 -0
  196. package/packages/flow/node_modules/@forge/contracts/schemas/v1/lease-receipt.schema.json +1 -0
  197. package/packages/flow/node_modules/@forge/contracts/schemas/v1/monitor-event.schema.json +1 -0
  198. package/packages/flow/node_modules/@forge/contracts/schemas/v1/monitor-receipt.schema.json +1 -0
  199. package/packages/flow/node_modules/@forge/contracts/schemas/v1/run-receipt.schema.json +1 -0
  200. package/packages/flow/node_modules/@forge/contracts/schemas/v1/structured-error.schema.json +1 -0
  201. package/packages/flow/node_modules/@forge/contracts/schemas/v1/work-packet.schema.json +1 -0
  202. package/packages/flow/node_modules/@forge/contracts/src/baseline.js +23 -0
  203. package/packages/flow/node_modules/@forge/contracts/src/canonical.js +151 -0
  204. package/packages/flow/node_modules/@forge/contracts/src/definitions.js +176 -0
  205. package/packages/flow/node_modules/@forge/contracts/src/identity.js +42 -0
  206. package/packages/flow/node_modules/@forge/contracts/src/schema.js +72 -0
  207. package/packages/flow/node_modules/@forge/contracts/src/validate.js +305 -0
  208. package/packages/memory/node_modules/@forge/contracts/compatibility-matrix.v1.json +1 -0
  209. package/packages/memory/node_modules/@forge/contracts/contract-baseline.v1.json +134 -0
  210. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/canonical-hash.json +1 -0
  211. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/contract-inputs.v1.json +71 -0
  212. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/feedback-secret-reject.json +1 -0
  213. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/identity-conflict.json +1 -0
  214. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/malformed-envelope-inputs.v1.json +16 -0
  215. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/malformed-missing-required.json +1 -0
  216. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/monitor-bounds-reject.json +1 -0
  217. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/monitor-receipt-privacy-reject.json +1 -0
  218. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/not-executed-receipt.json +1 -0
  219. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/privacy-redaction.json +1 -0
  220. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/retry-identical.json +1 -0
  221. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/stale-authority-reject.json +1 -0
  222. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/structured-error-privacy-reject.json +1 -0
  223. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-live-reject.json +1 -0
  224. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/structured-error-stripe-test-reject.json +1 -0
  225. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/unknown-advisory-roundtrip.json +1 -0
  226. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/unknown-consequential-reject.json +1 -0
  227. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/valid-full.json +1 -0
  228. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/valid-minimal.json +1 -0
  229. package/packages/memory/node_modules/@forge/contracts/fixtures/v1/wrong-capability-digest.json +1 -0
  230. package/packages/memory/node_modules/@forge/contracts/index.js +32 -0
  231. package/packages/memory/node_modules/@forge/contracts/package.json +35 -0
  232. package/packages/memory/node_modules/@forge/contracts/schemas/v1/capability-manifest.schema.json +1 -0
  233. package/packages/memory/node_modules/@forge/contracts/schemas/v1/claim-request.schema.json +1 -0
  234. package/packages/memory/node_modules/@forge/contracts/schemas/v1/context-packet.schema.json +1 -0
  235. package/packages/memory/node_modules/@forge/contracts/schemas/v1/delivery-receipt.schema.json +1 -0
  236. package/packages/memory/node_modules/@forge/contracts/schemas/v1/feedback-report.schema.json +1 -0
  237. package/packages/memory/node_modules/@forge/contracts/schemas/v1/lease-receipt.schema.json +1 -0
  238. package/packages/memory/node_modules/@forge/contracts/schemas/v1/monitor-event.schema.json +1 -0
  239. package/packages/memory/node_modules/@forge/contracts/schemas/v1/monitor-receipt.schema.json +1 -0
  240. package/packages/memory/node_modules/@forge/contracts/schemas/v1/run-receipt.schema.json +1 -0
  241. package/packages/memory/node_modules/@forge/contracts/schemas/v1/structured-error.schema.json +1 -0
  242. package/packages/memory/node_modules/@forge/contracts/schemas/v1/work-packet.schema.json +1 -0
  243. package/packages/memory/node_modules/@forge/contracts/src/baseline.js +23 -0
  244. package/packages/memory/node_modules/@forge/contracts/src/canonical.js +151 -0
  245. package/packages/memory/node_modules/@forge/contracts/src/definitions.js +176 -0
  246. package/packages/memory/node_modules/@forge/contracts/src/identity.js +42 -0
  247. package/packages/memory/node_modules/@forge/contracts/src/schema.js +72 -0
  248. package/packages/memory/node_modules/@forge/contracts/src/validate.js +305 -0
  249. package/scripts/commitlint.js +13 -15
  250. package/scripts/generate-risk-manifest.js +91 -0
  251. package/scripts/github-context-bridge.sh +10 -0
  252. package/scripts/legacy-claim-repair.js +145 -0
  253. package/scripts/lib/behavioral-eval-runtime.js +3 -2
  254. package/scripts/process-tree.js +14 -2
  255. package/scripts/protected-state-check.js +440 -17
  256. package/scripts/sync-agent-skills.js +333 -34
  257. package/scripts/test-full-suite.js +704 -18
  258. package/scripts/test-profile.js +13 -3
  259. package/scripts/test.js +96 -15
  260. package/skills/coverage.json +1 -0
  261. package/skills/review/SKILL.md +2 -0
  262. package/skills/review/evals/scorecard.json +2 -2
  263. package/skills/setup/SKILL.md +18 -0
  264. package/skills/setup/evals/scorecard.json +3 -3
  265. package/skills/shepherd/SKILL.md +19 -2
  266. package/skills/shepherd/evals/scorecard.json +3 -3
  267. package/skills/validate/SKILL.md +3 -0
  268. package/skills/validate/evals/scorecard.json +1 -1
@@ -0,0 +1,225 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { createHash, randomUUID } = require('node:crypto');
6
+
7
+ const SCHEMA = 'forge.plan.v1';
8
+ const ARTIFACT_FILES = Object.freeze(['plan.md', 'tasks.md']);
9
+
10
+ function sha256(content) {
11
+ return createHash('sha256').update(content, 'utf8').digest('hex');
12
+ }
13
+
14
+ function readUtf8(absolutePath) {
15
+ try {
16
+ return new TextDecoder('utf-8', { fatal: true }).decode(fs.readFileSync(absolutePath));
17
+ } catch (error) {
18
+ throw new Error(`Plan artifact must be valid UTF-8: ${absolutePath} (${error.message})`);
19
+ }
20
+ }
21
+
22
+ function normalizeRelativePath(projectRoot, candidate) {
23
+ const absolute = path.resolve(projectRoot, candidate);
24
+ const relative = path.relative(projectRoot, absolute);
25
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
26
+ throw new Error('Plan artifact paths must stay inside the project root');
27
+ }
28
+ return relative.split(path.sep).join('/');
29
+ }
30
+
31
+ function artifactPath(projectRoot, relativePath) {
32
+ return path.join(projectRoot, ...relativePath.split('/'));
33
+ }
34
+
35
+ function isContained(root, candidate) {
36
+ const relative = path.relative(root, candidate);
37
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
38
+ }
39
+
40
+ // Resolve every existing component below the project root. Refuse links/reparse
41
+ // points even when their target happens to remain inside the repo: allowing them
42
+ // would make a later target swap bypass the containment decision.
43
+ function assertSafeArtifactPath(projectRoot, absolutePath) {
44
+ const rootAbsolute = path.resolve(projectRoot);
45
+ const candidateAbsolute = path.resolve(absolutePath);
46
+ if (!isContained(rootAbsolute, candidateAbsolute)) {
47
+ throw new Error('Plan artifact path escapes the project root');
48
+ }
49
+ const rootReal = fs.realpathSync.native(rootAbsolute);
50
+ const segments = path.relative(rootAbsolute, candidateAbsolute).split(path.sep).filter(Boolean);
51
+ let current = rootAbsolute;
52
+ for (const segment of segments) {
53
+ current = path.join(current, segment);
54
+ if (!fs.existsSync(current)) break;
55
+ const stat = fs.lstatSync(current);
56
+ if (stat.isSymbolicLink()) {
57
+ throw new Error('Plan artifact path contains a symbolic link or reparse point');
58
+ }
59
+ const currentReal = fs.realpathSync.native(current);
60
+ if (!isContained(rootReal, currentReal)) {
61
+ throw new Error('Plan artifact path resolves outside the project root');
62
+ }
63
+ }
64
+ }
65
+
66
+ function snapshotDigest(artifacts) {
67
+ const canonical = JSON.stringify(artifacts.map(({ path: artifact, sha256: digest }) => ({ path: artifact, sha256: digest })));
68
+ return sha256(canonical);
69
+ }
70
+
71
+ function createSnapshot({ projectRoot, workFolder }) {
72
+ const folder = normalizeRelativePath(projectRoot, workFolder);
73
+ const artifacts = ARTIFACT_FILES.map((filename) => {
74
+ const relativePath = `${folder}/${filename}`;
75
+ const absolutePath = artifactPath(projectRoot, relativePath);
76
+ assertSafeArtifactPath(projectRoot, absolutePath);
77
+ if (!fs.existsSync(absolutePath)) return null;
78
+ if (!fs.lstatSync(absolutePath).isFile()) {
79
+ throw new Error(`Plan artifact must be a regular file: ${relativePath}`);
80
+ }
81
+ const content = readUtf8(absolutePath);
82
+ return { path: relativePath, content, sha256: sha256(content) };
83
+ });
84
+ if (artifacts.some((entry) => entry === null)) return null;
85
+ return { schema: SCHEMA, digest: snapshotDigest(artifacts), artifacts };
86
+ }
87
+
88
+ function findPlanWorkFolder(projectRoot, featureSlug) {
89
+ if (!projectRoot || !featureSlug) return null;
90
+ const workRoot = path.join(projectRoot, 'docs', 'work');
91
+ if (!fs.existsSync(workRoot)) return null;
92
+ const suffix = `-${featureSlug}`;
93
+ const matches = fs.readdirSync(workRoot, { withFileTypes: true })
94
+ .filter((entry) => entry.isDirectory() && (entry.name === featureSlug || entry.name.endsWith(suffix)))
95
+ .map((entry) => `docs/work/${entry.name}`)
96
+ .filter((folder) => ARTIFACT_FILES.every((filename) => fs.existsSync(artifactPath(projectRoot, `${folder}/${filename}`))))
97
+ .sort();
98
+ return matches.length === 1 ? matches[0] : null;
99
+ }
100
+
101
+ function validateSnapshot(snapshot) {
102
+ if (!snapshot || snapshot.schema !== SCHEMA || !Array.isArray(snapshot.artifacts)) {
103
+ throw new Error('Kernel plan snapshot is invalid');
104
+ }
105
+ if (snapshot.artifacts.length !== ARTIFACT_FILES.length) {
106
+ throw new Error('Kernel plan snapshot is invalid');
107
+ }
108
+ const expectedNames = new Set(ARTIFACT_FILES);
109
+ const observedNames = new Set();
110
+ for (const artifact of snapshot.artifacts) {
111
+ if (!artifact || typeof artifact.path !== 'string' || typeof artifact.content !== 'string'
112
+ || sha256(artifact.content) !== artifact.sha256) {
113
+ throw new Error('Kernel plan snapshot is invalid');
114
+ }
115
+ const filename = path.posix.basename(artifact.path);
116
+ if (!expectedNames.has(filename) || observedNames.has(filename)) {
117
+ throw new Error('Kernel plan snapshot is invalid');
118
+ }
119
+ observedNames.add(filename);
120
+ }
121
+ if (snapshot.digest !== snapshotDigest(snapshot.artifacts)) {
122
+ throw new Error('Kernel plan snapshot is invalid');
123
+ }
124
+ return snapshot;
125
+ }
126
+
127
+ function readPlanSnapshot(driver, issueId) {
128
+ if (!driver || typeof driver.loadPlanSnapshot !== 'function') return null;
129
+ const snapshot = driver.loadPlanSnapshot({ issue_id: issueId }, {});
130
+ return snapshot ? validateSnapshot(snapshot) : null;
131
+ }
132
+
133
+ function inspectArtifacts(projectRoot, snapshot) {
134
+ const missing = [];
135
+ const drifted = [];
136
+ for (const artifact of snapshot.artifacts) {
137
+ const relative = normalizeRelativePath(projectRoot, artifact.path);
138
+ const absolute = artifactPath(projectRoot, relative);
139
+ assertSafeArtifactPath(projectRoot, absolute);
140
+ if (!fs.existsSync(absolute)) {
141
+ missing.push({ ...artifact, absolute });
142
+ continue;
143
+ }
144
+ const content = readUtf8(absolute);
145
+ if (sha256(content) !== artifact.sha256) drifted.push(artifact.path);
146
+ }
147
+ return { missing, drifted };
148
+ }
149
+
150
+ function materializeMissing(projectRoot, missing) {
151
+ const staged = [];
152
+ const created = [];
153
+ try {
154
+ for (const artifact of missing) {
155
+ assertSafeArtifactPath(projectRoot, artifact.absolute);
156
+ fs.mkdirSync(path.dirname(artifact.absolute), { recursive: true });
157
+ assertSafeArtifactPath(projectRoot, artifact.absolute);
158
+ const temporary = `${artifact.absolute}.forge-${randomUUID()}.tmp`;
159
+ fs.writeFileSync(temporary, artifact.content, { encoding: 'utf8', flag: 'wx' });
160
+ staged.push({ temporary, destination: artifact.absolute });
161
+ }
162
+ for (const entry of staged) {
163
+ // link is create-only (fails EEXIST), unlike rename which may overwrite a
164
+ // file another process materialized after our drift check.
165
+ fs.linkSync(entry.temporary, entry.destination);
166
+ fs.rmSync(entry.temporary, { force: true });
167
+ created.push(entry.destination);
168
+ }
169
+ } catch (error) {
170
+ for (const entry of staged) {
171
+ if (fs.existsSync(entry.temporary)) fs.rmSync(entry.temporary, { force: true });
172
+ }
173
+ for (const destination of created) {
174
+ if (fs.existsSync(destination)) fs.rmSync(destination, { force: true });
175
+ }
176
+ throw error;
177
+ }
178
+ }
179
+
180
+ function guidance(message, repairCommand) {
181
+ return `${message} ${repairCommand}`;
182
+ }
183
+
184
+ function reconcilePlanAuthority({
185
+ driver,
186
+ issueId,
187
+ projectRoot,
188
+ workFolder,
189
+ mode = 'dev',
190
+ repairCommand = `forge plan "<feature>" --issue ${issueId}`,
191
+ } = {}) {
192
+ if (!driver || !issueId || !projectRoot) {
193
+ throw new Error('Plan authority requires a Kernel driver, issue id, and project root');
194
+ }
195
+ const existing = readPlanSnapshot(driver, issueId);
196
+ if (!existing) {
197
+ const snapshot = workFolder ? createSnapshot({ projectRoot, workFolder }) : null;
198
+ if (!snapshot) {
199
+ throw new Error(guidance('Plan authority is missing. Create plan.md and tasks.md, then run:', repairCommand));
200
+ }
201
+ if (typeof driver.recordPlanSnapshotTransition !== 'function') {
202
+ throw new Error('Kernel driver cannot persist plan authority');
203
+ }
204
+ driver.recordPlanSnapshotTransition({ issue_id: issueId, snapshot }, {});
205
+ return { status: 'captured', snapshot };
206
+ }
207
+
208
+ const { missing, drifted } = inspectArtifacts(projectRoot, existing);
209
+ if (drifted.length > 0) {
210
+ throw new Error(guidance('Plan artifacts drifted from Kernel authority. Reconcile the files, then run:', repairCommand));
211
+ }
212
+ if (missing.length > 0) {
213
+ materializeMissing(projectRoot, missing);
214
+ return { status: 'materialized', snapshot: existing };
215
+ }
216
+ return { status: mode === 'plan' ? 'reconciled' : 'verified', snapshot: existing };
217
+ }
218
+
219
+ module.exports = {
220
+ SCHEMA,
221
+ createSnapshot,
222
+ findPlanWorkFolder,
223
+ readPlanSnapshot,
224
+ reconcilePlanAuthority,
225
+ };
@@ -0,0 +1 @@
1
+ {"matrix_version":1,"readers":{"0.1.0-beta.6":{"accepted":{"forge.memory.work-packet.v1":[1],"forge.memory.context-packet.v1":[1],"forge.memory.claim-request.v1":[1],"forge.memory.lease-receipt.v1":[1],"forge.memory.capability-manifest.v1":[1],"forge.memory.run-receipt.v1":[1],"forge.memory.feedback-report.v1":[1],"forge.memory.structured-error.v1":[1],"forge.memory.monitor-event.v1":[1],"forge.memory.delivery-receipt.v1":[1],"forge.memory.monitor-receipt.v1":[1]},"validation_surfaces":{"structural":"no_authority_or_freshness_claim","consequential":"requires_independent_live_expected"},"schema_annotations":{"generic_json_schema_enforces_x_forge":false,"conformance_helper":"validateContractStructure","requirement":"x-forge bounds and privacy annotations require the Forge runtime validator"},"run_receipt_non_authoritative_statuses":["NOT_EXECUTED"],"unknown_advisory":"preserve","unknown_consequential":"reject","unknown_schema_version":"reject"}}}
@@ -0,0 +1,134 @@
1
+ {
2
+ "baseline_version": 1,
3
+ "generator_version": "contracts-schema-gen/7",
4
+ "artifacts": [
5
+ {
6
+ "path": "compatibility-matrix.v1.json",
7
+ "sha256": "4ca93d10ae9bff80dd3785bb5ebfc77610cf19e928b9b9ae3f6a1ad9c2fea18e"
8
+ },
9
+ {
10
+ "path": "fixtures/v1/canonical-hash.json",
11
+ "sha256": "469c5b83ebe5e02601cd41b83f35f013f8fb4b118b8e213dc1790bb61301dc3c"
12
+ },
13
+ {
14
+ "path": "fixtures/v1/contract-inputs.v1.json",
15
+ "sha256": "40f28821f77ea153259a43e0ca8a5d6611f3e5e0ec4e4e47114d4cddeadac3fc"
16
+ },
17
+ {
18
+ "path": "fixtures/v1/feedback-secret-reject.json",
19
+ "sha256": "d2a8762a169617a6c98f5654e1d5265732485037e55af107018d139895b47869"
20
+ },
21
+ {
22
+ "path": "fixtures/v1/identity-conflict.json",
23
+ "sha256": "c703733d89f8adb079fb0e0ffe01ad35238d9a5f3ae725af54bca8b518fd6039"
24
+ },
25
+ {
26
+ "path": "fixtures/v1/malformed-envelope-inputs.v1.json",
27
+ "sha256": "17354a1178523332645f27d506eeabaa39eb6ea6bfa448807f7d0b8d4a1226f2"
28
+ },
29
+ {
30
+ "path": "fixtures/v1/malformed-missing-required.json",
31
+ "sha256": "e4031505309e8b172d274ef7c4ef617e71217742ff2b7285f37859db0eea42b9"
32
+ },
33
+ {
34
+ "path": "fixtures/v1/monitor-bounds-reject.json",
35
+ "sha256": "36594e37f3707572ec73c60134f24f5fb3ae17a41d804c409fc03a83e9716c26"
36
+ },
37
+ {
38
+ "path": "fixtures/v1/monitor-receipt-privacy-reject.json",
39
+ "sha256": "e2c53bc43d727d3583f9f2da6538c127a08997fe279f9e74d585c5b95983b4bf"
40
+ },
41
+ {
42
+ "path": "fixtures/v1/not-executed-receipt.json",
43
+ "sha256": "4582002c36cca422ac1ad9a5858558234d5ed162dbe72b36665fe09ab098099f"
44
+ },
45
+ {
46
+ "path": "fixtures/v1/privacy-redaction.json",
47
+ "sha256": "be4bae1d68db334875b3d198525dcd46f3efb46dbeea62de03399a915b716e20"
48
+ },
49
+ {
50
+ "path": "fixtures/v1/retry-identical.json",
51
+ "sha256": "41c944e15725d45a19bd97015c4bf7fb6ca1a4740426225426bc38799046bd8a"
52
+ },
53
+ {
54
+ "path": "fixtures/v1/stale-authority-reject.json",
55
+ "sha256": "700173546cff08486df201316472921d8304ea892c29770b5f199e63c92601b3"
56
+ },
57
+ {
58
+ "path": "fixtures/v1/structured-error-privacy-reject.json",
59
+ "sha256": "008186d22ed5048e4926c7b56c08a71802392886425944d0e1a22b10c7433d58"
60
+ },
61
+ {
62
+ "path": "fixtures/v1/structured-error-stripe-live-reject.json",
63
+ "sha256": "6e7e0d865ccab874fed66cefd15943bbaf51e4be37bfc99cd38f2e8cd6cafce6"
64
+ },
65
+ {
66
+ "path": "fixtures/v1/structured-error-stripe-test-reject.json",
67
+ "sha256": "ab9d748875e4688299a8678a551a2d3f13eb85c6f852ccbaaf102b870b3da82c"
68
+ },
69
+ {
70
+ "path": "fixtures/v1/unknown-advisory-roundtrip.json",
71
+ "sha256": "674e1dd9585d86ed7c8851a3d7e2b0ce81427a3dbc59c149409ee87375f9e879"
72
+ },
73
+ {
74
+ "path": "fixtures/v1/unknown-consequential-reject.json",
75
+ "sha256": "4228ce85d8f92d6eea61802fd34a410eab778314c70c8315cd1d9c9ba8ef2813"
76
+ },
77
+ {
78
+ "path": "fixtures/v1/valid-full.json",
79
+ "sha256": "2ba47dfcd5bc6dc4fae83160b05eeca480b51b065d251a0f531ca2c3effb0397"
80
+ },
81
+ {
82
+ "path": "fixtures/v1/valid-minimal.json",
83
+ "sha256": "e7d4e7d5cb11b4de809140d572c6f40a5ed4fc813f0044983930a6fbaab99444"
84
+ },
85
+ {
86
+ "path": "fixtures/v1/wrong-capability-digest.json",
87
+ "sha256": "8599acc3eebfba3883ec05e496cfc66e08e79877c8193c24db75540b4549062a"
88
+ },
89
+ {
90
+ "path": "schemas/v1/capability-manifest.schema.json",
91
+ "sha256": "8435c1ec9ebfd0f9b9b6d06f490dcfdac4696f002a83692899e1e172f17cd6dd"
92
+ },
93
+ {
94
+ "path": "schemas/v1/claim-request.schema.json",
95
+ "sha256": "eb9a6aa46c51550fa5505caeeff6e7773fce128e940fdb85a851cfd13cbf1375"
96
+ },
97
+ {
98
+ "path": "schemas/v1/context-packet.schema.json",
99
+ "sha256": "36f422011e03fafe07de5fb16a1e9c745015b4257f640e77f1ae1f4ba70971eb"
100
+ },
101
+ {
102
+ "path": "schemas/v1/delivery-receipt.schema.json",
103
+ "sha256": "1e505c9a790d2e5a3ccf1cd227b7a708924f9d92a61c2220964f7cb05a9d8f4c"
104
+ },
105
+ {
106
+ "path": "schemas/v1/feedback-report.schema.json",
107
+ "sha256": "6f9f272b831d30574ecf56601307a361544f022c7690fd8077aeae8ca5913e37"
108
+ },
109
+ {
110
+ "path": "schemas/v1/lease-receipt.schema.json",
111
+ "sha256": "e7b3c1f6857e4ebad930518236011b8346054b1fa7d38607def4a42c1ba9a739"
112
+ },
113
+ {
114
+ "path": "schemas/v1/monitor-event.schema.json",
115
+ "sha256": "df270f5b7e280c10293f2c964727d13baa0488c9e1cc87037ba1307bc76958dc"
116
+ },
117
+ {
118
+ "path": "schemas/v1/monitor-receipt.schema.json",
119
+ "sha256": "555dba3db355498a1813bfcf045fe2c3f10057789539918e3303c11191048b33"
120
+ },
121
+ {
122
+ "path": "schemas/v1/run-receipt.schema.json",
123
+ "sha256": "de55aca54248a208560fffade7bcfdc555e83daf330f37fe482bb8068495ece6"
124
+ },
125
+ {
126
+ "path": "schemas/v1/structured-error.schema.json",
127
+ "sha256": "ea8b6d40528634743efa91a550d27d8191adc8ce95e630356dadce98ba864d64"
128
+ },
129
+ {
130
+ "path": "schemas/v1/work-packet.schema.json",
131
+ "sha256": "82f149e5ceedf004a5c129f264d0cb94e6704a7eadae8f02dbd40a62b75a556c"
132
+ }
133
+ ]
134
+ }
@@ -0,0 +1 @@
1
+ {"fixture_id":"canonical-hash","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"operation":"canonical-hash","expected":{"stable_under_key_reordering":true,"content_hash_excluded":true}}
@@ -0,0 +1,71 @@
1
+ {
2
+ "corpus_version": 1,
3
+ "inputs": [
4
+ {
5
+ "schema_id": "forge.memory.work-packet.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000001", "created_at": "2026-08-09T12:00:00.000Z",
6
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
7
+ "provenance": { "source_kind": "fixture", "actor_class": "system", "actor_id": "fixture" }, "content_hash": "b5b6527735acceed41f41cb4b7ae778ad8e3d3fd517832c4936e8c632881c10c",
8
+ "payload": { "issue_id": "issue-1", "expected_issue_revision": 1, "packet_id": "packet-1", "packet_revision": 1, "repository_id": "github.com/example/forge", "target_head": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "objective": "fixture objective", "authority": { "kind": "kernel", "issue_revision": 1 }, "allowed_mutations": ["files"], "workflow_config_revision": "config-1", "capability_manifest_digest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" }, "extensions": {}
9
+ },
10
+ {
11
+ "schema_id": "forge.memory.context-packet.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000002", "created_at": "2026-08-09T12:00:00.000Z",
12
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
13
+ "provenance": { "source_kind": "fixture", "actor_class": "system", "actor_id": "fixture" }, "content_hash": "278663383d458667b71eb25f6bed8c5828445e070b5af2369a46bc2953b34999",
14
+ "payload": { "work_packet_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "context_selection_revision": 1, "privacy_scope_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "retention_class": "local_sensitive", "disclosure_class": "remote_redacted", "redaction_policy_revision": "redaction-1", "summaries": [{ "kind": "issue", "text": "redacted fixture" }] }, "extensions": {}
15
+ },
16
+ {
17
+ "schema_id": "forge.memory.claim-request.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000003", "created_at": "2026-08-09T12:00:00.000Z",
18
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
19
+ "provenance": { "source_kind": "fixture", "actor_class": "agent", "actor_id": "agent-1" }, "content_hash": "aa1972081945dbfff1b9a800ce139968f6bc8581f19d5f243906181565a665aa",
20
+ "payload": { "issue_id": "issue-1", "expected_issue_revision": 1, "actor_id": "agent-1", "request_id": "request-1", "requested_scope": { "mutations": ["files"] }, "idempotency_key": "claim-1" }, "extensions": {}
21
+ },
22
+ {
23
+ "schema_id": "forge.memory.lease-receipt.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000004", "created_at": "2026-08-09T12:00:00.000Z",
24
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
25
+ "provenance": { "source_kind": "kernel", "actor_class": "authority", "actor_id": "kernel" }, "content_hash": "f3fdc336f2da33d69ed4e1e360e455d9903123add962464062d29f373cabe3d0",
26
+ "payload": { "claim_request_id": "request-1", "lease_id": "lease-1", "lease_epoch": 1, "issue_revision": 1, "actor_id": "agent-1", "scope": { "mutations": ["files"] }, "expires_at": "2026-08-09T13:00:00.000Z", "durable": true, "authority_signature": "fixture-signature" }, "extensions": {}
27
+ },
28
+ {
29
+ "schema_id": "forge.memory.capability-manifest.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000005", "created_at": "2026-08-09T12:00:00.000Z",
30
+ "producer": { "product_id": "forge-flow", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
31
+ "provenance": { "source_kind": "probe", "actor_class": "system", "actor_id": "probe" }, "content_hash": "296ff678e04103e339231fef672db2220f5bd23981fefdc96dcfcd6f338f355e",
32
+ "payload": { "provider_id": "codex", "manifest_revision": 1, "config_revision": "config-1", "executable_identity": { "path_hash": "fixture" }, "provider_version": "1.0.0", "probe_revision": "probe-1", "result_hash": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "capabilities": [{ "capability_id": "flow.execute", "available": true }], "evaluator_status": "approved", "probed_at": "2026-08-09T12:00:00.000Z", "expires_at": "2026-08-09T13:00:00.000Z" }, "extensions": {}
33
+ },
34
+ {
35
+ "schema_id": "forge.memory.run-receipt.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000006", "created_at": "2026-08-09T12:30:00.000Z",
36
+ "producer": { "product_id": "forge-flow", "product_version": "0.1.0-beta.6", "instance_id": "run-1" }, "capabilities_used": [],
37
+ "provenance": { "source_kind": "execution", "actor_class": "agent", "actor_id": "agent-1" }, "content_hash": "4f919795d2c62ad6520b54fc526c215621ef046a59326f673aa6e41a1f6fc751",
38
+ "payload": { "packet_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "run_id": "run-1", "attempt_id": "attempt-1", "exact_head": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "packet_revision": 1, "manifest_digest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "workflow_config_revision": "config-1", "status": "PASS", "executor": { "product": "forge-flow" }, "started_at": "2026-08-09T12:00:00.000Z", "ended_at": "2026-08-09T12:30:00.000Z", "evidence_refs": [], "validation": { "status": "PASS" }, "cleanup": { "status": "PASS" } }, "extensions": {}
39
+ },
40
+ {
41
+ "schema_id": "forge.memory.feedback-report.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000007", "created_at": "2026-08-09T12:00:00.000Z",
42
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
43
+ "provenance": { "source_kind": "feedback", "actor_class": "anonymous-user", "actor_id": "report-1" }, "content_hash": "3adb5b3f1b726b7b67032bf607ab89e54aee3f9eeefa6d4cdbd29340bee555c1",
44
+ "payload": { "report_id": "report-1", "product_version": "0.1.0-beta.6", "contract_version": 1, "stable_error_code": "FORGE_FIXTURE", "affected_capability": "flow.execute", "redacted_reproduction_steps": ["run fixture"], "expected_classification": "PASS", "actual_classification": "FAIL", "occurrence_count": 1, "content_fingerprint": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "consent_event_id": "consent-1", "redaction_policy_revision": "redaction-1" }, "extensions": {}
45
+ },
46
+ {
47
+ "schema_id": "forge.memory.structured-error.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000008", "created_at": "2026-08-09T12:00:00.000Z",
48
+ "producer": { "product_id": "forge-memory", "product_version": "0.1.0-beta.6", "instance_id": "fixture" }, "capabilities_used": [],
49
+ "provenance": { "source_kind": "execution", "actor_class": "system", "actor_id": "forge" }, "content_hash": "50d181d71714a308539f5612fee7dfa854a4abe9591981842303de24db64982d",
50
+ "payload": { "parent_object_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "error_occurrence_id": "error-1", "code": "FORGE_FIXTURE", "terminal_classification": "FAIL", "safe_details": { "summary": "fixture failure" } }, "extensions": {}
51
+ },
52
+ {
53
+ "schema_id": "forge.memory.monitor-event.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000009", "created_at": "2026-08-09T12:00:00.000Z",
54
+ "producer": { "product_id": "forge-flow", "product_version": "0.1.0-beta.6", "instance_id": "monitor-1" }, "capabilities_used": [],
55
+ "provenance": { "source_kind": "monitor", "actor_class": "system", "actor_id": "monitor" }, "content_hash": "01b1e7086a5ba2ddf521ad8e8901db925d9f9e8fe2db75c43ca5eea941d68559",
56
+ "payload": { "monitor_id": "monitor-1", "event_id": "event-1", "sequence": 0, "subject_revision": "head-1", "type": "check.completed", "actionability": "advisory", "observed_at": "2026-08-09T12:00:00.000Z", "bounded_payload": { "status": "PASS" } }, "extensions": {}
57
+ },
58
+ {
59
+ "schema_id": "forge.memory.delivery-receipt.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000010", "created_at": "2026-08-09T12:00:00.000Z",
60
+ "producer": { "product_id": "forge-flow", "product_version": "0.1.0-beta.6", "instance_id": "delivery-1" }, "capabilities_used": [],
61
+ "provenance": { "source_kind": "delivery", "actor_class": "system", "actor_id": "adapter" }, "content_hash": "0bfe86d8a48be6ac271c92c1e767ec53ce0f7bfc2e228a47832522eefa44b40a",
62
+ "payload": { "event_id": "event-1", "target": "agent-1", "transport_tier": "T1", "attempt": 1, "delivered_at": "2026-08-09T12:00:00.000Z", "acknowledged": true, "outcome": "acknowledged" }, "extensions": {}
63
+ },
64
+ {
65
+ "schema_id": "forge.memory.monitor-receipt.v1", "schema_version": 1, "object_id": "00000000-0000-4000-8000-000000000011", "created_at": "2026-08-09T12:00:00.000Z",
66
+ "producer": { "product_id": "forge-flow", "product_version": "0.1.0-beta.6", "instance_id": "monitor-1" }, "capabilities_used": [],
67
+ "provenance": { "source_kind": "monitor", "actor_class": "system", "actor_id": "monitor" }, "content_hash": "01da8754bae5d5a17501a7e20bfc93959e274227add6a31e451424b2c1ac7251",
68
+ "payload": { "monitor_id": "monitor-1", "owner_run_id": "run-1", "terminal_state": "PASS", "terminal_reason": "predicate satisfied", "last_sequence": 0, "evidence_digest": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "cancellation_acknowledged": true, "process_cleanup": { "status": "PASS" }, "lease_cleanup": { "status": "PASS" } }, "extensions": {}
69
+ }
70
+ ]
71
+ }
@@ -0,0 +1 @@
1
+ {"fixture_id":"feedback-secret-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.feedback-report.v1"},"mutation":{"operation":"replace","path":"payload.redacted_reproduction_steps","value":["token=ghp_123456789012345678901234567890"],"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"PRIVACY_SECRET_PATTERN"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"identity-conflict","accepted_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"candidate_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"candidate_mutation":{"operation":"replace","path":"payload.objective","value":"conflicting objective","rehash":true},"operation":"classify-semantic-attempt","expected":{"status":"identity-conflict"}}
@@ -0,0 +1,16 @@
1
+ {
2
+ "corpus_version": 1,
3
+ "base_input": { "ref": "contract-inputs.v1.json", "schema_id": "forge.memory.work-packet.v1" },
4
+ "cases": [
5
+ { "missing_field": "schema_id", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
6
+ { "missing_field": "schema_version", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
7
+ { "missing_field": "object_id", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
8
+ { "missing_field": "created_at", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
9
+ { "missing_field": "producer", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
10
+ { "missing_field": "capabilities_used", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
11
+ { "missing_field": "provenance", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
12
+ { "missing_field": "content_hash", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
13
+ { "missing_field": "payload", "operation": "remove", "expected_code": "MISSING_REQUIRED" },
14
+ { "missing_field": "extensions", "operation": "remove", "expected_code": "MISSING_REQUIRED" }
15
+ ]
16
+ }
@@ -0,0 +1 @@
1
+ {"fixture_id":"malformed-missing-required","input_ref":{"file":"malformed-envelope-inputs.v1.json"},"operation":"materialize-cases","expected":{"case_count":10,"code":"MISSING_REQUIRED"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"monitor-bounds-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.monitor-event.v1"},"mutation":{"operation":"replace","path":"payload.bounded_payload","value":{"shape":"nine-level nested object; materializer repeats key child nine times"},"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"BOUNDED_VALUE_TOO_DEEP"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"monitor-receipt-privacy-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.monitor-receipt.v1"},"mutation":{"operation":"replace","path":"payload.process_cleanup","value":{"detail":"password=supersecretvalue"},"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"PRIVACY_SECRET_PATTERN"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"not-executed-receipt","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.run-receipt.v1"},"mutation":{"operation":"replace","path":"payload.status","value":"NOT_EXECUTED","rehash":true},"operation":"validate-structure-then-authority","expected":{"structural_ok":true,"authority_ok":false,"authority_code":"NOT_EXECUTED_NO_TRANSITION"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"privacy-redaction","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.context-packet.v1"},"live_expected":{"workPacketHash":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","privacyScopeHash":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd","redactionPolicyRevision":"redaction-1","allowedDisclosureClasses":["remote_redacted"]},"operation":"validate-expected","expected":{"code":"STALE_PRIVACY_SCOPE","raw_content_embedded":false}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"retry-identical","accepted_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"candidate_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"operation":"classify-semantic-attempt","expected":{"status":"retry-identical"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"stale-authority-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"live_expected":{"issueRevision":2,"workflowConfigRevision":"config-1","capabilityManifestDigest":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","exactHead":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},"operation":"validate-expected","expected":{"code":"STALE_ISSUE_REVISION"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"structured-error-privacy-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.structured-error.v1"},"mutation":{"operation":"replace","path":"payload.safe_details","value":{"detail":"token=ghp_123456789012345678901234567890"},"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"PRIVACY_SECRET_PATTERN"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"structured-error-stripe-live-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.structured-error.v1"},"mutation":{"operation":"replace","path":"payload.safe_details","value":{"detail":"sk_live_1234567890ABCDEF"},"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"PRIVACY_SECRET_PATTERN"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"structured-error-stripe-test-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.structured-error.v1"},"mutation":{"operation":"replace","path":"payload.safe_details","value":{"detail":"sk_test_ABCDEF1234567890"},"rehash":true},"operation":"validate-structure","expected":{"ok":false,"code":"PRIVACY_SECRET_PATTERN"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"unknown-advisory-roundtrip","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"mutation":{"operation":"add","path":"extensions.vendor.example/advisory","value":{"impact":"advisory","schema_version":1,"value":{"note":"preserve"}},"rehash":true},"operation":"roundtrip-extension","expected":{"preserved":true}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"unknown-consequential-reject","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"mutation":{"operation":"add","path":"extensions.vendor.example/authority","value":{"impact":"consequential","schema_version":1,"value":{"permit":true}},"rehash":true},"operation":"validate-extension","expected":{"code":"UNKNOWN_CONSEQUENTIAL_EXTENSION"}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"valid-full","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"mutations":[{"operation":"add","path":"payload.acceptance_criteria","value":["all gates pass"]},{"operation":"add","path":"payload.prohibited_actions","value":["merge"]}],"operation":"rehash-and-validate-structure","authority_claim":false,"expected":{"ok":true}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"valid-minimal","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"operation":"validate-structure","authority_claim":false,"expected":{"ok":true}}
@@ -0,0 +1 @@
1
+ {"fixture_id":"wrong-capability-digest","input_ref":{"file":"contract-inputs.v1.json","schema_id":"forge.memory.work-packet.v1"},"live_expected":{"issueRevision":1,"workflowConfigRevision":"config-1","capabilityManifestDigest":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd","exactHead":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},"operation":"validate-expected","expected":{"code":"WRONG_CAPABILITY_DIGEST"}}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ const { canonicalize, computeContentHash } = require("./src/canonical.js");
4
+ const { verifyContractBaseline } = require("./src/baseline.js");
5
+ const { CONTRACTS } = require("./src/definitions.js");
6
+ const { classifySemanticAttempt, semanticIdentity } = require("./src/identity.js");
7
+ const { generateJsonSchema, supportedSchemaVersions } = require("./src/schema.js");
8
+ const {
9
+ ContractValidationError,
10
+ ENVELOPE_FIELDS,
11
+ parseContract,
12
+ validateContract,
13
+ validateContractStructure,
14
+ validateEnvelope,
15
+ } = require("./src/validate.js");
16
+
17
+ module.exports = {
18
+ ENVELOPE_FIELDS,
19
+ CONTRACTS,
20
+ ContractValidationError,
21
+ canonicalize,
22
+ classifySemanticAttempt,
23
+ computeContentHash,
24
+ generateJsonSchema,
25
+ parseContract,
26
+ semanticIdentity,
27
+ supportedSchemaVersions,
28
+ validateContract,
29
+ validateContractStructure,
30
+ validateEnvelope,
31
+ verifyContractBaseline,
32
+ };
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@forge/contracts",
3
+ "version": "0.1.0-beta.6",
4
+ "description": "Behavior-neutral packet and receipt contracts for Forge products",
5
+ "main": "index.js",
6
+ "type": "commonjs",
7
+ "files": [
8
+ "index.js",
9
+ "src/",
10
+ "schemas/",
11
+ "fixtures/",
12
+ "contract-baseline.v1.json",
13
+ "compatibility-matrix.v1.json"
14
+ ],
15
+ "scripts": {
16
+ "test": "bun test test",
17
+ "lint": "eslint . --max-warnings 0"
18
+ },
19
+ "license": "MIT",
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/harshanandak/forge.git",
26
+ "directory": "packages/contracts"
27
+ },
28
+ "homepage": "https://github.com/harshanandak/forge#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/harshanandak/forge/issues"
31
+ },
32
+ "engines": {
33
+ "node": ">=22.16.0"
34
+ }
35
+ }
@@ -0,0 +1 @@
1
+ {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"forge.memory.capability-manifest.v1","title":"CapabilityManifest","type":"object","required":["schema_id","schema_version","object_id","created_at","producer","capabilities_used","provenance","content_hash","payload","extensions"],"properties":{"schema_id":{"const":"forge.memory.capability-manifest.v1"},"schema_version":{"const":1},"object_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"producer":{"type":"object","required":["product_id","product_version","instance_id"],"properties":{"product_id":{"type":"string","minLength":1},"product_version":{"type":"string","minLength":1},"instance_id":{"type":"string","minLength":1}},"additionalProperties":false},"capabilities_used":{"type":"array","items":{"type":"object","required":["capability_id","manifest_digest"],"properties":{"capability_id":{"type":"string","minLength":1},"manifest_digest":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"additionalProperties":false}},"provenance":{"type":"object","required":["source_kind","actor_class","actor_id"],"properties":{"source_kind":{"type":"string","minLength":1},"actor_class":{"type":"string","minLength":1},"actor_id":{"type":"string","minLength":1}},"additionalProperties":false},"content_hash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"payload":{"type":"object","required":["provider_id","manifest_revision","config_revision","executable_identity","provider_version","probe_revision","result_hash","capabilities","evaluator_status","probed_at","expires_at"],"properties":{"provider_id":{"type":"string","minLength":1},"manifest_revision":{"type":"integer","minimum":1},"config_revision":{"type":"string","minLength":1},"executable_identity":{"type":"object"},"provider_version":{"type":"string","minLength":1},"probe_revision":{"type":"string","minLength":1},"result_hash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"capabilities":{"type":"array","items":{"type":"object","required":["capability_id","available"],"properties":{"capability_id":{"type":"string","minLength":1},"available":{"type":"boolean"}}}},"evaluator_status":{"type":"string","enum":["approved","unavailable","quarantined"]},"probed_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"extensions":{"type":"object","propertyNames":{"pattern":"^[A-Za-z0-9][A-Za-z0-9_-]*(?:[./][A-Za-z0-9][A-Za-z0-9_-]*)+$","maxLength":255},"additionalProperties":{"type":"object","required":["impact","schema_version","value"],"properties":{"impact":{"const":"advisory"},"schema_version":{"type":"integer","minimum":1},"value":{}},"additionalProperties":false}}},"additionalProperties":false}
@@ -0,0 +1 @@
1
+ {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"forge.memory.claim-request.v1","title":"ClaimRequest","type":"object","required":["schema_id","schema_version","object_id","created_at","producer","capabilities_used","provenance","content_hash","payload","extensions"],"properties":{"schema_id":{"const":"forge.memory.claim-request.v1"},"schema_version":{"const":1},"object_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"producer":{"type":"object","required":["product_id","product_version","instance_id"],"properties":{"product_id":{"type":"string","minLength":1},"product_version":{"type":"string","minLength":1},"instance_id":{"type":"string","minLength":1}},"additionalProperties":false},"capabilities_used":{"type":"array","items":{"type":"object","required":["capability_id","manifest_digest"],"properties":{"capability_id":{"type":"string","minLength":1},"manifest_digest":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"additionalProperties":false}},"provenance":{"type":"object","required":["source_kind","actor_class","actor_id"],"properties":{"source_kind":{"type":"string","minLength":1},"actor_class":{"type":"string","minLength":1},"actor_id":{"type":"string","minLength":1}},"additionalProperties":false},"content_hash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"payload":{"type":"object","required":["issue_id","expected_issue_revision","actor_id","request_id","requested_scope","idempotency_key"],"properties":{"issue_id":{"type":"string","minLength":1},"expected_issue_revision":{"type":"integer","minimum":0},"actor_id":{"type":"string","minLength":1},"request_id":{"type":"string","minLength":1},"requested_scope":{"type":"object"},"idempotency_key":{"type":"string","minLength":1}},"additionalProperties":false},"extensions":{"type":"object","propertyNames":{"pattern":"^[A-Za-z0-9][A-Za-z0-9_-]*(?:[./][A-Za-z0-9][A-Za-z0-9_-]*)+$","maxLength":255},"additionalProperties":{"type":"object","required":["impact","schema_version","value"],"properties":{"impact":{"const":"advisory"},"schema_version":{"type":"integer","minimum":1},"value":{}},"additionalProperties":false}}},"additionalProperties":false}