@intentius/chant 0.18.20 → 0.18.21

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":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAoBlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAwE/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C3E;AA6TD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6G3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9E;AAkBD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C/E"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgDlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqF/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyF3E;AA4TD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6G3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9E;AAkBD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C/E"}
@@ -70,7 +70,7 @@ export interface ComponentGraphResult {
70
70
  }
71
71
  /** Compute the components' dependency graph under `path`, for `chant graph --components`. */
72
72
  export declare function computeComponentGraph(path: string): Promise<ComponentGraphResult>;
73
- /** A generate-mode target lexicon name — any lexicon whose plugin implements `generateComponentPipeline` (currently gitlab; github/forgejo as they add it). */
73
+ /** A generate-mode target lexicon name — any lexicon whose plugin implements `generateComponentPipeline` (gitlab, github, and forgejo today). */
74
74
  export type GenerateLexicon = string;
75
75
  /** Result of `chant build --components --generate <lexicon>`. */
76
76
  export interface GenerateComponentsResult {
@@ -1 +1 @@
1
- {"version":3,"file":"cli-support.d.ts","sourceRoot":"","sources":["../../src/components/cli-support.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-support.d.ts","sourceRoot":"","sources":["../../src/components/cli-support.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -94,6 +94,22 @@ export interface ChantConfig {
94
94
  * Defaults to "." (the project root). The `--src` flag overrides it.
95
95
  */
96
96
  sourceDir?: string;
97
+ /**
98
+ * Multi-stack projects: the independently-deployed CloudFormation stacks this
99
+ * project comprises, each built from its own source directory. When set,
100
+ * lifecycle commands (`snapshot`/`diff`) iterate every stack — building each
101
+ * `src` scoped (so its logical ids match what that stack actually deploys) and
102
+ * observing it against its own live stack `name` — instead of assuming one
103
+ * stack per environment. Leave unset for a single-stack project (the default:
104
+ * one build from `sourceDir`/root, observed as the stack named after the
105
+ * environment). See {@link resolveStackTargets}.
106
+ */
107
+ stacks?: Array<{
108
+ /** The deployed CloudFormation stack name (what `cfn-deploy` targets). */
109
+ name: string;
110
+ /** Source directory to build for this stack, relative to the project root. */
111
+ src: string;
112
+ }>;
97
113
  /** Lint configuration (rules, extends, overrides, plugins) */
98
114
  lint?: LintConfig;
99
115
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsCd,CAAC;AAEjB;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,0EAA0E;QAC1E,IAAI,EAAE,MAAM,CAAC;QACb,8EAA8E;QAC9E,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;IAEH,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QACV,2EAA2E;QAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,qCAAqC;QACrC,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,kEAAkE;QAClE,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE;QACR,8KAA8K;QAC9K,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IAEF;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE;QACL,+OAA+O;QAC/O,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,4cAA4c;QAC5c,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEF;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE;QACR,wJAAwJ;QACxJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,sRAAsR;QACtR,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,2IAA2I;QAC3I,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,0IAA0I;QAC1I,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,4UAA4U;QAC5U,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IAEF;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE;QACX,kEAAkE;QAClE,YAAY,CAAC,EAAE,QAAQ,CAAC;QACxB,2EAA2E;QAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,gEAAgE;QAChE,YAAY,CAAC,EAAE,QAAQ,CAAC;QACxB,wEAAwE;QACxE,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,0FAA0F;QAC1F,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,+EAA+E;QAC/E,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QAChD,yKAAyK;QACzK,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;QAC5B,kHAAkH;QAClH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,MAAM,EAAE,WAAW,CAAC;IAEpB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAgB,CAAC;AAEpD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB1E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,GAAG,SAAS,CAIvF;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAG1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,UAAU,CAE1F;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,uBAAuB;IACtC,gJAAgJ;IAChJ,OAAO,EAAE,OAAO,CAAC;IACjB,qIAAqI;IACrI,GAAG,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,6RAA6R;IAC7R,sBAAsB,EAAE;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,uBAAuB,CAanF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAW1E"}
@@ -6,12 +6,28 @@ import { type Declarable } from "../declarable.js";
6
6
  * LexiconOutput exports are also collected so that build() can
7
7
  * extract them and pass them to the serializer.
8
8
  *
9
+ * A bare entity name must be unique *within a single stack directory*, not
10
+ * across the whole project. A multi-stack project (independently-deployed
11
+ * sibling stacks under one root — e.g. `src/loom-backend/`, `src/loom-agents/`)
12
+ * legitimately reuses conventional cross-stack `Parameter` names like
13
+ * `pArtifactBucket`/`pImageUri` across siblings, because each directory is its
14
+ * own CloudFormation template where that name is the real, deployed logical id.
15
+ * When the same bare name is declared (as distinct objects) in two different
16
+ * directories, each is disambiguated by a stack prefix derived from its
17
+ * directory ({@link stackPrefix}) rather than throwing — so an unscoped
18
+ * whole-project build / `chant lifecycle snapshot|diff` no longer collides
19
+ * (#932). A per-stack scoped build (`chant build <dir>`) has a single directory
20
+ * relative to its root, so nothing is prefixed and the deployed logical ids are
21
+ * unchanged. A genuine *same-directory* duplicate is still an error.
22
+ *
9
23
  * @param modules - Array of module records with their exports
24
+ * @param buildRoot - The build root the discovery ran against; stack prefixes
25
+ * are derived relative to it so keys stay portable across machines.
10
26
  * @returns Map of export name to Declarable entity
11
- * @throws {DiscoveryError} with type "resolution" if duplicate export names are found
27
+ * @throws {DiscoveryError} with type "resolution" if a name is duplicated within one directory
12
28
  */
13
29
  export declare function collectEntities(modules: Array<{
14
30
  file: string;
15
31
  exports: Record<string, unknown>;
16
- }>): Map<string, Declarable>;
32
+ }>, buildRoot?: string): Map<string, Declarable>;
17
33
  //# sourceMappingURL=collect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/discovery/collect.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAkB9D;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACjE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAqEzB"}
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/discovery/collect.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAkG9D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,EAClE,SAAS,CAAC,EAAE,MAAM,GACjB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAiEzB"}
package/dist/lexicon.d.ts CHANGED
@@ -329,6 +329,13 @@ export interface LexiconPlugin {
329
329
  entityType: string;
330
330
  props: Record<string, unknown>;
331
331
  }>;
332
+ /**
333
+ * The deployed stack name to observe, for a multi-stack project where the
334
+ * stack is not named after the environment (see `stacks` in {@link
335
+ * ChantConfig}). When omitted, an implementation keeps its single-stack
336
+ * convention (AWS: the stack named after `environment`).
337
+ */
338
+ stack?: string;
332
339
  /**
333
340
  * Restrict the result to chant-owned resources (those carrying the
334
341
  * ownership marker, #119). Where a lexicon has no durable marker channel,
@@ -378,6 +385,9 @@ export interface LexiconPlugin {
378
385
  entityType: string;
379
386
  props: Record<string, unknown>;
380
387
  }>;
388
+ /** The deployed stack to scope enumeration to, for a multi-stack project
389
+ * (see `stacks` in {@link ChantConfig}). Omitted for single-stack projects. */
390
+ stack?: string;
381
391
  }): Promise<Record<string, ArtifactMetadata>>;
382
392
  /**
383
393
  * Export full-fidelity import IR from a live API — the cloud→code primitive
@@ -1 +1 @@
1
- {"version":3,"file":"lexicon.d.ts","sourceRoot":"","sources":["../src/lexicon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lexicon.d.ts","sourceRoot":"","sources":["../src/lexicon.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,16 @@ export declare function writeBlobToPath(environment: string, filename: string, c
32
32
  export declare function readBlobFromPath(environment: string, filename: string, opts?: {
33
33
  cwd?: string;
34
34
  }): Promise<string | null>;
35
+ /**
36
+ * Storage key for a snapshot on the orphan branch. Single-stack projects key by
37
+ * lexicon (`<env>/<lexicon>.json`, unchanged). A multi-stack project (see
38
+ * `stacks` in ChantConfig, #932) folds the stack in as `<stack>__<lexicon>`
39
+ * (`<env>/<stack>__<lexicon>.json`) so sibling stacks that deploy the same
40
+ * lexicon don't overwrite each other's snapshots. The `__` separator can't
41
+ * collide with a lexicon name (lexicons are single tokens) and round-trips
42
+ * through `readSnapshot`/`readEnvironmentSnapshots` unchanged.
43
+ */
44
+ export declare function snapshotStorageKey(lexicon: string, stack?: string): string;
35
45
  /**
36
46
  * Write a state snapshot JSON to the orphan branch.
37
47
  *
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"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"}
@@ -16,5 +16,6 @@ export interface TakeSnapshotResult {
16
16
  */
17
17
  export declare function takeSnapshot(environment: string, plugins: ObservationLexicon[], buildResult: BuildResult, opts?: {
18
18
  cwd?: string;
19
+ stack?: string;
19
20
  }): Promise<TakeSnapshotResult>;
20
21
  //# sourceMappingURL=snapshot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/lifecycle/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAsC,MAAM,YAAY,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiEjD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,WAAW,EACxB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA+G7B"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/lifecycle/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAsC,MAAM,YAAY,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiEjD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,WAAW,EACxB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC,OAAO,CAAC,kBAAkB,CAAC,CAkH7B"}
@@ -6,6 +6,10 @@ export type { ResourceMetadata, ArtifactMetadata } from "../lexicon.js";
6
6
  export interface LifecycleSnapshot {
7
7
  lexicon: string;
8
8
  environment: string;
9
+ /** Deployed stack name, for a multi-stack project (see `stacks` in
10
+ * ChantConfig). Absent for single-stack projects. Snapshots are stored per
11
+ * `<env>/<stack>/<lexicon>` when set, so sibling stacks don't overwrite. */
12
+ stack?: string;
9
13
  /** Main branch commit this corresponds to */
10
14
  commit: string;
11
15
  /** ISO timestamp when the snapshot was taken */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lifecycle/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC5C,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC7C,qFAAqF;IACrF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/E,iCAAiC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wCAAwC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wCAAwC;IACxC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lifecycle/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB;;gFAE4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC5C,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC7C,qFAAqF;IACrF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/E,iCAAiC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wCAAwC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wCAAwC;IACxC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.18.20",
3
+ "version": "0.18.21",
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",
@@ -19,6 +19,7 @@ vi.mock("../../lifecycle/git", () => ({
19
19
  readSnapshot: (...args: unknown[]) => readSnapshotMock(...args),
20
20
  readEnvironmentSnapshots: (...args: unknown[]) => readEnvironmentSnapshotsMock(...args),
21
21
  listSnapshots: (...args: unknown[]) => listSnapshotsMock(...args),
22
+ snapshotStorageKey: (lexicon: string, stack?: string) => (stack ? `${stack}__${lexicon}` : lexicon),
22
23
  }));
23
24
  vi.mock("../../lifecycle/snapshot", () => ({
24
25
  takeSnapshot: (...args: unknown[]) => takeSnapshotMock(...args),
@@ -167,6 +168,47 @@ describe("runLifecycleDiff --live", () => {
167
168
  expect(builtPath.endsWith(`${sep}infra`)).toBe(true);
168
169
  });
169
170
 
171
+ // #932 — a multi-stack project builds each stack from its own source and
172
+ // observes each against its own live CloudFormation stack (not one stack/env).
173
+ test("multi-stack: config.stacks builds each stack scoped and observes its own stack name", async () => {
174
+ buildMock.mockResolvedValue(makeBuildResult({ aws: ["bucket"] }));
175
+ fetchLifecycleMock.mockResolvedValue(undefined);
176
+ readSnapshotMock.mockResolvedValue(null);
177
+ loadChantConfigMock.mockResolvedValue({ config: { stacks: [
178
+ { name: "loom-backend", src: "src/loom-backend" },
179
+ { name: "loom-agents", src: "src/loom-agents" },
180
+ ] } });
181
+
182
+ const observedStacks: (string | undefined)[] = [];
183
+ const plugins: LexiconPlugin[] = [
184
+ createMockPlugin({
185
+ name: "aws",
186
+ describeResources: async (options: { stack?: string }) => {
187
+ observedStacks.push(options.stack);
188
+ return {};
189
+ },
190
+ }),
191
+ ];
192
+
193
+ const exit = await runLifecycleDiff({
194
+ args: makeArgs({ path: "diff", extraPositional: "prod", live: true }),
195
+ plugins,
196
+ serializers: plugins.map((p) => p.serializer),
197
+ });
198
+
199
+ expect(exit).toBe(0);
200
+ // Each stack built from its own source directory.
201
+ const builtPaths = buildMock.mock.calls.map((c) => c[0] as string);
202
+ expect(builtPaths.some((p) => p.endsWith(`${sep}src${sep}loom-backend`))).toBe(true);
203
+ expect(builtPaths.some((p) => p.endsWith(`${sep}src${sep}loom-agents`))).toBe(true);
204
+ // Each observed against its own live stack name.
205
+ expect(observedStacks).toEqual(["loom-backend", "loom-agents"]);
206
+ // Each read its own stack-scoped snapshot key.
207
+ const readKeys = readSnapshotMock.mock.calls.map((c) => c[1]);
208
+ expect(readKeys).toContain("loom-backend__aws");
209
+ expect(readKeys).toContain("loom-agents__aws");
210
+ });
211
+
170
212
  test("warns and skips lexicons without describeResources", async () => {
171
213
  buildMock.mockResolvedValue(makeBuildResult({ k8s: ["pod"] }));
172
214
  fetchLifecycleMock.mockResolvedValue(undefined);
@@ -1,7 +1,7 @@
1
1
  import { resolve } from "node:path";
2
2
  import { build } from "../../build";
3
3
  import { takeSnapshot } from "../../lifecycle/snapshot";
4
- import { readSnapshot, readSnapshotAt, readEnvironmentSnapshots, listSnapshots, fetchLifecycle, StaleLifecycleBranchError } from "../../lifecycle/git";
4
+ import { readSnapshot, readSnapshotAt, readEnvironmentSnapshots, listSnapshots, fetchLifecycle, snapshotStorageKey, StaleLifecycleBranchError } from "../../lifecycle/git";
5
5
  import { computeBuildDigest, diffDigests } from "../../lifecycle/digest";
6
6
  import { diffLive, diffLiveArtifacts, diffSnapshots, type LiveDiffResult, type LiveArtifactDiffResult, type SnapshotDiffResult } from "../../lifecycle/live-diff";
7
7
  import { buildChangeSet, renderChangeSet, gitlabMrReport, type ChangeSet } from "../../lifecycle/change-set";
@@ -29,6 +29,34 @@ function resolveBuildRoot(args: ParsedArgs, config: ChantConfig): string {
29
29
  return resolve(args.src ?? config.sourceDir ?? ".");
30
30
  }
31
31
 
32
+ /** One stack a lifecycle command operates on: its build root and, for a
33
+ * multi-stack project, the deployed CloudFormation stack name it observes
34
+ * against. */
35
+ interface StackTarget {
36
+ /** The deployed stack name to observe (undefined ⇒ single-stack convention:
37
+ * the stack named after the environment). */
38
+ stack?: string;
39
+ /** Build root to synthesize this stack from, scoped so its logical ids match
40
+ * what the stack actually deploys. */
41
+ root: string;
42
+ }
43
+
44
+ /**
45
+ * The stacks a lifecycle command (`snapshot`/`diff`) iterates. A multi-stack
46
+ * project declares them via `stacks` in chant.config (#932) — each built from
47
+ * its own `src` and observed against its own live stack `name`. A single-stack
48
+ * project (no `stacks`) resolves to one target built from `sourceDir`/root and
49
+ * observed as the stack named after the environment (unchanged behavior). An
50
+ * explicit `--src` always wins and forces a single scoped target.
51
+ */
52
+ function resolveStackTargets(args: ParsedArgs, config: ChantConfig): StackTarget[] {
53
+ if (args.src) return [{ root: resolve(args.src) }];
54
+ if (config.stacks && config.stacks.length > 0) {
55
+ return config.stacks.map((s) => ({ stack: s.name, root: resolve(s.src) }));
56
+ }
57
+ return [{ root: resolveBuildRoot(args, config) }];
58
+ }
59
+
32
60
  /**
33
61
  * chant lifecycle snapshot <environment> [lexicon]
34
62
  */
@@ -59,13 +87,6 @@ export async function runLifecycleSnapshot(ctx: CommandContext): Promise<number>
59
87
  : plugins;
60
88
  const targetSerializers = targetPlugins.map((p) => p.serializer);
61
89
 
62
- // Build first to get entity names and build output
63
- const buildResult = await build(resolveBuildRoot(args, config), targetSerializers);
64
- if (buildResult.errors.length > 0) {
65
- console.error(formatError({ message: "Build failed — fix errors before taking a snapshot" }));
66
- return 1;
67
- }
68
-
69
90
  const observingPlugins = targetPlugins.filter((p) => p.describeResources || p.listArtifacts);
70
91
  if (observingPlugins.length === 0) {
71
92
  console.error(formatError({
@@ -75,35 +96,55 @@ export async function runLifecycleSnapshot(ctx: CommandContext): Promise<number>
75
96
  return 1;
76
97
  }
77
98
 
78
- let result;
79
- try {
80
- result = await takeSnapshot(environment, observingPlugins, buildResult);
81
- } catch (err) {
82
- if (err instanceof StaleLifecycleBranchError) {
83
- console.error(formatError({
84
- message: `Another snapshot completed for chant/lifecycle after this run started (env: ${environment}).`,
85
- hint: `Pull and retry: \`git fetch origin ${"chant/lifecycle"}:${"chant/lifecycle"}\` && \`chant lifecycle snapshot ${environment}\`.`,
86
- }));
87
- return 1;
99
+ // One target per stack (single-stack projects: exactly one). Each stack builds
100
+ // from its own scoped root — so its logical ids match what it deploys — and
101
+ // snapshots against its own live stack name (#932).
102
+ const targets = resolveStackTargets(args, config);
103
+ let anySnapshotSaved = false;
104
+ let anyHardError = false;
105
+
106
+ for (const target of targets) {
107
+ const label = target.stack ? `stack "${target.stack}"` : "project";
108
+ const buildResult = await build(target.root, targetSerializers);
109
+ if (buildResult.errors.length > 0) {
110
+ console.error(formatError({ message: `Build failed for ${label} — fix errors before taking a snapshot` }));
111
+ anyHardError = true;
112
+ continue;
88
113
  }
89
- throw err;
90
- }
91
114
 
92
- for (const w of result.warnings) {
93
- console.error(formatWarning({ message: w }));
94
- }
95
- for (const e of result.errors) {
96
- console.error(formatError({ message: e }));
97
- }
115
+ let result;
116
+ try {
117
+ result = await takeSnapshot(environment, observingPlugins, buildResult, { stack: target.stack });
118
+ } catch (err) {
119
+ if (err instanceof StaleLifecycleBranchError) {
120
+ console.error(formatError({
121
+ message: `Another snapshot completed for chant/lifecycle after this run started (env: ${environment}).`,
122
+ hint: `Pull and retry: \`git fetch origin ${"chant/lifecycle"}:${"chant/lifecycle"}\` && \`chant lifecycle snapshot ${environment}\`.`,
123
+ }));
124
+ return 1;
125
+ }
126
+ throw err;
127
+ }
128
+
129
+ for (const w of result.warnings) {
130
+ console.error(formatWarning({ message: w }));
131
+ }
132
+ for (const e of result.errors) {
133
+ console.error(formatError({ message: e }));
134
+ }
98
135
 
99
- if (result.snapshots.length > 0) {
100
- const counts = result.snapshots
101
- .map((s) => `${s.lexicon}(${Object.keys(s.resources).length})`)
102
- .join(" ");
103
- console.error(formatSuccess(`Snapshot saved to chant/lifecycle (${counts})`));
136
+ if (result.snapshots.length > 0) {
137
+ anySnapshotSaved = true;
138
+ const prefix = target.stack ? `${target.stack}: ` : "";
139
+ const counts = result.snapshots
140
+ .map((s) => `${s.lexicon}(${Object.keys(s.resources).length})`)
141
+ .join(" ");
142
+ console.error(formatSuccess(`${prefix}Snapshot saved to chant/lifecycle (${counts})`));
143
+ }
144
+ if (result.errors.length > 0) anyHardError = true;
104
145
  }
105
146
 
106
- return result.errors.length > 0 && result.snapshots.length === 0 ? 1 : 0;
147
+ return anyHardError && !anySnapshotSaved ? 1 : 0;
107
148
  }
108
149
 
109
150
  /**
@@ -209,26 +250,68 @@ export async function runLifecycleDiff(ctx: CommandContext): Promise<number> {
209
250
  ? plugins.filter((p) => p.name === lexiconFilter).map((p) => p.serializer)
210
251
  : serializers;
211
252
 
212
- // Build to get current state (from the configured source root, not necessarily ".")
253
+ // Fetch previous snapshots once (all stacks share the orphan branch).
213
254
  const { config } = await loadChantConfig(resolve("."));
214
- const buildResult = await build(resolveBuildRoot(args, config), targetSerializers);
215
- if (buildResult.errors.length > 0) {
216
- console.error(formatError({ message: "Build failed — fix errors before diffing" }));
217
- return 1;
218
- }
219
-
220
- // Fetch and read previous snapshot
221
255
  await fetchLifecycle();
222
256
 
223
- const lexicons = lexiconFilter
224
- ? [lexiconFilter]
225
- : Array.from(buildResult.manifest.lexicons);
257
+ // One target per stack (single-stack projects: exactly one), each built from
258
+ // its own scoped root and diffed against its own live stack name (#932).
259
+ const targets = resolveStackTargets(args, config);
260
+ const json = !!args.json;
261
+ const perStackJson: Record<string, unknown> = {};
262
+ let combinedLexiconsJson: Record<string, unknown> | undefined;
263
+ let totalDrift = 0;
264
+ let totalChecked = 0;
265
+ let anyBuildError = false;
266
+
267
+ for (const target of targets) {
268
+ const buildResult = await build(target.root, targetSerializers);
269
+ if (buildResult.errors.length > 0) {
270
+ const label = target.stack ? `stack "${target.stack}"` : "project";
271
+ console.error(formatError({ message: `Build failed for ${label} — fix errors before diffing` }));
272
+ anyBuildError = true;
273
+ continue;
274
+ }
275
+
276
+ const lexicons = lexiconFilter
277
+ ? [lexiconFilter]
278
+ : Array.from(buildResult.manifest.lexicons);
279
+
280
+ if (args.live) {
281
+ const r = await runLifecycleDiffLive({ environment, lexicons, plugins, buildResult, json, stack: target.stack });
282
+ totalDrift += r.totalDrift;
283
+ totalChecked += r.totalLexiconsChecked;
284
+ if (json) {
285
+ if (target.stack) perStackJson[target.stack] = r.byLexicon;
286
+ else combinedLexiconsJson = r.byLexicon;
287
+ }
288
+ } else {
289
+ await runLifecycleDiffDigest({ environment, lexicons, buildResult, stack: target.stack });
290
+ }
291
+ }
226
292
 
227
293
  if (args.live) {
228
- return runLifecycleDiffLive({ environment, lexicons, plugins, buildResult, json: !!args.json });
294
+ if (json) {
295
+ // Single-stack keeps the original `{ environment, lexicons }` shape
296
+ // (behold's inspect diff, #852); multi-stack nests under `stacks`.
297
+ console.log(
298
+ JSON.stringify(
299
+ combinedLexiconsJson !== undefined
300
+ ? { environment, lexicons: combinedLexiconsJson }
301
+ : { environment, stacks: perStackJson },
302
+ ),
303
+ );
304
+ } else if (totalChecked === 0) {
305
+ console.error(formatWarning({
306
+ message: "No lexicons implement describeResources or listArtifacts — nothing to diff in --live mode",
307
+ }));
308
+ return 1;
309
+ } else if (totalDrift === 0) {
310
+ console.error(formatSuccess(`No drift detected across ${totalChecked} lexicon(s)`));
311
+ }
229
312
  }
230
313
 
231
- return runLifecycleDiffDigest({ environment, lexicons, buildResult });
314
+ return anyBuildError ? 1 : 0;
232
315
  }
233
316
 
234
317
  interface BetweenDiffArgs {
@@ -300,13 +383,16 @@ interface DigestDiffArgs {
300
383
  environment: string;
301
384
  lexicons: string[];
302
385
  buildResult: BuildResult;
386
+ /** Deployed stack name for a multi-stack project (#932); scopes the snapshot read. */
387
+ stack?: string;
303
388
  }
304
389
 
305
390
  async function runLifecycleDiffDigest(args: DigestDiffArgs): Promise<number> {
306
391
  const currentDigest = computeBuildDigest(args.buildResult);
392
+ if (args.stack) console.log(`\n${formatBold(`■ stack ${args.stack}`)}`);
307
393
 
308
394
  for (const lexicon of args.lexicons) {
309
- const content = await readSnapshot(args.environment, lexicon);
395
+ const content = await readSnapshot(args.environment, snapshotStorageKey(lexicon, args.stack));
310
396
  let previousDigest = undefined;
311
397
  if (content) {
312
398
  const snapshot: LifecycleSnapshot = JSON.parse(content);
@@ -343,17 +429,28 @@ interface LiveDiffArgs {
343
429
  buildResult: BuildResult;
344
430
  /** Emit machine-readable JSON on stdout instead of the human report (#852). */
345
431
  json: boolean;
432
+ /** Deployed stack name for a multi-stack project (#932); scopes the live
433
+ * observation (which CloudFormation stack to query) and the snapshot read. */
434
+ stack?: string;
346
435
  }
347
436
 
348
- async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<number> {
349
- let totalDrift = 0;
350
- let totalLexiconsChecked = 0;
351
- // Collected per-lexicon results, emitted as one JSON object when --json is set
352
- // (parsed by programmatic consumers, e.g. behold's inspect diff — #852).
353
- const byLexicon: Record<
437
+ interface LiveDiffOutcome {
438
+ byLexicon: Record<
354
439
  string,
355
440
  { resources?: LiveDiffResult; observed?: Record<string, ResourceMetadata>; artifacts?: LiveArtifactDiffResult }
356
- > = {};
441
+ >;
442
+ totalDrift: number;
443
+ totalLexiconsChecked: number;
444
+ }
445
+
446
+ /** Diff current build vs live cloud for one stack. Renders the human report
447
+ * inline; returns per-lexicon results so the caller emits the aggregate `--json`
448
+ * once (single-stack keeps the original shape; multi-stack nests under `stacks`). */
449
+ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<LiveDiffOutcome> {
450
+ let totalDrift = 0;
451
+ let totalLexiconsChecked = 0;
452
+ const byLexicon: LiveDiffOutcome["byLexicon"] = {};
453
+ if (!args.json && args.stack) console.log(`\n${formatBold(`■ stack ${args.stack}`)}`);
357
454
 
358
455
  for (const lexiconName of args.lexicons) {
359
456
  const plugin = args.plugins.find((p) => p.name === lexiconName);
@@ -391,7 +488,7 @@ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<number> {
391
488
 
392
489
  // Read previous snapshot once; both flows pull what they need.
393
490
  let prevSnapshot: LifecycleSnapshot | undefined;
394
- const content = await readSnapshot(args.environment, lexiconName);
491
+ const content = await readSnapshot(args.environment, snapshotStorageKey(lexiconName, args.stack));
395
492
  if (content) prevSnapshot = JSON.parse(content);
396
493
 
397
494
  let lexiconChecked = false;
@@ -405,6 +502,7 @@ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<number> {
405
502
  buildOutput,
406
503
  entityNames: Array.from(declared),
407
504
  entities,
505
+ stack: args.stack,
408
506
  });
409
507
  } catch (err) {
410
508
  console.error(formatError({
@@ -427,7 +525,7 @@ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<number> {
427
525
  if (plugin.listArtifacts) {
428
526
  let observedNow: Record<string, ArtifactMetadata>;
429
527
  try {
430
- observedNow = await plugin.listArtifacts({ environment: args.environment, entities });
528
+ observedNow = await plugin.listArtifacts({ environment: args.environment, entities, stack: args.stack });
431
529
  } catch (err) {
432
530
  console.error(formatError({
433
531
  message: `${lexiconName}: listArtifacts failed — ${err instanceof Error ? err.message : String(err)}`,
@@ -445,23 +543,7 @@ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<number> {
445
543
  if (lexiconChecked) totalLexiconsChecked++;
446
544
  }
447
545
 
448
- if (totalLexiconsChecked === 0) {
449
- console.error(formatWarning({
450
- message: "No lexicons implement describeResources or listArtifacts — nothing to diff in --live mode",
451
- }));
452
- return 1;
453
- }
454
-
455
- if (args.json) {
456
- console.log(JSON.stringify({ environment: args.environment, lexicons: byLexicon }));
457
- return 0;
458
- }
459
-
460
- if (totalDrift === 0) {
461
- console.error(formatSuccess(`No drift detected across ${totalLexiconsChecked} lexicon(s)`));
462
- }
463
-
464
- return 0;
546
+ return { byLexicon, totalDrift, totalLexiconsChecked };
465
547
  }
466
548
 
467
549
  function renderLiveDiff(lexiconName: string, environment: string, diff: LiveDiffResult): void {
@@ -160,7 +160,7 @@ export async function computeComponentGraph(path: string): Promise<ComponentGrap
160
160
  }
161
161
  }
162
162
 
163
- /** A generate-mode target lexicon name — any lexicon whose plugin implements `generateComponentPipeline` (currently gitlab; github/forgejo as they add it). */
163
+ /** A generate-mode target lexicon name — any lexicon whose plugin implements `generateComponentPipeline` (gitlab, github, and forgejo today). */
164
164
  export type GenerateLexicon = string;
165
165
 
166
166
  /** Result of `chant build --components --generate <lexicon>`. */
@@ -213,7 +213,7 @@ export async function generateComponentsPipeline(
213
213
  if (!plugin?.generateComponentPipeline) {
214
214
  return {
215
215
  success: false,
216
- error: `Lexicon "${lexicon}" does not support generate mode (no generateComponentPipeline). GitLab is supported today; GitHub/Forgejo as they add it.`,
216
+ error: `Lexicon "${lexicon}" does not support generate mode (no generateComponentPipeline). GitLab, GitHub, and Forgejo are supported today.`,
217
217
  };
218
218
  }
219
219
 
package/src/config.ts CHANGED
@@ -82,6 +82,23 @@ export interface ChantConfig {
82
82
  */
83
83
  sourceDir?: string;
84
84
 
85
+ /**
86
+ * Multi-stack projects: the independently-deployed CloudFormation stacks this
87
+ * project comprises, each built from its own source directory. When set,
88
+ * lifecycle commands (`snapshot`/`diff`) iterate every stack — building each
89
+ * `src` scoped (so its logical ids match what that stack actually deploys) and
90
+ * observing it against its own live stack `name` — instead of assuming one
91
+ * stack per environment. Leave unset for a single-stack project (the default:
92
+ * one build from `sourceDir`/root, observed as the stack named after the
93
+ * environment). See {@link resolveStackTargets}.
94
+ */
95
+ stacks?: Array<{
96
+ /** The deployed CloudFormation stack name (what `cfn-deploy` targets). */
97
+ name: string;
98
+ /** Source directory to build for this stack, relative to the project root. */
99
+ src: string;
100
+ }>;
101
+
85
102
  /** Lint configuration (rules, extends, overrides, plugins) */
86
103
  lint?: LintConfig;
87
104
 
@@ -280,6 +280,97 @@ describe("collectEntities", () => {
280
280
  });
281
281
  });
282
282
 
283
+ // #932 — a multi-stack project (independently-deployed sibling stacks under one
284
+ // root) legitimately reuses conventional cross-stack Parameter names across
285
+ // siblings. The unscoped whole-project build must namespace by directory instead
286
+ // of throwing, while a per-stack scoped build keeps the raw (deployed) names.
287
+ describe("collectEntities — cross-directory namespaces (#932)", () => {
288
+ test("the same bare name in two different directories is disambiguated by a stack prefix, not thrown", () => {
289
+ const agentsBucket = createMockEntity("param");
290
+ const backendBucket = createMockEntity("param");
291
+
292
+ const result = collectEntities(
293
+ [
294
+ { file: "src/loom-agents/params.ts", exports: { pArtifactBucket: agentsBucket } },
295
+ { file: "src/loom-backend/params.ts", exports: { pArtifactBucket: backendBucket } },
296
+ ],
297
+ "src",
298
+ );
299
+
300
+ expect(result.size).toBe(2);
301
+ expect(result.get("LoomAgentspArtifactBucket")).toBe(agentsBucket);
302
+ expect(result.get("LoomBackendpArtifactBucket")).toBe(backendBucket);
303
+ // The raw name is not used when it collides across directories.
304
+ expect(result.has("pArtifactBucket")).toBe(false);
305
+ // Disambiguated keys stay within CloudFormation's logical-id grammar.
306
+ for (const key of result.keys()) expect(key).toMatch(/^[A-Za-z0-9]+$/);
307
+ });
308
+
309
+ test("a genuine same-directory duplicate still throws", async () => {
310
+ const a = createMockEntity("param");
311
+ const b = createMockEntity("param");
312
+
313
+ await expectToThrow(
314
+ () =>
315
+ collectEntities(
316
+ [
317
+ { file: "src/loom-backend/params.ts", exports: { pArtifactBucket: a } },
318
+ { file: "src/loom-backend/more.ts", exports: { pArtifactBucket: b } },
319
+ ],
320
+ "src",
321
+ ),
322
+ DiscoveryError,
323
+ (error) => {
324
+ expect(error.type).toBe("resolution");
325
+ expect(error.message).toBe('Duplicate export name "pArtifactBucket" found');
326
+ },
327
+ );
328
+ });
329
+
330
+ test("the same object re-exported from two directories stays one raw-named entity", () => {
331
+ const shared = createMockEntity("param");
332
+
333
+ const result = collectEntities(
334
+ [
335
+ { file: "src/a/x.ts", exports: { shared } },
336
+ { file: "src/b/y.ts", exports: { shared } },
337
+ ],
338
+ "src",
339
+ );
340
+
341
+ expect(result.size).toBe(1);
342
+ expect(result.get("shared")).toBe(shared);
343
+ });
344
+
345
+ test("non-colliding names in different directories keep their raw names (single-stack subdirs unaffected)", () => {
346
+ const vpc = createMockEntity("resource");
347
+ const app = createMockEntity("resource");
348
+
349
+ const result = collectEntities(
350
+ [
351
+ { file: "src/network/vpc.ts", exports: { vpc } },
352
+ { file: "src/compute/app.ts", exports: { app } },
353
+ ],
354
+ "src",
355
+ );
356
+
357
+ expect(result.size).toBe(2);
358
+ expect(result.get("vpc")).toBe(vpc);
359
+ expect(result.get("app")).toBe(app);
360
+ });
361
+
362
+ test("a scoped per-stack build (buildRoot == the stack dir) keeps raw names — deploy fidelity", () => {
363
+ const bucket = createMockEntity("param");
364
+
365
+ const result = collectEntities(
366
+ [{ file: "src/loom-backend/params.ts", exports: { pArtifactBucket: bucket } }],
367
+ "src/loom-backend",
368
+ );
369
+
370
+ expect(result.get("pArtifactBucket")).toBe(bucket);
371
+ });
372
+ });
373
+
283
374
  describe("collectEntities with composites", () => {
284
375
  beforeEach(() => {
285
376
  CompositeRegistry.clear();
@@ -1,9 +1,9 @@
1
- import { basename } from "node:path";
1
+ import { basename, dirname, relative, resolve } from "node:path";
2
2
  import { isDeclarable, type Declarable } from "../declarable";
3
3
  import { isCompositeInstance, expandComposite } from "../composite";
4
4
  import { isLexiconOutput } from "../lexicon-output";
5
5
  import { DiscoveryError } from "../errors";
6
- import { setProvenance } from "../provenance";
6
+ import { setProvenance, type EntityProvenance } from "../provenance";
7
7
 
8
8
  /**
9
9
  * The entity key for an export. `export default` is per-module — the `Op` pattern
@@ -18,84 +18,177 @@ function exportKey(rawName: string, file: string): string {
18
18
  }
19
19
 
20
20
  /**
21
- * Collects all declarable entities from imported modules.
22
- * CompositeInstance exports are expanded into individual entities
23
- * with `{exportName}_{memberName}` naming.
24
- * LexiconOutput exports are also collected so that build() can
25
- * extract them and pass them to the serializer.
26
- *
27
- * @param modules - Array of module records with their exports
28
- * @returns Map of export name to Declarable entity
29
- * @throws {DiscoveryError} with type "resolution" if duplicate export names are found
21
+ * A stable, CloudFormation-valid prefix identifying the stack directory a file
22
+ * belongs to, relative to the build root. Used to disambiguate an entity name
23
+ * that legitimately repeats across sibling stack directories (see
24
+ * {@link collectEntities}). Derived from the path *relative to the build root*
25
+ * (not the absolute path) so the resulting key — and therefore any build digest
26
+ * that hashes it — is portable across machines and checkouts. Punctuation
27
+ * (`/`, `-`, `.`) is dropped and each segment PascalCased, keeping the key
28
+ * within CloudFormation's `^[A-Za-z0-9]+$` logical-id grammar.
30
29
  */
31
- export function collectEntities(
32
- modules: Array<{ file: string; exports: Record<string, unknown> }>
33
- ): Map<string, Declarable> {
34
- const entities = new Map<string, Declarable>();
30
+ function stackPrefix(file: string, buildRoot: string | undefined): string {
31
+ const dir = dirname(file);
32
+ const rel = buildRoot ? relative(resolve(buildRoot), resolve(dir)) : dir;
33
+ const segments = rel.split(/[^A-Za-z0-9]+/).filter((s) => s.length > 0);
34
+ return segments.map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
35
+ }
36
+
37
+ /** One entity to be placed into the map, produced by {@link enumerateEntries}. */
38
+ interface PendingEntry {
39
+ /** The un-disambiguated map key this entity would take (export name, indexed
40
+ * array name, or composite-expanded member name). */
41
+ bareKey: string;
42
+ value: Declarable;
43
+ file: string;
44
+ provenance: EntityProvenance;
45
+ }
46
+
47
+ /**
48
+ * Flatten every module's exports into the ordered list of entities they
49
+ * contribute — declarables directly, arrays element-by-element (indexed names),
50
+ * composite instances expanded into members, and LexiconOutputs. Order is
51
+ * preserved so downstream serializers emit resources in a stable order.
52
+ */
53
+ function enumerateEntries(
54
+ modules: Array<{ file: string; exports: Record<string, unknown> }>,
55
+ ): PendingEntry[] {
56
+ const entries: PendingEntry[] = [];
35
57
 
36
58
  for (const { file, exports } of modules) {
37
59
  for (const [rawName, value] of Object.entries(exports)) {
38
60
  const name = exportKey(rawName, file);
39
61
  if (isDeclarable(value)) {
40
- if (entities.has(name)) {
41
- // Same object re-exported from multiple files (e.g. re-exports from multiple files) is fine
42
- if (entities.get(name) !== value) {
43
- throw new DiscoveryError(
44
- file,
45
- `Duplicate export name "${name}" found`,
46
- "resolution"
47
- );
48
- }
49
- } else {
50
- setProvenance(value, { sourceFile: file });
51
- entities.set(name, value);
52
- }
62
+ entries.push({ bareKey: name, value, file, provenance: { sourceFile: file } });
53
63
  } else if (Array.isArray(value)) {
54
- // Arrays of Declarables or CompositeInstances — each element gets an indexed name: exportName_0, ...
55
64
  for (let i = 0; i < value.length; i++) {
56
65
  const item = value[i];
57
66
  if (isDeclarable(item)) {
58
- const indexedName = `${name}_${i}`;
59
- if (entities.has(indexedName) && entities.get(indexedName) !== item) {
60
- throw new DiscoveryError(file, `Duplicate entity name "${indexedName}"`, "resolution");
61
- }
62
- setProvenance(item, { sourceFile: file });
63
- entities.set(indexedName, item);
67
+ entries.push({ bareKey: `${name}_${i}`, value: item, file, provenance: { sourceFile: file } });
64
68
  } else if (isCompositeInstance(item)) {
65
69
  const indexedName = `${name}_${i}`;
66
- const expanded = expandComposite(indexedName, item);
67
- for (const [expandedName, entity] of expanded) {
68
- if (entities.has(expandedName)) {
69
- throw new DiscoveryError(
70
- file,
71
- `Duplicate entity name "${expandedName}" from composite expansion of "${indexedName}"`,
72
- "resolution",
73
- );
74
- }
75
- setProvenance(entity, { sourceFile: file, compositeInstance: indexedName });
76
- entities.set(expandedName, entity);
70
+ for (const [expandedName, entity] of expandComposite(indexedName, item)) {
71
+ entries.push({
72
+ bareKey: expandedName,
73
+ value: entity,
74
+ file,
75
+ provenance: { sourceFile: file, compositeInstance: indexedName },
76
+ });
77
77
  }
78
78
  }
79
79
  }
80
80
  } else if (isCompositeInstance(value)) {
81
- const expanded = expandComposite(name, value);
82
- for (const [expandedName, entity] of expanded) {
83
- if (entities.has(expandedName)) {
84
- throw new DiscoveryError(
85
- file,
86
- `Duplicate entity name "${expandedName}" from composite expansion of "${name}"`,
87
- "resolution",
88
- );
89
- }
90
- setProvenance(entity, { sourceFile: file, compositeInstance: name });
91
- entities.set(expandedName, entity);
81
+ for (const [expandedName, entity] of expandComposite(name, value)) {
82
+ entries.push({
83
+ bareKey: expandedName,
84
+ value: entity,
85
+ file,
86
+ provenance: { sourceFile: file, compositeInstance: name },
87
+ });
92
88
  }
93
89
  } else if (isLexiconOutput(value)) {
94
- // LexiconOutput is not a Declarable but build() expects to find them
95
- // in the entities map so it can collect and pass them to serializers
96
- entities.set(name, value as unknown as Declarable);
90
+ // LexiconOutput is not a Declarable but build() expects to find them in
91
+ // the entities map so it can collect and pass them to serializers.
92
+ entries.push({ bareKey: name, value: value as unknown as Declarable, file, provenance: { sourceFile: file } });
93
+ }
94
+ }
95
+ }
96
+
97
+ return entries;
98
+ }
99
+
100
+ /**
101
+ * Collects all declarable entities from imported modules.
102
+ * CompositeInstance exports are expanded into individual entities
103
+ * with `{exportName}_{memberName}` naming.
104
+ * LexiconOutput exports are also collected so that build() can
105
+ * extract them and pass them to the serializer.
106
+ *
107
+ * A bare entity name must be unique *within a single stack directory*, not
108
+ * across the whole project. A multi-stack project (independently-deployed
109
+ * sibling stacks under one root — e.g. `src/loom-backend/`, `src/loom-agents/`)
110
+ * legitimately reuses conventional cross-stack `Parameter` names like
111
+ * `pArtifactBucket`/`pImageUri` across siblings, because each directory is its
112
+ * own CloudFormation template where that name is the real, deployed logical id.
113
+ * When the same bare name is declared (as distinct objects) in two different
114
+ * directories, each is disambiguated by a stack prefix derived from its
115
+ * directory ({@link stackPrefix}) rather than throwing — so an unscoped
116
+ * whole-project build / `chant lifecycle snapshot|diff` no longer collides
117
+ * (#932). A per-stack scoped build (`chant build <dir>`) has a single directory
118
+ * relative to its root, so nothing is prefixed and the deployed logical ids are
119
+ * unchanged. A genuine *same-directory* duplicate is still an error.
120
+ *
121
+ * @param modules - Array of module records with their exports
122
+ * @param buildRoot - The build root the discovery ran against; stack prefixes
123
+ * are derived relative to it so keys stay portable across machines.
124
+ * @returns Map of export name to Declarable entity
125
+ * @throws {DiscoveryError} with type "resolution" if a name is duplicated within one directory
126
+ */
127
+ export function collectEntities(
128
+ modules: Array<{ file: string; exports: Record<string, unknown> }>,
129
+ buildRoot?: string,
130
+ ): Map<string, Declarable> {
131
+ const entries = enumerateEntries(modules);
132
+
133
+ // Which bare keys collide across more than one directory (as distinct
134
+ // objects)? Those — and only those — get a stack prefix. A bare key that
135
+ // resolves to a single object (even one re-exported from several files) keeps
136
+ // its raw name, so single-stack projects are unaffected.
137
+ const dirsByKey = new Map<string, Map<string, Set<Declarable>>>();
138
+ for (const { bareKey, value, file } of entries) {
139
+ const dir = dirname(file);
140
+ let byDir = dirsByKey.get(bareKey);
141
+ if (!byDir) {
142
+ byDir = new Map();
143
+ dirsByKey.set(bareKey, byDir);
144
+ }
145
+ let objs = byDir.get(dir);
146
+ if (!objs) {
147
+ objs = new Set();
148
+ byDir.set(dir, objs);
149
+ }
150
+ objs.add(value);
151
+ }
152
+ const crossDirKeys = new Set<string>();
153
+ for (const [bareKey, byDir] of dirsByKey) {
154
+ const dirsWithObjects = [...byDir.values()].filter((objs) => objs.size > 0).length;
155
+ const distinctObjects = new Set<Declarable>();
156
+ for (const objs of byDir.values()) for (const o of objs) distinctObjects.add(o);
157
+ if (dirsWithObjects > 1 && distinctObjects.size > 1) crossDirKeys.add(bareKey);
158
+ }
159
+
160
+ const entities = new Map<string, Declarable>();
161
+ // Per bare key, the object already claimed for each directory — a second,
162
+ // *different* object in the same directory is a genuine duplicate.
163
+ const claimedByDir = new Map<string, Map<string, Declarable>>();
164
+
165
+ for (const { bareKey, value, file, provenance } of entries) {
166
+ const dir = dirname(file);
167
+ let perDir = claimedByDir.get(bareKey);
168
+ if (!perDir) {
169
+ perDir = new Map();
170
+ claimedByDir.set(bareKey, perDir);
171
+ }
172
+ const claimed = perDir.get(dir);
173
+ if (claimed !== undefined && claimed !== value) {
174
+ // Same name, same directory, different object → a real collision.
175
+ throw new DiscoveryError(file, `Duplicate export name "${bareKey}" found`, "resolution");
176
+ }
177
+ perDir.set(dir, value);
178
+
179
+ const key = crossDirKeys.has(bareKey) ? `${stackPrefix(file, buildRoot)}${bareKey}` : bareKey;
180
+ const existing = entities.get(key);
181
+ if (existing !== undefined) {
182
+ // Same object re-exported (possibly from multiple files) is fine; a
183
+ // different object landing on the same disambiguated key would only
184
+ // happen if two directories produced an identical stack prefix.
185
+ if (existing !== value) {
186
+ throw new DiscoveryError(file, `Duplicate export name "${bareKey}" found`, "resolution");
97
187
  }
188
+ continue;
98
189
  }
190
+ setProvenance(value, provenance);
191
+ entities.set(key, value);
99
192
  }
100
193
 
101
194
  return entities;
@@ -67,7 +67,7 @@ export async function discover(path: string): Promise<DiscoveryResult> {
67
67
  let entities = new Map<string, Declarable>();
68
68
 
69
69
  try {
70
- entities = collectEntities(modules);
70
+ entities = collectEntities(modules, path);
71
71
  } catch (error) {
72
72
  // Collect resolution errors
73
73
  if (error instanceof Error && error.name === "DiscoveryError") {
package/src/lexicon.ts CHANGED
@@ -372,6 +372,13 @@ export interface LexiconPlugin {
372
372
  buildOutput: string;
373
373
  entityNames: string[];
374
374
  entities: Map<string, { entityType: string; props: Record<string, unknown> }>;
375
+ /**
376
+ * The deployed stack name to observe, for a multi-stack project where the
377
+ * stack is not named after the environment (see `stacks` in {@link
378
+ * ChantConfig}). When omitted, an implementation keeps its single-stack
379
+ * convention (AWS: the stack named after `environment`).
380
+ */
381
+ stack?: string;
375
382
  /**
376
383
  * Restrict the result to chant-owned resources (those carrying the
377
384
  * ownership marker, #119). Where a lexicon has no durable marker channel,
@@ -418,6 +425,9 @@ export interface LexiconPlugin {
418
425
  listArtifacts?(options: {
419
426
  environment: string;
420
427
  entities: Map<string, { entityType: string; props: Record<string, unknown> }>;
428
+ /** The deployed stack to scope enumeration to, for a multi-stack project
429
+ * (see `stacks` in {@link ChantConfig}). Omitted for single-stack projects. */
430
+ stack?: string;
421
431
  }): Promise<Record<string, ArtifactMetadata>>;
422
432
 
423
433
  // Live export (cloud → code)
@@ -141,6 +141,19 @@ export async function readBlobFromPath(
141
141
  return result.stdout;
142
142
  }
143
143
 
144
+ /**
145
+ * Storage key for a snapshot on the orphan branch. Single-stack projects key by
146
+ * lexicon (`<env>/<lexicon>.json`, unchanged). A multi-stack project (see
147
+ * `stacks` in ChantConfig, #932) folds the stack in as `<stack>__<lexicon>`
148
+ * (`<env>/<stack>__<lexicon>.json`) so sibling stacks that deploy the same
149
+ * lexicon don't overwrite each other's snapshots. The `__` separator can't
150
+ * collide with a lexicon name (lexicons are single tokens) and round-trips
151
+ * through `readSnapshot`/`readEnvironmentSnapshots` unchanged.
152
+ */
153
+ export function snapshotStorageKey(lexicon: string, stack?: string): string {
154
+ return stack ? `${stack}__${lexicon}` : lexicon;
155
+ }
156
+
144
157
  /**
145
158
  * Write a state snapshot JSON to the orphan branch.
146
159
  *
@@ -8,6 +8,7 @@ const pushLifecycleMock = vi.fn();
8
8
 
9
9
  vi.mock("./git", () => ({
10
10
  writeSnapshot: (...args: unknown[]) => writeSnapshotMock(...args),
11
+ snapshotStorageKey: (lexicon: string, stack?: string) => (stack ? `${stack}__${lexicon}` : lexicon),
11
12
  getHeadCommit: () => getHeadCommitMock(),
12
13
  pushLifecycle: () => pushLifecycleMock(),
13
14
  }));
@@ -57,6 +58,29 @@ describe("takeSnapshot", () => {
57
58
  });
58
59
  expect(writeSnapshotMock).toHaveBeenCalledTimes(1);
59
60
  expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
61
+ // Single-stack: written under the bare lexicon key, snapshot carries no stack.
62
+ expect(writeSnapshotMock.mock.calls[0][1]).toBe("aws");
63
+ expect(result.snapshots[0].stack).toBeUndefined();
64
+ });
65
+
66
+ // #932 — a multi-stack project observes each stack against its own live stack
67
+ // and stores its snapshot under a stack-scoped key so siblings don't overwrite.
68
+ test("stack option: observes the named stack and stores under a stack-scoped key", async () => {
69
+ let observedStack: string | undefined = "unset";
70
+ const plugin = createMockPlugin({
71
+ name: "aws",
72
+ describeResources: async (options: { stack?: string }) => {
73
+ observedStack = options.stack;
74
+ return { bucket: { type: "AWS::S3::Bucket", status: "CREATE_COMPLETE", physicalId: "b" } };
75
+ },
76
+ });
77
+ const result = await takeSnapshot("prod", [plugin], makeBuildResult({ aws: ["bucket"] }), { stack: "loom-backend" });
78
+ // describeResources was told which live stack to query.
79
+ expect(observedStack).toBe("loom-backend");
80
+ // The snapshot records its stack …
81
+ expect(result.snapshots[0].stack).toBe("loom-backend");
82
+ // … and is stored under `<stack>__<lexicon>`, not the bare lexicon key.
83
+ expect(writeSnapshotMock.mock.calls[0][1]).toBe("loom-backend__aws");
60
84
  });
61
85
 
62
86
  test("plugin without describeResources is skipped", async () => {
@@ -7,7 +7,7 @@ import type { BuildResult } from "../build";
7
7
  import type { SerializerResult } from "../serializer";
8
8
  import type { LifecycleSnapshot } from "./types";
9
9
  import { computeBuildDigest } from "./digest";
10
- import { writeSnapshot, getHeadCommit, pushLifecycle } from "./git";
10
+ import { writeSnapshot, snapshotStorageKey, getHeadCommit, pushLifecycle } from "./git";
11
11
  import { sortedJsonReplacer } from "../utils";
12
12
 
13
13
  /** Patterns in attribute names that suggest sensitive data. */
@@ -84,8 +84,9 @@ export async function takeSnapshot(
84
84
  environment: string,
85
85
  plugins: ObservationLexicon[],
86
86
  buildResult: BuildResult,
87
- opts?: { cwd?: string },
87
+ opts?: { cwd?: string; stack?: string },
88
88
  ): Promise<TakeSnapshotResult> {
89
+ const stack = opts?.stack;
89
90
  const warnings: string[] = [];
90
91
  const errors: string[] = [];
91
92
  const snapshots: LifecycleSnapshot[] = [];
@@ -131,6 +132,7 @@ export async function takeSnapshot(
131
132
  buildOutput,
132
133
  entityNames,
133
134
  entities,
135
+ stack,
134
136
  });
135
137
  const { valid, dropped, warnings: validationWarnings } = validateResources(raw);
136
138
  warnings.push(...validationWarnings);
@@ -141,7 +143,7 @@ export async function takeSnapshot(
141
143
  }
142
144
 
143
145
  if (plugin.listArtifacts) {
144
- const raw = await plugin.listArtifacts({ environment, entities });
146
+ const raw = await plugin.listArtifacts({ environment, entities, stack });
145
147
  const { valid, dropped, warnings: validationWarnings } = validateResources(raw);
146
148
  warnings.push(...validationWarnings);
147
149
  if (dropped.length > 0) {
@@ -158,6 +160,7 @@ export async function takeSnapshot(
158
160
  const snapshot: LifecycleSnapshot = {
159
161
  lexicon: plugin.name,
160
162
  environment,
163
+ ...(stack ? { stack } : {}),
161
164
  commit: headCommit,
162
165
  timestamp,
163
166
  resources,
@@ -179,7 +182,7 @@ export async function takeSnapshot(
179
182
  const json = JSON.stringify(snapshot, sortedJsonReplacer, 2);
180
183
  commitSha = await writeSnapshot(
181
184
  snapshot.environment,
182
- snapshot.lexicon,
185
+ snapshotStorageKey(snapshot.lexicon, snapshot.stack),
183
186
  json,
184
187
  opts,
185
188
  );
@@ -8,6 +8,10 @@ export type { ResourceMetadata, ArtifactMetadata } from "../lexicon";
8
8
  export interface LifecycleSnapshot {
9
9
  lexicon: string;
10
10
  environment: string;
11
+ /** Deployed stack name, for a multi-stack project (see `stacks` in
12
+ * ChantConfig). Absent for single-stack projects. Snapshots are stored per
13
+ * `<env>/<stack>/<lexicon>` when set, so sibling stacks don't overwrite. */
14
+ stack?: string;
11
15
  /** Main branch commit this corresponds to */
12
16
  commit: string;
13
17
  /** ISO timestamp when the snapshot was taken */