@intentius/chant 0.124.23 → 0.124.24

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 (123) hide show
  1. package/dist/ci-jobs.d.ts +41 -1
  2. package/dist/ci-jobs.d.ts.map +1 -1
  3. package/dist/ci-jobs.js +48 -1
  4. package/dist/cli/commands/build.d.ts.map +1 -1
  5. package/dist/cli/commands/build.js +14 -0
  6. package/dist/cli/handlers/approve.d.ts.map +1 -1
  7. package/dist/cli/handlers/approve.js +9 -0
  8. package/dist/cli/handlers/emulator.d.ts +13 -2
  9. package/dist/cli/handlers/emulator.d.ts.map +1 -1
  10. package/dist/cli/handlers/emulator.js +63 -3
  11. package/dist/cli/handlers/promote.d.ts.map +1 -1
  12. package/dist/cli/handlers/promote.js +7 -1
  13. package/dist/cli/handlers/run-wave.d.ts.map +1 -1
  14. package/dist/cli/handlers/run-wave.js +5 -4
  15. package/dist/cli/handlers/run.d.ts +4 -3
  16. package/dist/cli/handlers/run.d.ts.map +1 -1
  17. package/dist/cli/handlers/run.js +73 -9
  18. package/dist/cli/main.d.ts.map +1 -1
  19. package/dist/cli/main.js +17 -4
  20. package/dist/cli/parse-args.d.ts.map +1 -1
  21. package/dist/cli/parse-args.js +31 -0
  22. package/dist/cli/registry.d.ts +12 -0
  23. package/dist/cli/registry.d.ts.map +1 -1
  24. package/dist/components/cli-support.d.ts +45 -6
  25. package/dist/components/cli-support.d.ts.map +1 -1
  26. package/dist/components/cli-support.js +97 -22
  27. package/dist/components/driver.d.ts.map +1 -1
  28. package/dist/components/driver.js +25 -10
  29. package/dist/graph-detail.d.ts.map +1 -1
  30. package/dist/graph-detail.js +24 -2
  31. package/dist/lifecycle/git.d.ts +11 -0
  32. package/dist/lifecycle/git.d.ts.map +1 -1
  33. package/dist/lifecycle/git.js +62 -6
  34. package/dist/lifecycle/no-record.d.ts +59 -0
  35. package/dist/lifecycle/no-record.d.ts.map +1 -0
  36. package/dist/lifecycle/no-record.js +88 -0
  37. package/dist/op/activities/shell.d.ts.map +1 -1
  38. package/dist/op/activities/shell.js +30 -9
  39. package/dist/op/emulator-lifecycle.d.ts +23 -0
  40. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  41. package/dist/op/emulator-lifecycle.js +39 -2
  42. package/dist/op/gate.d.ts.map +1 -1
  43. package/dist/op/gate.js +3 -0
  44. package/dist/op/index.d.ts +1 -1
  45. package/dist/op/index.d.ts.map +1 -1
  46. package/dist/op/index.js +1 -1
  47. package/dist/op/local-executor.d.ts +10 -0
  48. package/dist/op/local-executor.d.ts.map +1 -1
  49. package/dist/op/local-executor.js +7 -2
  50. package/dist/op/op-waves-notify.d.ts +2 -0
  51. package/dist/op/op-waves-notify.d.ts.map +1 -1
  52. package/dist/op/op-waves-notify.js +9 -3
  53. package/dist/op/op-waves-run.d.ts +8 -2
  54. package/dist/op/op-waves-run.d.ts.map +1 -1
  55. package/dist/op/op-waves-run.js +36 -11
  56. package/dist/op/op-waves.d.ts +85 -1
  57. package/dist/op/op-waves.d.ts.map +1 -1
  58. package/dist/op/op-waves.js +153 -1
  59. package/dist/op/runtimes/local.d.ts.map +1 -1
  60. package/dist/op/runtimes/local.js +6 -0
  61. package/dist/op/step-console.d.ts +65 -0
  62. package/dist/op/step-console.d.ts.map +1 -0
  63. package/dist/op/step-console.js +140 -0
  64. package/dist/point-decision.d.ts.map +1 -1
  65. package/dist/point-decision.js +3 -0
  66. package/dist/wave-runtime.mjs +238 -238
  67. package/dist/workspace/compose-graph.d.ts +22 -3
  68. package/dist/workspace/compose-graph.d.ts.map +1 -1
  69. package/dist/workspace/compose-graph.js +18 -5
  70. package/dist/workspace/graph.schema.json +68 -1
  71. package/dist/workspace/nested-graph.d.ts +1 -1
  72. package/dist/workspace/nested-graph.d.ts.map +1 -1
  73. package/dist/workspace/nested-graph.js +5 -1
  74. package/dist/workspace/runs.d.ts.map +1 -1
  75. package/dist/workspace/runs.js +4 -2
  76. package/package.json +1 -1
  77. package/src/ci-jobs.ts +58 -1
  78. package/src/cli/commands/build.ts +18 -0
  79. package/src/cli/handlers/approve.ts +9 -0
  80. package/src/cli/handlers/emulator.test.ts +61 -1
  81. package/src/cli/handlers/emulator.ts +65 -4
  82. package/src/cli/handlers/promote.test.ts +7 -0
  83. package/src/cli/handlers/promote.ts +7 -1
  84. package/src/cli/handlers/run-no-record.e2e.test.ts +87 -0
  85. package/src/cli/handlers/run-wave.ts +5 -4
  86. package/src/cli/handlers/run.test.ts +126 -0
  87. package/src/cli/handlers/run.ts +69 -9
  88. package/src/cli/main.test.ts +24 -0
  89. package/src/cli/main.ts +17 -4
  90. package/src/cli/parse-args.ts +21 -0
  91. package/src/cli/registry.ts +12 -0
  92. package/src/components/cli-support.test.ts +75 -0
  93. package/src/components/cli-support.ts +130 -25
  94. package/src/components/driver.test.ts +28 -0
  95. package/src/components/driver.ts +23 -10
  96. package/src/components/generate-disabled.test.ts +56 -0
  97. package/src/graph-ci-edges.test.ts +50 -0
  98. package/src/graph-detail.ts +21 -2
  99. package/src/lifecycle/git.ts +61 -6
  100. package/src/lifecycle/no-record.test.ts +175 -0
  101. package/src/lifecycle/no-record.ts +108 -0
  102. package/src/op/activities/shell.ts +28 -6
  103. package/src/op/emulator-lifecycle.test.ts +24 -1
  104. package/src/op/emulator-lifecycle.ts +58 -2
  105. package/src/op/gate.ts +3 -0
  106. package/src/op/index.ts +1 -1
  107. package/src/op/local-executor.ts +20 -3
  108. package/src/op/op-waves-jobs.test.ts +213 -0
  109. package/src/op/op-waves-notify.ts +11 -5
  110. package/src/op/op-waves-run.ts +42 -11
  111. package/src/op/op-waves.ts +202 -2
  112. package/src/op/runtimes/local.ts +6 -0
  113. package/src/op/step-console.test.ts +150 -0
  114. package/src/op/step-console.ts +155 -0
  115. package/src/point-decision-bundle.test.ts +1 -0
  116. package/src/point-decision.ts +3 -0
  117. package/src/workspace/compose-graph.test.ts +55 -0
  118. package/src/workspace/compose-graph.ts +28 -6
  119. package/src/workspace/graph-contract.test.ts +26 -1
  120. package/src/workspace/graph.schema.json +68 -1
  121. package/src/workspace/nested-graph.test.ts +14 -0
  122. package/src/workspace/nested-graph.ts +7 -2
  123. package/src/workspace/runs.ts +4 -2
package/dist/ci-jobs.d.ts CHANGED
@@ -15,7 +15,9 @@
15
15
  * - the `setup` steps and `environment` a job may carry, checked once per
16
16
  * forge ({@link assertSetupSteps}, {@link assertEnvironment},
17
17
  * {@link gitlabSetupScript}, {@link assertGitlabEnvironment});
18
- * - GitLab's `rules:` expressions and `id_tokens:` declaration.
18
+ * - GitLab's `rules:` expressions and `id_tokens:` declaration;
19
+ * - where a job runs and the id tokens it asks for (#3914), {@link githubRunsOn},
20
+ * {@link gitlabTags}, {@link gitlabIdTokensDoc} and {@link idTokenAudienceEnv}.
19
21
  *
20
22
  * The Forgejo dialect (action refs, dropped `permissions:` and
21
23
  * `environment:`, the header note naming what was dropped) is the forgejo
@@ -66,8 +68,46 @@ export declare function environmentDoc(environment: OpEnvironment): {
66
68
  };
67
69
  /** The directory part of a relative path, `.` when there is none. */
68
70
  export declare function dirnameOf(path: string): string;
71
+ /**
72
+ * Where a generated job runs (#3914): a runner label, a list of labels the
73
+ * runner must all carry, or on GitHub a runner group with optional labels.
74
+ * `runs-on` on GitHub and Forgejo, `tags` on GitLab.
75
+ */
76
+ export type CiRunner = string | readonly string[] | {
77
+ group: string;
78
+ labels?: readonly string[];
79
+ };
80
+ /** True when `runner` is a GitHub runner group, which only GitHub has. */
81
+ export declare function isRunnerGroup(runner: CiRunner | undefined): runner is {
82
+ group: string;
83
+ labels?: readonly string[];
84
+ };
85
+ /**
86
+ * Refuse a runner group on a forge that has none (#3914). `subject` and
87
+ * `field` name whose runner it is, such as `Op waves "x"` and `wave "prod"
88
+ * runner`.
89
+ */
90
+ export declare function assertRunnerLabels(subject: string, field: string, runner: CiRunner | undefined, forge: "GitLab" | "Forgejo"): void;
91
+ /**
92
+ * Each id token's audience as a variable, `<NAME>_AUDIENCE` (#3914). On
93
+ * GitHub and Forgejo the audience is chosen when the job requests the token,
94
+ * so the job reads it from there; GitLab declares it in `id_tokens:`
95
+ * ({@link gitlabIdTokensDoc}).
96
+ */
97
+ export declare function idTokenAudienceEnv(idTokens: Readonly<Record<string, string>> | undefined): Record<string, string>;
98
+ /** A job's GitLab `id_tokens:` for `{ <variable>: <audience> }` (#3914), or undefined when there are none. */
99
+ export declare function gitlabIdTokensDoc(idTokens: Readonly<Record<string, string>> | undefined): Record<string, {
100
+ aud: string;
101
+ }> | undefined;
102
+ /** A job's GitLab `tags:` for `runner` (#3914), or undefined when it names none. */
103
+ export declare function gitlabTags(runner: CiRunner | undefined): string[] | undefined;
69
104
  /** The runner label a generated job asks for; the Forgejo dialect rewrites it to the project's label. */
70
105
  export declare const GITHUB_RUNNER = "ubuntu-latest";
106
+ /** A job's `runs-on` for `runner` (#3914): {@link GITHUB_RUNNER} when it names none. */
107
+ export declare function githubRunsOn(runner: CiRunner | undefined): string | string[] | {
108
+ group: string;
109
+ labels?: string[];
110
+ };
71
111
  /** The job token, which GitHub and Forgejo both mint for every run. */
72
112
  export declare const GITHUB_JOB_TOKEN = "${{ github.token }}";
73
113
  /** A repository secret, by name. */
@@ -1 +1 @@
1
- {"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../src/ci-jobs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../src/ci-jobs.ts"],"names":[],"mappings":"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"}
package/dist/ci-jobs.js CHANGED
@@ -15,7 +15,9 @@
15
15
  * - the `setup` steps and `environment` a job may carry, checked once per
16
16
  * forge ({@link assertSetupSteps}, {@link assertEnvironment},
17
17
  * {@link gitlabSetupScript}, {@link assertGitlabEnvironment});
18
- * - GitLab's `rules:` expressions and `id_tokens:` declaration.
18
+ * - GitLab's `rules:` expressions and `id_tokens:` declaration;
19
+ * - where a job runs and the id tokens it asks for (#3914), {@link githubRunsOn},
20
+ * {@link gitlabTags}, {@link gitlabIdTokensDoc} and {@link idTokenAudienceEnv}.
19
21
  *
20
22
  * The Forgejo dialect (action refs, dropped `permissions:` and
21
23
  * `environment:`, the header note naming what was dropped) is the forgejo
@@ -83,9 +85,54 @@ export function dirnameOf(path) {
83
85
  const i = path.lastIndexOf("/");
84
86
  return i <= 0 ? "." : path.slice(0, i);
85
87
  }
88
+ /** True when `runner` is a GitHub runner group, which only GitHub has. */
89
+ export function isRunnerGroup(runner) {
90
+ return runner !== undefined && typeof runner === "object" && !Array.isArray(runner);
91
+ }
92
+ /**
93
+ * Refuse a runner group on a forge that has none (#3914). `subject` and
94
+ * `field` name whose runner it is, such as `Op waves "x"` and `wave "prod"
95
+ * runner`.
96
+ */
97
+ export function assertRunnerLabels(subject, field, runner, forge) {
98
+ if (!isRunnerGroup(runner))
99
+ return;
100
+ throw new Error(`${subject}: ${field} is the runner group "${runner.group}", which only GitHub has. ` +
101
+ `${forge === "GitLab" ? "GitLab picks a runner by its tags" : "Forgejo picks a runner by its labels"}; give a label or a list of labels.`);
102
+ }
103
+ /**
104
+ * Each id token's audience as a variable, `<NAME>_AUDIENCE` (#3914). On
105
+ * GitHub and Forgejo the audience is chosen when the job requests the token,
106
+ * so the job reads it from there; GitLab declares it in `id_tokens:`
107
+ * ({@link gitlabIdTokensDoc}).
108
+ */
109
+ export function idTokenAudienceEnv(idTokens) {
110
+ return Object.fromEntries(Object.entries(idTokens ?? {}).map(([name, aud]) => [`${name}_AUDIENCE`, aud]));
111
+ }
112
+ /** A job's GitLab `id_tokens:` for `{ <variable>: <audience> }` (#3914), or undefined when there are none. */
113
+ export function gitlabIdTokensDoc(idTokens) {
114
+ const entries = Object.entries(idTokens ?? {});
115
+ return entries.length > 0 ? Object.fromEntries(entries.map(([name, aud]) => [name, { aud }])) : undefined;
116
+ }
117
+ /** A job's GitLab `tags:` for `runner` (#3914), or undefined when it names none. */
118
+ export function gitlabTags(runner) {
119
+ if (runner === undefined || isRunnerGroup(runner))
120
+ return undefined;
121
+ return typeof runner === "string" ? [runner] : [...runner];
122
+ }
86
123
  // ── GitHub Actions and Forgejo Actions ──────────────────────────────────────
87
124
  /** The runner label a generated job asks for; the Forgejo dialect rewrites it to the project's label. */
88
125
  export const GITHUB_RUNNER = "ubuntu-latest";
126
+ /** A job's `runs-on` for `runner` (#3914): {@link GITHUB_RUNNER} when it names none. */
127
+ export function githubRunsOn(runner) {
128
+ if (runner === undefined)
129
+ return GITHUB_RUNNER;
130
+ if (typeof runner === "string")
131
+ return runner;
132
+ if (isRunnerGroup(runner))
133
+ return { group: runner.group, ...(runner.labels && runner.labels.length > 0 ? { labels: [...runner.labels] } : {}) };
134
+ return [...runner];
135
+ }
89
136
  /** The job token, which GitHub and Forgejo both mint for every run. */
90
137
  export const GITHUB_JOB_TOKEN = "${{ github.token }}";
91
138
  /** A repository secret, by name. */
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ import { loadPolicyChecks } from "../../lint/policy.js";
20
20
  import { armSandboxPolicyExecution, runProjectPolicies } from "../../lint/policy-sandbox.js";
21
21
  import { sortedJsonReplacer } from "../../utils.js";
22
22
  import { rankFoldBlockers, toCollapsedFormat } from "../../discovery/fold-rank.js";
23
+ import { foldExecutionCounts } from "../../discovery/fold-import.js";
23
24
  import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format.js";
24
25
  import { writeFileSync, mkdirSync } from "fs";
25
26
  import { resolve, dirname, join, relative } from "path";
@@ -248,6 +249,19 @@ export async function buildCommand(options) {
248
249
  : (decision.reason ?? "fell back to run");
249
250
  console.error(formatInfo(`[fold:${decision.mode}] ${rel} — ${detail}`));
250
251
  }
252
+ // typescript-as-data#177 — the exact instrument beside the sampled one.
253
+ // `test/leftness` reports "0 MB of definition-library code on the path"
254
+ // from a `node --cpu-prof` recording, and a profile has a sampling
255
+ // floor: 0 MB is everything the profiler could see rather than nothing
256
+ // having run. L10.1's counters have no floor.
257
+ //
258
+ // Inside --verbose with the per-file lines, not beside them. The default
259
+ // path is deliberately quiet for the reason above, and the leftness
260
+ // capture already runs --verbose and greps this log for `[fold:fold]`.
261
+ const counts = foldExecutionCounts();
262
+ console.error(formatInfo(`[fold:counts] factoryInvocations=${counts.factoryInvocations} ` +
263
+ `projectFactoryInvocations=${counts.projectFactoryInvocations} ` +
264
+ `factoryInterpretations=${counts.factoryInterpretations}`));
251
265
  }
252
266
  else {
253
267
  console.error(formatInfo(summarizeFoldDecisions(result.foldDecisions)));
@@ -1 +1 @@
1
- {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/approve.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACuE,KAAK,UAAU,EAC5F,MAAM,6BAA6B,CAAC;AAOrC,OAAO,EAEuC,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAChG,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAkDlD,wBAAsB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuGrE;AAED,8DAA8D;AAC9D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oGAAoG;IACpG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAElB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAiT9B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,oBAAoB,EAC9B,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,oBAAoB,EAAE,EAC7B,QAAQ,EAAE,iBAAiB,GAAG,SAAS,EACvC,OAAO,GAAE,SAAS,iBAAiB,EAA+B,GACjE,MAAM,EAAE,CA8BV"}
1
+ {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/approve.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACuE,KAAK,UAAU,EAC5F,MAAM,6BAA6B,CAAC;AAOrC,OAAO,EAEuC,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAChG,MAAM,wBAAwB,CAAC;AAQhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAkDlD,wBAAsB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuGrE;AAED,8DAA8D;AAC9D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oGAAoG;IACpG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAElB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAyT9B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,oBAAoB,EAC9B,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,oBAAoB,EAAE,EAC7B,QAAQ,EAAE,iBAAiB,GAAG,SAAS,EACvC,OAAO,GAAE,SAAS,iBAAiB,EAA+B,GACjE,MAAM,EAAE,CA8BV"}
@@ -14,6 +14,7 @@ import { FAN_OUT_GATE_OP, OVERRIDE_GATE_OP, WORKSPACE_UPGRADE_GATE_OP } from "..
14
14
  import { PR_GATE_OP } from "../../pr-loop.js";
15
15
  import { pushLifecycleReport, requireLifecycleLedger } from "../../lifecycle/git.js";
16
16
  import { LIFECYCLE_LOCAL_NOTE, isLifecycleLocalNote } from "../../lifecycle/local-note.js";
17
+ import { ledgerRecordingOff, NO_RECORD_ENV } from "../../lifecycle/no-record.js";
17
18
  import { formatError, formatWarning, formatSuccess, formatInfo } from "../format.js";
18
19
  // ── chant approve <op> <gate> ───────────────────────────────────────────────
19
20
  /**
@@ -171,6 +172,14 @@ export async function runApprove(ctx) {
171
172
  * approval mean "the next run" instead of "this plan".
172
173
  */
173
174
  export async function recordGateApproval(opName, gate, opts) {
175
+ // #3955: with recording off the approval would be dropped with the process.
176
+ if (ledgerRecordingOff()) {
177
+ console.error(formatError({
178
+ message: `Cannot record the approval of "${gate}": ${NO_RECORD_ENV} is set, so nothing is written to chant/lifecycle`,
179
+ hint: `Unset ${NO_RECORD_ENV} to approve the gate.`,
180
+ }));
181
+ return { ok: false };
182
+ }
174
183
  const { ops } = await discoverOps();
175
184
  // `fan-out` is the op name every `chant components fan-out` gate is recorded
176
185
  // under (../handlers/fan-out.ts). It is a command rather than a declaration,
@@ -1,6 +1,6 @@
1
- import { type EmulatorCapability } from "../../op/index.js";
1
+ import { type EmulatorCapability, type EmulatorUpArgs } from "../../op/index.js";
2
2
  import type { LexiconPlugin } from "../../lexicon.js";
3
- import type { CommandContext } from "../registry.js";
3
+ import type { CommandContext, ParsedArgs } from "../registry.js";
4
4
  /** One emulator's state — the machine-readable `--json` unit (#920). */
5
5
  export interface EmulatorReport {
6
6
  lexicon: string;
@@ -28,6 +28,16 @@ export declare function endpointConflict(lexicon: string, cap: EmulatorCapabilit
28
28
  * applies when exactly one emulator is selected.
29
29
  */
30
30
  export declare function parsePortMappings(values: readonly string[], targets: readonly EmulatorCapability[]): Map<number, number>;
31
+ /** The `up` options other than the port (#3952), per selected emulator. */
32
+ type UpOptions = Pick<EmulatorUpArgs, "image" | "network" | "settings" | "loopback">;
33
+ /**
34
+ * `--image`, `--network`, `--setting` and `--loopback` as each selected
35
+ * emulator's `up` options (#3952). `--image` needs exactly one emulator
36
+ * selected, the way a bare `--port` does. A `--setting` goes to each emulator
37
+ * whose settings prefix its key starts with, and a key that no selected
38
+ * emulator takes is refused rather than passed to a container as plain env.
39
+ */
40
+ export declare function parseUpOptions(args: Pick<ParsedArgs, "image" | "network" | "setting" | "loopback">, targets: readonly EmulatorCapability[]): Map<EmulatorCapability, UpOptions>;
31
41
  /**
32
42
  * `chant emulator --help` (#3673): the subcommands and flags, and for each
33
43
  * configured lexicon's emulator the port, endpoint and sign-in a client uses.
@@ -43,4 +53,5 @@ export declare function formatEmulatorHelp(plugins: readonly LexiconPlugin[]): s
43
53
  * tooling at it. Consumed by behold `serve --local`.
44
54
  */
45
55
  export declare function runEmulator(ctx: CommandContext): Promise<number>;
56
+ export {};
46
57
  //# sourceMappingURL=emulator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"emulator.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/emulator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiCD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoB7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxH;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAkC5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqFtE"}
1
+ {"version":3,"file":"emulator.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/emulator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiD,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AACvH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9D,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiCD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoB7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxH;AAED,2EAA2E;AAC3E,KAAK,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC;AAErF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC,EACpE,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC,CA+BpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAwC5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8FtE"}
@@ -1,6 +1,6 @@
1
1
  import { exec, execFile } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
- import { emulatorLifecycle, emulatorsOf } from "../../op/index.js";
3
+ import { checkSettings, emulatorLifecycle, emulatorsOf } from "../../op/index.js";
4
4
  import { formatError, formatWarning, formatSuccess } from "../format.js";
5
5
  const execAsync = promisify(exec);
6
6
  const execFileAsync = promisify(execFile);
@@ -90,13 +90,58 @@ export function parsePortMappings(values, targets) {
90
90
  }
91
91
  return ports;
92
92
  }
93
+ /**
94
+ * `--image`, `--network`, `--setting` and `--loopback` as each selected
95
+ * emulator's `up` options (#3952). `--image` needs exactly one emulator
96
+ * selected, the way a bare `--port` does. A `--setting` goes to each emulator
97
+ * whose settings prefix its key starts with, and a key that no selected
98
+ * emulator takes is refused rather than passed to a container as plain env.
99
+ */
100
+ export function parseUpOptions(args, targets) {
101
+ if (args.image !== undefined && targets.length !== 1) {
102
+ throw new Error(`--image ${args.image} is ambiguous with ${targets.length} emulators selected; pick one with --lexicon <name>`);
103
+ }
104
+ const settings = new Map();
105
+ for (const value of args.setting ?? []) {
106
+ const match = /^([^=]+)=(.*)$/s.exec(value);
107
+ if (!match)
108
+ throw new Error(`--setting ${value}: expected <KEY>=<VALUE>, e.g. --setting FLOCI_<NAME>=<value>`);
109
+ const [, key, val] = match;
110
+ const takers = targets.filter((t) => t.spec.settingsPrefix && key.startsWith(t.spec.settingsPrefix));
111
+ if (takers.length === 0) {
112
+ const prefixes = targets.filter((t) => t.spec.settingsPrefix).map((t) => `${t.spec.settingsPrefix}* (${t.spec.name})`);
113
+ throw new Error(`--setting ${key}: no selected emulator takes it; ${prefixes.length ? `the selected ones take ${prefixes.join(", ")}` : "the selected ones take no settings"}`);
114
+ }
115
+ for (const t of takers) {
116
+ const own = { ...settings.get(t), [key]: val };
117
+ checkSettings(t.spec, own);
118
+ settings.set(t, own);
119
+ }
120
+ }
121
+ const out = new Map();
122
+ for (const t of targets) {
123
+ const opts = {};
124
+ if (args.image !== undefined)
125
+ opts.image = args.image;
126
+ if (args.network !== undefined)
127
+ opts.network = args.network;
128
+ if (args.loopback)
129
+ opts.loopback = true;
130
+ const own = settings.get(t);
131
+ if (own)
132
+ opts.settings = own;
133
+ out.set(t, opts);
134
+ }
135
+ return out;
136
+ }
93
137
  /**
94
138
  * `chant emulator --help` (#3673): the subcommands and flags, and for each
95
139
  * configured lexicon's emulator the port, endpoint and sign-in a client uses.
96
140
  */
97
141
  export function formatEmulatorHelp(plugins) {
98
142
  const lines = [
99
- "Usage: chant emulator <up|down|status> [--lexicon <name>] [--port <container-port>=<host-port>] [--json]",
143
+ "Usage: chant emulator <up|down|status> [--lexicon <name>] [--port <container-port>=<host-port>] [--image <ref>]",
144
+ " [--network <name>] [--setting <KEY>=<VALUE>] [--loopback] [--json]",
100
145
  "",
101
146
  "Boot, stop or inspect the local emulators of the project's configured lexicons.",
102
147
  "",
@@ -111,6 +156,11 @@ export function formatEmulatorHelp(plugins) {
111
156
  " --lexicon <name> Act on one lexicon's emulators only.",
112
157
  " --port <c>=<h> up: publish container port <c> on host port <h>; repeatable.",
113
158
  " A bare <h> works when one emulator is selected.",
159
+ " --image <ref> up: start this image instead of the pinned default; one emulator only.",
160
+ " --network <name> up: join each started container to this Docker network.",
161
+ " --setting <K>=<V> up: pass an emulator setting as -e K=V; repeatable. The key must",
162
+ " start with the emulator's prefix (FLOCI_ for aws).",
163
+ " --loopback up: publish ports on 127.0.0.1 only, not on every interface.",
114
164
  " --json Print the machine-readable report on stdout.",
115
165
  "",
116
166
  ];
@@ -168,10 +218,20 @@ export async function runEmulator(ctx) {
168
218
  return 0;
169
219
  }
170
220
  let ports;
221
+ let upOptions;
171
222
  try {
172
223
  if (args.port?.length && action !== "up")
173
224
  throw new Error("--port applies to `chant emulator up` only");
225
+ const upOnly = [
226
+ args.image !== undefined && "--image",
227
+ args.network !== undefined && "--network",
228
+ args.setting?.length && "--setting",
229
+ args.loopback && "--loopback",
230
+ ].filter(Boolean);
231
+ if (upOnly.length && action !== "up")
232
+ throw new Error(`${upOnly.join(", ")} applies to \`chant emulator up\` only`);
174
233
  ports = parsePortMappings(args.port ?? [], targets.map((t) => t.cap));
234
+ upOptions = parseUpOptions(args, targets.map((t) => t.cap));
175
235
  }
176
236
  catch (err) {
177
237
  console.error(formatError({ message: err instanceof Error ? err.message : String(err) }));
@@ -183,7 +243,7 @@ export async function runEmulator(ctx) {
183
243
  if (action === "up") {
184
244
  const port = ports.get(cap.spec.containerPort);
185
245
  try {
186
- const { endpoint } = await lc.up(port === undefined ? {} : { port });
246
+ const { endpoint } = await lc.up({ ...upOptions.get(cap), ...(port === undefined ? {} : { port }) });
187
247
  reports.push({ lexicon, name: cap.spec.name, endpoint, env: cap.env(endpoint) });
188
248
  }
189
249
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/promote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuCH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA6OlD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C/E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BhF;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BhF"}
1
+ {"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/promote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuCH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAmPlD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C/E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BhF;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BhF"}
@@ -18,7 +18,7 @@ import { readFileSync } from "node:fs";
18
18
  import { loadChantConfig } from "../../config.js";
19
19
  import { fetchLifecycle, getHeadCommit, pushLifecycle } from "../../lifecycle/git.js";
20
20
  import { appendReleaseRecord, readReleaseLedger, resolveRunId, } from "../../lifecycle/release-ledger.js";
21
- import { resolveComponentTargets } from "../../components/cli-support.js";
21
+ import { isComponentList, resolveComponentTargets } from "../../components/cli-support.js";
22
22
  import { applyConfigDefaults } from "../../components/config-defaults.js";
23
23
  import { fanOutRegistry } from "../../components/fan-out-support.js";
24
24
  import { renderDriverHuman } from "../../components/driver-output.js";
@@ -76,6 +76,12 @@ async function loadProject(ctx, selector) {
76
76
  console.error(message);
77
77
  return 1;
78
78
  }
79
+ // A comma list is `chant run --components`' selector (#3950), which pulls in
80
+ // dependencies; promote, rollback and redeploy act on the one named component.
81
+ if (isComponentList(selector)) {
82
+ console.error(formatError({ message: `--component takes one component name, not a list ("${selector}")` }));
83
+ return 1;
84
+ }
79
85
  const targets = await resolveComponentTargets(projectPath, selector, args.sandbox, paramsResolution.provenance);
80
86
  if (!targets.success) {
81
87
  console.error(formatError({ message: targets.error ?? "Could not discover components" }));
@@ -1 +1 @@
1
- {"version":3,"file":"run-wave.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run-wave.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiD3E"}
1
+ {"version":3,"file":"run-wave.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run-wave.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAkD3E"}
@@ -29,16 +29,16 @@ export async function runOpWaveCommand(ctx) {
29
29
  if (!specFile || args.wave === undefined) {
30
30
  console.error(formatError({
31
31
  message: "`chant run wave` needs --spec <file> and --wave <k>",
32
- hint: "Run it as a generated Op waves pipeline does: chant run wave --spec <file> --wave <k> [--decide | --share <i>]",
32
+ hint: "Run it as a generated Op waves pipeline does: chant run wave --spec <file> --wave <k> [--decide | --share <i> | --group <name> [--share <i>]]",
33
33
  }));
34
34
  return 1;
35
35
  }
36
- if (args.decide && args.share !== undefined) {
37
- console.error(formatError({ message: "--decide and --share are two different jobs; pass one" }));
36
+ if (args.decide && (args.share !== undefined || args.group !== undefined)) {
37
+ console.error(formatError({ message: `--decide and --${args.share !== undefined ? "share" : "group"} are two different jobs; pass one` }));
38
38
  return 1;
39
39
  }
40
40
  let spec;
41
- const job = args.share !== undefined ? { share: args.share } : {};
41
+ const job = { ...(args.share !== undefined ? { share: args.share } : {}), ...(args.group !== undefined ? { group: args.group } : {}) };
42
42
  try {
43
43
  const path = resolve(specFile);
44
44
  spec = parseOpWavesSpec(readFileSync(path, "utf-8"), `--spec ${specFile}`);
@@ -48,6 +48,7 @@ export async function runOpWaveCommand(ctx) {
48
48
  wave: args.wave,
49
49
  ...(args.decide ? { decide: true } : {}),
50
50
  ...(args.share !== undefined ? { share: args.share } : {}),
51
+ ...(args.group !== undefined ? { group: args.group } : {}),
51
52
  ...(args.base ? { base: args.base } : {}),
52
53
  });
53
54
  if (args.json)
@@ -85,9 +85,10 @@ export declare function runOp(ctx: CommandContext): Promise<number>;
85
85
  */
86
86
  export declare function recordAutoReleasesForRun(results: DriverComponentResult[], env: string, runId: string, disabled: boolean): Promise<ReleaseRecord[]>;
87
87
  /**
88
- * `chant run --components <name|all> [--env <env>]` (#585) — the interpret
89
- * driver's CLI entrypoint, and since #2116 the only component run path there
90
- * is. `args.path` is the component name (or `all`), matching `chant run
88
+ * `chant run --components <name|all|a,b,c> [--env <env>]` (#585) — the
89
+ * interpret driver's CLI entrypoint, and since #2116 the only component run
90
+ * path there is. `args.path` is the component name (or `all`, or a comma list
91
+ * that also runs what the named components depend on, #3950), matching `chant run
91
92
  * <name>`'s Op-dispatch convention exactly (`args.path` is the Op name there
92
93
  * too) rather than a project directory — components are always discovered from
93
94
  * the current working directory, the same way Op discovery (`discoverOps()`)
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAkD,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAU1G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAWlD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AA+BjC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GAAG,OAAO,CAMjF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAChC,eAAe,EAAE,OAAO,GAAG,SAAS,EACpC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GACzC,MAAM,CAQR;AAuLD,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpE;AAuED,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAetE;AA8BD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAenE;AA2CD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6CvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAQvE;AAID,iGAAiG;AACjG,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBtE;AAsMD,wBAAsB,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BhE;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,qBAAqB,EAAE,EAChC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,aAAa,EAAE,CAAC,CA0C1B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8I1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAgLzE;AA0DD,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAMjE"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAkD,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAU1G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAYlD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AA+BjC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GAAG,OAAO,CAMjF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAChC,eAAe,EAAE,OAAO,GAAG,SAAS,EACpC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GACzC,MAAM,CAQR;AAuLD,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpE;AAuED,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAetE;AA8BD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAenE;AA2CD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6CvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAQvE;AAID,iGAAiG;AACjG,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBtE;AAsMD,wBAAsB,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BhE;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,qBAAqB,EAAE,EAChC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,aAAa,EAAE,CAAC,CA0C1B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAmMD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AA4OD,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAMjE"}
@@ -20,10 +20,12 @@ import { acquireStewardTurn, STEWARD_TURN_WAIT_MS } from "../../op/operator.js";
20
20
  import { releaseLease, currentHolderId } from "../../lifecycle/lease.js";
21
21
  import { StaleLockError } from "../../lifecycle/git.js";
22
22
  import { LIFECYCLE_LOCAL_NOTE, isLifecycleLocalNote } from "../../lifecycle/local-note.js";
23
+ import { ledgerRecordingOff, noRecordEndNote, noRecordStartNote, resetNoRecordLedger, NO_RECORD_ENV } from "../../lifecycle/no-record.js";
23
24
  import { renderDriverHuman, renderDriverJson } from "../../components/driver-output.js";
24
25
  import { ndjsonProgressSink } from "../../components/run-progress.js";
25
26
  import { maybeRecordAutoRelease } from "../../components/auto-release.js";
26
27
  import { maybePersistBuildManifest } from "../../components/manifest-persistence.js";
28
+ import { isComponentList } from "../../components/cli-support.js";
27
29
  import { runOpGenerate } from "./run-generate.js";
28
30
  /**
29
31
  * The exit code a run that stopped at an unapproved gate uses (#2119).
@@ -768,11 +770,12 @@ export async function recordAutoReleasesForRun(results, env, runId, disabled) {
768
770
  }
769
771
  return recorded;
770
772
  }
771
- // ── chant run --components <name|all> ────────────────────────────────────────
773
+ // ── chant run --components <name|all|a,b,c> ──────────────────────────────────
772
774
  /**
773
- * `chant run --components <name|all> [--env <env>]` (#585) — the interpret
774
- * driver's CLI entrypoint, and since #2116 the only component run path there
775
- * is. `args.path` is the component name (or `all`), matching `chant run
775
+ * `chant run --components <name|all|a,b,c> [--env <env>]` (#585) — the
776
+ * interpret driver's CLI entrypoint, and since #2116 the only component run
777
+ * path there is. `args.path` is the component name (or `all`, or a comma list
778
+ * that also runs what the named components depend on, #3950), matching `chant run
776
779
  * <name>`'s Op-dispatch convention exactly (`args.path` is the Op name there
777
780
  * too) rather than a project directory — components are always discovered from
778
781
  * the current working directory, the same way Op discovery (`discoverOps()`)
@@ -803,11 +806,55 @@ export async function recordAutoReleasesForRun(results, env, runId, disabled) {
803
806
  * auto-release check below used to apply itself) and reused for that check,
804
807
  * rather than loaded a second time.
805
808
  */
806
- export async function runOpComponents(ctx) {
809
+ export function runOpComponents(ctx) {
810
+ return withRecordingChoice(ctx, () => runComponentSelection(ctx));
811
+ }
812
+ /**
813
+ * Run `run` with recording off when `--no-record` or `CHANT_NO_RECORD` asks
814
+ * for it (#3955), and say so before it starts and after it ends, whatever
815
+ * the outcome. The flag sets `CHANT_NO_RECORD` for the length of the run, so
816
+ * the ledger seam (`../../lifecycle/git.ts`) and every chant process a step
817
+ * starts see the same choice. A run with recording on is untouched.
818
+ */
819
+ async function withRecordingChoice(ctx, run) {
820
+ const flagged = ctx.args.noRecord === true;
821
+ if (!flagged && !ledgerRecordingOff())
822
+ return run();
823
+ const source = flagged ? "--no-record" : `${NO_RECORD_ENV}=${process.env[NO_RECORD_ENV]}`;
824
+ const prior = process.env[NO_RECORD_ENV];
825
+ if (flagged)
826
+ process.env[NO_RECORD_ENV] = "1";
827
+ resetNoRecordLedger();
828
+ console.error(formatWarning({ message: noRecordStartNote(source) }));
829
+ try {
830
+ return await run();
831
+ }
832
+ finally {
833
+ console.error(formatWarning({ message: noRecordEndNote(source) }));
834
+ resetNoRecordLedger();
835
+ if (flagged) {
836
+ if (prior === undefined)
837
+ delete process.env[NO_RECORD_ENV];
838
+ else
839
+ process.env[NO_RECORD_ENV] = prior;
840
+ }
841
+ }
842
+ }
843
+ /** A run that records nothing stays in this process (#3955): a runtime that runs it elsewhere would record there. */
844
+ function refusesNoRecordOn(runtime) {
845
+ if (!ledgerRecordingOff() || runtime.name === "local")
846
+ return false;
847
+ console.error(formatError({
848
+ message: `--no-record runs on the local runtime; the "${runtime.name}" runtime records the run where it executes it`,
849
+ hint: `Omit --on to run it here without recording, or drop --no-record (and ${NO_RECORD_ENV}).`,
850
+ }));
851
+ return true;
852
+ }
853
+ async function runComponentSelection(ctx) {
807
854
  const selector = ctx.args.path;
808
855
  if (!selector || selector === ".") {
809
856
  console.error(formatError({
810
- message: "Component name is required: chant run --components <name|all>",
857
+ message: "Component name is required: chant run --components <name|all|a,b,c>",
811
858
  hint: "Run `chant list --components` to see available components.",
812
859
  }));
813
860
  return 1;
@@ -830,6 +877,8 @@ export async function runOpComponents(ctx) {
830
877
  const runtime = await resolveOpRuntime(ctx);
831
878
  if (!runtime)
832
879
  return 1;
880
+ if (refusesNoRecordOn(runtime))
881
+ return 1;
833
882
  if (!runtime.runComponents) {
834
883
  console.error(formatError({
835
884
  message: `--components is not supported on the "${runtime.name}" runtime`,
@@ -860,12 +909,23 @@ export async function runOpComponents(ctx) {
860
909
  // `undefined` and every `onProgress?.(...)` call in the driver is a no-op —
861
910
  // behavior is byte-for-byte unchanged from before this flag existed.
862
911
  const onProgress = ctx.args.progressJson ? ndjsonProgressSink() : undefined;
912
+ // A list (#3950) pulls in what its components depend on; say which ones and
913
+ // in what order before the first one runs. stderr, so --json and
914
+ // --progress-json keep stdout to themselves.
915
+ const onPlan = isComponentList(selector)
916
+ ? (plan) => {
917
+ console.error(formatInfo(`run order: ${plan.waves.map((wave) => wave.join(" + ")).join(", then ")}`));
918
+ if (plan.added.length > 0)
919
+ console.error(formatInfo(`added as dependencies: ${plan.added.join(", ")}`));
920
+ }
921
+ : undefined;
863
922
  const result = await runtime.runComponents(projectPath, selector, {
864
923
  env: ctx.args.env,
865
924
  componentOutputs: seededOutputs,
866
925
  onProgress,
867
926
  sandbox: ctx.args.sandbox,
868
927
  buildParams: paramsResolution.provenance,
928
+ ...(onPlan ? { onPlan } : {}),
869
929
  });
870
930
  // Dump the accumulated outputs for a downstream job to seed from. Written
871
931
  // even on failure (partial outputs) so a resumed run still has what completed.
@@ -928,7 +988,8 @@ export async function runOpComponents(ctx) {
928
988
  return gatedExit;
929
989
  }
930
990
  if (result.success && result.run) {
931
- const disabled = resolveAutoReleaseDisabled(config, ctx.args.noReleaseRecord);
991
+ // #3955: a run that records nothing has no release to report either.
992
+ const disabled = resolveAutoReleaseDisabled(config, ctx.args.noReleaseRecord) || ledgerRecordingOff();
932
993
  const recorded = await recordAutoReleasesForRun(result.run.results, env, `local-${Date.now()}`, disabled);
933
994
  // `--digest-file` (#2602): the releases this run recorded, one
934
995
  // `<component>=<digest>` line each, the form `chant components promote
@@ -954,7 +1015,10 @@ export async function runOpComponents(ctx) {
954
1015
  * what they were before the seam existed; a runtime that reports only a state
955
1016
  * gets the terser render instead.
956
1017
  */
957
- export async function runOpOnRuntime(ctx) {
1018
+ export function runOpOnRuntime(ctx) {
1019
+ return withRecordingChoice(ctx, () => runOpOnResolvedRuntime(ctx));
1020
+ }
1021
+ async function runOpOnResolvedRuntime(ctx) {
958
1022
  const opName = ctx.args.path;
959
1023
  if (!opName || opName === ".") {
960
1024
  console.error(formatError({
@@ -993,7 +1057,7 @@ export async function runOpOnRuntime(ctx) {
993
1057
  return 1;
994
1058
  }
995
1059
  const runtime = await resolveOpRuntime(ctx);
996
- if (!runtime) {
1060
+ if (!runtime || refusesNoRecordOn(runtime)) {
997
1061
  await stewardGate?.release?.();
998
1062
  return 1;
999
1063
  }
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAkB,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAC;AAa9E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAgB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;AA+iCzC;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBzE;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,EA2KvC,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAkB,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAC;AAa9E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAgB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;AA4jCzC;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBzE;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,EA2KvC,CAAC"}