@clossys/launcher 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +1324 -60
  2. package/contracts/conversation-contract.md +2 -2
  3. package/contracts/product-ci-workflow.yml +74 -0
  4. package/contracts/repository-inventory.json +53 -0
  5. package/dist/admission-fixture.d.ts +168 -0
  6. package/dist/admission-fixture.d.ts.map +1 -0
  7. package/dist/admission-fixture.js +453 -0
  8. package/dist/admission-fixture.js.map +1 -0
  9. package/dist/admission.d.ts +124 -0
  10. package/dist/admission.d.ts.map +1 -0
  11. package/dist/admission.js +799 -0
  12. package/dist/admission.js.map +1 -0
  13. package/dist/agents-guide.d.ts +9 -0
  14. package/dist/agents-guide.d.ts.map +1 -0
  15. package/dist/agents-guide.js +26 -0
  16. package/dist/agents-guide.js.map +1 -0
  17. package/dist/apply-command-options.check.d.ts +12 -0
  18. package/dist/apply-command-options.check.d.ts.map +1 -0
  19. package/dist/apply-command-options.check.js +20 -0
  20. package/dist/apply-command-options.check.js.map +1 -0
  21. package/dist/apply-plan-cli.d.ts +39 -1
  22. package/dist/apply-plan-cli.d.ts.map +1 -1
  23. package/dist/apply-plan-cli.js +432 -15
  24. package/dist/apply-plan-cli.js.map +1 -1
  25. package/dist/apply-plan.d.ts +46 -59
  26. package/dist/apply-plan.d.ts.map +1 -1
  27. package/dist/apply-plan.js +112 -97
  28. package/dist/apply-plan.js.map +1 -1
  29. package/dist/apply-step-fixture.d.ts +87 -0
  30. package/dist/apply-step-fixture.d.ts.map +1 -0
  31. package/dist/apply-step-fixture.js +199 -0
  32. package/dist/apply-step-fixture.js.map +1 -0
  33. package/dist/apply-store.d.ts +93 -0
  34. package/dist/apply-store.d.ts.map +1 -0
  35. package/dist/apply-store.js +625 -0
  36. package/dist/apply-store.js.map +1 -0
  37. package/dist/approval-sheet.d.ts +21 -0
  38. package/dist/approval-sheet.d.ts.map +1 -0
  39. package/dist/approval-sheet.js +157 -0
  40. package/dist/approval-sheet.js.map +1 -0
  41. package/dist/body-command.d.ts +42 -0
  42. package/dist/body-command.d.ts.map +1 -0
  43. package/dist/body-command.js +143 -0
  44. package/dist/body-command.js.map +1 -0
  45. package/dist/change-set-contract.d.ts +381 -0
  46. package/dist/change-set-contract.d.ts.map +1 -0
  47. package/dist/change-set-contract.js +738 -0
  48. package/dist/change-set-contract.js.map +1 -0
  49. package/dist/change-set-digest.d.ts +28 -0
  50. package/dist/change-set-digest.d.ts.map +1 -0
  51. package/dist/change-set-digest.js +65 -0
  52. package/dist/change-set-digest.js.map +1 -0
  53. package/dist/check-cli.d.ts.map +1 -1
  54. package/dist/check-cli.js +14 -3
  55. package/dist/check-cli.js.map +1 -1
  56. package/dist/cli.d.ts +17 -6
  57. package/dist/cli.d.ts.map +1 -1
  58. package/dist/cli.js +84 -23
  59. package/dist/cli.js.map +1 -1
  60. package/dist/core.d.ts +79 -22
  61. package/dist/core.d.ts.map +1 -1
  62. package/dist/core.js +843 -268
  63. package/dist/core.js.map +1 -1
  64. package/dist/dry-materialize.d.ts +63 -0
  65. package/dist/dry-materialize.d.ts.map +1 -0
  66. package/dist/dry-materialize.js +330 -0
  67. package/dist/dry-materialize.js.map +1 -0
  68. package/dist/generated/contract-schema.generated.d.ts +97 -0
  69. package/dist/generated/contract-schema.generated.d.ts.map +1 -0
  70. package/dist/generated/contract-schema.generated.js +496 -0
  71. package/dist/generated/contract-schema.generated.js.map +1 -0
  72. package/dist/generated/package-scope.generated.d.ts +6 -0
  73. package/dist/generated/package-scope.generated.d.ts.map +1 -0
  74. package/dist/generated/package-scope.generated.js +10 -0
  75. package/dist/generated/package-scope.generated.js.map +1 -0
  76. package/dist/generated/plan-contracts.generated.d.ts +3 -0
  77. package/dist/generated/plan-contracts.generated.d.ts.map +1 -0
  78. package/dist/generated/plan-contracts.generated.js +2840 -0
  79. package/dist/generated/plan-contracts.generated.js.map +1 -0
  80. package/dist/host.d.ts.map +1 -1
  81. package/dist/host.js +11 -0
  82. package/dist/host.js.map +1 -1
  83. package/dist/identity.d.ts +15 -0
  84. package/dist/identity.d.ts.map +1 -0
  85. package/dist/identity.js +48 -0
  86. package/dist/identity.js.map +1 -0
  87. package/dist/index.d.ts +34 -5
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +19 -2
  90. package/dist/index.js.map +1 -1
  91. package/dist/inventory-adoption.d.ts +24 -5
  92. package/dist/inventory-adoption.d.ts.map +1 -1
  93. package/dist/inventory-adoption.js +70 -25
  94. package/dist/inventory-adoption.js.map +1 -1
  95. package/dist/inventory-choice.d.ts +40 -0
  96. package/dist/inventory-choice.d.ts.map +1 -0
  97. package/dist/inventory-choice.js +156 -0
  98. package/dist/inventory-choice.js.map +1 -0
  99. package/dist/inventory-contract.d.ts +89 -0
  100. package/dist/inventory-contract.d.ts.map +1 -0
  101. package/dist/inventory-contract.js +121 -0
  102. package/dist/inventory-contract.js.map +1 -0
  103. package/dist/key-editor.d.ts +30 -0
  104. package/dist/key-editor.d.ts.map +1 -0
  105. package/dist/key-editor.js +445 -0
  106. package/dist/key-editor.js.map +1 -0
  107. package/dist/ledger-contract.d.ts +187 -0
  108. package/dist/ledger-contract.d.ts.map +1 -0
  109. package/dist/ledger-contract.js +532 -0
  110. package/dist/ledger-contract.js.map +1 -0
  111. package/dist/ledger-trust.d.ts +90 -0
  112. package/dist/ledger-trust.d.ts.map +1 -0
  113. package/dist/ledger-trust.js +198 -0
  114. package/dist/ledger-trust.js.map +1 -0
  115. package/dist/lockfile-invariants.d.ts +48 -0
  116. package/dist/lockfile-invariants.d.ts.map +1 -0
  117. package/dist/lockfile-invariants.js +375 -0
  118. package/dist/lockfile-invariants.js.map +1 -0
  119. package/dist/lockfile-readers.d.ts +72 -0
  120. package/dist/lockfile-readers.d.ts.map +1 -0
  121. package/dist/lockfile-readers.js +713 -0
  122. package/dist/lockfile-readers.js.map +1 -0
  123. package/dist/lockfile-regen.d.ts +106 -0
  124. package/dist/lockfile-regen.d.ts.map +1 -0
  125. package/dist/lockfile-regen.js +760 -0
  126. package/dist/lockfile-regen.js.map +1 -0
  127. package/dist/lockfile-tool-env.d.ts +29 -0
  128. package/dist/lockfile-tool-env.d.ts.map +1 -0
  129. package/dist/lockfile-tool-env.js +111 -0
  130. package/dist/lockfile-tool-env.js.map +1 -0
  131. package/dist/materialize.d.ts +113 -0
  132. package/dist/materialize.d.ts.map +1 -0
  133. package/dist/materialize.js +840 -0
  134. package/dist/materialize.js.map +1 -0
  135. package/dist/observe-repository.d.ts +90 -0
  136. package/dist/observe-repository.d.ts.map +1 -0
  137. package/dist/observe-repository.js +1367 -0
  138. package/dist/observe-repository.js.map +1 -0
  139. package/dist/plan-bundle-setup-fixture.d.ts +68 -0
  140. package/dist/plan-bundle-setup-fixture.d.ts.map +1 -0
  141. package/dist/plan-bundle-setup-fixture.js +167 -0
  142. package/dist/plan-bundle-setup-fixture.js.map +1 -0
  143. package/dist/plan-bundle.d.ts +250 -0
  144. package/dist/plan-bundle.d.ts.map +1 -0
  145. package/dist/plan-bundle.js +827 -0
  146. package/dist/plan-bundle.js.map +1 -0
  147. package/dist/plan-command.d.ts +29 -0
  148. package/dist/plan-command.d.ts.map +1 -0
  149. package/dist/plan-command.js +493 -0
  150. package/dist/plan-command.js.map +1 -0
  151. package/dist/plan-contract.d.ts +153 -0
  152. package/dist/plan-contract.d.ts.map +1 -0
  153. package/dist/plan-contract.js +61 -0
  154. package/dist/plan-contract.js.map +1 -0
  155. package/dist/plan-digest.d.ts +25 -0
  156. package/dist/plan-digest.d.ts.map +1 -0
  157. package/dist/plan-digest.js +106 -0
  158. package/dist/plan-digest.js.map +1 -0
  159. package/dist/plan-rules.d.ts +23 -0
  160. package/dist/plan-rules.d.ts.map +1 -0
  161. package/dist/plan-rules.js +177 -0
  162. package/dist/plan-rules.js.map +1 -0
  163. package/dist/planned-bundle.d.ts +20 -0
  164. package/dist/planned-bundle.d.ts.map +1 -0
  165. package/dist/planned-bundle.js +191 -0
  166. package/dist/planned-bundle.js.map +1 -0
  167. package/dist/product-repository.d.ts +4 -0
  168. package/dist/product-repository.d.ts.map +1 -1
  169. package/dist/product-repository.js +9 -1
  170. package/dist/product-repository.js.map +1 -1
  171. package/dist/provenance-gate.d.ts +48 -0
  172. package/dist/provenance-gate.d.ts.map +1 -0
  173. package/dist/provenance-gate.js +324 -0
  174. package/dist/provenance-gate.js.map +1 -0
  175. package/dist/pull-request-body.d.ts +45 -0
  176. package/dist/pull-request-body.d.ts.map +1 -0
  177. package/dist/pull-request-body.js +232 -0
  178. package/dist/pull-request-body.js.map +1 -0
  179. package/dist/registry-snapshot.d.ts +141 -0
  180. package/dist/registry-snapshot.d.ts.map +1 -0
  181. package/dist/registry-snapshot.js +483 -0
  182. package/dist/registry-snapshot.js.map +1 -0
  183. package/dist/release-age-edit.d.ts +52 -0
  184. package/dist/release-age-edit.d.ts.map +1 -0
  185. package/dist/release-age-edit.js +413 -0
  186. package/dist/release-age-edit.js.map +1 -0
  187. package/dist/root-entries.d.ts +36 -0
  188. package/dist/root-entries.d.ts.map +1 -0
  189. package/dist/root-entries.js +80 -0
  190. package/dist/root-entries.js.map +1 -0
  191. package/dist/setup-template-scripts.d.ts +34 -0
  192. package/dist/setup-template-scripts.d.ts.map +1 -0
  193. package/dist/setup-template-scripts.js +557 -0
  194. package/dist/setup-template-scripts.js.map +1 -0
  195. package/dist/setup-templates.d.ts +54 -0
  196. package/dist/setup-templates.d.ts.map +1 -0
  197. package/dist/setup-templates.js +427 -0
  198. package/dist/setup-templates.js.map +1 -0
  199. package/dist/skills.d.ts +34 -1
  200. package/dist/skills.d.ts.map +1 -1
  201. package/dist/skills.js +129 -17
  202. package/dist/skills.js.map +1 -1
  203. package/dist/status.d.ts +63 -0
  204. package/dist/status.d.ts.map +1 -0
  205. package/dist/status.js +539 -0
  206. package/dist/status.js.map +1 -0
  207. package/dist/types.d.ts +151 -13
  208. package/dist/types.d.ts.map +1 -1
  209. package/package.json +4 -4
  210. package/skeleton/README.md +14 -9
  211. package/skeleton/package.json +2 -1
  212. package/skill/SKILL.md +23 -7
  213. package/skill-catalogue/advisor/SKILL.md +59 -6
  214. package/skill-catalogue/architect/SKILL.md +2 -2
  215. package/skill-catalogue/bouncer/SKILL.md +2 -2
  216. package/skill-catalogue/builder/SKILL.md +2 -2
  217. package/skill-catalogue/butler/SKILL.md +2 -2
  218. package/skill-catalogue/controller/SKILL.md +2 -2
  219. package/skill-catalogue/customer/SKILL.md +2 -2
  220. package/skill-catalogue/designer/SKILL.md +4 -2
  221. package/skill-catalogue/giver/SKILL.md +2 -2
  222. package/skill-catalogue/influencer/SKILL.md +2 -2
  223. package/skill-catalogue/inspector/SKILL.md +2 -2
  224. package/skill-catalogue/integrator/SKILL.md +2 -2
  225. package/skill-catalogue/keeper/SKILL.md +2 -2
  226. package/skill-catalogue/launcher/SKILL.md +23 -7
  227. package/skill-catalogue/locksmith/SKILL.md +2 -2
  228. package/skill-catalogue/messenger/SKILL.md +2 -2
  229. package/skill-catalogue/observer/SKILL.md +2 -2
  230. package/skill-catalogue/publisher/SKILL.md +2 -2
  231. package/skill-catalogue/starter/SKILL.md +3 -2
  232. package/skill-catalogue/strategist/SKILL.md +12 -4
  233. package/skill-catalogue/writer/SKILL.md +2 -2
  234. package/src/admission-fixture.ts +572 -0
  235. package/src/admission.ts +816 -0
  236. package/src/agents-guide.ts +29 -0
  237. package/src/apply-command-options.check.ts +27 -0
  238. package/src/apply-plan-cli.ts +454 -14
  239. package/src/apply-plan.ts +112 -124
  240. package/src/apply-step-fixture.ts +236 -0
  241. package/src/apply-store.ts +584 -0
  242. package/src/approval-sheet.ts +164 -0
  243. package/src/body-command.ts +162 -0
  244. package/src/change-set-contract.ts +937 -0
  245. package/src/change-set-digest.ts +70 -0
  246. package/src/check-cli.ts +14 -3
  247. package/src/cli.ts +90 -22
  248. package/src/core.ts +973 -275
  249. package/src/dry-materialize.ts +353 -0
  250. package/src/generated/contract-schema.generated.ts +520 -0
  251. package/src/generated/package-scope.generated.ts +10 -0
  252. package/src/generated/plan-contracts.generated.ts +2840 -0
  253. package/src/host.ts +10 -0
  254. package/src/identity.ts +51 -0
  255. package/src/index.ts +72 -3
  256. package/src/inventory-adoption.ts +107 -29
  257. package/src/inventory-choice.ts +172 -0
  258. package/src/inventory-contract.ts +166 -0
  259. package/src/key-editor.ts +446 -0
  260. package/src/ledger-contract.ts +637 -0
  261. package/src/ledger-trust.ts +267 -0
  262. package/src/lockfile-invariants.ts +421 -0
  263. package/src/lockfile-readers.ts +749 -0
  264. package/src/lockfile-regen.ts +851 -0
  265. package/src/lockfile-tool-env.ts +131 -0
  266. package/src/materialize.ts +886 -0
  267. package/src/observe-repository.ts +1365 -0
  268. package/src/plan-bundle-setup-fixture.ts +200 -0
  269. package/src/plan-bundle.ts +964 -0
  270. package/src/plan-command.ts +509 -0
  271. package/src/plan-contract.ts +179 -0
  272. package/src/plan-digest.ts +102 -0
  273. package/src/plan-rules.ts +188 -0
  274. package/src/planned-bundle.ts +211 -0
  275. package/src/product-repository.ts +10 -1
  276. package/src/provenance-gate.ts +352 -0
  277. package/src/pull-request-body.ts +261 -0
  278. package/src/registry-snapshot.ts +534 -0
  279. package/src/release-age-edit.ts +430 -0
  280. package/src/root-entries.ts +81 -0
  281. package/src/setup-template-scripts.ts +571 -0
  282. package/src/setup-templates.ts +471 -0
  283. package/src/skills.ts +161 -18
  284. package/src/status.ts +557 -0
  285. package/src/types.ts +148 -13
@@ -0,0 +1,330 @@
1
+ // Dry materialization for `launcher-apply-plan plan` (issue #1178, RFC apply-approved-plan section 7, V6 and V9).
2
+ //
3
+ // The planner is pure and cannot regenerate a lockfile, so it reports every set that changes one as V6 indeterminate
4
+ // (`lockfile-not-run`). This module runs the part it cannot: it writes the base commit's tree and the set's changes into a
5
+ // temporary directory, regenerates the lockfile there with the same runner materialize uses, and, only when that passes,
6
+ // runs the hub's provenance check (V9) on that same tree. It reads the clone through git plumbing at the base commit
7
+ // (`ls-tree` and `cat-file`, see readCommittedFiles) and never writes it: no checkout, worktree, index or ref.
8
+ //
9
+ // Every ambiguity refuses. A rule is one of a fixed set of tokens and never carries tool output, a path, an id or a file
10
+ // name. The temporary tree is a directory of its own under the real operating-system temporary directory, removed before
11
+ // this returns, whatever happened. Nothing here changes a set, its digest or the bundle's digest: only the checks move.
12
+ import { createHash } from "node:crypto";
13
+ import { chmodSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
14
+ import { tmpdir } from "node:os";
15
+ import { dirname, join, sep } from "node:path";
16
+ import { canonicalOrder, contentDigest, lockfilePath, validateApplyBundle, validateRepositoryChangeSet, worstVerdict } from "./change-set-contract.js";
17
+ import { JsonEditUnstableError, editJsonPointer } from "./key-editor.js";
18
+ import { regenerateLockfile } from "./lockfile-regen.js";
19
+ import { derivedLockfile, packagesForLockfile, provesReleaseAgeEditWith, refuseReservedSymlinks, removePath, resolveFileText, textsFromChangeSet, writeRegularFile, writeSymlink } from "./materialize.js";
20
+ import { fold, readCommittedFiles } from "./observe-repository.js";
21
+ import { checkSetProvenance } from "./provenance-gate.js";
22
+ /** The rule the planner gives a set that changes a lockfile, and this module replaces. */
23
+ export const LOCKFILE_NOT_RUN = "lockfile-not-run";
24
+ /** The V9 rule of a set whose lockfile step did not pass: the provenance check is not run on a tree that is not the result. */
25
+ export const LOCKFILE_NOT_REGENERATED = "lockfile-not-regenerated";
26
+ /** The V6 rule of a repository whose dry tree could not be built or run, for any reason that is not one of the named ones. */
27
+ export const DRY_TREE_FAILED = "dry-tree-failed";
28
+ /** The V6 rule of a committed tree that is not safe to write: a path segment or a link that could reach outside the tree. */
29
+ export const DRY_TREE_UNSAFE = "tree-unsafe";
30
+ const TOKEN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
31
+ const TEMP_PREFIX = "launcher-dry-materialize-";
32
+ const v6 = (verdict, rule) => ({ check: "V6", verdict, rule: TOKEN.test(rule) ? rule : DRY_TREE_FAILED });
33
+ const V6_SATISFIED = { check: "V6", verdict: "satisfied" };
34
+ const isWhole = (file) => !("derived" in file);
35
+ /** The V6 check a materialize step's result is: its exit code 1 is violated, anything else indeterminate; its reason is a fixed id. */
36
+ const fromStep = (step) => v6(step.exitCode === 1 ? "violated" : "indeterminate", step.reason ?? DRY_TREE_FAILED);
37
+ // ---------------------------------------------------------------------------
38
+ // the committed tree, before anything is written
39
+ /** A path segment as a filesystem that folds case, normalization and format characters would read it. */
40
+ const folded = (segment) => segment.normalize("NFKC").replace(/\p{Cf}/gu, "").toLowerCase();
41
+ const CONTROL = /\p{Cc}/u;
42
+ function segmentsSafe(path) {
43
+ if (path.length === 0 || CONTROL.test(path))
44
+ return false;
45
+ return path.split("/").every((segment) => {
46
+ const key = folded(segment);
47
+ return segment.length > 0 && key !== "" && key !== "." && key !== ".." && key !== ".git";
48
+ });
49
+ }
50
+ /**
51
+ * Whether a link's target stays inside the tree however the links along it resolve: relative, no empty segment, no `..` after a
52
+ * name, no more leading `..` than the directories above the link, and no `.git` segment.
53
+ */
54
+ function linkStaysInside(path, target) {
55
+ if (target.length === 0 || CONTROL.test(target) || target.startsWith("/") || target.includes("\\"))
56
+ return false;
57
+ const parts = target.split("/");
58
+ let up = 0;
59
+ while (up < parts.length && parts[up] === "..")
60
+ up += 1;
61
+ if (up > path.split("/").length - 1)
62
+ return false;
63
+ return parts.slice(up).every((segment) => {
64
+ const key = folded(segment);
65
+ return segment.length > 0 && key !== ".." && key !== ".git";
66
+ });
67
+ }
68
+ /**
69
+ * Whether every path, and every link, of the committed tree is one the dry tree may hold. A filesystem that folds case or
70
+ * normalization reads two spellings as one name, so a link and a directory kept apart only by spelling would be the same entry
71
+ * there and a later write would go through the link. Every entry (link or file) is therefore folded as observeRepository folds
72
+ * it, and the tree is refused when that fold repeats, or is a proper prefix of another entry's fold.
73
+ */
74
+ export function treeIsSafe(files) {
75
+ const seen = [new Set(), new Set()];
76
+ const entries = [];
77
+ for (const file of files) {
78
+ if (!segmentsSafe(file.path))
79
+ return false;
80
+ // A tree that keeps two paths apart only by case or normalization would be one path on a filesystem that folds them.
81
+ const keys = [file.path.normalize("NFC").toLowerCase(), fold(file.path)];
82
+ for (const [index, key] of keys.entries()) {
83
+ if (seen[index].has(key))
84
+ return false;
85
+ seen[index].add(key);
86
+ }
87
+ entries.push(fold(file.path));
88
+ if (file.mode === "120000" && !linkStaysInside(file.path, file.bytes.toString("utf8")))
89
+ return false;
90
+ }
91
+ const named = new Set(entries);
92
+ for (const entry of entries) {
93
+ const segments = entry.split("/");
94
+ for (let length = 1; length < segments.length; length += 1)
95
+ if (named.has(segments.slice(0, length).join("/")))
96
+ return false;
97
+ }
98
+ return true;
99
+ }
100
+ /** Whether `directory`'s real path is `root` or inside it. */
101
+ function insideRoot(root, directory) {
102
+ const real = realpathSync(directory);
103
+ return real === root || real.startsWith(`${root}${sep}`);
104
+ }
105
+ /**
106
+ * Makes each directory of `relative` (a path inside `root`) one segment at a time, and throws when a segment already exists as
107
+ * anything but a real directory: nothing is created through a link, and nothing is created before the segment is looked at.
108
+ */
109
+ function ensureDirectory(root, relative) {
110
+ let current = root;
111
+ if (relative === "")
112
+ return current;
113
+ for (const segment of relative.split("/")) {
114
+ current = join(current, segment);
115
+ let stat = null;
116
+ try {
117
+ stat = lstatSync(current);
118
+ }
119
+ catch (cause) {
120
+ if (cause.code !== "ENOENT")
121
+ throw cause;
122
+ }
123
+ if (stat === null)
124
+ mkdirSync(current);
125
+ else if (!stat.isDirectory())
126
+ throw new Error("a directory of the base tree is not a directory");
127
+ }
128
+ return current;
129
+ }
130
+ /**
131
+ * Writes the committed tree under `root` (a real path of its own): directories and regular files first and links last, so no
132
+ * write of a file goes through a link, and before each write the real path of its parent must be inside `root`.
133
+ */
134
+ export function writeBaseTree(root, files) {
135
+ const ordered = [...files.filter((file) => file.mode !== "120000"), ...files.filter((file) => file.mode === "120000")];
136
+ for (const file of ordered) {
137
+ const path = join(root, file.path);
138
+ ensureDirectory(root, dirname(file.path) === "." ? "" : dirname(file.path));
139
+ if (!insideRoot(root, dirname(path)))
140
+ throw new Error("a path of the base tree resolves outside the temporary directory");
141
+ if (file.mode === "120000") {
142
+ symlinkSync(file.bytes.toString("utf8"), path);
143
+ continue;
144
+ }
145
+ writeFileSync(path, file.bytes, { flag: "wx" });
146
+ chmodSync(path, file.mode === "100755" ? 0o755 : 0o644);
147
+ }
148
+ }
149
+ // ---------------------------------------------------------------------------
150
+ // one repository
151
+ const digestOfBytes = (bytes) => contentDigest(bytes.toString("utf8"));
152
+ const sha256Hex = (bytes) => createHash("sha256").update(bytes).digest("hex");
153
+ /**
154
+ * V6 and V9 for a set that changes a lockfile, or null when it changes none. V6 is the result of writing the set into a
155
+ * temporary copy of the base tree and regenerating the lockfile there; V9 is run on that same copy, and only when V6 is
156
+ * satisfied. The ledger is not written: it is bound by an approval that does not exist yet, and nothing here reads it.
157
+ */
158
+ export async function dryMaterialize(input, ports = {}) {
159
+ const { set } = input;
160
+ const lock = derivedLockfile(set);
161
+ if (lock === null)
162
+ return null;
163
+ const held = { root: null };
164
+ try {
165
+ const outcome = await runDry(input, ports, lock, held);
166
+ if ("checks" in outcome)
167
+ return outcome.checks;
168
+ return [outcome.v6, { check: "V9", verdict: "indeterminate", rule: LOCKFILE_NOT_REGENERATED }];
169
+ }
170
+ catch {
171
+ return [v6("indeterminate", DRY_TREE_FAILED), { check: "V9", verdict: "indeterminate", rule: LOCKFILE_NOT_REGENERATED }];
172
+ }
173
+ finally {
174
+ if (held.root !== null) {
175
+ try {
176
+ rmSync(held.root, { recursive: true, force: true });
177
+ }
178
+ catch {
179
+ // The verdict does not depend on the removal, and the tree is under the operating-system temporary directory.
180
+ }
181
+ }
182
+ }
183
+ }
184
+ async function runDry(input, ports, lock, held) {
185
+ const { set } = input;
186
+ if (!validateRepositoryChangeSet(set).valid)
187
+ return { v6: v6("indeterminate", "change-set-invalid") };
188
+ const lockpath = lockfilePath({ packageManager: set.observed.packageManager, lockfile: set.observed.lockfile });
189
+ if (lockpath === null || lockpath !== lock.path)
190
+ return { v6: v6("indeterminate", "lockfile-format-unsupported") };
191
+ const packages = packagesForLockfile(set, lock.invariants);
192
+ if (packages === null)
193
+ return { v6: v6("indeterminate", "lockfile-invariants") };
194
+ const committed = readCommittedFiles(input.clone, set.repository.baseCommit);
195
+ if (!committed.ok)
196
+ return { v6: v6("indeterminate", committed.reason) };
197
+ if (!treeIsSafe(committed.files))
198
+ return { v6: v6("indeterminate", DRY_TREE_UNSAFE) };
199
+ const base = new Map(committed.files.map((file) => [file.path, file]));
200
+ const baseText = (path) => base.get(path)?.bytes.toString("utf8") ?? null;
201
+ // The set's own claim about the base: every file it replaces is, at the base commit, the bytes it names as `before`.
202
+ const whole = set.files.filter(isWhole);
203
+ for (const file of whole) {
204
+ const at = base.get(file.path);
205
+ if ((at === undefined ? null : digestOfBytes(at.bytes)) !== file.before)
206
+ return { v6: v6("violated", "base-mismatch") };
207
+ }
208
+ const parent = ports.tempRoot === undefined ? realpathSync(tmpdir()) : realpathSync(ports.tempRoot);
209
+ const root = mkdtempSync(join(parent, TEMP_PREFIX));
210
+ held.root = root;
211
+ // The runner and the provenance check both need a directory that is its own real path.
212
+ if (realpathSync(root) !== root)
213
+ return { v6: v6("indeterminate", DRY_TREE_FAILED) };
214
+ writeBaseTree(root, committed.files);
215
+ // What every change writes is resolved and proved before the first write, from the tree as the base has it.
216
+ const texts = textsFromChangeSet(set);
217
+ const toWrite = whole.filter((file) => file.before !== file.after);
218
+ const resolved = new Map();
219
+ for (const file of toWrite) {
220
+ const text = resolveFileText(root, set, file, texts);
221
+ if (typeof text !== "string")
222
+ return { v6: fromStep(text) };
223
+ if (file.after !== null && contentDigest(text) !== file.after)
224
+ return { v6: v6("violated", "content-mismatch") };
225
+ if (!provesReleaseAgeEditWith(baseText, set, file, text))
226
+ return { v6: v6("violated", "content-mismatch") };
227
+ resolved.set(file.path, text);
228
+ }
229
+ let packageText;
230
+ if (set.keys.length > 0) {
231
+ const existing = baseText("package.json");
232
+ if (existing === null)
233
+ return { v6: v6("indeterminate", "manifest-absent") };
234
+ try {
235
+ packageText = editJsonPointer(existing, set.keys.map((key) => (key.after === null ? { pointer: key.pointer, remove: true } : { pointer: key.pointer, value: key.after })));
236
+ }
237
+ catch (cause) {
238
+ if (cause instanceof JsonEditUnstableError)
239
+ return { v6: v6("indeterminate", "json-edit-unstable") };
240
+ throw cause;
241
+ }
242
+ }
243
+ const touched = [...toWrite.map((file) => file.path), ...(packageText === undefined ? [] : ["package.json"])];
244
+ const symlinked = refuseReservedSymlinks(root, touched);
245
+ if (symlinked !== null)
246
+ return { v6: fromStep(symlinked) };
247
+ for (const file of toWrite) {
248
+ if (file.after === null) {
249
+ const removed = removePath(root, file.path);
250
+ if (removed !== null)
251
+ return { v6: fromStep(removed) };
252
+ }
253
+ else if (file.mode === "120000") {
254
+ const linked = writeSymlink(root, file.path, resolved.get(file.path), file.after);
255
+ if (linked !== null)
256
+ return { v6: fromStep(linked) };
257
+ }
258
+ else {
259
+ const written = writeRegularFile(root, file.path, resolved.get(file.path), file.after);
260
+ if (written !== null)
261
+ return { v6: fromStep(written) };
262
+ }
263
+ }
264
+ if (packageText !== undefined) {
265
+ const written = writeRegularFile(root, "package.json", packageText, contentDigest(packageText));
266
+ if (written !== null)
267
+ return { v6: fromStep(written) };
268
+ }
269
+ // The lockfile step, as materialize runs it: the tool version is not supplied here, so pnpm and Yarn are refused by the runner.
270
+ const regen = await regenerateLockfile({
271
+ root,
272
+ packageManager: set.observed.packageManager,
273
+ lockfile: set.observed.lockfile,
274
+ toolVersion: null,
275
+ baseLockfile: baseText(lock.path) ?? "",
276
+ packages,
277
+ now: input.now,
278
+ }, { spawn: ports.lockfileSpawn });
279
+ // Only the runner's fixed rule or reason is kept, never its tool output or paths.
280
+ if (regen.verdict === "violated")
281
+ return { v6: v6("violated", regen.rule) };
282
+ if (regen.verdict === "indeterminate")
283
+ return { v6: v6("indeterminate", regen.reason) };
284
+ let onDisk;
285
+ try {
286
+ onDisk = readFileSync(join(root, regen.path));
287
+ }
288
+ catch {
289
+ return { v6: v6("violated", "lockfile-invariants") };
290
+ }
291
+ if (sha256Hex(onDisk) !== regen.after)
292
+ return { v6: v6("violated", "lockfile-invariants") };
293
+ const provenance = await checkSetProvenance({ tree: root, hubRoot: input.hubRoot, items: set.items }, { spawn: ports.provenanceSpawn });
294
+ return { checks: [V6_SATISFIED, ...provenance] };
295
+ }
296
+ const sortChecks = (checks) => canonicalOrder(checks, (check) => [check.check, check.rule ?? ""]);
297
+ /**
298
+ * The planner's result with each dry-materializable repository's `lockfile-not-run` replaced by V6 and V9 as this module
299
+ * computes them. A repository is dry-materialized only when its set changes a lockfile, has no refused path or key, and every
300
+ * other check is already satisfied: a repository that cannot be applied anyway launches nothing. The sets, their digests and
301
+ * the bundle digest are unchanged (the digest does not cover checks); each repository's verdict is recomputed as the worst of
302
+ * its checks, and the bundle is validated again. Throws when it does not validate.
303
+ */
304
+ export async function dryMaterializeBundle(result, options) {
305
+ const repositories = [];
306
+ for (const entry of result.bundle.repositories) {
307
+ if (!("changeSet" in entry)) {
308
+ repositories.push(entry);
309
+ continue;
310
+ }
311
+ const others = entry.checks.filter((check) => !(check.check === "V6" && check.rule === LOCKFILE_NOT_RUN));
312
+ const set = result.changeSets.find((candidate) => candidate.changeSetDigest === entry.changeSet);
313
+ if (others.length === entry.checks.length || set === undefined || set.refused.length > 0 || others.some((check) => check.verdict !== "satisfied")) {
314
+ repositories.push(entry);
315
+ continue;
316
+ }
317
+ const replaced = await dryMaterialize({ clone: options.cloneFor(set.repository.id), hubRoot: options.hub, set, now: options.now }, options.ports);
318
+ if (replaced === null) {
319
+ repositories.push(entry);
320
+ continue;
321
+ }
322
+ const checks = sortChecks([...others, ...replaced]);
323
+ repositories.push({ ...entry, verdict: worstVerdict(checks.map((check) => check.verdict)), checks });
324
+ }
325
+ const bundle = { ...result.bundle, repositories };
326
+ if (!validateApplyBundle(bundle).valid)
327
+ throw new Error("the bundle with its dry-materialization checks does not validate");
328
+ return { bundle, changeSets: result.changeSets };
329
+ }
330
+ //# sourceMappingURL=dry-materialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-materialize.js","sourceRoot":"","sources":["../src/dry-materialize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * A minimal JSON Schema (draft-07) checker for this repository's shared
3
+ * contracts (issue #1475): the plan record and the engagement brief, which
4
+ * two packages validate against without either depending on the other.
5
+ *
6
+ * It implements exactly the keywords those contracts use, and throws on any
7
+ * other keyword, or keyword form, it meets instead of half-checking it.
8
+ * `assertImplementedContract()` walks a whole contract, so a test can prove
9
+ * every subschema is implemented, visited by a value or not. Property
10
+ * lookups use Object.hasOwn, so an inherited name (toString, constructor,
11
+ * __proto__) is never mistaken for a declared or present property.
12
+ *
13
+ * Messages, paths and errors never echo text from the document under test
14
+ * -- neither a value nor a key. A brief can carry founder text, a refusal
15
+ * can end up in a log, and these messages are read by agents: a hostile
16
+ * document can put prompt-injection text in a key name as easily as in a
17
+ * value. A path names only fields the contract declares (schema text, not
18
+ * document text) and array indices. A field the contract does not declare,
19
+ * or a repeated key, is reported at the object that holds it, by the key's
20
+ * 1-based position in that object ("key 3 of this object"), never by name.
21
+ *
22
+ * Every string, and every object key, must be well-formed Unicode: a lone
23
+ * surrogate is refused whatever the contract says, because it has no UTF-8
24
+ * encoding and so no canonical form. A document this checker accepts can
25
+ * always be digested.
26
+ *
27
+ * `readContractDocument()` is the one way to turn a plan or brief FILE into
28
+ * a value: it refuses bytes that are not valid UTF-8 and any object that
29
+ * repeats a key, at any depth. `JSON.parse` alone would silently keep the
30
+ * last of two duplicate keys, so a reviewer reading the file could see a
31
+ * value that is not the one validated and digested.
32
+ *
33
+ * This file imports nothing. It is the one implementation: a package that
34
+ * cannot import it carries a generated, byte-identical copy.
35
+ */
36
+ export type ContractSchema = Readonly<Record<string, unknown>>;
37
+ /**
38
+ * One place a value breaks its contract. `path` is `""` for the document
39
+ * itself, else like `blockers[0].nextAction.who`: only names the contract
40
+ * declares, and array indices. Neither `path` nor `message` ever carries
41
+ * document text.
42
+ */
43
+ export interface ContractViolation {
44
+ readonly path: string;
45
+ readonly message: string;
46
+ }
47
+ /** Resolves a file-level `$ref` (for example `engagement-context.json`) to that contract. Throws when it cannot. */
48
+ export type ContractLoader = (name: string) => ContractSchema;
49
+ /** Walks every subschema of `schema`, visited by a value or not, and throws on the first keyword this checker does not implement. */
50
+ export declare function assertImplementedContract(schema: ContractSchema, at?: string): void;
51
+ /**
52
+ * Every violation of `value` against `contract`; empty when it conforms. A
53
+ * type mismatch stops there and returns alone, since every other keyword
54
+ * assumes the value is already the right type. Otherwise, on an object, any
55
+ * `const` or `enum` violation of the object itself comes before a missing
56
+ * required field, which comes before each present key's violations in the
57
+ * order the keys were written (see `keyOrder()`), then any from `oneOf`,
58
+ * `allOf` and `not`. Never throws for a bad value. Throws only when the
59
+ * contract itself uses a keyword this checker does not implement, or a
60
+ * `$ref` it cannot resolve -- a defect in the contract, not in the value.
61
+ */
62
+ export declare function validateAgainstContract(contract: ContractSchema, value: unknown, load: ContractLoader): ContractViolation[];
63
+ /** `label.path message` (for example `plan.blockers[0].capabilityId is required`), or `label message` for the document itself. */
64
+ export declare function formatContractViolation(label: string, violation: ContractViolation): string;
65
+ /**
66
+ * Why `readContractDocument()` refused a file, as data a caller can act on
67
+ * without parsing the message: `reason` says which rule failed, and
68
+ * `position` (never file text) is set only for a syntax error or a leading
69
+ * byte order mark. The message carries no file text either: a repeated key
70
+ * is named by its 1-based position in its object, and that object as the
71
+ * top-level object or by its position, never by any key.
72
+ *
73
+ * A position, here and in every message, is a 0-based index into the
74
+ * decoded text in UTF-16 code units: JavaScript's string index. It equals
75
+ * the byte offset only for ASCII text; a character outside the Basic
76
+ * Multilingual Plane (an emoji, say) counts as two.
77
+ */
78
+ export declare class ContractDocumentError extends Error {
79
+ readonly reason: "encoding" | "syntax" | "repeated-key";
80
+ readonly position?: number | undefined;
81
+ constructor(message: string, reason: "encoding" | "syntax" | "repeated-key", position?: number | undefined);
82
+ }
83
+ /**
84
+ * Reads a plan or brief file's bytes as strict JSON: UTF-8 that decodes
85
+ * without error (never silently replaced with U+FFFD) and does not start
86
+ * with a byte order mark, exactly one JSON value, and no object that repeats a key at any depth -- the I-JSON rules
87
+ * RFC 8785 canonicalization assumes. Refuses bytes that break a rule with a
88
+ * ContractDocumentError whose message says which rule, by position only: a
89
+ * syntax error by its position (a UTF-16 code-unit index, see
90
+ * ContractDocumentError), a repeated key by its 1-based position in its
91
+ * object and that object's position (or "the top-level object") -- never
92
+ * any text from the file. It does not validate the value against a contract; call
93
+ * `validateAgainstContract()` next, which then numbers an undeclared field
94
+ * by its position as written in the file.
95
+ */
96
+ export declare function readContractDocument(bytes: Uint8Array): unknown;
97
+ //# sourceMappingURL=contract-schema.generated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-schema.generated.d.ts","sourceRoot":"","sources":["../../src/generated/contract-schema.generated.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,oHAAoH;AACpH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;AAkE9D,qIAAqI;AACrI,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,SAAM,GAAG,IAAI,CAShF;AA+LD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,iBAAiB,EAAE,CAE3H;AAED,kIAAkI;AAClI,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAG3F;AAQD;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,cAAc;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM;gBAF1B,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,cAAc,EAC9C,QAAQ,CAAC,EAAE,MAAM,YAAA;CAI7B;AA2HD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAY/D"}