@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.
- package/README.md +1324 -60
- package/contracts/conversation-contract.md +2 -2
- package/contracts/product-ci-workflow.yml +74 -0
- package/contracts/repository-inventory.json +53 -0
- package/dist/admission-fixture.d.ts +168 -0
- package/dist/admission-fixture.d.ts.map +1 -0
- package/dist/admission-fixture.js +453 -0
- package/dist/admission-fixture.js.map +1 -0
- package/dist/admission.d.ts +124 -0
- package/dist/admission.d.ts.map +1 -0
- package/dist/admission.js +799 -0
- package/dist/admission.js.map +1 -0
- package/dist/agents-guide.d.ts +9 -0
- package/dist/agents-guide.d.ts.map +1 -0
- package/dist/agents-guide.js +26 -0
- package/dist/agents-guide.js.map +1 -0
- package/dist/apply-command-options.check.d.ts +12 -0
- package/dist/apply-command-options.check.d.ts.map +1 -0
- package/dist/apply-command-options.check.js +20 -0
- package/dist/apply-command-options.check.js.map +1 -0
- package/dist/apply-plan-cli.d.ts +39 -1
- package/dist/apply-plan-cli.d.ts.map +1 -1
- package/dist/apply-plan-cli.js +432 -15
- package/dist/apply-plan-cli.js.map +1 -1
- package/dist/apply-plan.d.ts +46 -59
- package/dist/apply-plan.d.ts.map +1 -1
- package/dist/apply-plan.js +112 -97
- package/dist/apply-plan.js.map +1 -1
- package/dist/apply-step-fixture.d.ts +87 -0
- package/dist/apply-step-fixture.d.ts.map +1 -0
- package/dist/apply-step-fixture.js +199 -0
- package/dist/apply-step-fixture.js.map +1 -0
- package/dist/apply-store.d.ts +93 -0
- package/dist/apply-store.d.ts.map +1 -0
- package/dist/apply-store.js +625 -0
- package/dist/apply-store.js.map +1 -0
- package/dist/approval-sheet.d.ts +21 -0
- package/dist/approval-sheet.d.ts.map +1 -0
- package/dist/approval-sheet.js +157 -0
- package/dist/approval-sheet.js.map +1 -0
- package/dist/body-command.d.ts +42 -0
- package/dist/body-command.d.ts.map +1 -0
- package/dist/body-command.js +143 -0
- package/dist/body-command.js.map +1 -0
- package/dist/change-set-contract.d.ts +381 -0
- package/dist/change-set-contract.d.ts.map +1 -0
- package/dist/change-set-contract.js +738 -0
- package/dist/change-set-contract.js.map +1 -0
- package/dist/change-set-digest.d.ts +28 -0
- package/dist/change-set-digest.d.ts.map +1 -0
- package/dist/change-set-digest.js +65 -0
- package/dist/change-set-digest.js.map +1 -0
- package/dist/check-cli.d.ts.map +1 -1
- package/dist/check-cli.js +14 -3
- package/dist/check-cli.js.map +1 -1
- package/dist/cli.d.ts +17 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +84 -23
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +79 -22
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +843 -268
- package/dist/core.js.map +1 -1
- package/dist/dry-materialize.d.ts +63 -0
- package/dist/dry-materialize.d.ts.map +1 -0
- package/dist/dry-materialize.js +330 -0
- package/dist/dry-materialize.js.map +1 -0
- package/dist/generated/contract-schema.generated.d.ts +97 -0
- package/dist/generated/contract-schema.generated.d.ts.map +1 -0
- package/dist/generated/contract-schema.generated.js +496 -0
- package/dist/generated/contract-schema.generated.js.map +1 -0
- package/dist/generated/package-scope.generated.d.ts +6 -0
- package/dist/generated/package-scope.generated.d.ts.map +1 -0
- package/dist/generated/package-scope.generated.js +10 -0
- package/dist/generated/package-scope.generated.js.map +1 -0
- package/dist/generated/plan-contracts.generated.d.ts +3 -0
- package/dist/generated/plan-contracts.generated.d.ts.map +1 -0
- package/dist/generated/plan-contracts.generated.js +2840 -0
- package/dist/generated/plan-contracts.generated.js.map +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +11 -0
- package/dist/host.js.map +1 -1
- package/dist/identity.d.ts +15 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +48 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +34 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory-adoption.d.ts +24 -5
- package/dist/inventory-adoption.d.ts.map +1 -1
- package/dist/inventory-adoption.js +70 -25
- package/dist/inventory-adoption.js.map +1 -1
- package/dist/inventory-choice.d.ts +40 -0
- package/dist/inventory-choice.d.ts.map +1 -0
- package/dist/inventory-choice.js +156 -0
- package/dist/inventory-choice.js.map +1 -0
- package/dist/inventory-contract.d.ts +89 -0
- package/dist/inventory-contract.d.ts.map +1 -0
- package/dist/inventory-contract.js +121 -0
- package/dist/inventory-contract.js.map +1 -0
- package/dist/key-editor.d.ts +30 -0
- package/dist/key-editor.d.ts.map +1 -0
- package/dist/key-editor.js +445 -0
- package/dist/key-editor.js.map +1 -0
- package/dist/ledger-contract.d.ts +187 -0
- package/dist/ledger-contract.d.ts.map +1 -0
- package/dist/ledger-contract.js +532 -0
- package/dist/ledger-contract.js.map +1 -0
- package/dist/ledger-trust.d.ts +90 -0
- package/dist/ledger-trust.d.ts.map +1 -0
- package/dist/ledger-trust.js +198 -0
- package/dist/ledger-trust.js.map +1 -0
- package/dist/lockfile-invariants.d.ts +48 -0
- package/dist/lockfile-invariants.d.ts.map +1 -0
- package/dist/lockfile-invariants.js +375 -0
- package/dist/lockfile-invariants.js.map +1 -0
- package/dist/lockfile-readers.d.ts +72 -0
- package/dist/lockfile-readers.d.ts.map +1 -0
- package/dist/lockfile-readers.js +713 -0
- package/dist/lockfile-readers.js.map +1 -0
- package/dist/lockfile-regen.d.ts +106 -0
- package/dist/lockfile-regen.d.ts.map +1 -0
- package/dist/lockfile-regen.js +760 -0
- package/dist/lockfile-regen.js.map +1 -0
- package/dist/lockfile-tool-env.d.ts +29 -0
- package/dist/lockfile-tool-env.d.ts.map +1 -0
- package/dist/lockfile-tool-env.js +111 -0
- package/dist/lockfile-tool-env.js.map +1 -0
- package/dist/materialize.d.ts +113 -0
- package/dist/materialize.d.ts.map +1 -0
- package/dist/materialize.js +840 -0
- package/dist/materialize.js.map +1 -0
- package/dist/observe-repository.d.ts +90 -0
- package/dist/observe-repository.d.ts.map +1 -0
- package/dist/observe-repository.js +1367 -0
- package/dist/observe-repository.js.map +1 -0
- package/dist/plan-bundle-setup-fixture.d.ts +68 -0
- package/dist/plan-bundle-setup-fixture.d.ts.map +1 -0
- package/dist/plan-bundle-setup-fixture.js +167 -0
- package/dist/plan-bundle-setup-fixture.js.map +1 -0
- package/dist/plan-bundle.d.ts +250 -0
- package/dist/plan-bundle.d.ts.map +1 -0
- package/dist/plan-bundle.js +827 -0
- package/dist/plan-bundle.js.map +1 -0
- package/dist/plan-command.d.ts +29 -0
- package/dist/plan-command.d.ts.map +1 -0
- package/dist/plan-command.js +493 -0
- package/dist/plan-command.js.map +1 -0
- package/dist/plan-contract.d.ts +153 -0
- package/dist/plan-contract.d.ts.map +1 -0
- package/dist/plan-contract.js +61 -0
- package/dist/plan-contract.js.map +1 -0
- package/dist/plan-digest.d.ts +25 -0
- package/dist/plan-digest.d.ts.map +1 -0
- package/dist/plan-digest.js +106 -0
- package/dist/plan-digest.js.map +1 -0
- package/dist/plan-rules.d.ts +23 -0
- package/dist/plan-rules.d.ts.map +1 -0
- package/dist/plan-rules.js +177 -0
- package/dist/plan-rules.js.map +1 -0
- package/dist/planned-bundle.d.ts +20 -0
- package/dist/planned-bundle.d.ts.map +1 -0
- package/dist/planned-bundle.js +191 -0
- package/dist/planned-bundle.js.map +1 -0
- package/dist/product-repository.d.ts +4 -0
- package/dist/product-repository.d.ts.map +1 -1
- package/dist/product-repository.js +9 -1
- package/dist/product-repository.js.map +1 -1
- package/dist/provenance-gate.d.ts +48 -0
- package/dist/provenance-gate.d.ts.map +1 -0
- package/dist/provenance-gate.js +324 -0
- package/dist/provenance-gate.js.map +1 -0
- package/dist/pull-request-body.d.ts +45 -0
- package/dist/pull-request-body.d.ts.map +1 -0
- package/dist/pull-request-body.js +232 -0
- package/dist/pull-request-body.js.map +1 -0
- package/dist/registry-snapshot.d.ts +141 -0
- package/dist/registry-snapshot.d.ts.map +1 -0
- package/dist/registry-snapshot.js +483 -0
- package/dist/registry-snapshot.js.map +1 -0
- package/dist/release-age-edit.d.ts +52 -0
- package/dist/release-age-edit.d.ts.map +1 -0
- package/dist/release-age-edit.js +413 -0
- package/dist/release-age-edit.js.map +1 -0
- package/dist/root-entries.d.ts +36 -0
- package/dist/root-entries.d.ts.map +1 -0
- package/dist/root-entries.js +80 -0
- package/dist/root-entries.js.map +1 -0
- package/dist/setup-template-scripts.d.ts +34 -0
- package/dist/setup-template-scripts.d.ts.map +1 -0
- package/dist/setup-template-scripts.js +557 -0
- package/dist/setup-template-scripts.js.map +1 -0
- package/dist/setup-templates.d.ts +54 -0
- package/dist/setup-templates.d.ts.map +1 -0
- package/dist/setup-templates.js +427 -0
- package/dist/setup-templates.js.map +1 -0
- package/dist/skills.d.ts +34 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +129 -17
- package/dist/skills.js.map +1 -1
- package/dist/status.d.ts +63 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +539 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +151 -13
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/skeleton/README.md +14 -9
- package/skeleton/package.json +2 -1
- package/skill/SKILL.md +23 -7
- package/skill-catalogue/advisor/SKILL.md +59 -6
- package/skill-catalogue/architect/SKILL.md +2 -2
- package/skill-catalogue/bouncer/SKILL.md +2 -2
- package/skill-catalogue/builder/SKILL.md +2 -2
- package/skill-catalogue/butler/SKILL.md +2 -2
- package/skill-catalogue/controller/SKILL.md +2 -2
- package/skill-catalogue/customer/SKILL.md +2 -2
- package/skill-catalogue/designer/SKILL.md +4 -2
- package/skill-catalogue/giver/SKILL.md +2 -2
- package/skill-catalogue/influencer/SKILL.md +2 -2
- package/skill-catalogue/inspector/SKILL.md +2 -2
- package/skill-catalogue/integrator/SKILL.md +2 -2
- package/skill-catalogue/keeper/SKILL.md +2 -2
- package/skill-catalogue/launcher/SKILL.md +23 -7
- package/skill-catalogue/locksmith/SKILL.md +2 -2
- package/skill-catalogue/messenger/SKILL.md +2 -2
- package/skill-catalogue/observer/SKILL.md +2 -2
- package/skill-catalogue/publisher/SKILL.md +2 -2
- package/skill-catalogue/starter/SKILL.md +3 -2
- package/skill-catalogue/strategist/SKILL.md +12 -4
- package/skill-catalogue/writer/SKILL.md +2 -2
- package/src/admission-fixture.ts +572 -0
- package/src/admission.ts +816 -0
- package/src/agents-guide.ts +29 -0
- package/src/apply-command-options.check.ts +27 -0
- package/src/apply-plan-cli.ts +454 -14
- package/src/apply-plan.ts +112 -124
- package/src/apply-step-fixture.ts +236 -0
- package/src/apply-store.ts +584 -0
- package/src/approval-sheet.ts +164 -0
- package/src/body-command.ts +162 -0
- package/src/change-set-contract.ts +937 -0
- package/src/change-set-digest.ts +70 -0
- package/src/check-cli.ts +14 -3
- package/src/cli.ts +90 -22
- package/src/core.ts +973 -275
- package/src/dry-materialize.ts +353 -0
- package/src/generated/contract-schema.generated.ts +520 -0
- package/src/generated/package-scope.generated.ts +10 -0
- package/src/generated/plan-contracts.generated.ts +2840 -0
- package/src/host.ts +10 -0
- package/src/identity.ts +51 -0
- package/src/index.ts +72 -3
- package/src/inventory-adoption.ts +107 -29
- package/src/inventory-choice.ts +172 -0
- package/src/inventory-contract.ts +166 -0
- package/src/key-editor.ts +446 -0
- package/src/ledger-contract.ts +637 -0
- package/src/ledger-trust.ts +267 -0
- package/src/lockfile-invariants.ts +421 -0
- package/src/lockfile-readers.ts +749 -0
- package/src/lockfile-regen.ts +851 -0
- package/src/lockfile-tool-env.ts +131 -0
- package/src/materialize.ts +886 -0
- package/src/observe-repository.ts +1365 -0
- package/src/plan-bundle-setup-fixture.ts +200 -0
- package/src/plan-bundle.ts +964 -0
- package/src/plan-command.ts +509 -0
- package/src/plan-contract.ts +179 -0
- package/src/plan-digest.ts +102 -0
- package/src/plan-rules.ts +188 -0
- package/src/planned-bundle.ts +211 -0
- package/src/product-repository.ts +10 -1
- package/src/provenance-gate.ts +352 -0
- package/src/pull-request-body.ts +261 -0
- package/src/registry-snapshot.ts +534 -0
- package/src/release-age-edit.ts +430 -0
- package/src/root-entries.ts +81 -0
- package/src/setup-template-scripts.ts +571 -0
- package/src/setup-templates.ts +471 -0
- package/src/skills.ts +161 -18
- package/src/status.ts +557 -0
- package/src/types.ts +148 -13
package/dist/apply-plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../src/apply-plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../src/apply-plan.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAgB,MAAM,oBAAoB,CAAC;AAErF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClF,YAAY,EACV,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAC7K,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,GACxD,MAAM,oBAAoB,CAAC;AAoB5B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAOhE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAGzD;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,EACnB,mBAAmB,EAAE,MAAM,EAC3B,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,MAAM,GACnB,gBAAgB,CA2BlB"}
|
package/dist/apply-plan.js
CHANGED
|
@@ -1,129 +1,144 @@
|
|
|
1
1
|
// Apply an approved plan (#1178): writes clossys/brief.json into a staffed
|
|
2
|
-
// repository
|
|
3
|
-
//
|
|
2
|
+
// repository once clossys/advisor/plan.json is approved, both validated
|
|
3
|
+
// against the shared plan and brief contracts (#1175, #1475).
|
|
4
4
|
//
|
|
5
5
|
// SCOPE OF THIS MODULE (see the wave-2 PR body for the full explanation):
|
|
6
6
|
// this lands the mechanical, auditable core the landed contract fully
|
|
7
7
|
// specifies -- reading clossys/advisor/plan.json, confirming it is
|
|
8
8
|
// approved, validating an EngagementBrief, and writing clossys/brief.json
|
|
9
|
-
// byte-identically.
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
9
|
+
// byte-identically. The plan contract now says which roles work in which
|
|
10
|
+
// inventory repository (`staffing`) and which exact package acts are
|
|
11
|
+
// authorized (`packages`), and approvedSubject() below says what an
|
|
12
|
+
// approval binds (#1178). Multi-repository orchestration (computing each
|
|
13
|
+
// repository's change, branch creation, exact package installs, Starter's
|
|
14
|
+
// caller workflow, opening one pull request per repository) is not built
|
|
15
|
+
// yet, and this module does not act on those fields.
|
|
16
16
|
//
|
|
17
17
|
// clossys/brief.json's shape is NOT re-derived here -- @clossys/advisor's
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// package
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!nonEmptyString(role.why))
|
|
49
|
-
return { valid: false, reason: `brief.roles[${index}].why must be a non-empty string` };
|
|
50
|
-
if (!isRecord(role.goal) || !nonEmptyString(role.goal.metric) || (role.goal.direction !== "increase" && role.goal.direction !== "decrease")) {
|
|
51
|
-
return { valid: false, reason: `brief.roles[${index}].goal must have a metric and a direction of increase or decrease` };
|
|
52
|
-
}
|
|
53
|
-
if (!stringArray(role.inputsFrom))
|
|
54
|
-
return { valid: false, reason: `brief.roles[${index}].inputsFrom must be a string array` };
|
|
55
|
-
if (!stringArray(role.outputsTo))
|
|
56
|
-
return { valid: false, reason: `brief.roles[${index}].outputsTo must be a string array` };
|
|
57
|
-
}
|
|
58
|
-
if (!stringArray(value.sequence) || value.sequence.length === 0)
|
|
59
|
-
return { valid: false, reason: "brief.sequence must be a non-empty string array" };
|
|
60
|
-
if (!stringArray(value.deliverables))
|
|
61
|
-
return { valid: false, reason: "brief.deliverables must be a string array" };
|
|
62
|
-
return { valid: true };
|
|
18
|
+
// toEngagementBrief() is the one owner of that computation. This module
|
|
19
|
+
// receives an already-computed brief and only validates it and writes it,
|
|
20
|
+
// exactly the split #1187's governing principle draws between
|
|
21
|
+
// package-owned definition and judgment versus Launcher's deterministic
|
|
22
|
+
// mechanics.
|
|
23
|
+
//
|
|
24
|
+
// VALIDATION (issue #1475): see plan-contract.ts. There is no second,
|
|
25
|
+
// hand-written shape check here to drift from Advisor's: a plan or brief
|
|
26
|
+
// Advisor accepts, Launcher accepts, and every object in them is closed, so
|
|
27
|
+
// an unknown field is refused. This package still has no runtime
|
|
28
|
+
// dependency on @clossys/advisor.
|
|
29
|
+
import { validateAdvisorPlan, validateEngagementBrief } from "./plan-contract.js";
|
|
30
|
+
import { planDigest } from "./plan-digest.js";
|
|
31
|
+
export { validateAdvisorPlan, validateEngagementBrief } from "./plan-contract.js";
|
|
32
|
+
/**
|
|
33
|
+
* The decisions made at the latest instant, by `at` -- never by array
|
|
34
|
+
* position -- or null when there are none, or when any decision's `at` does
|
|
35
|
+
* not parse to a finite time (the plan contract already refuses one; this
|
|
36
|
+
* does not rely on that), because then time cannot say which is latest.
|
|
37
|
+
*/
|
|
38
|
+
function latestDecisions(plan) {
|
|
39
|
+
if (plan.decisions.length === 0)
|
|
40
|
+
return null;
|
|
41
|
+
const times = plan.decisions.map((decision) => Date.parse(decision.at));
|
|
42
|
+
if (!times.every(Number.isFinite))
|
|
43
|
+
return null;
|
|
44
|
+
// A reduce, not Math.max(...times): spreading a very long list into
|
|
45
|
+
// arguments throws a RangeError.
|
|
46
|
+
const latest = times.reduce((highest, time) => (time > highest ? time : highest), Number.NEGATIVE_INFINITY);
|
|
47
|
+
return plan.decisions.filter((_, index) => times[index] === latest);
|
|
63
48
|
}
|
|
64
|
-
const
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (!
|
|
91
|
-
return
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
return { valid: true };
|
|
49
|
+
const SUBJECT_DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
50
|
+
/**
|
|
51
|
+
* What an approval binds (#1178): the `subjectDigest` of the plan's latest
|
|
52
|
+
* decision, by `at`, when that decision has chosen "approved" -- the digest of
|
|
53
|
+
* the exact change the approver was shown. Otherwise null, and null binds
|
|
54
|
+
* nothing. Fails closed:
|
|
55
|
+
*
|
|
56
|
+
* - a plan that does not validate against the plan contract, rules
|
|
57
|
+
* included: null. It checks this itself rather than trusting its caller,
|
|
58
|
+
* because on an unchecked plan a time with no offset parses as local time,
|
|
59
|
+
* so the machine's time zone could decide which decision is latest;
|
|
60
|
+
* - no decisions, or any decision time that does not parse: null;
|
|
61
|
+
* - a latest decision that is not "approved": null;
|
|
62
|
+
* - an approval with no `subjectDigest`, or one that is not a sha256 digest:
|
|
63
|
+
* null -- an approval that names no bytes approves no bytes;
|
|
64
|
+
* - several decisions at the latest instant: their subject only when every
|
|
65
|
+
* one of them is "approved" with the same `subjectDigest`, else null.
|
|
66
|
+
*
|
|
67
|
+
* It says what was approved, not whether that is what is about to be applied:
|
|
68
|
+
* the caller recomputes the digest of the change it holds and refuses unless
|
|
69
|
+
* the two are equal.
|
|
70
|
+
*/
|
|
71
|
+
export function approvedSubject(plan) {
|
|
72
|
+
if (!validateAdvisorPlan(plan).valid)
|
|
73
|
+
return null;
|
|
74
|
+
const latest = latestDecisions(plan);
|
|
75
|
+
if (latest === null || !latest.every((decision) => decision.chosen === "approved"))
|
|
76
|
+
return null;
|
|
77
|
+
const subject = latest[0].subjectDigest;
|
|
78
|
+
if (typeof subject !== "string" || !SUBJECT_DIGEST.test(subject))
|
|
79
|
+
return null;
|
|
80
|
+
return latest.every((decision) => decision.subjectDigest === subject) ? subject : null;
|
|
98
81
|
}
|
|
99
82
|
/**
|
|
100
83
|
* The plan is approved when its most recent decision (by `at`) records
|
|
101
84
|
* chosen === "approved". No decisions, or a most-recent decision that
|
|
102
85
|
* isn't "approved", is not approved -- this never assumes approval from
|
|
103
|
-
* absence.
|
|
86
|
+
* absence. Fails closed on anything that would let array order decide
|
|
87
|
+
* instead of time: a decision whose `at` does not parse to a finite time
|
|
88
|
+
* (the plan contract already refuses one; this does not rely on that), or
|
|
89
|
+
* two decisions at the same latest instant that do not all say "approved".
|
|
90
|
+
*
|
|
91
|
+
* It binds no bytes (#1178): it does not look at `subjectDigest`, so it is
|
|
92
|
+
* true for an approval that names no change at all. It says only that the
|
|
93
|
+
* latest decision is an approval. Anything that applies a plan must use
|
|
94
|
+
* `approvedSubject()` instead, and compare the subject it returns with the
|
|
95
|
+
* digest of the change it holds. The one stated exception is the legacy
|
|
96
|
+
* brief-only path, `applyEngagementBrief()`, which predates the binding.
|
|
104
97
|
*/
|
|
105
98
|
export function isPlanApproved(plan) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const mostRecent = [...plan.decisions].sort((left, right) => Date.parse(left.at) - Date.parse(right.at)).at(-1);
|
|
109
|
-
return mostRecent?.chosen === "approved";
|
|
99
|
+
const latest = latestDecisions(plan);
|
|
100
|
+
return latest !== null && latest.every((decision) => decision.chosen === "approved");
|
|
110
101
|
}
|
|
111
102
|
/**
|
|
112
103
|
* Writes clossys/brief.json into `repositoryDirectory`, byte-identically
|
|
113
104
|
* from the validated brief -- never re-authors its prose. Refuses (does
|
|
114
|
-
* not write) unless
|
|
105
|
+
* not write) unless the plan validates and is approved and the brief,
|
|
106
|
+
* including its context snapshot, validates. Reports the canonical digest
|
|
107
|
+
* of the plan it applied.
|
|
108
|
+
*
|
|
109
|
+
* LEGACY (#1178): this path predates the approval binding. It accepts an
|
|
110
|
+
* approval whether or not it carries a `subjectDigest` and checks no
|
|
111
|
+
* binding (it uses `isPlanApproved()`), exactly as before; it is kept
|
|
112
|
+
* working, not extended. Anything that must know what an approval binds uses
|
|
113
|
+
* `approvedSubject()`.
|
|
115
114
|
*/
|
|
116
115
|
export function applyEngagementBrief(host, repositoryDirectory, plan, brief, briefRelPath) {
|
|
116
|
+
const planValidation = validateAdvisorPlan(plan);
|
|
117
|
+
if (!planValidation.valid) {
|
|
118
|
+
return { state: "refused", reason: `plan does not validate: ${planValidation.reason}` };
|
|
119
|
+
}
|
|
117
120
|
if (!isPlanApproved(plan)) {
|
|
118
|
-
return { state: "refused", reason: "the plan's most recent decision is not \"approved\"" };
|
|
121
|
+
return { state: "refused", reason: "the plan's most recent decision is not \"approved\", or decisions made at that same time disagree" };
|
|
119
122
|
}
|
|
120
123
|
const validation = validateEngagementBrief(brief);
|
|
121
124
|
if (!validation.valid) {
|
|
122
125
|
return { state: "refused", reason: `brief does not validate: ${validation.reason}` };
|
|
123
126
|
}
|
|
127
|
+
// Everything that can refuse runs before the first write, so a refusal
|
|
128
|
+
// never leaves a brief behind. A plan that validates always has a digest
|
|
129
|
+
// (the contract refuses what canonical JSON cannot carry); this catch is
|
|
130
|
+
// the backstop that keeps that a refusal rather than a throw after writing.
|
|
131
|
+
let digest;
|
|
132
|
+
try {
|
|
133
|
+
digest = planDigest(plan);
|
|
134
|
+
}
|
|
135
|
+
catch (cause) {
|
|
136
|
+
return { state: "refused", reason: `plan has no canonical digest: ${cause instanceof Error ? cause.message : String(cause)}` };
|
|
137
|
+
}
|
|
138
|
+
const contents = `${JSON.stringify(brief, null, 2)}\n`;
|
|
124
139
|
const path = `${repositoryDirectory}/${briefRelPath}`;
|
|
125
140
|
host.mkdirp(path.slice(0, path.lastIndexOf("/")));
|
|
126
|
-
host.writeText(path,
|
|
127
|
-
return { state: "applied", path };
|
|
141
|
+
host.writeText(path, contents);
|
|
142
|
+
return { state: "applied", path, planDigest: digest };
|
|
128
143
|
}
|
|
129
144
|
//# sourceMappingURL=apply-plan.js.map
|
package/dist/apply-plan.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-plan.js","sourceRoot":"","sources":["../src/apply-plan.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"apply-plan.js","sourceRoot":"","sources":["../src/apply-plan.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wEAAwE;AACxE,8DAA8D;AAC9D,EAAE;AACF,0EAA0E;AAC1E,sEAAsE;AACtE,mEAAmE;AACnE,0EAA0E;AAC1E,yEAAyE;AACzE,qEAAqE;AACrE,oEAAoE;AACpE,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,qDAAqD;AACrD,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,0EAA0E;AAC1E,8DAA8D;AAC9D,wEAAwE;AACxE,aAAa;AACb,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,4EAA4E;AAC5E,iEAAiE;AACjE,kCAAkC;AAElC,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAMlF;;;;;GAKG;AACH,SAAS,eAAe,CAAC,IAAiB;IACxC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,oEAAoE;IACpE,iCAAiC;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC5G,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,IAAiB;IAC/C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAChG,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,aAAa,CAAC;IACzC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACzF,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;AACvF,CAAC;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAmB,EACnB,mBAA2B,EAC3B,IAAiB,EACjB,KAAsB,EACtB,YAAoB;IAEpB,MAAM,cAAc,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,2BAA2B,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;IAC1F,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,mGAAmG,EAAE,CAAC;IAC3I,CAAC;IACD,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,4BAA4B,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;IACvF,CAAC;IACD,uEAAuE;IACvE,yEAAyE;IACzE,yEAAyE;IACzE,4EAA4E;IAC5E,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IACjI,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACvD,MAAM,IAAI,GAAG,GAAG,mBAAmB,IAAI,YAAY,EAAE,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { reseal } from "./admission-fixture.js";
|
|
2
|
+
import type { HubOptions, World, WorldOptions } from "./admission-fixture.js";
|
|
3
|
+
import type { ApplyBundle, RepositoryChangeSet } from "./change-set-contract.js";
|
|
4
|
+
import type { LockfileSpawn } from "./lockfile-regen.js";
|
|
5
|
+
import type { AdvisorPlan } from "./plan-contract.js";
|
|
6
|
+
export { reseal };
|
|
7
|
+
type Loose = Record<string, any>;
|
|
8
|
+
export interface MaterializedFixtureOptions {
|
|
9
|
+
/** Overrides for the hub: options, or a function of what the fixture built (its plan, its approved bundle and its set). */
|
|
10
|
+
readonly hub?: Partial<HubOptions> | ((built: {
|
|
11
|
+
plan: AdvisorPlan;
|
|
12
|
+
bundle: ApplyBundle;
|
|
13
|
+
set: RepositoryChangeSet;
|
|
14
|
+
}) => Partial<HubOptions>);
|
|
15
|
+
/** Store the set, with its whole-file texts, in the hub's change-set store, where the command line finds it. Default false. */
|
|
16
|
+
readonly storeSet?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A setup change set whose whole-file bytes are known, with the pin already
|
|
20
|
+
* satisfied and no lockfile to regenerate, checked out from a local clone, and
|
|
21
|
+
* a hub that approved it: a git repository whose HEAD holds a plan (its latest
|
|
22
|
+
* decision approves the bundle that holds the set) and an execution
|
|
23
|
+
* authorization, with the bundle stored and the hub's readiness executable
|
|
24
|
+
* installed. `binding` is the binding admission is expected to compute; it is
|
|
25
|
+
* never an input to materialize or verify.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildMaterializedFixture(roots: string[], options?: MaterializedFixtureOptions): {
|
|
28
|
+
clone: string;
|
|
29
|
+
hub: string;
|
|
30
|
+
set: RepositoryChangeSet;
|
|
31
|
+
texts: Record<string, string>;
|
|
32
|
+
binding: {
|
|
33
|
+
kind: "approved";
|
|
34
|
+
subjectDigest: string;
|
|
35
|
+
};
|
|
36
|
+
planPackages: {
|
|
37
|
+
planItem: string;
|
|
38
|
+
act: "install" | "pin-starter";
|
|
39
|
+
name: string;
|
|
40
|
+
version: string;
|
|
41
|
+
integrity: string;
|
|
42
|
+
placement: "dependencies" | "devDependencies";
|
|
43
|
+
}[];
|
|
44
|
+
plan: AdvisorPlan;
|
|
45
|
+
bundle: ApplyBundle;
|
|
46
|
+
origin: string;
|
|
47
|
+
};
|
|
48
|
+
export interface AdmittedFixtureOptions {
|
|
49
|
+
readonly world?: WorldOptions;
|
|
50
|
+
readonly hub?: Partial<HubOptions> | ((world: World) => Partial<HubOptions>);
|
|
51
|
+
/** How the setup set reached the default branch. Default `squash`: no ancestor of the setup branch. */
|
|
52
|
+
readonly mergeStyle?: "direct" | "squash";
|
|
53
|
+
/** Edits the base tree before it is committed. */
|
|
54
|
+
readonly tree?: (tree: World["tree"]) => void;
|
|
55
|
+
/** Store the apply set in the hub too. Default false. */
|
|
56
|
+
readonly storeApplySet?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The two phases of one plan. The setup set was approved (the plan's latest
|
|
60
|
+
* decision approves the bundle that holds it), materialized and merged into
|
|
61
|
+
* the clone's default branch (by squash by default), and the apply set was
|
|
62
|
+
* then computed against the merged base and is held by a later run's bundle,
|
|
63
|
+
* which the hub stores. `spawn` stands in for the package manager: it
|
|
64
|
+
* regenerates the lockfile the apply set's installs write.
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildAdmittedFixture(roots: string[], options?: AdmittedFixtureOptions): {
|
|
67
|
+
world: World;
|
|
68
|
+
hub: string;
|
|
69
|
+
clone: string;
|
|
70
|
+
baseCommit: string;
|
|
71
|
+
sideTip: string | null;
|
|
72
|
+
set: RepositoryChangeSet;
|
|
73
|
+
setup: RepositoryChangeSet;
|
|
74
|
+
texts: Record<string, string>;
|
|
75
|
+
spawn: LockfileSpawn;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Everything a refused materialize must leave alone: the clone's refs, HEAD,
|
|
79
|
+
* index, status and every file outside .git, and every file the hub keeps
|
|
80
|
+
* under clossys/.state. Two snapshots are equal only when nothing moved.
|
|
81
|
+
*/
|
|
82
|
+
export declare function writeSnapshot(clone: string, hub: string): string;
|
|
83
|
+
/** Whether the clone holds a local branch of this name. */
|
|
84
|
+
export declare function branchExists(clone: string, branch: string): boolean;
|
|
85
|
+
/** The ledger a clone holds at clossys/.state/installed.json, parsed, or null when it holds none. */
|
|
86
|
+
export declare function readCloneLedger(clone: string): Loose | null;
|
|
87
|
+
//# sourceMappingURL=apply-step-fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-step-fixture.d.ts","sourceRoot":"","sources":["../src/apply-step-fixture.ts"],"names":[],"mappings":"AAKA,OAAO,EASL,MAAM,EAEP,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,CAAC;AAKlB,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAsBjC,MAAM,WAAW,0BAA0B;IACzC,2HAA2H;IAC3H,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,mBAAmB,CAAA;KAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5I,+HAA+H;IAC/H,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,0BAA+B;;;;;;;;;;;;;;;;;;;;EAuDjG;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7E,uGAAuG;IACvG,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1C,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC9C,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,sBAA2B;;;;;;;;;;EAsCzF;AAmBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAchE;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAG3D"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, readlinkSync, realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { SITE_ID, approvedPlan, basePlan, buildWorld, bundleOf, committedPlanPackages, hubRepo, lockfileText, reseal, siteRepo, } from "./admission-fixture.js";
|
|
7
|
+
import { contentDigest, discoveryLinkRole, discoveryLinkTarget } from "./change-set-contract.js";
|
|
8
|
+
import { planDigest } from "./plan-digest.js";
|
|
9
|
+
export { reseal };
|
|
10
|
+
const REPO = new URL("../../../", import.meta.url);
|
|
11
|
+
const read = (path) => readFileSync(new URL(path, REPO), "utf8");
|
|
12
|
+
const gitEnv = {
|
|
13
|
+
...process.env,
|
|
14
|
+
PATH: process.env.PATH ?? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
15
|
+
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
16
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
17
|
+
GIT_AUTHOR_NAME: "Example Author",
|
|
18
|
+
GIT_AUTHOR_EMAIL: "author@example.com",
|
|
19
|
+
GIT_COMMITTER_NAME: "Example Author",
|
|
20
|
+
GIT_COMMITTER_EMAIL: "author@example.com",
|
|
21
|
+
};
|
|
22
|
+
function git(cwd, ...args) {
|
|
23
|
+
return execFileSync("git", ["-c", "commit.gpgsign=false", "-c", "core.hooksPath=/dev/null", ...args], {
|
|
24
|
+
cwd,
|
|
25
|
+
env: gitEnv,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A setup change set whose whole-file bytes are known, with the pin already
|
|
32
|
+
* satisfied and no lockfile to regenerate, checked out from a local clone, and
|
|
33
|
+
* a hub that approved it: a git repository whose HEAD holds a plan (its latest
|
|
34
|
+
* decision approves the bundle that holds the set) and an execution
|
|
35
|
+
* authorization, with the bundle stored and the hub's readiness executable
|
|
36
|
+
* installed. `binding` is the binding admission is expected to compute; it is
|
|
37
|
+
* never an input to materialize or verify.
|
|
38
|
+
*/
|
|
39
|
+
export function buildMaterializedFixture(roots, options = {}) {
|
|
40
|
+
const parent = mkdtempSync(join(tmpdir(), "launcher-apply-step-"));
|
|
41
|
+
roots.push(parent);
|
|
42
|
+
const origin = join(parent, "origin.git");
|
|
43
|
+
const clone = join(parent, "site");
|
|
44
|
+
mkdirSync(clone, { recursive: true });
|
|
45
|
+
git(clone, "init", "-b", "main");
|
|
46
|
+
git(clone, "config", "core.autocrlf", "false");
|
|
47
|
+
writeFileSync(join(clone, "README.md"), "# Site\n");
|
|
48
|
+
git(clone, "add", "README.md");
|
|
49
|
+
git(clone, "commit", "-m", "init");
|
|
50
|
+
execFileSync("git", ["init", "--bare", origin], { env: gitEnv, stdio: "ignore" });
|
|
51
|
+
git(clone, "remote", "add", "origin", origin);
|
|
52
|
+
git(clone, "push", "-u", "origin", "HEAD");
|
|
53
|
+
const baseCommit = git(clone, "rev-parse", "HEAD").trim();
|
|
54
|
+
const corpus = JSON.parse(read("docs/contracts/apply-change-set-digest.fixture.json"));
|
|
55
|
+
const set = structuredClone(corpus.changeSets.find((entry) => entry.name === "setup-site").changeSet);
|
|
56
|
+
set.repository.baseCommit = baseCommit;
|
|
57
|
+
set.keys = [];
|
|
58
|
+
set.deferred = [];
|
|
59
|
+
set.files = set.files.filter((file) => file.path !== "package-lock.json");
|
|
60
|
+
for (const item of set.items) {
|
|
61
|
+
if (item.act === "pin-starter" || item.act === "install")
|
|
62
|
+
item.satisfiedInBase = true;
|
|
63
|
+
}
|
|
64
|
+
const plan0 = basePlan();
|
|
65
|
+
set.planDigest = planDigest(plan0);
|
|
66
|
+
const texts = {};
|
|
67
|
+
for (const file of set.files) {
|
|
68
|
+
if (file.derived === true)
|
|
69
|
+
continue;
|
|
70
|
+
if (file.mode === "120000") {
|
|
71
|
+
const role = discoveryLinkRole(file.path);
|
|
72
|
+
const target = discoveryLinkTarget(role);
|
|
73
|
+
texts[file.path] = target;
|
|
74
|
+
file.before = null;
|
|
75
|
+
file.after = contentDigest(target);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const text = `fixture ${file.path}\n`;
|
|
79
|
+
texts[file.path] = text;
|
|
80
|
+
file.before = null;
|
|
81
|
+
file.after = contentDigest(text);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const sealed = reseal(set);
|
|
85
|
+
const bundle = bundleOf(plan0, [{ id: SITE_ID, set: sealed }]);
|
|
86
|
+
const built = { ...sealed, bundle: bundle.bundleDigest };
|
|
87
|
+
const plan = approvedPlan(bundle.bundleDigest, plan0);
|
|
88
|
+
const override = typeof options.hub === "function" ? options.hub({ plan, bundle, set: built }) : (options.hub ?? {});
|
|
89
|
+
// What the planner stores carries the whole-file texts, so the command line can write from the store alone.
|
|
90
|
+
const stored = { ...built, texts: Object.entries(texts).map(([path, text]) => ({ path, text })).sort((left, right) => left.path.localeCompare(right.path)) };
|
|
91
|
+
const hub = hubRepo(roots, { plans: [plan], sets: options.storeSet === true ? [stored] : [], bundles: [bundle], ...override });
|
|
92
|
+
const binding = { kind: "approved", subjectDigest: bundle.bundleDigest };
|
|
93
|
+
return { clone: realpathSync(clone), hub: hub.hub, set: built, texts, binding, planPackages: committedPlanPackages(plan, SITE_ID), plan, bundle, origin };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The two phases of one plan. The setup set was approved (the plan's latest
|
|
97
|
+
* decision approves the bundle that holds it), materialized and merged into
|
|
98
|
+
* the clone's default branch (by squash by default), and the apply set was
|
|
99
|
+
* then computed against the merged base and is held by a later run's bundle,
|
|
100
|
+
* which the hub stores. `spawn` stands in for the package manager: it
|
|
101
|
+
* regenerates the lockfile the apply set's installs write.
|
|
102
|
+
*/
|
|
103
|
+
export function buildAdmittedFixture(roots, options = {}) {
|
|
104
|
+
let site;
|
|
105
|
+
const world = buildWorld({
|
|
106
|
+
...options.world,
|
|
107
|
+
commitBase: (tree) => {
|
|
108
|
+
options.tree?.(tree);
|
|
109
|
+
site = siteRepo(roots, tree, { mergeStyle: options.mergeStyle ?? "squash" });
|
|
110
|
+
const origin = join(dirname(site.clone), "origin.git");
|
|
111
|
+
execFileSync("git", ["init", "--bare", origin], { env: gitEnv, stdio: "ignore" });
|
|
112
|
+
git(site.clone, "remote", "add", "origin", origin);
|
|
113
|
+
git(site.clone, "push", "-u", "origin", "main");
|
|
114
|
+
return site.baseCommit;
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
const override = typeof options.hub === "function" ? options.hub(world) : (options.hub ?? {});
|
|
118
|
+
const hub = hubRepo(roots, {
|
|
119
|
+
plans: [world.plan],
|
|
120
|
+
sets: options.storeApplySet === true ? [world.setup, world.apply] : [world.setup],
|
|
121
|
+
bundles: [world.approvedBundle, world.applyBundle],
|
|
122
|
+
...override,
|
|
123
|
+
});
|
|
124
|
+
const packages = committedPlanPackages(world.plan, SITE_ID);
|
|
125
|
+
const spawn = async (request) => {
|
|
126
|
+
if (request.args.includes("--version"))
|
|
127
|
+
return { status: 0, stdout: "10.9.0\n", stderr: "" };
|
|
128
|
+
writeFileSync(join(request.cwd, "package-lock.json"), lockfileText(packages));
|
|
129
|
+
return { status: 0, stdout: "", stderr: "" };
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
world,
|
|
133
|
+
hub: hub.hub,
|
|
134
|
+
clone: site.clone,
|
|
135
|
+
baseCommit: site.baseCommit,
|
|
136
|
+
sideTip: site.sideTip,
|
|
137
|
+
set: world.apply,
|
|
138
|
+
setup: world.setup,
|
|
139
|
+
texts: world.texts,
|
|
140
|
+
spawn,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function walk(root, skip, into, relative = "") {
|
|
144
|
+
let names;
|
|
145
|
+
try {
|
|
146
|
+
names = readdirSync(join(root, relative)).sort();
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
for (const name of names) {
|
|
152
|
+
const path = relative === "" ? name : `${relative}/${name}`;
|
|
153
|
+
if (skip(path))
|
|
154
|
+
continue;
|
|
155
|
+
const stat = lstatSync(join(root, path));
|
|
156
|
+
if (stat.isDirectory())
|
|
157
|
+
walk(root, skip, into, path);
|
|
158
|
+
else if (stat.isSymbolicLink())
|
|
159
|
+
into.push(`${path} -> ${readlinkSync(join(root, path))}`);
|
|
160
|
+
else
|
|
161
|
+
into.push(`${path} ${createHash("sha256").update(readFileSync(join(root, path))).digest("hex")} ${stat.mode & 0o777}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Everything a refused materialize must leave alone: the clone's refs, HEAD,
|
|
166
|
+
* index, status and every file outside .git, and every file the hub keeps
|
|
167
|
+
* under clossys/.state. Two snapshots are equal only when nothing moved.
|
|
168
|
+
*/
|
|
169
|
+
export function writeSnapshot(clone, hub) {
|
|
170
|
+
const files = [];
|
|
171
|
+
walk(clone, (path) => path === ".git", files);
|
|
172
|
+
const hubFiles = [];
|
|
173
|
+
walk(join(hub, "clossys", ".state"), () => false, hubFiles);
|
|
174
|
+
return JSON.stringify({
|
|
175
|
+
refs: git(clone, "for-each-ref").trim(),
|
|
176
|
+
head: git(clone, "rev-parse", "HEAD").trim(),
|
|
177
|
+
branch: git(clone, "rev-parse", "--abbrev-ref", "HEAD").trim(),
|
|
178
|
+
index: git(clone, "ls-files", "-s").trim(),
|
|
179
|
+
status: git(clone, "status", "--porcelain", "--untracked-files=all").trim(),
|
|
180
|
+
files,
|
|
181
|
+
hub: hubFiles,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/** Whether the clone holds a local branch of this name. */
|
|
185
|
+
export function branchExists(clone, branch) {
|
|
186
|
+
try {
|
|
187
|
+
git(clone, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** The ledger a clone holds at clossys/.state/installed.json, parsed, or null when it holds none. */
|
|
195
|
+
export function readCloneLedger(clone) {
|
|
196
|
+
const path = join(clone, "clossys/.state/installed.json");
|
|
197
|
+
return existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : null;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=apply-step-fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-step-fixture.js","sourceRoot":"","sources":["../src/apply-step-fixture.ts"],"names":[],"mappings":"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"}
|