@intentius/chant 0.124.14 → 0.124.16

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 (178) hide show
  1. package/dist/build.d.ts +6 -0
  2. package/dist/build.d.ts.map +1 -1
  3. package/dist/build.js +1 -0
  4. package/dist/change-set.d.ts +24 -2
  5. package/dist/change-set.d.ts.map +1 -1
  6. package/dist/change-set.js +50 -1
  7. package/dist/ci-jobs.d.ts +227 -0
  8. package/dist/ci-jobs.d.ts.map +1 -0
  9. package/dist/ci-jobs.js +448 -0
  10. package/dist/cli/flush.d.ts +16 -0
  11. package/dist/cli/flush.d.ts.map +1 -0
  12. package/dist/cli/flush.js +42 -0
  13. package/dist/cli/handlers/approve.d.ts +98 -0
  14. package/dist/cli/handlers/approve.d.ts.map +1 -0
  15. package/dist/cli/handlers/approve.js +495 -0
  16. package/dist/cli/handlers/operator.d.ts +1 -95
  17. package/dist/cli/handlers/operator.d.ts.map +1 -1
  18. package/dist/cli/handlers/operator.js +4 -488
  19. package/dist/cli/handlers/override-approve.js +1 -1
  20. package/dist/cli/main.d.ts +4 -15
  21. package/dist/cli/main.d.ts.map +1 -1
  22. package/dist/cli/main.js +4 -1062
  23. package/dist/cli/parse-args.d.ts +6 -0
  24. package/dist/cli/parse-args.d.ts.map +1 -0
  25. package/dist/cli/parse-args.js +1028 -0
  26. package/dist/components/fan-out-record.d.ts +1 -1
  27. package/dist/components/fan-out-record.d.ts.map +1 -1
  28. package/dist/components/fan-out-record.js +3 -7
  29. package/dist/components/fan-out-run.d.ts +5 -3
  30. package/dist/components/fan-out-run.d.ts.map +1 -1
  31. package/dist/components/fan-out-run.js +7 -5
  32. package/dist/components/pr-pipeline.d.ts.map +1 -1
  33. package/dist/components/pr-pipeline.js +3 -2
  34. package/dist/composite.d.ts +10 -2
  35. package/dist/composite.d.ts.map +1 -1
  36. package/dist/composite.js +8 -0
  37. package/dist/discovery/collect.d.ts +2 -1
  38. package/dist/discovery/collect.d.ts.map +1 -1
  39. package/dist/discovery/collect.js +16 -1
  40. package/dist/discovery/fold-import.d.ts.map +1 -1
  41. package/dist/discovery/fold-import.js +2 -107
  42. package/dist/discovery/host-composite.d.ts +35 -0
  43. package/dist/discovery/host-composite.d.ts.map +1 -0
  44. package/dist/discovery/host-composite.js +93 -0
  45. package/dist/discovery/index.d.ts +9 -0
  46. package/dist/discovery/index.d.ts.map +1 -1
  47. package/dist/discovery/index.js +1 -1
  48. package/dist/gate-decision.d.ts +20 -9
  49. package/dist/gate-decision.d.ts.map +1 -1
  50. package/dist/gate-decision.js +72 -19
  51. package/dist/gated-waves.d.ts +25 -6
  52. package/dist/gated-waves.d.ts.map +1 -1
  53. package/dist/gated-waves.js +21 -6
  54. package/dist/lifecycle/gate-audit.d.ts +69 -2
  55. package/dist/lifecycle/gate-audit.d.ts.map +1 -1
  56. package/dist/lifecycle/gate-audit.js +76 -2
  57. package/dist/lifecycle/gate-ledger.d.ts +24 -0
  58. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  59. package/dist/lifecycle/gate-ledger.js +9 -1
  60. package/dist/op/activities/activity-contracts.d.ts +5 -5
  61. package/dist/op/activities/activity-contracts.js +1 -1
  62. package/dist/op/activities/change-set.d.ts +8 -3
  63. package/dist/op/activities/change-set.d.ts.map +1 -1
  64. package/dist/op/activities/change-set.js +5 -2
  65. package/dist/op/activities/reconcile.d.ts +28 -16
  66. package/dist/op/activities/reconcile.d.ts.map +1 -1
  67. package/dist/op/activities/reconcile.js +34 -20
  68. package/dist/op/builders.d.ts +1 -1
  69. package/dist/op/builders.d.ts.map +1 -1
  70. package/dist/op/builders.js +1 -1
  71. package/dist/op/op-waves-run.d.ts +2 -2
  72. package/dist/op/op-waves-run.d.ts.map +1 -1
  73. package/dist/op/op-waves-run.js +8 -9
  74. package/dist/op/op-waves.d.ts.map +1 -1
  75. package/dist/op/op-waves.js +4 -8
  76. package/dist/package-version.d.ts +2 -0
  77. package/dist/package-version.d.ts.map +1 -0
  78. package/dist/package-version.js +10 -0
  79. package/dist/wave-engine.d.ts +62 -0
  80. package/dist/wave-engine.d.ts.map +1 -0
  81. package/dist/wave-engine.js +59 -0
  82. package/dist/wave-layout.d.ts +29 -0
  83. package/dist/wave-layout.d.ts.map +1 -0
  84. package/dist/wave-layout.js +41 -0
  85. package/dist/wave-runtime.d.ts +29 -0
  86. package/dist/wave-runtime.d.ts.map +1 -0
  87. package/dist/wave-runtime.js +103 -0
  88. package/dist/wave-runtime.mjs +331 -0
  89. package/dist/workspace/__fixtures__/contract-repo.d.ts +7 -0
  90. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  91. package/dist/workspace/__fixtures__/contract-repo.js +17 -1
  92. package/dist/workspace/__fixtures__/sessions.d.ts +1 -1
  93. package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -1
  94. package/dist/workspace/__fixtures__/sessions.js +3 -3
  95. package/dist/workspace/ajv2020.d.ts +5 -0
  96. package/dist/workspace/ajv2020.d.ts.map +1 -0
  97. package/dist/workspace/ajv2020.js +14 -0
  98. package/dist/workspace/change-set.schema.json +5 -3
  99. package/dist/workspace/ci-green-workflow.d.ts +3 -1
  100. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  101. package/dist/workspace/ci-green-workflow.js +5 -2
  102. package/dist/workspace/class-data.d.ts +84 -0
  103. package/dist/workspace/class-data.d.ts.map +1 -0
  104. package/dist/workspace/class-data.js +238 -0
  105. package/dist/workspace/declaration.d.ts.map +1 -1
  106. package/dist/workspace/declaration.js +4 -8
  107. package/dist/workspace/kinds.d.ts +3 -7
  108. package/dist/workspace/kinds.d.ts.map +1 -1
  109. package/dist/workspace/kinds.js +8 -45
  110. package/dist/workspace/points.d.ts.map +1 -1
  111. package/dist/workspace/points.js +2 -5
  112. package/dist/workspace/principal-classes.d.ts +4 -11
  113. package/dist/workspace/principal-classes.d.ts.map +1 -1
  114. package/dist/workspace/principal-classes.js +13 -99
  115. package/package.json +5 -3
  116. package/src/build.ts +8 -0
  117. package/src/change-set.test.ts +48 -0
  118. package/src/change-set.ts +52 -2
  119. package/src/ci-jobs.test.ts +49 -0
  120. package/src/ci-jobs.ts +515 -0
  121. package/src/cli/flush.ts +44 -0
  122. package/src/cli/handlers/approve.ts +618 -0
  123. package/src/cli/handlers/operator.ts +10 -608
  124. package/src/cli/handlers/override-approve.test.ts +1 -1
  125. package/src/cli/handlers/override-approve.ts +1 -1
  126. package/src/cli/main.ts +5 -816
  127. package/src/cli/parse-args.ts +781 -0
  128. package/src/components/fan-out-record.ts +3 -7
  129. package/src/components/fan-out-run.ts +7 -5
  130. package/src/components/pr-pipeline.ts +3 -2
  131. package/src/composite.ts +15 -3
  132. package/src/discovery/collect.ts +15 -1
  133. package/src/discovery/fold-build-parity.test.ts +71 -0
  134. package/src/discovery/fold-import.ts +2 -113
  135. package/src/discovery/fold-project-provenance.test.ts +21 -4
  136. package/src/discovery/host-composite.ts +101 -0
  137. package/src/discovery/index.ts +11 -1
  138. package/src/gate-decision-bundle.test.ts +6 -4
  139. package/src/gate-decision-identity.test.ts +59 -6
  140. package/src/gate-decision.ts +81 -21
  141. package/src/gated-waves.ts +28 -6
  142. package/src/lifecycle/gate-audit.test.ts +55 -1
  143. package/src/lifecycle/gate-audit.ts +116 -3
  144. package/src/lifecycle/gate-ledger.test.ts +20 -1
  145. package/src/lifecycle/gate-ledger.ts +33 -1
  146. package/src/op/activities/activity-contracts.ts +1 -1
  147. package/src/op/activities/change-set.ts +11 -3
  148. package/src/op/activities/lexicon-upgrade.test.ts +2 -0
  149. package/src/op/activities/reconcile.test.ts +62 -2
  150. package/src/op/activities/reconcile.ts +46 -22
  151. package/src/op/builders.ts +1 -1
  152. package/src/op/op-waves-run.ts +9 -9
  153. package/src/op/op-waves.test.ts +2 -0
  154. package/src/op/op-waves.ts +4 -8
  155. package/src/op/work-lease-run.test.ts +12 -4
  156. package/src/package-version.ts +11 -0
  157. package/src/wave-engine.test.ts +107 -0
  158. package/src/wave-engine.ts +98 -0
  159. package/src/wave-layout.ts +44 -0
  160. package/src/wave-runtime-bundle.test.ts +70 -0
  161. package/src/wave-runtime.e2e.test.ts +177 -0
  162. package/src/wave-runtime.ts +104 -0
  163. package/src/workspace/__fixtures__/contract-repo.ts +17 -1
  164. package/src/workspace/__fixtures__/sessions.ts +3 -3
  165. package/src/workspace/ajv2020.ts +17 -0
  166. package/src/workspace/change-set.schema.json +5 -3
  167. package/src/workspace/ci-green-workflow.test.ts +4 -4
  168. package/src/workspace/ci-green-workflow.ts +5 -2
  169. package/src/workspace/class-data.test.ts +64 -0
  170. package/src/workspace/class-data.ts +236 -0
  171. package/src/workspace/declaration.ts +4 -10
  172. package/src/workspace/kinds.ts +8 -40
  173. package/src/workspace/points.ts +2 -5
  174. package/src/workspace/principal-classes.ts +13 -99
  175. package/src/workspace/records-formats.test.ts +7 -2
  176. package/src/workspace/records-sessions-write.test.ts +3 -3
  177. package/src/workspace/status-contract.e2e.test.ts +37 -0
  178. package/src/workspace/status-contract.test.ts +23 -21
@@ -67,6 +67,7 @@
67
67
  */
68
68
  import { gatePointProblems } from "./gate-point.js";
69
69
  import { notifyConfigProblem } from "../notify.js";
70
+ import { WAVE_GATE_NAME_PATTERN, waveGateNameFrom, waveShare } from "../wave-layout.js";
70
71
  /**
71
72
  * The variables a wave job reads its notify secrets from, for the lexicons
72
73
  * that generate wave pipelines. Re-exported here because a lexicon's source
@@ -109,10 +110,10 @@ export const OP_WAVE_HOOK_MOMENTS = ["before-plan", "after-plan", "after-gate",
109
110
  export const OP_WAVE_APPLY_HOOKS_RUNNERS = ["chant", "apply"];
110
111
  export const OP_WAVES_DIGEST_OVER = ["all", "changing"];
111
112
  /** The default gate name pattern. */
112
- export const OP_WAVE_DEFAULT_GATE_NAME = "{gate}-wave-{k}";
113
+ export const OP_WAVE_DEFAULT_GATE_NAME = WAVE_GATE_NAME_PATTERN;
113
114
  /** The gate wave `k` waits on (#3821): the spec's `gateName` pattern, by default `<gate>-wave-<k>`. */
114
115
  export function opWaveGateName(spec, k) {
115
- return (spec.gateName ?? OP_WAVE_DEFAULT_GATE_NAME).replaceAll("{gate}", spec.gate ?? spec.name).replaceAll("{k}", String(k));
116
+ return waveGateNameFrom(spec.gateName, spec.gate ?? spec.name, k);
116
117
  }
117
118
  /** The command a resume job runs. */
118
119
  export function opWavesResumeCommand(spec) {
@@ -365,12 +366,7 @@ export function opWaveApplyHooksRunBy(spec, name) {
365
366
  * by target, cut into contiguous slices whose sizes differ by at most one.
366
367
  */
367
368
  export function opWaveShare(runs, share, shares) {
368
- const sorted = [...runs].sort((a, b) => (a.target < b.target ? -1 : a.target > b.target ? 1 : 0));
369
- const base = Math.floor(sorted.length / shares);
370
- const extra = sorted.length % shares;
371
- const start = (share - 1) * base + Math.min(share - 1, extra);
372
- const size = base + (share <= extra ? 1 : 0);
373
- return sorted.slice(start, start + size);
369
+ return waveShare(runs, share, shares, (run) => run.target);
374
370
  }
375
371
  /**
376
372
  * The jobs of an Op waves pipeline, in order. `specFile` is the spec's path
@@ -0,0 +1,2 @@
1
+ export declare function readChantPackageVersion(): string;
2
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAQA,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `@intentius/chant`'s own version, read from its package.json as a file. The
3
+ * path is the same from `src/` and `dist/`. The slim wave-job runtime (#3896)
4
+ * has no package.json beside it, and its build writes the version in here.
5
+ */
6
+ import { readFileSync } from "node:fs";
7
+ import { fileURLToPath } from "node:url";
8
+ export function readChantPackageVersion() {
9
+ return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf-8")).version;
10
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The wave engine (#3766): what `chant run wave` (the Op waves spec,
3
+ * `./op/op-waves-run.ts`) and `chant components fan-out --wave-gate`
4
+ * (`./components/fan-out-run.ts`) share once a wave is planned.
5
+ *
6
+ * - Gate naming: {@link waveGateName} and {@link waveGateNameFrom}.
7
+ * - The set digest: {@link waveSetDigest} over {@link waveDigestMembers}.
8
+ * - The share split of a wide wave: {@link waveShare}.
9
+ * - The gate decision call: {@link decideWaveGate}.
10
+ * - The record file a wave job hands the next one: {@link writeWaveRecordFile}.
11
+ *
12
+ * The parts that need neither the gate ledger nor the filesystem live in
13
+ * `./gated-waves.ts`, which terragucci bundles on its own (#3421), and
14
+ * `./wave-layout.ts`, which imports nothing so the Op waves spec module can
15
+ * use it without the change-set code; this module re-exports both so a
16
+ * runner imports the engine from one place.
17
+ *
18
+ * What stays with each entry point: how a wave is planned (Op runs' plan
19
+ * commands, or each component's capabilities), the gate policy, approval
20
+ * mode, decision point, hooks and spend rule (Op waves only), and the shape
21
+ * of the record each writes. Those shapes are read by jobs and approvals
22
+ * already in the wild, so the engine writes what it is handed.
23
+ */
24
+ import { type GateCheck, type GateLedgerPort } from "./op/gate.js";
25
+ import type { AppliedGateRecord } from "./lifecycle/gate-applied.js";
26
+ export { WAVE_GATE_NAME_PATTERN, waveGateNameFrom, waveShare } from "./wave-layout.js";
27
+ export { layerWaves, waveGateName, waveDigestMembers, waveSetDigest, readWaveRecords, withWaveRecord, describeChangedWave, type WaveDigestOver, type WaveMember, type WaveNode, type WaveRecord, type WaveStatus, } from "./gated-waves.js";
28
+ /** What a wave asks its gate. */
29
+ export interface WaveGateRequest {
30
+ /** The op the gate is recorded under: the fan-out's op, or the Op waves spec's name. */
31
+ op: string;
32
+ /** The wave's full gate name. */
33
+ gate: string;
34
+ /** The wave's set digest. */
35
+ digest: string;
36
+ /** The pending fact's description. */
37
+ description: string;
38
+ /** The pending fact's expiry, as a gate's `timeout`. */
39
+ timeout?: string;
40
+ now?: string;
41
+ /** Approvals a wave already applied under, which count for nothing (#3784). */
42
+ spent?: readonly AppliedGateRecord[];
43
+ /** Fields the pending fact carries (#3821). */
44
+ fields?: Record<string, unknown>;
45
+ /** The pending fact carries `neverOverMcp` (#3821). */
46
+ neverOverMcp?: boolean;
47
+ }
48
+ /**
49
+ * Decide a wave's gate: an approval of `digest` under `gate` on `op`'s
50
+ * ledger, or the pending fact that stands for it. A field left out of the
51
+ * request is left out of the call, so each entry point's pending facts are
52
+ * the ones it always wrote.
53
+ */
54
+ export declare function decideWaveGate(port: GateLedgerPort, request: WaveGateRequest): Promise<GateCheck>;
55
+ /**
56
+ * Write a wave record file as indented JSON, through a temporary file and a
57
+ * rename, so a job killed during the write leaves the previous record whole.
58
+ * The fan-out attempt record and an Op wave's decision record both go
59
+ * through it.
60
+ */
61
+ export declare function writeWaveRecordFile(path: string, value: unknown): void;
62
+ //# sourceMappingURL=wave-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wave-engine.d.ts","sourceRoot":"","sources":["../src/wave-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAgB,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EACL,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AAEvB,iCAAiC;AACjC,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrC,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAYjG;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAKtE"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The wave engine (#3766): what `chant run wave` (the Op waves spec,
3
+ * `./op/op-waves-run.ts`) and `chant components fan-out --wave-gate`
4
+ * (`./components/fan-out-run.ts`) share once a wave is planned.
5
+ *
6
+ * - Gate naming: {@link waveGateName} and {@link waveGateNameFrom}.
7
+ * - The set digest: {@link waveSetDigest} over {@link waveDigestMembers}.
8
+ * - The share split of a wide wave: {@link waveShare}.
9
+ * - The gate decision call: {@link decideWaveGate}.
10
+ * - The record file a wave job hands the next one: {@link writeWaveRecordFile}.
11
+ *
12
+ * The parts that need neither the gate ledger nor the filesystem live in
13
+ * `./gated-waves.ts`, which terragucci bundles on its own (#3421), and
14
+ * `./wave-layout.ts`, which imports nothing so the Op waves spec module can
15
+ * use it without the change-set code; this module re-exports both so a
16
+ * runner imports the engine from one place.
17
+ *
18
+ * What stays with each entry point: how a wave is planned (Op runs' plan
19
+ * commands, or each component's capabilities), the gate policy, approval
20
+ * mode, decision point, hooks and spend rule (Op waves only), and the shape
21
+ * of the record each writes. Those shapes are read by jobs and approvals
22
+ * already in the wild, so the engine writes what it is handed.
23
+ */
24
+ import { dirname } from "node:path";
25
+ import { mkdirSync, renameSync, writeFileSync } from "node:fs";
26
+ import { evaluateGate } from "./op/gate.js";
27
+ export { WAVE_GATE_NAME_PATTERN, waveGateNameFrom, waveShare } from "./wave-layout.js";
28
+ export { layerWaves, waveGateName, waveDigestMembers, waveSetDigest, readWaveRecords, withWaveRecord, describeChangedWave, } from "./gated-waves.js";
29
+ /**
30
+ * Decide a wave's gate: an approval of `digest` under `gate` on `op`'s
31
+ * ledger, or the pending fact that stands for it. A field left out of the
32
+ * request is left out of the call, so each entry point's pending facts are
33
+ * the ones it always wrote.
34
+ */
35
+ export function decideWaveGate(port, request) {
36
+ return evaluateGate(port, {
37
+ op: request.op,
38
+ gate: request.gate,
39
+ planDigest: request.digest,
40
+ description: request.description,
41
+ ...(request.timeout ? { timeout: request.timeout } : {}),
42
+ ...(request.now !== undefined ? { now: request.now } : {}),
43
+ ...(request.spent ? { spent: request.spent } : {}),
44
+ ...(request.fields ? { fields: request.fields } : {}),
45
+ ...(request.neverOverMcp ? { neverOverMcp: true } : {}),
46
+ });
47
+ }
48
+ /**
49
+ * Write a wave record file as indented JSON, through a temporary file and a
50
+ * rename, so a job killed during the write leaves the previous record whole.
51
+ * The fan-out attempt record and an Op wave's decision record both go
52
+ * through it.
53
+ */
54
+ export function writeWaveRecordFile(path, value) {
55
+ mkdirSync(dirname(path), { recursive: true });
56
+ const temporary = `${path}.${process.pid}.tmp`;
57
+ writeFileSync(temporary, JSON.stringify(value, null, 2) + "\n");
58
+ renameSync(temporary, path);
59
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Wave gate names and the share split of a wide wave (#3766), the parts of
3
+ * the wave engine (`./wave-engine.ts`) that the Op waves spec module
4
+ * (`./op/op-waves.ts`) needs. That module is in the gate-decision bundle
5
+ * (`./gate-decision.ts` re-exports a constant from it), so this imports
6
+ * nothing and keeps the change-set digest code out of that bundle.
7
+ */
8
+ /** The default wave gate name pattern: `{gate}` is the base gate name, `{k}` the wave's number. */
9
+ export declare const WAVE_GATE_NAME_PATTERN = "{gate}-wave-{k}";
10
+ /**
11
+ * The gate wave `k` waits on under a name pattern (#3821). With the default
12
+ * pattern this is `waveGateName(gate, k)` from `./gated-waves.ts`; an Op
13
+ * waves spec's `gateName` names another (such as `"wave-{k}"`) so approvals
14
+ * already on the ledger under a product's old names keep matching.
15
+ *
16
+ * `{gate}` is filled in before `{k}`, as `opWaveGateName` always did, so a
17
+ * base gate name holding the text `{k}` is filled in too. That is the one
18
+ * input on which this and `waveGateName` differ, and each entry point keeps
19
+ * the one it shipped with.
20
+ */
21
+ export declare function waveGateNameFrom(pattern: string | undefined, gate: string, k: number): string;
22
+ /**
23
+ * Share `share` (1-based) of `shares` of a wide wave (#3679): the items
24
+ * sorted by `keyOf`, cut into contiguous slices whose sizes differ by at most
25
+ * one. The deciding job and every share job cut the same way, so each item
26
+ * is applied by exactly one share.
27
+ */
28
+ export declare function waveShare<T>(items: readonly T[], share: number, shares: number, keyOf: (item: T) => string): T[];
29
+ //# sourceMappingURL=wave-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wave-layout.d.ts","sourceRoot":"","sources":["../src/wave-layout.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7F;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,CAAC,EAAE,CAWhH"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Wave gate names and the share split of a wide wave (#3766), the parts of
3
+ * the wave engine (`./wave-engine.ts`) that the Op waves spec module
4
+ * (`./op/op-waves.ts`) needs. That module is in the gate-decision bundle
5
+ * (`./gate-decision.ts` re-exports a constant from it), so this imports
6
+ * nothing and keeps the change-set digest code out of that bundle.
7
+ */
8
+ /** The default wave gate name pattern: `{gate}` is the base gate name, `{k}` the wave's number. */
9
+ export const WAVE_GATE_NAME_PATTERN = "{gate}-wave-{k}";
10
+ /**
11
+ * The gate wave `k` waits on under a name pattern (#3821). With the default
12
+ * pattern this is `waveGateName(gate, k)` from `./gated-waves.ts`; an Op
13
+ * waves spec's `gateName` names another (such as `"wave-{k}"`) so approvals
14
+ * already on the ledger under a product's old names keep matching.
15
+ *
16
+ * `{gate}` is filled in before `{k}`, as `opWaveGateName` always did, so a
17
+ * base gate name holding the text `{k}` is filled in too. That is the one
18
+ * input on which this and `waveGateName` differ, and each entry point keeps
19
+ * the one it shipped with.
20
+ */
21
+ export function waveGateNameFrom(pattern, gate, k) {
22
+ return (pattern ?? WAVE_GATE_NAME_PATTERN).replaceAll("{gate}", gate).replaceAll("{k}", String(k));
23
+ }
24
+ /**
25
+ * Share `share` (1-based) of `shares` of a wide wave (#3679): the items
26
+ * sorted by `keyOf`, cut into contiguous slices whose sizes differ by at most
27
+ * one. The deciding job and every share job cut the same way, so each item
28
+ * is applied by exactly one share.
29
+ */
30
+ export function waveShare(items, share, shares, keyOf) {
31
+ const sorted = [...items].sort((a, b) => {
32
+ const x = keyOf(a);
33
+ const y = keyOf(b);
34
+ return x < y ? -1 : x > y ? 1 : 0;
35
+ });
36
+ const base = Math.floor(sorted.length / shares);
37
+ const extra = sorted.length % shares;
38
+ const start = (share - 1) * base + Math.min(share - 1, extra);
39
+ const size = base + (share <= extra ? 1 : 0);
40
+ return sorted.slice(start, start + size);
41
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The slim wave-job runtime (#3896): the four commands a generated Op waves
3
+ * pipeline runs, and nothing else.
4
+ *
5
+ * chant run wave --spec <file> --wave <k> [--decide | --share <i> | --record-plans]
6
+ * chant run resume [--gate <op>/<gate>] [--dry-run]
7
+ * chant approve <op> <gate> [...]
8
+ * chant workspace points ask|answer|list|... [...]
9
+ *
10
+ * `scripts/build-runtime.mjs` bundles this file with esbuild into
11
+ * `dist/wave-runtime.mjs`: one self-contained ES module whose only imports are
12
+ * `node:` builtins, with no TypeScript compiler, esbuild, tsx or zod in it. A
13
+ * product copies that one file into its CI image and runs it with plain node,
14
+ * or runs it from an installed `@intentius/chant`
15
+ * (`node node_modules/@intentius/chant/dist/wave-runtime.mjs run wave ...`).
16
+ *
17
+ * The handlers are the full CLI's own (`./cli/main.ts` dispatches to the same
18
+ * functions), parsed by the same `parseArgs`, so flags, output, exit codes and
19
+ * the ledgers each command writes are the same. What the runtime does not do:
20
+ * evaluate `chant.config.ts` (which needs a TypeScript loader). None of the
21
+ * four commands reads the config; the full CLI loads it only to check `--env`
22
+ * against the declared `environments`, a check the runtime skips.
23
+ */
24
+ import { type CommandDef } from "./cli/registry.js";
25
+ /** The commands the runtime carries, under the names the full CLI registers them by. */
26
+ export declare const RUNTIME_COMMANDS: CommandDef[];
27
+ /** Parse, dispatch and return the exit code. Exported for tests. */
28
+ export declare function runRuntime(argv: string[]): Promise<number>;
29
+ //# sourceMappingURL=wave-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wave-runtime.d.ts","sourceRoot":"","sources":["../src/wave-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAkB,KAAK,UAAU,EAAmB,MAAM,gBAAgB,CAAC;AAYlF,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,EAAE,UAAU,EAKxC,CAAC;AAsBF,oEAAoE;AACpE,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BhE"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The slim wave-job runtime (#3896): the four commands a generated Op waves
3
+ * pipeline runs, and nothing else.
4
+ *
5
+ * chant run wave --spec <file> --wave <k> [--decide | --share <i> | --record-plans]
6
+ * chant run resume [--gate <op>/<gate>] [--dry-run]
7
+ * chant approve <op> <gate> [...]
8
+ * chant workspace points ask|answer|list|... [...]
9
+ *
10
+ * `scripts/build-runtime.mjs` bundles this file with esbuild into
11
+ * `dist/wave-runtime.mjs`: one self-contained ES module whose only imports are
12
+ * `node:` builtins, with no TypeScript compiler, esbuild, tsx or zod in it. A
13
+ * product copies that one file into its CI image and runs it with plain node,
14
+ * or runs it from an installed `@intentius/chant`
15
+ * (`node node_modules/@intentius/chant/dist/wave-runtime.mjs run wave ...`).
16
+ *
17
+ * The handlers are the full CLI's own (`./cli/main.ts` dispatches to the same
18
+ * functions), parsed by the same `parseArgs`, so flags, output, exit codes and
19
+ * the ledgers each command writes are the same. What the runtime does not do:
20
+ * evaluate `chant.config.ts` (which needs a TypeScript loader). None of the
21
+ * four commands reads the config; the full CLI loads it only to check `--env`
22
+ * against the declared `environments`, a check the runtime skips.
23
+ */
24
+ import { parseArgs } from "./cli/parse-args.js";
25
+ import { resolveCommand } from "./cli/registry.js";
26
+ import { formatError } from "./cli/format.js";
27
+ import { flushAndExit } from "./cli/flush.js";
28
+ import { CHANT_VERSION } from "./cli/version.js";
29
+ import { isEntryPoint } from "./cli/is-entry-point.js";
30
+ import { ENV_VAR } from "./env.js";
31
+ import { initRuntime } from "./runtime-adapter.js";
32
+ import { runOpWaveCommand } from "./cli/handlers/run-wave.js";
33
+ import { runResumeCommand } from "./cli/handlers/gate-resume.js";
34
+ import { runApprove } from "./cli/handlers/approve.js";
35
+ import { runWorkspacePoints } from "./workspace/points-cli.js";
36
+ /** The commands the runtime carries, under the names the full CLI registers them by. */
37
+ export const RUNTIME_COMMANDS = [
38
+ { name: "run wave", handler: runOpWaveCommand },
39
+ { name: "run resume", handler: runResumeCommand },
40
+ { name: "approve", handler: runApprove },
41
+ { name: "workspace points", handler: runWorkspacePoints },
42
+ ];
43
+ const HELP = `
44
+ chant runtime ${CHANT_VERSION} - the wave-job commands of chant, in one file
45
+
46
+ Usage: node wave-runtime.mjs <command> [options]
47
+
48
+ Commands:
49
+ run wave --spec <file> --wave <k> Plan, gate and apply wave k of an Op waves spec
50
+ (--decide, --share <i>, --record-plans, --base <ref>, --json)
51
+ run resume Start the CI jobs that wait at gates whose approval arrived
52
+ (--gate <op>/<gate>, --dry-run, --json)
53
+ approve <op> <gate> Record a gate's resolution on the lifecycle ledger
54
+ (--actor, --plan, --note, --url, --sign, --expire, --resume, ...)
55
+ workspace points <verb> Ask, answer and list decision points
56
+
57
+ Flags, output, exit codes and ledger formats are the full chant CLI's;
58
+ see "chant --help" in @intentius/chant for every flag. This runtime does
59
+ not evaluate chant.config.ts, so --env is not checked against the
60
+ declared environments.
61
+ `;
62
+ /** Parse, dispatch and return the exit code. Exported for tests. */
63
+ export async function runRuntime(argv) {
64
+ let args;
65
+ try {
66
+ args = parseArgs(argv);
67
+ }
68
+ catch (err) {
69
+ console.error(formatError({ message: err instanceof Error ? err.message : String(err) }));
70
+ return 1;
71
+ }
72
+ const match = resolveCommand(args, RUNTIME_COMMANDS);
73
+ if (args.version && (!args.command || match)) {
74
+ console.log(CHANT_VERSION);
75
+ return 0;
76
+ }
77
+ if (args.help || !args.command) {
78
+ console.log(HELP);
79
+ return args.help ? 0 : 1;
80
+ }
81
+ if (!match) {
82
+ const name = args.path && args.path !== "." ? `${args.command} ${args.path}` : args.command;
83
+ console.error(formatError({
84
+ message: `"${name}" is not part of chant's wave-job runtime`,
85
+ hint: "It runs run wave, run resume, approve and workspace points. Every other command needs the full @intentius/chant CLI.",
86
+ }));
87
+ return 1;
88
+ }
89
+ if (args.env)
90
+ process.env[ENV_VAR] = args.env;
91
+ initRuntime();
92
+ return match.def.handler({ args, plugins: [], serializers: [] });
93
+ }
94
+ if (isEntryPoint(process.argv[1], import.meta.url)) {
95
+ runRuntime(process.argv.slice(2)).then(flushAndExit, async (err) => {
96
+ const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
97
+ if (verbose && err instanceof Error && err.stack)
98
+ console.error(err.stack);
99
+ else
100
+ console.error(formatError({ message: err instanceof Error ? err.message : String(err) }));
101
+ await flushAndExit(1);
102
+ });
103
+ }