@intentius/chant 0.124.44 → 0.124.46

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 (249) hide show
  1. package/dist/capabilities/aws.paths +148 -0
  2. package/dist/capabilities/base-mappings.json +122 -0
  3. package/dist/capabilities/catalog.d.ts +89 -0
  4. package/dist/capabilities/catalog.d.ts.map +1 -0
  5. package/dist/capabilities/catalog.js +204 -0
  6. package/dist/capabilities/language.d.ts +103 -0
  7. package/dist/capabilities/language.d.ts.map +1 -0
  8. package/dist/capabilities/language.js +335 -0
  9. package/dist/capabilities/matcher.d.ts +65 -0
  10. package/dist/capabilities/matcher.d.ts.map +1 -0
  11. package/dist/capabilities/matcher.js +299 -0
  12. package/dist/capabilities/view.d.ts +207 -0
  13. package/dist/capabilities/view.d.ts.map +1 -0
  14. package/dist/capabilities/view.js +484 -0
  15. package/dist/ci-identity.d.ts +183 -12
  16. package/dist/ci-identity.d.ts.map +1 -1
  17. package/dist/ci-identity.js +362 -53
  18. package/dist/cli/commands/lint.d.ts.map +1 -1
  19. package/dist/cli/commands/lint.js +1 -0
  20. package/dist/cli/handlers/build.d.ts.map +1 -1
  21. package/dist/cli/handlers/build.js +17 -1
  22. package/dist/cli/handlers/declared-graph.d.ts +44 -0
  23. package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
  24. package/dist/cli/handlers/declared-graph.js +87 -0
  25. package/dist/cli/handlers/graph.d.ts +25 -0
  26. package/dist/cli/handlers/graph.d.ts.map +1 -1
  27. package/dist/cli/handlers/graph.js +93 -87
  28. package/dist/cli/handlers/pr-env.d.ts +8 -2
  29. package/dist/cli/handlers/pr-env.d.ts.map +1 -1
  30. package/dist/cli/handlers/pr-env.js +127 -225
  31. package/dist/cli/handlers/pr.d.ts +3 -0
  32. package/dist/cli/handlers/pr.d.ts.map +1 -1
  33. package/dist/cli/handlers/pr.js +1 -0
  34. package/dist/cli/handlers/search-count.d.ts +89 -0
  35. package/dist/cli/handlers/search-count.d.ts.map +1 -0
  36. package/dist/cli/handlers/search-count.js +132 -0
  37. package/dist/cli/handlers/search.d.ts +358 -6
  38. package/dist/cli/handlers/search.d.ts.map +1 -1
  39. package/dist/cli/handlers/search.js +1065 -155
  40. package/dist/cli/main.d.ts.map +1 -1
  41. package/dist/cli/main.js +23 -3
  42. package/dist/cli/mcp/server.d.ts.map +1 -1
  43. package/dist/cli/mcp/server.js +3 -0
  44. package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
  45. package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
  46. package/dist/cli/mcp/tools/capabilities.js +27 -0
  47. package/dist/cli/mcp/workspace-tools.d.ts +3 -1
  48. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  49. package/dist/cli/mcp/workspace-tools.js +47 -2
  50. package/dist/cli/parse-args.d.ts.map +1 -1
  51. package/dist/cli/parse-args.js +64 -17
  52. package/dist/cli/registry.d.ts +22 -0
  53. package/dist/cli/registry.d.ts.map +1 -1
  54. package/dist/components/cli-support.d.ts +2 -0
  55. package/dist/components/cli-support.d.ts.map +1 -1
  56. package/dist/components/cli-support.js +4 -2
  57. package/dist/components/fan-out-support.d.ts +3 -0
  58. package/dist/components/fan-out-support.d.ts.map +1 -1
  59. package/dist/components/fan-out-support.js +1 -1
  60. package/dist/components/pr-env-ports.d.ts +29 -0
  61. package/dist/components/pr-env-ports.d.ts.map +1 -0
  62. package/dist/components/pr-env-ports.js +77 -0
  63. package/dist/components/pr-env-run.d.ts +254 -0
  64. package/dist/components/pr-env-run.d.ts.map +1 -0
  65. package/dist/components/pr-env-run.js +376 -0
  66. package/dist/components/pr-environment.d.ts +91 -15
  67. package/dist/components/pr-environment.d.ts.map +1 -1
  68. package/dist/components/pr-environment.js +95 -9
  69. package/dist/components/pr-pipeline.d.ts +10 -1
  70. package/dist/components/pr-pipeline.d.ts.map +1 -1
  71. package/dist/config-environments.d.ts +92 -0
  72. package/dist/config-environments.d.ts.map +1 -0
  73. package/dist/config-environments.js +102 -0
  74. package/dist/config.d.ts +24 -84
  75. package/dist/config.d.ts.map +1 -1
  76. package/dist/config.js +9 -96
  77. package/dist/graph-detail.d.ts.map +1 -1
  78. package/dist/graph-detail.js +15 -3
  79. package/dist/graph-effective.d.ts +33 -2
  80. package/dist/graph-effective.d.ts.map +1 -1
  81. package/dist/graph-effective.js +215 -68
  82. package/dist/graph-ir.d.ts +23 -0
  83. package/dist/graph-ir.d.ts.map +1 -1
  84. package/dist/graph-ir.js +130 -0
  85. package/dist/graph-sub-template.d.ts +11 -0
  86. package/dist/graph-sub-template.d.ts.map +1 -0
  87. package/dist/graph-sub-template.js +19 -0
  88. package/dist/lexicon.d.ts +9 -0
  89. package/dist/lexicon.d.ts.map +1 -1
  90. package/dist/lifecycle/observe.d.ts +28 -0
  91. package/dist/lifecycle/observe.d.ts.map +1 -1
  92. package/dist/lifecycle/observe.js +23 -1
  93. package/dist/lint/rule.d.ts +6 -0
  94. package/dist/lint/rule.d.ts.map +1 -1
  95. package/dist/live-endpoint.d.ts +1 -1
  96. package/dist/live-endpoint.d.ts.map +1 -1
  97. package/dist/live-endpoint.js +1 -1
  98. package/dist/observation.d.ts +48 -1
  99. package/dist/observation.d.ts.map +1 -1
  100. package/dist/observation.js +21 -5
  101. package/dist/op/activities/activity-contracts.d.ts +4 -4
  102. package/dist/op/op-waves.d.ts +17 -0
  103. package/dist/op/op-waves.d.ts.map +1 -1
  104. package/dist/op/op-waves.js +23 -1
  105. package/dist/pr-forge.d.ts +15 -1
  106. package/dist/pr-forge.d.ts.map +1 -1
  107. package/dist/pr-forge.js +28 -16
  108. package/dist/pr-requires.d.ts +5 -1
  109. package/dist/pr-requires.d.ts.map +1 -1
  110. package/dist/wave-runtime.mjs +251 -250
  111. package/dist/workspace/capabilities-contract.d.ts +66 -0
  112. package/dist/workspace/capabilities-contract.d.ts.map +1 -0
  113. package/dist/workspace/capabilities-contract.js +107 -0
  114. package/dist/workspace/capabilities.schema.json +229 -0
  115. package/dist/workspace/ci-cloud-identity.d.ts +3 -1
  116. package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
  117. package/dist/workspace/ci-cloud-identity.js +16 -1
  118. package/dist/workspace/ci-run.d.ts +35 -8
  119. package/dist/workspace/ci-run.d.ts.map +1 -1
  120. package/dist/workspace/ci-run.js +95 -21
  121. package/dist/workspace/ci-secrets.d.ts.map +1 -1
  122. package/dist/workspace/ci-secrets.js +4 -3
  123. package/dist/workspace/compose-graph.d.ts +9 -0
  124. package/dist/workspace/compose-graph.d.ts.map +1 -1
  125. package/dist/workspace/compose-graph.js +3 -1
  126. package/dist/workspace/conformance/index.d.ts +1 -1
  127. package/dist/workspace/conformance/index.d.ts.map +1 -1
  128. package/dist/workspace/conformance/index.js +39 -2
  129. package/dist/workspace/declaration.d.ts +10 -0
  130. package/dist/workspace/declaration.d.ts.map +1 -1
  131. package/dist/workspace/declaration.js +17 -1
  132. package/dist/workspace/declaration.schema.json +36 -1
  133. package/dist/workspace/graph-cache.d.ts +8 -0
  134. package/dist/workspace/graph-cache.d.ts.map +1 -1
  135. package/dist/workspace/graph-cache.js +27 -3
  136. package/dist/workspace/graph-cli.d.ts +39 -2
  137. package/dist/workspace/graph-cli.d.ts.map +1 -1
  138. package/dist/workspace/graph-cli.js +66 -24
  139. package/dist/workspace/graph.schema.json +148 -0
  140. package/dist/workspace/kind-readers.d.ts +3 -0
  141. package/dist/workspace/kind-readers.d.ts.map +1 -1
  142. package/dist/workspace/kind-readers.js +7 -1
  143. package/dist/workspace/member-commands.d.ts +10 -1
  144. package/dist/workspace/member-commands.d.ts.map +1 -1
  145. package/dist/workspace/member-commands.js +17 -1
  146. package/dist/workspace/nested-graph.d.ts +2 -0
  147. package/dist/workspace/nested-graph.d.ts.map +1 -1
  148. package/dist/workspace/nested-graph.js +32 -1
  149. package/dist/workspace/reason-codes.d.ts +10 -0
  150. package/dist/workspace/reason-codes.d.ts.map +1 -1
  151. package/dist/workspace/reason-codes.js +12 -0
  152. package/dist/workspace/search-cli.d.ts +204 -0
  153. package/dist/workspace/search-cli.d.ts.map +1 -0
  154. package/dist/workspace/search-cli.js +466 -0
  155. package/dist/workspace/search-contract.d.ts +56 -0
  156. package/dist/workspace/search-contract.d.ts.map +1 -0
  157. package/dist/workspace/search-contract.js +70 -0
  158. package/dist/workspace/search.schema.json +822 -0
  159. package/package.json +1 -1
  160. package/src/__snapshots__/okf.test.ts.snap +10 -0
  161. package/src/capabilities/aws.paths +148 -0
  162. package/src/capabilities/base-mappings.json +122 -0
  163. package/src/capabilities/catalog.ts +230 -0
  164. package/src/capabilities/language.test.ts +191 -0
  165. package/src/capabilities/language.ts +373 -0
  166. package/src/capabilities/matcher.ts +315 -0
  167. package/src/capabilities/view-compose.test.ts +76 -0
  168. package/src/capabilities/view.ts +631 -0
  169. package/src/ci-identity-targets.test.ts +275 -0
  170. package/src/ci-identity.ts +394 -61
  171. package/src/cli/commands/lint.ts +1 -0
  172. package/src/cli/handlers/build.ts +15 -1
  173. package/src/cli/handlers/declared-graph.ts +99 -0
  174. package/src/cli/handlers/graph.test.ts +94 -3
  175. package/src/cli/handlers/graph.ts +123 -96
  176. package/src/cli/handlers/pr-env.ts +135 -227
  177. package/src/cli/handlers/pr.ts +4 -0
  178. package/src/cli/handlers/search-build-roots.test.ts +144 -0
  179. package/src/cli/handlers/search-count.test.ts +191 -0
  180. package/src/cli/handlers/search-count.ts +165 -0
  181. package/src/cli/handlers/search-json.test.ts +333 -0
  182. package/src/cli/handlers/search-live.test.ts +387 -0
  183. package/src/cli/handlers/search-paths.test.ts +235 -0
  184. package/src/cli/handlers/search.ts +1312 -166
  185. package/src/cli/main.test.ts +28 -3
  186. package/src/cli/main.ts +23 -3
  187. package/src/cli/mcp/server.test.ts +3 -3
  188. package/src/cli/mcp/server.ts +3 -0
  189. package/src/cli/mcp/tools/capabilities.ts +32 -0
  190. package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
  191. package/src/cli/mcp/workspace-tools.ts +47 -2
  192. package/src/cli/parse-args.ts +52 -13
  193. package/src/cli/registry.ts +22 -0
  194. package/src/components/cli-support.ts +6 -1
  195. package/src/components/fan-out-support.ts +4 -1
  196. package/src/components/pr-env-ports.ts +89 -0
  197. package/src/components/pr-env-run-bundle.test.ts +54 -0
  198. package/src/components/pr-env-run.test.ts +290 -0
  199. package/src/components/pr-env-run.ts +563 -0
  200. package/src/components/pr-environment.ts +161 -13
  201. package/src/components/pr-pipeline.ts +10 -1
  202. package/src/config-environments.ts +133 -0
  203. package/src/config.ts +37 -124
  204. package/src/graph-detail.ts +15 -3
  205. package/src/graph-effective.ts +226 -75
  206. package/src/graph-ir.test.ts +163 -0
  207. package/src/graph-ir.ts +147 -0
  208. package/src/graph-sub-template.ts +22 -0
  209. package/src/lexicon.ts +10 -0
  210. package/src/lifecycle/observe.test.ts +27 -1
  211. package/src/lifecycle/observe.ts +43 -1
  212. package/src/lint/rule.ts +6 -0
  213. package/src/live-endpoint.ts +1 -1
  214. package/src/observation.test.ts +25 -0
  215. package/src/observation.ts +69 -5
  216. package/src/op/op-waves.ts +38 -1
  217. package/src/pr-forge-bundle.test.ts +1 -1
  218. package/src/pr-forge.ts +44 -17
  219. package/src/pr-requires.test.ts +43 -6
  220. package/src/pr-requires.ts +5 -1
  221. package/src/workspace/capabilities-contract.test.ts +88 -0
  222. package/src/workspace/capabilities-contract.ts +132 -0
  223. package/src/workspace/capabilities.schema.json +229 -0
  224. package/src/workspace/ci-cloud-identity.test.ts +20 -0
  225. package/src/workspace/ci-cloud-identity.ts +14 -1
  226. package/src/workspace/ci-run.test.ts +74 -1
  227. package/src/workspace/ci-run.ts +122 -29
  228. package/src/workspace/ci-secrets.test.ts +1 -1
  229. package/src/workspace/ci-secrets.ts +4 -3
  230. package/src/workspace/compose-graph.ts +10 -1
  231. package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
  232. package/src/workspace/conformance/index.ts +31 -2
  233. package/src/workspace/declaration.schema.json +36 -1
  234. package/src/workspace/declaration.test.ts +7 -0
  235. package/src/workspace/declaration.ts +24 -2
  236. package/src/workspace/graph-cache.ts +27 -3
  237. package/src/workspace/graph-cli.ts +96 -24
  238. package/src/workspace/graph.schema.json +148 -0
  239. package/src/workspace/kind-readers.e2e.test.ts +28 -0
  240. package/src/workspace/kind-readers.test.ts +1 -1
  241. package/src/workspace/kind-readers.ts +7 -1
  242. package/src/workspace/member-commands.ts +22 -1
  243. package/src/workspace/nested-graph.ts +32 -1
  244. package/src/workspace/reason-codes.test.ts +7 -0
  245. package/src/workspace/reason-codes.ts +12 -0
  246. package/src/workspace/search-cli.e2e.test.ts +305 -0
  247. package/src/workspace/search-cli.ts +591 -0
  248. package/src/workspace/search-contract.ts +95 -0
  249. package/src/workspace/search.schema.json +822 -0
@@ -0,0 +1,87 @@
1
+ import { dirname } from "node:path";
2
+ import { mergeBuildRootEntities } from "../../build.js";
3
+ import { loadChantConfigUpward } from "../../config.js";
4
+ import { applyLexiconGraphEdges } from "../../graph-ir.js";
5
+ import { formatError, formatWarning } from "../format.js";
6
+ import { collectBuildRootContributors, loadPlugins, resolveProjectLexicons } from "../plugins.js";
7
+ /**
8
+ * The pieces of the declared graph that `chant graph` and `chant search` both
9
+ * read (#1626, #4365, #4368). They live here, once, so the two commands answer
10
+ * over the same entity set and the same edges: search drifted from graph once
11
+ * already, answering `(no matches)` over a `terraform.roots` project graph drew
12
+ * in full, because it never ran the build-root contributors.
13
+ */
14
+ /**
15
+ * The build-root contributors this invocation's project configures (#1626):
16
+ * a `terraform.roots` root's blocks, a `k8s.kustomize.roots` root's rendered
17
+ * objects. The same closures `chant build` and the lifecycle handlers hand to
18
+ * `BuildOptions.buildRoots`, bound here for the discover-based paths, which
19
+ * never run `build()` and so never ran the hook.
20
+ *
21
+ * Neither command is `requiresPlugins` (Op/source-graph modes must work
22
+ * without a lexicon), so plugins are loaded here when `ctx.plugins` is empty.
23
+ * Rooted at the config's own directory, like `cli/commands/build.ts`: a
24
+ * relative root resolves against where it was declared, not against a
25
+ * sourceDir-scoped path. A project that fails to load plugins degrades to no
26
+ * contributors with a warning rather than failing modes that never needed
27
+ * plugins at all.
28
+ */
29
+ export async function declaredBuildRootContributors(ctx, projectPath) {
30
+ const { config, configPath } = await loadChantConfigUpward(projectPath).catch(() => ({ config: {}, configPath: undefined }));
31
+ let plugins = ctx.plugins;
32
+ if (plugins.length === 0) {
33
+ try {
34
+ plugins = await loadPlugins(await resolveProjectLexicons(projectPath));
35
+ }
36
+ catch (err) {
37
+ console.error(formatWarning({
38
+ message: `could not load the project's lexicons — build-root entities (terraform and kustomize roots) will be missing from the graph (${err instanceof Error ? err.message : String(err)})`,
39
+ }));
40
+ return [];
41
+ }
42
+ }
43
+ return collectBuildRootContributors(plugins, config, configPath ? dirname(configPath) : projectPath);
44
+ }
45
+ /**
46
+ * Merge build-root contributions into a discovered entity set: the exact
47
+ * merge `build()` performs (one implementation: `mergeBuildRootEntities`,
48
+ * ../../build.ts), with its warnings and errors printed. Returns false when a
49
+ * contributor failed or a name collided; the caller stops, because a graph
50
+ * missing the entities the build would refuse over must not be answered from
51
+ * as if complete.
52
+ */
53
+ export async function mergeDeclaredBuildRoots(entities, contributors) {
54
+ if (contributors.length === 0)
55
+ return true;
56
+ const merged = await mergeBuildRootEntities(entities, contributors);
57
+ for (const w of merged.warnings)
58
+ console.error(formatWarning({ message: w }));
59
+ if (merged.errors.length > 0) {
60
+ for (const message of merged.errors)
61
+ console.error(formatError({ message }));
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ /**
67
+ * Add the edges the lexicons' `graphEdges` hooks resolve (#3910): CI
68
+ * dependencies written as strings (`needs`, `uses:`, `trigger:`, `include:`,
69
+ * `extends`), which the AttrRef walk in `buildGraphIr` cannot see. A hook that
70
+ * throws costs its own edges and a warning, not the graph.
71
+ */
72
+ export function withLexiconEdges(ir, plugins, entities) {
73
+ const reports = [];
74
+ for (const p of plugins) {
75
+ if (!p.graphEdges)
76
+ continue;
77
+ try {
78
+ const report = p.graphEdges(entities);
79
+ if (report)
80
+ reports.push(report);
81
+ }
82
+ catch (err) {
83
+ console.error(formatWarning({ message: `the ${p.name} lexicon's graphEdges failed (${err instanceof Error ? err.message : String(err)}); its edges are left out` }));
84
+ }
85
+ }
86
+ return reports.length === 0 ? ir : applyLexiconGraphEdges(ir, reports);
87
+ }
@@ -1,3 +1,4 @@
1
+ import { type LintResult } from "../commands/lint.js";
1
2
  import type { CommandContext } from "../registry.js";
2
3
  /**
3
4
  * `chant graph` — the Op dependency graph by default; `--stacks` renders the
@@ -16,4 +17,28 @@ import type { CommandContext } from "../registry.js";
16
17
  * is the read the other gets.
17
18
  */
18
19
  export declare function runGraph(ctx: CommandContext): Promise<number>;
20
+ /** One lint finding as `meta.lint` carries it (INTENTIUS/behold#919). */
21
+ export interface GraphLintFinding {
22
+ ruleId: string;
23
+ severity: string;
24
+ message: string;
25
+ /** Relative to the project when inside it, else as lint reported it. */
26
+ file: string;
27
+ line: number;
28
+ column: number;
29
+ /** The entity a post-synth check named, which is the graph node's id. Absent for a source-file rule. */
30
+ entity?: string;
31
+ }
32
+ /**
33
+ * What a `graph.lint: "report"` project's entity graph carries on `meta.lint`:
34
+ * the counts `chant lint` would print and every finding behind them, warnings
35
+ * included. Present on every graph such a project emits, findings or none, so
36
+ * a reader can tell "linted, clean" from "not looked" (no key).
37
+ */
38
+ export interface GraphLintReport {
39
+ errors: number;
40
+ warnings: number;
41
+ findings: GraphLintFinding[];
42
+ }
43
+ export declare function graphLintReport(lint: LintResult, projectPath: string): GraphLintReport;
19
44
  //# sourceMappingURL=graph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/graph.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AA+H9D;;;;;;;;;GASG;AACH;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D"}
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/graph.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAYhE,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AAgE9D;;;;;;;;;GASG;AACH;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D;AAoaD,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAQD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,eAAe,CAoBtF"}
@@ -1,14 +1,14 @@
1
- import { dirname, resolve } from "node:path";
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
2
  import { discoverOps } from "../../op/discover.js";
3
3
  import { discover } from "../../discovery/index.js";
4
- import { partitionByLexicon, computeStackGraph, build, mergeBuildRootEntities } from "../../build.js";
5
- import { applyLexiconGraphEdges, applyLexiconOutputs, buildGraphIr, buildLiveGraphIr, collectUnobserved, overlayGraphs, sourceOverlayGraphs, GRAPH_IR_VERSION } from "../../graph-ir.js";
4
+ import { partitionByLexicon, computeStackGraph, build } from "../../build.js";
5
+ import { applyLexiconOutputs, buildGraphIr, buildLiveGraphIr, collectUnobserved, overlayGraphs, sourceOverlayGraphs, GRAPH_IR_VERSION } from "../../graph-ir.js";
6
6
  import { behaviourOverlay } from "../../behaviour-overlay.js";
7
7
  import { applyBehaviourOverlay, behaviourRequestFromIr } from "../../behaviour-graph.js";
8
8
  import { buildDeclaredPerStack } from "../../graph-declared.js";
9
9
  import { mergeProjectOps } from "../../graph-ops.js";
10
10
  import { reconstructEdges, mergeCatalogs, containmentGroups } from "../../graph-refs.js";
11
- import { observeResources } from "../../lifecycle/observe.js";
11
+ import { carryAnnotations, observeResources } from "../../lifecycle/observe.js";
12
12
  import { withLiveReadSession } from "../../live-read-session.js";
13
13
  import { replaySnapshots, hasSnapshot } from "../../lifecycle/replay.js";
14
14
  import { loadChantConfig, environmentNames, matchesDeclaredEnvironment, loadChantConfigUpward } from "../../config.js";
@@ -21,6 +21,8 @@ import { getLayoutEngine, toLayoutInput } from "../../graph-layout.js";
21
21
  import { lintCommand } from "../commands/lint.js";
22
22
  import { reportUninstalledDependencies } from "../dependencies.js";
23
23
  import { loadPlugins, resolveProjectLexicons, collectBuildRootContributors } from "../plugins.js";
24
+ // One copy for graph and search (#4365): the build-root join and the lexicon edges.
25
+ import { declaredBuildRootContributors as graphBuildRootContributors, mergeDeclaredBuildRoots as mergeGraphBuildRoots, withLexiconEdges, } from "./declared-graph.js";
24
26
  import { isNoLexiconDetected } from "../../detectLexicon.js";
25
27
  import { readFileSync } from "node:fs";
26
28
  import { formatError, formatWarning, formatBold } from "../format.js";
@@ -71,59 +73,6 @@ async function graphBuildParams(ctx, projectPath) {
71
73
  }
72
74
  return resolution.provenance;
73
75
  }
74
- /**
75
- * The build-root contributors this invocation's project configures (#1626) —
76
- * the same closures `chant build` and the lifecycle handlers hand to
77
- * `BuildOptions.buildRoots`, bound here for the graph command's
78
- * discover-based paths, which never run `build()` and so never ran the hook:
79
- * a `k8s.kustomize.roots` estate graphed only its typed source while its
80
- * built (and deployed) output carried the rendered manifests too.
81
- *
82
- * `graph` is not `requiresPlugins` (Op/source-graph modes must work without a
83
- * lexicon), so plugins are loaded here when `ctx.plugins` is empty, mirroring
84
- * `runGraphLive`. Rooted at the config's own directory, like
85
- * `cli/commands/build.ts` — a relative kustomize root resolves against where
86
- * it was declared, not against a sourceDir-scoped graph path. A project that
87
- * fails to load plugins degrades to no contributors with a warning rather
88
- * than failing modes that never needed plugins at all.
89
- */
90
- async function graphBuildRootContributors(ctx, projectPath) {
91
- const { config, configPath } = await loadChantConfigUpward(projectPath).catch(() => ({ config: {}, configPath: undefined }));
92
- let plugins = ctx.plugins;
93
- if (plugins.length === 0) {
94
- try {
95
- plugins = await loadPlugins(await resolveProjectLexicons(projectPath));
96
- }
97
- catch (err) {
98
- console.error(formatWarning({
99
- message: `could not load the project's lexicons — build-root entities (kustomize roots) will be missing from the graph (${err instanceof Error ? err.message : String(err)})`,
100
- }));
101
- return [];
102
- }
103
- }
104
- return collectBuildRootContributors(plugins, config, configPath ? dirname(configPath) : projectPath);
105
- }
106
- /**
107
- * Merge build-root contributions into a discovered entity set — the exact
108
- * merge `build()` performs (one implementation: `mergeBuildRootEntities`,
109
- * ../../build.ts), surfaced in the graph command's error style. Returns false
110
- * when a contributor failed or a name collided; the caller stops, matching
111
- * how the discover-based paths treat discovery errors — a graph missing the
112
- * entities the build would refuse over must not be emitted as if complete.
113
- */
114
- async function mergeGraphBuildRoots(entities, contributors) {
115
- if (contributors.length === 0)
116
- return true;
117
- const merged = await mergeBuildRootEntities(entities, contributors);
118
- for (const w of merged.warnings)
119
- console.error(formatWarning({ message: w }));
120
- if (merged.errors.length > 0) {
121
- for (const message of merged.errors)
122
- console.error(formatError({ message }));
123
- return false;
124
- }
125
- return true;
126
- }
127
76
  /** #1675 — join git-root ops into a discovered entity map; op-discovery
128
77
  * errors are warnings here (the lint gate never saw those files). */
129
78
  async function mergeGraphOps(entities, sourceFiles, projectPath) {
@@ -165,6 +114,15 @@ async function runGraphCommand(ctx) {
165
114
  }));
166
115
  return 1;
167
116
  }
117
+ // The capability view (#4378) is built from the declared entity graph's IR,
118
+ // the read `chant workspace graph --capability-view` asks each member for.
119
+ if (ctx.args.capabilityView && (ctx.args.format !== "ir" || ctx.args.components || ctx.args.live || ctx.args.at)) {
120
+ console.error(formatError({
121
+ message: "--capability-view adds the capability view to the declared graph's IR, so it needs --format ir and takes no --components, --live or --at",
122
+ hint: "chant graph --format ir --detail 3 --capability-view",
123
+ }));
124
+ return 1;
125
+ }
168
126
  // `--at` graphs a recorded observation instead of reading the estate (#1279).
169
127
  // Two different observations with no rule for which wins, so not both.
170
128
  if (ctx.args.at && ctx.args.live) {
@@ -300,6 +258,8 @@ async function runGraphLive(ctx, format) {
300
258
  console.error(formatWarning({ message: endpointResult.notice }));
301
259
  let ir;
302
260
  let observations;
261
+ // Facts about absent entities (#4372), carried onto the overlay's nodes.
262
+ let annotations;
303
263
  // A replay is a graph of what was recorded, so it must not reach the provider
304
264
  // at all — not for observation and not for enrichment. Anything that quietly
305
265
  // called out would make `--at` a live read with an older label on it.
@@ -329,6 +289,7 @@ async function runGraphLive(ctx, format) {
329
289
  ...(args.namespace ? { namespace: args.namespace } : {}),
330
290
  });
331
291
  observations = observeResult.observations;
292
+ annotations = observeResult.annotations;
332
293
  const { errors, warnings, notes = [] } = observeResult;
333
294
  for (const e of errors)
334
295
  console.error(formatWarning({ message: e }));
@@ -443,6 +404,10 @@ async function runGraphLive(ctx, format) {
443
404
  : sourceOverlayGraphs(declaredIr, ir, overlayOpts);
444
405
  }
445
406
  }
407
+ // What a read learned about an entity it found absent (#4372), on the
408
+ // declared node beside the overlay's `_status`. A planned create keeps its
409
+ // pending paint and carries the plan's attributes.
410
+ ir = { ...ir, nodes: carryAnnotations(ir.nodes, annotations) };
446
411
  }
447
412
  // Behaviour overlay (#2377, epic #2355): carry a prediction on the graph.
448
413
  // After the drift overlay so it lands on the final node set beside `_status`,
@@ -544,6 +509,55 @@ function refuseLintGate(lint, projectPath) {
544
509
  message: "Refusing to emit graph: source has lint errors. Run `chant lint` and fix them first.",
545
510
  }));
546
511
  }
512
+ /** The project's `graph.lint`: `"report"` only when it says so (#919). */
513
+ async function graphLintMode(projectPath) {
514
+ const { config } = await loadChantConfigUpward(projectPath).catch(() => ({ config: {} }));
515
+ return config.graph?.lint === "report" ? "report" : "gate";
516
+ }
517
+ export function graphLintReport(lint, projectPath) {
518
+ const rel = (file) => {
519
+ if (!isAbsolute(file))
520
+ return file;
521
+ const r = relative(projectPath, file);
522
+ return r.startsWith("..") ? file : r;
523
+ };
524
+ const findings = (lint.diagnostics ?? []).map((d) => ({
525
+ ruleId: d.ruleId,
526
+ severity: d.severity,
527
+ message: d.message,
528
+ file: rel(d.file),
529
+ line: d.line,
530
+ column: d.column,
531
+ ...(d.entity ? { entity: d.entity } : {}),
532
+ }));
533
+ return {
534
+ errors: findings.filter((f) => f.severity === "error").length,
535
+ warnings: findings.filter((f) => f.severity === "warning").length,
536
+ findings,
537
+ };
538
+ }
539
+ /**
540
+ * The lint gate for the entity graph. Returns false when the graph must not be
541
+ * emitted, having printed why. A `graph.lint: "report"` project passes with
542
+ * lint errors and says so on stderr, unless an error is an uninstalled
543
+ * dependency: then there is no source to read, and it refuses as the gate does.
544
+ */
545
+ function passLintGate(lint, projectPath, mode) {
546
+ if (lint.success)
547
+ return true;
548
+ if (mode === "gate") {
549
+ refuseLintGate(lint, projectPath);
550
+ return false;
551
+ }
552
+ const errors = (lint.diagnostics ?? []).filter((d) => d.severity === "error").map((d) => d.message);
553
+ if (reportUninstalledDependencies(errors, projectPath))
554
+ return false;
555
+ const n = errors.length;
556
+ console.error(formatWarning({
557
+ message: `Emitting the graph with ${n} lint error${n === 1 ? "" : "s"}: graph.lint is "report", so every finding is on the IR's meta.lint. Run \`chant lint\` to see them.`,
558
+ }));
559
+ return true;
560
+ }
547
561
  /**
548
562
  * `chant graph --components --format ir|mermaid|dot|layout` — the component DAG
549
563
  * projected into the renderable IR (nodes = components, `groups.byWave` = the
@@ -673,7 +687,9 @@ async function buildPipelineProjection(projectPath, lexicon, sandbox) {
673
687
  * `--node-sizes` so spacing fits real node footprints, and defaults to the dagre
674
688
  * engine (no native dependency); `--layout-engine graphviz` opts into `dot`.
675
689
  * Lint-gated: the IR represents valid infra, so we refuse to emit for source that
676
- * does not pass lint. Non-zero on discovery errors or a layout-engine failure.
690
+ * does not pass lint, unless the project's config sets `graph.lint: "report"`
691
+ * (#919): then the graph is emitted and the findings ride on `meta.lint`.
692
+ * Non-zero on discovery errors or a layout-engine failure.
677
693
  */
678
694
  /**
679
695
  * Add what the lexicons' `graphMeta` hooks report to `ir.meta` (#2559). A
@@ -696,28 +712,6 @@ function withGraphMeta(ir, plugins, entities) {
696
712
  }
697
713
  return Object.keys(added).length === 0 ? ir : { ...ir, meta: { ...(ir.meta ?? {}), ...added } };
698
714
  }
699
- /**
700
- * Add the edges the lexicons' `graphEdges` hooks resolve (#3910): CI
701
- * dependencies written as strings (`needs`, `uses:`, `trigger:`, `include:`,
702
- * `extends`), which the AttrRef walk in `buildGraphIr` cannot see. A hook that
703
- * throws costs its own edges and a warning, not the graph.
704
- */
705
- function withLexiconEdges(ir, plugins, entities) {
706
- const reports = [];
707
- for (const p of plugins) {
708
- if (!p.graphEdges)
709
- continue;
710
- try {
711
- const report = p.graphEdges(entities);
712
- if (report)
713
- reports.push(report);
714
- }
715
- catch (err) {
716
- console.error(formatWarning({ message: `the ${p.name} lexicon's graphEdges failed (${err instanceof Error ? err.message : String(err)}); its edges are left out` }));
717
- }
718
- }
719
- return reports.length === 0 ? ir : applyLexiconGraphEdges(ir, reports);
720
- }
721
715
  /**
722
716
  * Add the outputs the lexicons' `workspaceOutputs` hooks report (#3931) to
723
717
  * the IR's `exports`: a sql table and each of its columns, which `chant
@@ -821,17 +815,17 @@ async function runGraphView(ctx, format) {
821
815
  const buildParams = await graphBuildParams(ctx, projectPath);
822
816
  if (!buildParams)
823
817
  return 1;
824
- // Gate: only emit for lint-clean source.
818
+ // Gate: only emit for lint-clean source, unless the project reads source it
819
+ // did not author and asks for the findings instead (`graph.lint`, #919).
825
820
  const lint = await lintCommand({
826
821
  path: ctx.args.path,
827
822
  format: "stylish",
828
823
  sandbox: ctx.args.sandbox,
829
824
  buildParams,
830
825
  });
831
- if (!lint.success) {
832
- refuseLintGate(lint, projectPath);
826
+ const lintMode = await graphLintMode(projectPath);
827
+ if (!passLintGate(lint, projectPath, lintMode))
833
828
  return 1;
834
- }
835
829
  const result = await discover(projectPath, { buildParams });
836
830
  if (result.errors.length > 0) {
837
831
  for (const e of result.errors)
@@ -854,10 +848,10 @@ async function runGraphView(ctx, format) {
854
848
  // The declared half of the epic's delta (#2355): this path predicts the
855
849
  // file, the live path predicts the account. Same helper, so the two shapes
856
850
  // reach the engine by one route and stay comparable.
851
+ const plugins = ctx.plugins.length > 0
852
+ ? ctx.plugins
853
+ : await loadPlugins(await projectLexiconsOrNone(projectPath));
857
854
  {
858
- const plugins = ctx.plugins.length > 0
859
- ? ctx.plugins
860
- : await loadPlugins(await projectLexiconsOrNone(projectPath));
861
855
  ir = withLexiconEdges(ir, plugins, result.entities);
862
856
  ir = withLexiconOutputs(ir, plugins, result.entities);
863
857
  const predicted = await predictOntoIr(ir, plugins, ctx.args, {
@@ -894,6 +888,18 @@ async function runGraphView(ctx, format) {
894
888
  console.error(formatWarning({ message: notice }));
895
889
  }
896
890
  }
891
+ // Last, so no lens or detail pass can drop it: the findings are about the
892
+ // whole source read, not about the nodes this view kept.
893
+ if (lintMode === "report")
894
+ ir = { ...ir, meta: { ...ir.meta, lint: graphLintReport(lint, projectPath) } };
895
+ // The view capability rules read (#4378), mapped by this project's own
896
+ // lexicons, so a workspace's rules read each member as its chant maps it.
897
+ if (ctx.args.capabilityView) {
898
+ const { buildView, serializeView } = await import("../../capabilities/view.js");
899
+ const { resolvePacks } = await import("../../capabilities/catalog.js");
900
+ const packs = plugins.map((p) => p.capabilityPack).filter((p) => !!p);
901
+ ir = { ...ir, capabilityView: serializeView(buildView(ir, resolvePacks(packs))) };
902
+ }
897
903
  return emitIr(ir, ctx, format);
898
904
  }
899
905
  /** Emit a built IR in the requested view format — shared by the source
@@ -25,8 +25,14 @@
25
25
  * `down` reads the environment's record on chant/lifecycle, checks it names
26
26
  * this pull request's environment, and tears down what `planTeardown` finds
27
27
  * under the record's marker, after dropping any entry whose marker is not
28
- * exactly that one. No gate holds it: closing the pull request is the
29
- * decision, as is the TTL the base set for `sweep`.
28
+ * exactly that one. The lexicons tear down what they own, and the command
29
+ * `ci.prEnvironment.teardown` names tears down the rest (#4330). No gate
30
+ * holds it: closing the pull request is the decision, as is the TTL the base
31
+ * set for `sweep`.
32
+ *
33
+ * The runs themselves are ../../components/pr-env-run.ts, which a product
34
+ * calls with an adapter of its own (#4330). This file supplies the
35
+ * components adapter and the CLI's ports.
30
36
  */
31
37
  import type { CommandContext } from "../registry.js";
32
38
  /** chant components pr-env <up|down|sweep> */
@@ -1 +1 @@
1
- {"version":3,"file":"pr-env.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/pr-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA0CH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AASlD,8CAA8C;AAC9C,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7E"}
1
+ {"version":3,"file":"pr-env.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/pr-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AA0CH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUlD,8CAA8C;AAC9C,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7E"}