@intentius/chant 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/lint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAW,MAAM,iBAAiB,CAAC;AAiBzE;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAW5D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAmBhC;AAgDD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,qCAAqC;IACrC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAiND;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyI3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAIxD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GACtC,MAAM,IAAI,CAiCZ"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/lint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAW,MAAM,iBAAiB,CAAC;AAkBzE;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAW5D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAmBhC;AAgDD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,qCAAqC;IACrC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAsND;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyI3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAIxD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GACtC,MAAM,IAAI,CAiCZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAiB9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAmLpD"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAiB9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAuLpD"}
@@ -60,6 +60,11 @@ export interface ParsedArgs {
60
60
  /** `chant graph --live --overlay` — classify the provisioned graph against
61
61
  * declared source: managed / foreign / pending (#780). */
62
62
  overlay?: boolean;
63
+ /** `chant graph --live --overlay --overlay-anchor <source|live>` (#821) — which
64
+ * graph is the canvas. `source` (default) keeps the declared edges (the
65
+ * cross-substrate topology) and joins live status per node; `live` keeps the
66
+ * provisioned graph's reconstructed edges (the pre-#821 behaviour). */
67
+ overlayAnchor?: "source" | "live";
63
68
  /** `chant list --components` / `chant graph --components` — surface discovered
64
69
  * `Component` declarations (#560) instead of/alongside lexicon resources. */
65
70
  components?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,7 @@
21
21
  */
22
22
  import { type SurfaceDelta, type ChangeSeverity, type SurfaceSnapshot } from "./surface-snapshot.js";
23
23
  import { type RegenOptions, type RegenResult } from "./lexicon-regen.js";
24
- export type RollingLexicon = "aws" | "azure" | "github";
24
+ export type RollingLexicon = "aws" | "azure" | "github" | "fly";
25
25
  /**
26
26
  * An API-version change for one Azure ARM provider.
27
27
  * Only populated for the azure lexicon.
@@ -1 +1 @@
1
- {"version":3,"file":"rolling-upgrade.d.ts","sourceRoot":"","sources":["../../src/codegen/rolling-upgrade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAmC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAIvG,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,EAAE,cAAc,CAAC;IACzB,gCAAgC;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;IACtB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAClC,0EAA0E;IAC1E,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,wEAAwE;IACxE,aAAa,EAAE,eAAe,GAAG,IAAI,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACzD;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAoC/B;AA6BD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,eAAe,GACrB,qBAAqB,EAAE,CA6BzB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,qBAAqB,EAAE,CAmBzB;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,eAAe,GACrB,YAAY,CAEd;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG;IAClD,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAIA"}
1
+ {"version":3,"file":"rolling-upgrade.d.ts","sourceRoot":"","sources":["../../src/codegen/rolling-upgrade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAmC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAIvG,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,EAAE,cAAc,CAAC;IACzB,gCAAgC;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;IACtB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAClC,0EAA0E;IAC1E,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,wEAAwE;IACxE,aAAa,EAAE,eAAe,GAAG,IAAI,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACzD;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAoC/B;AA+BD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,eAAe,GACrB,qBAAqB,EAAE,CA6BzB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,qBAAqB,EAAE,CAmBzB;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,eAAe,GACrB,YAAY,CAEd;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG;IAClD,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAIA"}
@@ -1,7 +1,16 @@
1
+ /**
2
+ * Marker chant writes at the top of files it generates (worker/workflow/activities
3
+ * bootstrap for Temporal Ops, etc.). Discovery must not treat these as authored
4
+ * infra source: they hold no Declarables, they self-execute on import (the worker
5
+ * bootstrap calls `run()`), and they use runtime patterns the authored-source lint
6
+ * rules forbid (dynamic `process.env[...]` access, spreads). Skipping them keeps
7
+ * `chant lint`/`build` from importing or linting the tool's own output.
8
+ */
9
+ export declare const GENERATED_MARKER = "Generated by chant \u2014 do not edit directly";
1
10
  /**
2
11
  * Recursively find all TypeScript infrastructure files in a directory
3
12
  * @param path - The directory path to search
4
- * @returns Array of file paths to .ts files (excluding test files)
13
+ * @returns Array of file paths to .ts files (excluding test files and chant-generated files)
5
14
  */
6
15
  export declare function findInfraFiles(path: string): Promise<string[]>;
7
16
  //# sourceMappingURL=files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/discovery/files.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmDpE"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/discovery/files.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,mDAA8C,CAAC;AAgB5E;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoDpE"}
@@ -137,4 +137,22 @@ export declare function buildLiveGraphIr(observations: LiveObservation[]): Graph
137
137
  * no live edges). Sorted; the live groups pass through unchanged.
138
138
  */
139
139
  export declare function overlayGraphs(live: GraphIR, declared: GraphIR): GraphIR;
140
+ /**
141
+ * Source-anchored overlay (#821) — the inverse of {@link overlayGraphs}. The
142
+ * **declared** graph is the canvas, so its edges are kept: cross-substrate edges
143
+ * (an ECS service wired to a k8s workload) are a source-graph property, since live
144
+ * reconstruction is per-substrate (identifier value-match) and never crosses
145
+ * providers. Use this when the overlay must keep the mixed topology; use
146
+ * `overlayGraphs` when the provisioned graph itself is the subject.
147
+ *
148
+ * Each declared node is classified against live observation and tagged `_status`:
149
+ * - **managed** (declared + provisioned) → `good`, carrying the observed
150
+ * `physicalId` / `ownership` onto the declared node
151
+ * - **pending** (declared, not provisioned) → `accent`
152
+ * **Foreign** resources (provisioned, not declared) are appended and tagged
153
+ * `warn`, together with any live-reconstructed edges that touch them — a declared
154
+ * edge cannot describe an undeclared resource. Declared groups/exports pass
155
+ * through unchanged; nodes and edges are sorted for deterministic output.
156
+ */
157
+ export declare function sourceOverlayGraphs(declared: GraphIR, live: GraphIR): GraphIR;
140
158
  //# sourceMappingURL=graph-ir.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"graph-ir.d.ts","sourceRoot":"","sources":["../src/graph-ir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"graph-ir.d.ts","sourceRoot":"","sources":["../src/graph-ir.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Declarative infrastructure-as-code toolkit — TypeScript on Node.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -13,6 +13,7 @@ import type { RollbackPolicy } from "../../components/capability";
13
13
  import { rule } from "../../lint/declarative";
14
14
  import { watchDirectory, formatTimestamp, formatChangedFiles } from "../watch";
15
15
  import { formatError, formatInfo } from "../format";
16
+ import { GENERATED_MARKER } from "../../discovery/files";
16
17
 
17
18
  // Import config loader
18
19
  import { loadConfig, resolveRulesForFile, parseRuleConfig } from "../../lint/config";
@@ -156,6 +157,11 @@ function getTypeScriptFiles(dir: string): string[] {
156
157
  scan(fullPath);
157
158
  }
158
159
  } else if (entry.endsWith(".ts") && !entry.endsWith(".test.ts") && !entry.endsWith(".spec.ts")) {
160
+ // Skip chant-generated files (worker/workflow/activities bootstrap): they
161
+ // hold no authored source and use runtime patterns the EVL* rules forbid.
162
+ if (readFileSync(fullPath, "utf-8").slice(0, 256).includes(GENERATED_MARKER)) {
163
+ continue;
164
+ }
159
165
  files.push(fullPath);
160
166
  }
161
167
  }
@@ -2,7 +2,7 @@ import { resolve } from "node:path";
2
2
  import { discoverOps } from "../../op/discover";
3
3
  import { discover } from "../../discovery/index";
4
4
  import { partitionByLexicon, computeStackGraph, build } from "../../build";
5
- import { buildGraphIr, buildLiveGraphIr, overlayGraphs, type GraphIR } from "../../graph-ir";
5
+ import { buildGraphIr, buildLiveGraphIr, overlayGraphs, sourceOverlayGraphs, type GraphIR } from "../../graph-ir";
6
6
  import { reconstructEdges, mergeCatalogs, containmentGroups, type ReferenceCatalog, type ContainmentPair } from "../../graph-refs";
7
7
  import { observeResources } from "../../lifecycle/observe";
8
8
  import { loadChantConfig } from "../../config";
@@ -117,12 +117,19 @@ async function runGraphLive(
117
117
  containment = reconstructed.containment;
118
118
  }
119
119
 
120
- // Drift overlay (#780): classify the provisioned graph against declared source
121
- // (managed / foreign / pending) so a renderer colours the drift.
120
+ // Drift overlay: classify each resource against declared source (managed /
121
+ // foreign / pending) so a renderer colours the drift. Two anchorings:
122
+ // - source (default, #821): declared graph is the canvas — keeps its edges,
123
+ // so cross-substrate topology survives; live status joined per node.
124
+ // - live (#780): provisioned graph is the canvas — reconstructed live edges.
122
125
  if (args.overlay) {
123
126
  const declared = await discover(resolve(args.src ?? config.sourceDir ?? "."));
124
127
  if (declared.errors.length === 0) {
125
- ir = overlayGraphs(ir, buildGraphIr(declared.entities, projectPath));
128
+ const declaredIr = buildGraphIr(declared.entities, projectPath);
129
+ ir =
130
+ args.overlayAnchor === "live"
131
+ ? overlayGraphs(ir, declaredIr)
132
+ : sourceOverlayGraphs(declaredIr, ir);
126
133
  } else {
127
134
  console.error(formatWarning({ message: "overlay: source has discovery errors — showing the provisioned graph without the declared overlay" }));
128
135
  }
package/src/cli/main.ts CHANGED
@@ -94,6 +94,10 @@ export function parseArgs(args: string[]): ParsedArgs {
94
94
  result.live = true;
95
95
  } else if (arg === "--overlay") {
96
96
  result.overlay = true;
97
+ } else if (arg === "--overlay-anchor") {
98
+ const v = args[++i];
99
+ if (v !== "source" && v !== "live") throw new Error(`--overlay-anchor must be 'source' or 'live', got '${v}'`);
100
+ result.overlayAnchor = v;
97
101
  } else if (arg === "--from") {
98
102
  // Shared by `migrate --from <lexicon>` and `import --from <env>`; the
99
103
  // two commands never run together, so one field carries both.
@@ -61,6 +61,11 @@ export interface ParsedArgs {
61
61
  /** `chant graph --live --overlay` — classify the provisioned graph against
62
62
  * declared source: managed / foreign / pending (#780). */
63
63
  overlay?: boolean;
64
+ /** `chant graph --live --overlay --overlay-anchor <source|live>` (#821) — which
65
+ * graph is the canvas. `source` (default) keeps the declared edges (the
66
+ * cross-substrate topology) and joins live status per node; `live` keeps the
67
+ * provisioned graph's reconstructed edges (the pre-#821 behaviour). */
68
+ overlayAnchor?: "source" | "live";
64
69
  /** `chant list --components` / `chant graph --components` — surface discovered
65
70
  * `Component` declarations (#560) instead of/alongside lexicon resources. */
66
71
  components?: boolean;
@@ -211,6 +211,65 @@ describe("checkRollingUpgrade — surface changed vs unchanged", () => {
211
211
  });
212
212
  });
213
213
 
214
+ // ── fly lexicon detection (rolls off the live Fly Machines OpenAPI) ────
215
+
216
+ function baselineFly(): SurfaceSnapshot {
217
+ return {
218
+ schemaVersion: 1,
219
+ generatedAt: "2026-01-01T00:00:00.000Z",
220
+ entries: {
221
+ Machine: {
222
+ kind: "resource",
223
+ resourceType: "Fly::Machines::Machine",
224
+ props: ["name:false", "region:false", "config:false"],
225
+ },
226
+ },
227
+ };
228
+ }
229
+
230
+ /** Adds a new resource → additive upgrade. */
231
+ function freshFlyAdditive(): SurfaceSnapshot {
232
+ const s = baselineFly();
233
+ s.entries.Volume = {
234
+ kind: "resource",
235
+ resourceType: "Fly::Machines::Volume",
236
+ props: ["name:false", "size_gb:false"],
237
+ };
238
+ return s;
239
+ }
240
+
241
+ describe("checkRollingUpgrade — fly", () => {
242
+ test("detects fly lexicon by package name", async () => {
243
+ const dir = makeLexiconDir("fly", baselineFly());
244
+ try {
245
+ const res = await checkRollingUpgrade({
246
+ lexiconDir: dir,
247
+ _regenFn: makeRegen(baselineFly(), baselineFly()),
248
+ });
249
+ expect(res.lexicon).toBe("fly");
250
+ expect(res.hasUpgrade).toBe(false);
251
+ expect(res.apiVersionDelta).toEqual([]); // fly has no ARM-style version delta
252
+ } finally {
253
+ rmSync(dir, { recursive: true, force: true });
254
+ }
255
+ });
256
+
257
+ test("a new resource in the Machines surface is an additive upgrade", async () => {
258
+ const dir = makeLexiconDir("fly", baselineFly());
259
+ try {
260
+ const res = await checkRollingUpgrade({
261
+ lexiconDir: dir,
262
+ _regenFn: makeRegen(freshFlyAdditive(), baselineFly()),
263
+ });
264
+ expect(res.lexicon).toBe("fly");
265
+ expect(res.hasUpgrade).toBe(true);
266
+ expect(res.severity).toBe("additive");
267
+ } finally {
268
+ rmSync(dir, { recursive: true, force: true });
269
+ }
270
+ });
271
+ });
272
+
214
273
  // ── azure lexicon detection + apiVersionDelta ─────────────────────────
215
274
 
216
275
  describe("checkRollingUpgrade — azure", () => {
@@ -34,7 +34,7 @@ import { regenLexicon, SNAPSHOT_FILENAME, type RegenOptions, type RegenResult }
34
34
 
35
35
  // ── Public types ──────────────────────────────────────────────────────
36
36
 
37
- export type RollingLexicon = "aws" | "azure" | "github";
37
+ export type RollingLexicon = "aws" | "azure" | "github" | "fly";
38
38
 
39
39
  /**
40
40
  * An API-version change for one Azure ARM provider.
@@ -157,6 +157,7 @@ function detectLexicon(lexiconDir: string): RollingLexicon {
157
157
  const name = pkg.name ?? "";
158
158
  if (name.includes("azure")) return "azure";
159
159
  if (name.includes("github")) return "github";
160
+ if (name.includes("fly")) return "fly";
160
161
  }
161
162
  } catch {
162
163
  // Fall through to directory-based detection
@@ -165,6 +166,7 @@ function detectLexicon(lexiconDir: string): RollingLexicon {
165
166
  const normalized = lexiconDir.replace(/\\/g, "/");
166
167
  if (/\/azure(\/|$)/.test(normalized)) return "azure";
167
168
  if (/\/github(\/|$)/.test(normalized)) return "github";
169
+ if (/\/fly(\/|$)/.test(normalized)) return "fly";
168
170
  return "aws";
169
171
  }
170
172
 
@@ -151,4 +151,21 @@ describe("findInfraFiles", () => {
151
151
  expect(files).toEqual([]);
152
152
  });
153
153
  });
154
+
155
+ test("skips chant-generated files (marker header)", async () => {
156
+ await withTestDir(async (testDir) => {
157
+ await writeFile(join(testDir, "app.ts"), "export const app = {};");
158
+ // A generated worker bootstrap: self-executes on import and uses runtime
159
+ // patterns the EVL* rules forbid — discovery must not pick it up.
160
+ await writeFile(
161
+ join(testDir, "worker.ts"),
162
+ "// Generated by chant — do not edit directly.\nrun();",
163
+ );
164
+
165
+ const files = await findInfraFiles(testDir);
166
+ expect(files).toHaveLength(1);
167
+ expect(files[0]).toMatch(/app\.ts$/);
168
+ expect(files.some((f) => f.endsWith("worker.ts"))).toBe(false);
169
+ });
170
+ });
154
171
  });
@@ -1,11 +1,35 @@
1
- import { readdir, stat } from "node:fs/promises";
1
+ import { readdir, stat, open } from "node:fs/promises";
2
2
  import { existsSync } from "node:fs";
3
3
  import { join, relative } from "node:path";
4
4
 
5
+ /**
6
+ * Marker chant writes at the top of files it generates (worker/workflow/activities
7
+ * bootstrap for Temporal Ops, etc.). Discovery must not treat these as authored
8
+ * infra source: they hold no Declarables, they self-execute on import (the worker
9
+ * bootstrap calls `run()`), and they use runtime patterns the authored-source lint
10
+ * rules forbid (dynamic `process.env[...]` access, spreads). Skipping them keeps
11
+ * `chant lint`/`build` from importing or linting the tool's own output.
12
+ */
13
+ export const GENERATED_MARKER = "Generated by chant — do not edit directly";
14
+
15
+ /** True when a file's header carries the {@link GENERATED_MARKER}. Reads only the head. */
16
+ async function isGeneratedFile(file: string): Promise<boolean> {
17
+ let fh;
18
+ try {
19
+ fh = await open(file, "r");
20
+ const { buffer, bytesRead } = await fh.read({ buffer: Buffer.alloc(256), position: 0 });
21
+ return buffer.toString("utf8", 0, bytesRead).includes(GENERATED_MARKER);
22
+ } catch {
23
+ return false;
24
+ } finally {
25
+ await fh?.close();
26
+ }
27
+ }
28
+
5
29
  /**
6
30
  * Recursively find all TypeScript infrastructure files in a directory
7
31
  * @param path - The directory path to search
8
- * @returns Array of file paths to .ts files (excluding test files)
32
+ * @returns Array of file paths to .ts files (excluding test files and chant-generated files)
9
33
  */
10
34
  export async function findInfraFiles(path: string): Promise<string[]> {
11
35
  const files: string[] = [];
@@ -44,11 +68,12 @@ export async function findInfraFiles(path: string): Promise<string[]> {
44
68
  }
45
69
  await scanDirectory(fullPath);
46
70
  } else if (entry.isFile()) {
47
- // Include only .ts files, exclude test files
71
+ // Include only .ts files, exclude test files and chant-generated files
48
72
  if (
49
73
  entry.name.endsWith(".ts") &&
50
74
  !entry.name.endsWith(".test.ts") &&
51
- !entry.name.endsWith(".spec.ts")
75
+ !entry.name.endsWith(".spec.ts") &&
76
+ !(await isGeneratedFile(fullPath))
52
77
  ) {
53
78
  files.push(fullPath);
54
79
  }
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { buildLiveGraphIr, overlayGraphs, type LiveObservation, type GraphIR } from "./graph-ir";
2
+ import { buildLiveGraphIr, overlayGraphs, sourceOverlayGraphs, type LiveObservation, type GraphIR } from "./graph-ir";
3
3
 
4
4
  // A fixture "snapshot" — what a lexicon's describeResources() returns for a live
5
5
  // environment (managed-only). Two AWS resources; the subnet references the VPC by
@@ -86,3 +86,58 @@ describe("overlayGraphs (#780 drift overlay)", () => {
86
86
  expect(ir.edges).toHaveLength(1);
87
87
  });
88
88
  });
89
+
90
+ describe("sourceOverlayGraphs (#821 source-anchored overlay)", () => {
91
+ const n = (id: string, lexicon = "aws") => ({ id, kind: "K", lexicon, attrs: {} });
92
+ // Declared graph carries a *cross-substrate* edge (a k8s ingress → an aws vpc)
93
+ // that live reconstruction — per-substrate identifier matching — can never make.
94
+ const declared: GraphIR = {
95
+ nodes: [n("web-vpc", "aws"), n("app-ingress", "k8s"), n("planned-db", "aws")],
96
+ edges: [{ from: "app-ingress", to: "web-vpc", kind: "ref", viaAttr: "vpcId" }],
97
+ groups: { byLexicon: { aws: ["planned-db", "web-vpc"], k8s: ["app-ingress"] } },
98
+ };
99
+ const live: GraphIR = {
100
+ nodes: [
101
+ { id: "web-vpc", kind: "AWS::EC2::VPC", lexicon: "aws", attrs: {}, physicalId: "vpc-0a1b", ownership: "owned" },
102
+ n("app-ingress", "k8s"),
103
+ n("rogue-sg", "aws"),
104
+ ],
105
+ edges: [{ from: "rogue-sg", to: "web-vpc", kind: "ref", viaAttr: "sg" }],
106
+ groups: {},
107
+ };
108
+ const statusOf = (ir: GraphIR, id: string) =>
109
+ (ir.nodes.find((x) => x.id === id)!.attrs as { _status?: string })._status;
110
+
111
+ it("classifies managed / pending / foreign via _status", () => {
112
+ const ir = sourceOverlayGraphs(declared, live);
113
+ expect(statusOf(ir, "web-vpc")).toBe("good"); // declared + provisioned
114
+ expect(statusOf(ir, "app-ingress")).toBe("good"); // declared + provisioned
115
+ expect(statusOf(ir, "planned-db")).toBe("accent"); // declared, not provisioned
116
+ expect(statusOf(ir, "rogue-sg")).toBe("warn"); // provisioned, not declared → foreign
117
+ });
118
+
119
+ it("keeps the declared cross-substrate edge (the whole point of source-anchoring)", () => {
120
+ const ir = sourceOverlayGraphs(declared, live);
121
+ expect(ir.edges).toContainEqual({ from: "app-ingress", to: "web-vpc", kind: "ref", viaAttr: "vpcId" });
122
+ });
123
+
124
+ it("carries the observed physicalId/ownership onto a managed declared node", () => {
125
+ const ir = sourceOverlayGraphs(declared, live);
126
+ const vpc = ir.nodes.find((x) => x.id === "web-vpc")!;
127
+ expect(vpc.physicalId).toBe("vpc-0a1b");
128
+ expect(vpc.ownership).toBe("owned");
129
+ });
130
+
131
+ it("appends foreign nodes with their live edges, and keeps declared groups", () => {
132
+ const ir = sourceOverlayGraphs(declared, live);
133
+ expect(ir.nodes.map((x) => x.id)).toContain("rogue-sg");
134
+ expect(ir.edges).toContainEqual({ from: "rogue-sg", to: "web-vpc", kind: "ref", viaAttr: "sg" }); // foreign-touching
135
+ expect(ir.groups.byLexicon).toEqual({ aws: ["planned-db", "web-vpc"], k8s: ["app-ingress"] });
136
+ });
137
+
138
+ it("drops a live edge between two managed nodes — declared edges already cover it", () => {
139
+ const liveDup: GraphIR = { ...live, edges: [{ from: "app-ingress", to: "web-vpc", kind: "ref", viaAttr: "live-label" }] };
140
+ const ir = sourceOverlayGraphs(declared, liveDup);
141
+ expect(ir.edges.filter((e) => e.from === "app-ingress" && e.to === "web-vpc")).toHaveLength(1);
142
+ });
143
+ });
package/src/graph-ir.ts CHANGED
@@ -421,3 +421,54 @@ export function overlayGraphs(live: GraphIR, declared: GraphIR): GraphIR {
421
421
 
422
422
  return { ...live, nodes };
423
423
  }
424
+
425
+ /**
426
+ * Source-anchored overlay (#821) — the inverse of {@link overlayGraphs}. The
427
+ * **declared** graph is the canvas, so its edges are kept: cross-substrate edges
428
+ * (an ECS service wired to a k8s workload) are a source-graph property, since live
429
+ * reconstruction is per-substrate (identifier value-match) and never crosses
430
+ * providers. Use this when the overlay must keep the mixed topology; use
431
+ * `overlayGraphs` when the provisioned graph itself is the subject.
432
+ *
433
+ * Each declared node is classified against live observation and tagged `_status`:
434
+ * - **managed** (declared + provisioned) → `good`, carrying the observed
435
+ * `physicalId` / `ownership` onto the declared node
436
+ * - **pending** (declared, not provisioned) → `accent`
437
+ * **Foreign** resources (provisioned, not declared) are appended and tagged
438
+ * `warn`, together with any live-reconstructed edges that touch them — a declared
439
+ * edge cannot describe an undeclared resource. Declared groups/exports pass
440
+ * through unchanged; nodes and edges are sorted for deterministic output.
441
+ */
442
+ export function sourceOverlayGraphs(declared: GraphIR, live: GraphIR): GraphIR {
443
+ const liveById = new Map(live.nodes.map((n) => [n.id, n]));
444
+ const declaredIds = new Set(declared.nodes.map((n) => n.id));
445
+ const foreignIds = new Set(live.nodes.filter((n) => !declaredIds.has(n.id)).map((n) => n.id));
446
+ const tagged = (n: IRNode, status: "good" | "warn" | "accent"): IRNode => ({ ...n, attrs: { ...n.attrs, _status: status } });
447
+
448
+ const nodes: IRNode[] = declared.nodes.map((n) => {
449
+ const obs = liveById.get(n.id);
450
+ if (!obs) return tagged(n, "accent"); // pending — declared, not provisioned
451
+ const merged: IRNode = { ...n }; // managed — carry the observed identity
452
+ if (obs.physicalId) merged.physicalId = obs.physicalId;
453
+ if (obs.ownership) merged.ownership = obs.ownership;
454
+ return tagged(merged, "good");
455
+ });
456
+ for (const n of live.nodes) if (foreignIds.has(n.id)) nodes.push(tagged(n, "warn")); // foreign
457
+ nodes.sort((a, b) => a.id.localeCompare(b.id));
458
+
459
+ // Declared edges are the canvas (the cross-substrate topology). Add only the
460
+ // live edges that touch a foreign node — declared edges already cover every
461
+ // declared relationship, so keeping all live edges would double managed ones.
462
+ const seen = new Set(declared.edges.map(edgeKey));
463
+ const edges = [...declared.edges];
464
+ for (const e of live.edges) {
465
+ if (!(foreignIds.has(e.from) || foreignIds.has(e.to))) continue;
466
+ const k = edgeKey(e);
467
+ if (seen.has(k)) continue;
468
+ seen.add(k);
469
+ edges.push(e);
470
+ }
471
+ edges.sort((a, b) => edgeKey(a).localeCompare(edgeKey(b)));
472
+
473
+ return { ...declared, nodes, edges };
474
+ }
@@ -12,7 +12,7 @@ describe("loadActivities", () => {
12
12
  // Real export names from lexicons/temporal/src/op/activities.
13
13
  expect(activities.has("shellCmd")).toBe(true);
14
14
  expect(activities.has("chantBuild")).toBe(true);
15
- expect(activities.has("kubectlApply")).toBe(true);
15
+ expect(activities.has("waitForStack")).toBe(true);
16
16
  expect(activities.has("lifecycleDiff")).toBe(true);
17
17
  expect(typeof activities.get("shellCmd")).toBe("function");
18
18
  });
@@ -49,12 +49,12 @@ describe("resolveActivity", () => {
49
49
 
50
50
  describe("loadActivities — heartbeat-shim safety", () => {
51
51
  test("the activity library loads without @temporalio/activity installed", async () => {
52
- // kubectlApply/helmInstall/waitForStack/gitlabPipeline heartbeat via the
53
- // lazy shim; if the shim statically required the SDK, this import would
54
- // throw (the SDK is not installed in this environment).
52
+ // waitForStack (and the relocated kubectlApply/helmInstall/gitlabPipeline)
53
+ // heartbeat via the lazy shim; if the shim statically required the SDK, this
54
+ // import would throw (the SDK is not installed in this environment).
55
55
  const activities = await loadActivities();
56
- expect(activities.has("kubectlApply")).toBe(true);
57
56
  expect(activities.has("waitForStack")).toBe(true);
57
+ expect(activities.has("chantBuild")).toBe(true);
58
58
  });
59
59
  });
60
60
 
@@ -62,10 +62,12 @@ describe("loadActivities — heartbeat-shim safety", () => {
62
62
  // lexicons (#706); the loader pulls them in per the project's configured
63
63
  // `lexicons`. Proves the relocation resolves end-to-end.
64
64
  describe("loadActivities — multi-lexicon (#706)", () => {
65
- test("base (no lexicons): temporal activities present, cloud appliers absent", async () => {
65
+ test("base (no lexicons): temporal activities present, product activities absent", async () => {
66
66
  const a = await loadActivities();
67
- expect(a.has("kubectlApply")).toBe(true); // temporal base
68
- expect(a.has("k3dUp")).toBe(true); // cloud-agnostic, stays in temporal
67
+ expect(a.has("waitForStack")).toBe(true); // temporal base
68
+ expect(a.has("shellCmd")).toBe(true); // temporal base
69
+ expect(a.has("kubectlApply")).toBe(false); // relocated to k8s (#809)
70
+ expect(a.has("k3dUp")).toBe(false); // relocated to k8s (#809)
69
71
  expect(a.has("gcpApply")).toBe(false); // relocated to gcp
70
72
  expect(a.has("flociUp")).toBe(false); // relocated to aws
71
73
  expect(a.has("azGroupEnsure")).toBe(false); // relocated to azure
@@ -74,7 +76,16 @@ describe("loadActivities — multi-lexicon (#706)", () => {
74
76
  test("gcp lexicon contributes the GCP applier", async () => {
75
77
  const a = await loadActivities(["gcp"]);
76
78
  expect(a.has("gcpApply")).toBe(true);
77
- expect(a.has("kubectlApply")).toBe(true); // base still loaded alongside
79
+ expect(a.has("waitForStack")).toBe(true); // base still loaded alongside
80
+ });
81
+
82
+ test("k8s lexicon contributes kubectl / k3d / argo activities (#809)", async () => {
83
+ const a = await loadActivities(["k8s"]);
84
+ expect(a.has("kubectlApply")).toBe(true);
85
+ expect(a.has("k3dUp")).toBe(true);
86
+ expect(a.has("k3dDown")).toBe(true);
87
+ expect(a.has("waitForArgoSync")).toBe(true);
88
+ expect(a.has("waitForStack")).toBe(true); // base still loaded alongside
78
89
  });
79
90
 
80
91
  test("aws lexicon contributes the Floci lifecycle", async () => {
@@ -92,6 +103,6 @@ describe("loadActivities — multi-lexicon (#706)", () => {
92
103
 
93
104
  test("unknown lexicon is skipped without throwing", async () => {
94
105
  const a = await loadActivities(["definitely-not-a-lexicon"]);
95
- expect(a.has("kubectlApply")).toBe(true);
106
+ expect(a.has("waitForStack")).toBe(true); // temporal base still loads
96
107
  });
97
108
  });