@intentius/chant 0.21.0 → 0.22.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.
package/dist/build.d.ts CHANGED
@@ -87,6 +87,13 @@ export interface BuildOptions {
87
87
  * The CLI populates this from `options.plugins.flatMap(p => p.intrinsics?.() ?? [])`.
88
88
  */
89
89
  intrinsics?: IntrinsicDef[];
90
+ /**
91
+ * chant #1063 — the lexicon names loaded for this build. Passed straight
92
+ * through to {@link DiscoveryOptions.lexicons} in `./discovery/index`;
93
+ * ignored unless {@link fold} is set. The CLI populates this from
94
+ * `options.plugins.map(p => p.name)`.
95
+ */
96
+ lexicons?: readonly string[];
90
97
  /**
91
98
  * chant #1045 Phase 2 — opt-in: run-fallback files (or, when {@link fold}
92
99
  * isn't set, every file) execute together, isolated, in one sandboxed
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAsB,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,cAAc,EAAiC,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAGlE,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAmB,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAKvF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CACb,MAAM,EACN;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CACtD,CAAC;IACF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,wEAAwE;IACxE,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAClB,yEAAyE;IACzE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,YAAY,EAAE,MAAM,EAAE,GACrB,UAAU,CAuEZ;AAED;;GAEG;AACH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAE5B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;IAChD,8CAA8C;IAC9C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,qDAAqD;IACrD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6DAA6D;IAC7D,MAAM,EAAE,KAAK,CAAC,cAAc,GAAG,UAAU,CAAC,CAAC;IAC3C,wDAAwD;IACxD,QAAQ,EAAE,aAAa,CAAC;IACxB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;IAE9B;;;;;;OAMG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CActC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,aAAa,EAAE,CA4DjB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,aAAa,EAAE,CAyFjB;AA6ED;;;;;;;GAOG;AACH,wBAAsB,KAAK,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,UAAU,EAAE,EACzB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,CAUtB;AA0KD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,sBAAsB,EAC5B,WAAW,EAAE,UAAU,EAAE,EACzB,KAAK,SAAsB,EAC3B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,CAgBtB"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AASnD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2CAA2C;IAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB;IAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAoB/C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2JAA2J;IAC3J,WAAW,CAAC,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;CACjE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA2V9E;AAiDD;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAIlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAItD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACxC,MAAM,IAAI,CAmCZ"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AASnD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2CAA2C;IAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB;IAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAoB/C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2JAA2J;IAC3J,WAAW,CAAC,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;CACjE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAoW9E;AAiDD;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAIlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAItD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACxC,MAAM,IAAI,CAmCZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"check-lexicon-examples.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check-lexicon-examples.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAsD1F"}
1
+ {"version":3,"file":"check-lexicon-examples.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check-lexicon-examples.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAUH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAoE1F"}
@@ -147,9 +147,41 @@ export interface FoldSession {
147
147
  * doesn't use build-time parameters pays nothing extra here.
148
148
  */
149
149
  readonly buildParams?: Readonly<Record<string, BuildParamValue>>;
150
+ /**
151
+ * chant #1063 — the exact package specifiers of the lexicons LOADED for
152
+ * this build (`@intentius/chant-lexicon-aws`, …), derived from the lexicon
153
+ * names the build already resolved (`resolveProjectLexicons` ->
154
+ * `loadPlugins`, see ../cli/plugins.ts). This is the entire allowlist
155
+ * {@link buildExternals} will follow a bare import specifier into — see
156
+ * {@link activeLexiconPackage} for why the set is matched by TEXT and
157
+ * built from names the build already knows, rather than by resolving
158
+ * specifiers to find out what they are.
159
+ *
160
+ * Empty when the caller supplied no lexicon list, which disables
161
+ * lexicon-package resolution entirely rather than falling back to
162
+ * something more permissive: "an active lexicon of this build" is the
163
+ * boundary, and a build that can't say what its lexicons are hasn't
164
+ * established one.
165
+ */
166
+ readonly lexiconPackages: ReadonlySet<string>;
150
167
  }
151
- /** Create a fresh, empty {@link FoldSession}. */
152
- export declare function createFoldSession(intrinsics?: readonly IntrinsicDef[], buildParams?: Readonly<Record<string, BuildParamValue>>): FoldSession;
168
+ /**
169
+ * chant #1063 the package specifier a lexicon NAME (`"aws"`, `"gitlab"`)
170
+ * is installed under. The one naming convention the whole CLI already
171
+ * depends on: `loadPlugin(name)` imports exactly this
172
+ * (../cli/plugins.ts), `detectLexicons` scans source for exactly this
173
+ * (../detectLexicon.ts), and `chant init` writes exactly this into
174
+ * package.json.
175
+ */
176
+ export declare function lexiconPackageName(lexiconName: string): string;
177
+ /**
178
+ * Create a fresh, empty {@link FoldSession}.
179
+ *
180
+ * @param lexicons - chant #1063: the lexicon NAMES active for this build
181
+ * (`["aws", "k8s"]`). Converted to package specifiers via
182
+ * {@link lexiconPackageName}; see {@link FoldSession.lexiconPackages}.
183
+ */
184
+ export declare function createFoldSession(intrinsics?: readonly IntrinsicDef[], buildParams?: Readonly<Record<string, BuildParamValue>>, lexicons?: readonly string[]): FoldSession;
153
185
  /**
154
186
  * Attempt to fold one source file with zero execution of its own top-level
155
187
  * code. Returns the folded, instantiated entities on success, or a reason
@@ -1 +1 @@
1
- {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAgB3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,mGAAmG;AACnG,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,iBAAiB,CAAC,CAAC;AAElF,MAAM,MAAM,cAAc,GACtB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;;;;;OASG;IACH,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;;;;;;;;;OAYG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAClE;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAC/B,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,GACtD,WAAW,CAEb;AAsmDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CAEzB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GACrD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA8EtB"}
1
+ {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAkB3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,mGAAmG;AACnG,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,iBAAiB,CAAC,CAAC;AAElF,MAAM,MAAM,cAAc,GACtB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;;;;;OASG;IACH,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;;;;;;;;;OAYG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;IACjE;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EACvD,QAAQ,GAAE,SAAS,MAAM,EAAO,GAC/B,WAAW,CAUb;AAiwDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CAEzB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GACrD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA8EtB"}
@@ -43,6 +43,18 @@ export interface DiscoveryOptions {
43
43
  * then falls back to run at the unregistered tag).
44
44
  */
45
45
  intrinsics?: IntrinsicDef[];
46
+ /**
47
+ * chant #1063 — the lexicon NAMES loaded for this build (`["aws", "k8s"]`),
48
+ * i.e. what `resolveProjectLexicons()` returned and `loadPlugins()` then
49
+ * imported. Threaded into the fold session as the ALLOWLIST of packages a
50
+ * bare import specifier may be resolved into, so a lexicon's plain data
51
+ * exports (`Azure`/`GCP`'s pseudo-parameter namespaces, AWS's `S3Actions`,
52
+ * gitlab's `CI`) fold as identifier values instead of failing the file.
53
+ * Only meaningful when {@link fold} is set. Default: none — a caller that
54
+ * doesn't say which lexicons are active gets no bare-specifier resolution
55
+ * at all, rather than a looser fallback.
56
+ */
57
+ lexicons?: readonly string[];
46
58
  /**
47
59
  * chant #1045 Phase 2 — opt-in: whatever would otherwise reach the
48
60
  * in-process `importModule` step (every file, when {@link fold} isn't set;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAE5B;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,8DAA8D;IAC9D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,qDAAqD;IACrD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoQjG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAE5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE7B;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,8DAA8D;IAC9D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,qDAAqD;IACrD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAsQjG"}
@@ -1 +1 @@
1
- {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold/fold.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold/fold.ts"],"names":[],"mappings":"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"}
@@ -105,11 +105,34 @@ export declare const SUPPORTED_UNARY_OPERATORS: ReadonlySet<ts.SyntaxKind>;
105
105
  export declare function isLiteralPropertyName(node: ts.PropertyName): node is ts.Identifier | ts.StringLiteral | ts.NumericLiteral;
106
106
  /** An element-access key foldable without execution: a string or numeric LITERAL only (EVL003 semantics). */
107
107
  export declare function isLiteralElementKey(node: ts.Expression): node is ts.StringLiteral | ts.NumericLiteral;
108
+ /**
109
+ * A short, single-line rendering of `node`'s source text for embedding in a
110
+ * diagnostic message — never the raw `getText()`, which reproduces the
111
+ * node's ENTIRE source verbatim and can span dozens of lines for a real
112
+ * composite call or object literal (chant #1054: a fold fallback reason that
113
+ * embeds one of these buries the actual error after it, and breaks any
114
+ * line-oriented consumer of `[fold:run]` output). Internal whitespace
115
+ * (including newlines) collapses to a single space, and the result is capped
116
+ * to a bounded length so one pathological node can't blow out an otherwise
117
+ * one-line reason either.
118
+ */
119
+ export declare function briefNodeText(node: ts.Node, maxLength?: number): string;
108
120
  export declare function computedPropertyNameMessage(node: ts.PropertyName): string;
109
121
  export declare function dynamicElementAccessMessage(keyNode: ts.Expression): string;
110
122
  export declare const UNSUPPORTED_OBJECT_MEMBER_MESSAGE = "unsupported object member";
111
123
  export declare const UNSUPPORTED_UNARY_MESSAGE = "unsupported unary";
112
124
  export declare function unsupportedBinaryMessage(opKind: ts.SyntaxKind): string;
125
+ /**
126
+ * chant #1054 — the ONE wording for "a bare function/method call used where
127
+ * chant needs a value it can fold." Before this, `fold()` (this message) and
128
+ * `../discovery/fold-import.ts`'s `resolveCallExpression` (a top-level
129
+ * export's own call-as-a-value check) had each grown their own hand-written
130
+ * copy — "function call as a value" here, "call expression as a value"
131
+ * there — for the identical rejection, which meant a tool grouping fallback
132
+ * reasons by text had to match both to avoid silently under-counting one of
133
+ * them. `resolveCallExpression` now calls this function directly instead of
134
+ * building its own string.
135
+ */
113
136
  export declare function callExpressionMessage(node: ts.CallExpression): string;
114
137
  export declare function unsupportedExpressionMessage(node: ts.Node): string;
115
138
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"subset.d.ts","sourceRoot":"","sources":["../../src/fold/subset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AAEH,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C,uGAAuG;AACvG,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAchE,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAG/D,CAAC;AAEH,gHAAgH;AAChH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,EAAE,CAAC,YAAY,GACpB,IAAI,IAAI,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAE9D;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAErG;AAQD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,CAEzE;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAE1E;AAED,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAEtE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,CAErE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,EAAE,CAAC,wBAAwB,EACjC,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAc7B;AAWD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAiK7B"}
1
+ {"version":3,"file":"subset.d.ts","sourceRoot":"","sources":["../../src/fold/subset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AAEH,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C,uGAAuG;AACvG,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAchE,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAG/D,CAAC;AAEH,gHAAgH;AAChH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,EAAE,CAAC,YAAY,GACpB,IAAI,IAAI,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAE9D;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAErG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,SAAK,GAAG,MAAM,CAGnE;AAQD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,CAEzE;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAE1E;AAED,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAEtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,CAErE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,EAAE,CAAC,wBAAwB,EACjC,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAc7B;AAWD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAiK7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,mEAAmE;IACnE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,+DAA+D;IAC/D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAChF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAyDT"}
1
+ {"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,mEAAmE;IACnE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,+DAA+D;IAC/D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAChF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAuET"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.21.0",
3
+ "version": "0.22.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",
package/src/build.ts CHANGED
@@ -170,6 +170,14 @@ export interface BuildOptions {
170
170
  */
171
171
  intrinsics?: IntrinsicDef[];
172
172
 
173
+ /**
174
+ * chant #1063 — the lexicon names loaded for this build. Passed straight
175
+ * through to {@link DiscoveryOptions.lexicons} in `./discovery/index`;
176
+ * ignored unless {@link fold} is set. The CLI populates this from
177
+ * `options.plugins.map(p => p.name)`.
178
+ */
179
+ lexicons?: readonly string[];
180
+
173
181
  /**
174
182
  * chant #1045 Phase 2 — opt-in: run-fallback files (or, when {@link fold}
175
183
  * isn't set, every file) execute together, isolated, in one sandboxed
@@ -513,6 +521,7 @@ export async function build(
513
521
  const discoveryResult = await discover(path, {
514
522
  fold: options?.fold,
515
523
  intrinsics: options?.intrinsics,
524
+ lexicons: options?.lexicons,
516
525
  sandbox: options?.sandbox,
517
526
  buildParams: options?.buildParams,
518
527
  });
@@ -201,6 +201,14 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
201
201
  // any), hence the guard.
202
202
  const intrinsics = options.plugins?.flatMap((plugin) => plugin.intrinsics?.() ?? []) ?? [];
203
203
 
204
+ // #1063 — the same loaded plugins, by NAME, are this build's allowlist for
205
+ // following a bare import specifier into a lexicon package (so `Azure`,
206
+ // `GCP`, `S3Actions`, `CI` fold as values). A plugin's `name` is the
207
+ // lexicon name `loadPlugin()` was called with, which is exactly what
208
+ // `@intentius/chant-lexicon-<name>` was imported from — see
209
+ // ../plugins.ts and fold-import.ts's `lexiconPackageName`.
210
+ const lexicons = options.plugins?.map((plugin) => plugin.name) ?? [];
211
+
204
212
  // Run the build
205
213
  const result = await build(infraPath, options.serializers, undefined, {
206
214
  ownership,
@@ -208,6 +216,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
208
216
  fold,
209
217
  sandbox,
210
218
  intrinsics,
219
+ lexicons,
211
220
  buildParams: paramsResolution.provenance,
212
221
  });
213
222
 
@@ -32,6 +32,7 @@ import { join } from "path";
32
32
  import { build } from "../../build";
33
33
  import { findInfraFiles } from "../../discovery/files";
34
34
  import { detectLexicons } from "../../detectLexicon";
35
+ import { loadChantConfig } from "../../config";
35
36
  import { loadPlugins } from "../plugins";
36
37
 
37
38
  export interface ExampleBuildResult {
@@ -64,7 +65,21 @@ export async function checkExamplesBuild(lexiconDir: string): Promise<ExampleBui
64
65
  const files = await findInfraFiles(srcDir);
65
66
  if (files.length === 0) continue;
66
67
 
67
- const lexiconNames = await detectLexicons(files);
68
+ // An example's own chant.config.{ts,json} (living beside src/, not in
69
+ // it) can declare `lexicons` explicitly — the same precedence real
70
+ // `chant build` gives it via resolveProjectLexicons() in ../plugins.ts.
71
+ // Needed for examples like helm's HelmRender ones, whose composite
72
+ // legitimately produces entities tagged with a lexicon (e.g. "k8s")
73
+ // that no source-file import mentions — detection from imports alone
74
+ // can never see it, so the example built with only its "own" lexicon's
75
+ // plugin and silently dropped every entity of the other, undetectable
76
+ // one. Detection from source-file imports (unchanged) remains the
77
+ // fallback for the many examples with no declared `lexicons` list.
78
+ const { config: exampleConfig } = await loadChantConfig(join(examplesDir, entry.name));
79
+ const lexiconNames =
80
+ exampleConfig.lexicons && exampleConfig.lexicons.length > 0
81
+ ? exampleConfig.lexicons
82
+ : await detectLexicons(files);
68
83
  if (lexiconNames.length === 0) {
69
84
  results.push({
70
85
  example: entry.name,
@@ -7,6 +7,7 @@ import { tryFoldFile, createFoldSession } from "./fold-import";
7
7
  import { isDeclarable } from "../declarable";
8
8
  import { isCompositeInstance } from "../composite";
9
9
  import { isAttrRefLike } from "../utils";
10
+ import { isIntrinsic } from "../intrinsic";
10
11
  import { params as sharedParams } from "../params";
11
12
  import type { AttrRef } from "../attrref";
12
13
  import type { IntrinsicDef } from "../lexicon";
@@ -165,7 +166,28 @@ describe("tryFoldFile", () => {
165
166
 
166
167
  expect(result.ok).toBe(false);
167
168
  if (result.ok) return;
168
- expect(result.reason).toContain("LocalStack");
169
+ // chant #1054 — locks in the ONE wording for "a call used as a value,
170
+ // not foldable" (../fold/subset.ts's `callExpressionMessage`), which
171
+ // `resolveCallExpression` now reuses instead of its own hand-written
172
+ // "call expression as a value" copy.
173
+ expect(result.reason).toBe('"stack" is not foldable: function call as a value is not foldable: LocalStack(...)');
174
+ });
175
+
176
+ test("falls back when a top-level export's callee isn't a plain identifier (chant #1054: same wording as any other call-as-a-value rejection)", async () => {
177
+ const file = join(testDir, "main.ts");
178
+ await writeFile(
179
+ file,
180
+ `
181
+ const builder = { build: (props: { name: string }) => ({ name: props.name }) };
182
+ export const stack = builder.build({ name: "x" });
183
+ `,
184
+ );
185
+
186
+ const result = await tryFoldFile(file);
187
+
188
+ expect(result.ok).toBe(false);
189
+ if (result.ok) return;
190
+ expect(result.reason).toBe('"stack" is not foldable: function call as a value is not foldable: builder.build(...)');
169
191
  });
170
192
 
171
193
  test("falls back when a prop value is not foldable", async () => {
@@ -286,6 +308,77 @@ describe("tryFoldFile", () => {
286
308
  DependsOn: "otherResource",
287
309
  });
288
310
  });
311
+
312
+ // chant #1054 — a destructured composite export's fallback reason used to
313
+ // embed `decl.node.getText()`: the ENTIRE call expression, which for a
314
+ // real multi-prop composite call is many lines, burying the real error
315
+ // after all of it. These lock in the fix: the reason names the binding(s)
316
+ // and the callee briefly instead, and stays on one line.
317
+ test("a destructured composite export whose source fails to resolve reports a brief, single-line reason naming the binding names and the callee", async () => {
318
+ await writeFile(
319
+ join(testDir, "composites.ts"),
320
+ `
321
+ import { createResource } from ${JSON.stringify(runtimePath)};
322
+ import { Composite } from ${JSON.stringify(compositePath)};
323
+ const Cluster = createResource("Test::Cluster", "gcp", {});
324
+ const NodePool = createResource("Test::NodePool", "gcp", {});
325
+ export const GkeCluster = Composite<{ name: string; location: string }>((props) => {
326
+ const cluster = new Cluster({ name: props.name });
327
+ const nodePool = new NodePool({ location: props.location });
328
+ return { cluster, nodePool };
329
+ }, "GkeCluster");
330
+ `,
331
+ );
332
+ const file = join(testDir, "cluster.ts");
333
+ await writeFile(
334
+ file,
335
+ `
336
+ import { GkeCluster } from "./composites";
337
+ export const { cluster, nodePool } = GkeCluster({
338
+ name: config.clusterName,
339
+ location: config.region,
340
+ });
341
+ `,
342
+ );
343
+
344
+ const result = await tryFoldFile(file);
345
+
346
+ expect(result.ok).toBe(false);
347
+ if (result.ok) return;
348
+ expect(result.reason).not.toContain("\n");
349
+ expect(result.reason).toContain('"cluster, nodePool" (destructured from GkeCluster(...))');
350
+ expect(result.reason).toContain("unresolved identifier: config");
351
+ // The whole multi-line source is gone — the reason never reproduces the
352
+ // call's own argument list verbatim.
353
+ expect(result.reason).not.toContain("clusterName");
354
+ });
355
+
356
+ test("a destructured export whose source resolves but isn't an object still reports a brief, single-line reason", async () => {
357
+ await writeFile(
358
+ join(testDir, "factory.ts"),
359
+ `
360
+ export function StringFactory(props: { text: string }): string {
361
+ return props.text;
362
+ }
363
+ `,
364
+ );
365
+ const file = join(testDir, "main.ts");
366
+ await writeFile(
367
+ file,
368
+ `
369
+ import { StringFactory } from "./factory";
370
+ export const { length } = StringFactory({ text: "hello" });
371
+ `,
372
+ );
373
+
374
+ const result = await tryFoldFile(file);
375
+
376
+ expect(result.ok).toBe(false);
377
+ if (result.ok) return;
378
+ expect(result.reason).toBe(
379
+ '"length" (destructured from StringFactory(...)) is not foldable: not a composite call or object',
380
+ );
381
+ });
289
382
  });
290
383
 
291
384
  // chant #1020 (epic #1019) — cross-file resolution: an imported binding now
@@ -1596,3 +1689,237 @@ describe("tryFoldFile — registered call-form intrinsics (#1044)", () => {
1596
1689
  expect(result.reason).toContain("same-file resource reference");
1597
1690
  });
1598
1691
  });
1692
+
1693
+ /**
1694
+ * chant #1063 — cross-file references into an ACTIVE LEXICON PACKAGE's
1695
+ * exports.
1696
+ *
1697
+ * #1020 taught fold to follow an identifier into another module, but only
1698
+ * through a relative/absolute specifier — a bare package specifier was
1699
+ * skipped outright, so `Azure`, `GCP`, `S3Actions` and gitlab's `CI` all
1700
+ * failed as "unresolved identifier" even though every one of them is a plain
1701
+ * `as const` object the folder already handles. These tests install a real
1702
+ * package into the fixture tree's own `node_modules` and drive the identical
1703
+ * resolution a real `@intentius/chant-lexicon-azure` import takes: a genuine
1704
+ * bare specifier, resolved by {@link fastResolveBareSpecifier} walking up to
1705
+ * `<testDir>/node_modules`, then really imported.
1706
+ *
1707
+ * Every fixture package gets a UNIQUE name. `bareSpecifierPathCache` is
1708
+ * process-wide and keyed by specifier alone (deliberately — see its doc), so
1709
+ * two tests reusing one name would have the second silently resolve to the
1710
+ * first's already-deleted directory.
1711
+ */
1712
+ describe("tryFoldFile — active lexicon package exports (#1063)", () => {
1713
+ let testDir: string;
1714
+ let seq = 0;
1715
+
1716
+ beforeEach(async () => {
1717
+ testDir = join(tmpdir(), `chant-fold-import-lexpkg-test-${Date.now()}-${Math.random()}`);
1718
+ await mkdir(testDir, { recursive: true });
1719
+ });
1720
+
1721
+ afterEach(async () => {
1722
+ await rm(testDir, { recursive: true, force: true });
1723
+ });
1724
+
1725
+ /**
1726
+ * Install a package into `<testDir>/node_modules/<name>` and return its
1727
+ * bare specifier. `lexiconName` is what a build would list in
1728
+ * `chant.config.ts`'s `lexicons`; the package name follows chant's one
1729
+ * naming convention (`@intentius/chant-lexicon-<name>`), same as
1730
+ * `loadPlugin()` uses.
1731
+ */
1732
+ async function installLexiconPackage(source: string): Promise<{ lexicon: string; specifier: string }> {
1733
+ const lexicon = `fold1063x${seq++}${Date.now().toString(36)}`;
1734
+ const specifier = `@intentius/chant-lexicon-${lexicon}`;
1735
+ const dir = join(testDir, "node_modules", specifier);
1736
+ await mkdir(dir, { recursive: true });
1737
+ await writeFile(
1738
+ join(dir, "package.json"),
1739
+ JSON.stringify({ name: specifier, version: "0.0.0", type: "module", exports: { ".": "./index.js" } }),
1740
+ );
1741
+ await writeFile(join(dir, "index.js"), source);
1742
+ return { lexicon, specifier };
1743
+ }
1744
+
1745
+ /** A pseudo-parameter namespace shaped exactly like `lexicons/azure/src/pseudo.ts`'s `Azure`, plus a plain-data constants object and a callable export. */
1746
+ const LEXICON_SOURCE = `
1747
+ const INTRINSIC_MARKER = Symbol.for("chant.intrinsic");
1748
+ class ArmPseudoParameter {
1749
+ constructor(expression) {
1750
+ this[INTRINSIC_MARKER] = true;
1751
+ this.expression = expression;
1752
+ }
1753
+ toJSON() { return this.expression; }
1754
+ }
1755
+ export const ResourceGroupLocation = new ArmPseudoParameter("[resourceGroup().location]");
1756
+ export const Azure = { ResourceGroupLocation };
1757
+ export const CI = { CommitBranch: "$CI_COMMIT_BRANCH", DefaultBranch: "$CI_DEFAULT_BRANCH" };
1758
+ export const S3Actions = { ReadOnly: ["s3:GetObject", "s3:ListBucket"] };
1759
+ export function defaultTags(tags) { return tags; }
1760
+ `;
1761
+
1762
+ test("a lexicon package's plain-data export resolves and folds when referenced as a value", async () => {
1763
+ const { lexicon, specifier } = await installLexiconPackage(LEXICON_SOURCE);
1764
+ const file = join(testDir, "main.ts");
1765
+ await writeFile(
1766
+ file,
1767
+ `
1768
+ import { CI, S3Actions } from ${JSON.stringify(specifier)};
1769
+ throw new Error("must never execute — sentinel for #1063 fold verification");
1770
+ export const branch = CI.CommitBranch;
1771
+ export const rule = \`\${CI.CommitBranch} == \${CI.DefaultBranch}\`;
1772
+ export const actions = S3Actions.ReadOnly;
1773
+ `,
1774
+ );
1775
+
1776
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, [lexicon]));
1777
+
1778
+ expect(result.ok).toBe(true);
1779
+ if (!result.ok) return;
1780
+ expect(result.exportedValues.get("branch")).toBe("$CI_COMMIT_BRANCH");
1781
+ // A template literal is the real test that the VALUE arrived, not a
1782
+ // symbolic envelope: an envelope would stringify to "[object Object]".
1783
+ expect(result.exportedValues.get("rule")).toBe("$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH");
1784
+ expect(result.exportedValues.get("actions")).toEqual(["s3:GetObject", "s3:ListBucket"]);
1785
+ });
1786
+
1787
+ test("a pseudo-parameter reached through the namespace stays the REAL live Intrinsic instance, prototype intact", async () => {
1788
+ const { lexicon, specifier } = await installLexiconPackage(LEXICON_SOURCE);
1789
+ await writeFile(
1790
+ join(testDir, "resources.ts"),
1791
+ `
1792
+ import { createResource } from ${JSON.stringify(runtimePath)};
1793
+ export const Group = createResource("Test::Group", "azure", {});
1794
+ `,
1795
+ );
1796
+ const file = join(testDir, "main.ts");
1797
+ await writeFile(
1798
+ file,
1799
+ `
1800
+ import { Azure } from ${JSON.stringify(specifier)};
1801
+ import { Group } from "./resources";
1802
+ export const group = new Group({ location: Azure.ResourceGroupLocation });
1803
+ `,
1804
+ );
1805
+
1806
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, [lexicon]));
1807
+
1808
+ expect(result.ok).toBe(true);
1809
+ if (!result.ok) return;
1810
+ const [, entity] = result.entities[0];
1811
+ const location = (entity as unknown as { props: { location: unknown } }).props.location;
1812
+ // Not a plain-object copy: the generic revive walk would have rebuilt it
1813
+ // as `{ expression: … }` and dropped `toJSON`, which is what actually
1814
+ // reaches the serializer.
1815
+ expect(isIntrinsic(location)).toBe(true);
1816
+ expect((location as { toJSON(): unknown }).toJSON()).toBe("[resourceGroup().location]");
1817
+ // Identity: the very object the module exports, not a reconstruction —
1818
+ // the same one a run-path import of this package would hand the file.
1819
+ const mod = (await import(join(testDir, "node_modules", specifier, "index.js"))) as {
1820
+ Azure: { ResourceGroupLocation: unknown };
1821
+ };
1822
+ expect(location).toBe(mod.Azure.ResourceGroupLocation);
1823
+ });
1824
+
1825
+ test("a lexicon package NOT active for this build is not resolved", async () => {
1826
+ const { specifier } = await installLexiconPackage(LEXICON_SOURCE);
1827
+ const file = join(testDir, "main.ts");
1828
+ await writeFile(
1829
+ file,
1830
+ `
1831
+ import { CI } from ${JSON.stringify(specifier)};
1832
+ export const branch = CI.CommitBranch;
1833
+ `,
1834
+ );
1835
+
1836
+ // The package is installed and importable — the ONLY thing missing is
1837
+ // this build having loaded it as a lexicon.
1838
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, ["aws"]));
1839
+
1840
+ expect(result.ok).toBe(false);
1841
+ if (result.ok) return;
1842
+ expect(result.reason).toContain("unresolved identifier: CI");
1843
+ });
1844
+
1845
+ test("with no active lexicons at all, a bare specifier is skipped exactly as before", async () => {
1846
+ const { specifier } = await installLexiconPackage(LEXICON_SOURCE);
1847
+ const file = join(testDir, "main.ts");
1848
+ await writeFile(
1849
+ file,
1850
+ `
1851
+ import { CI } from ${JSON.stringify(specifier)};
1852
+ export const branch = CI.CommitBranch;
1853
+ `,
1854
+ );
1855
+
1856
+ const result = await tryFoldFile(file);
1857
+
1858
+ expect(result.ok).toBe(false);
1859
+ if (result.ok) return;
1860
+ expect(result.reason).toContain("unresolved identifier: CI");
1861
+ });
1862
+
1863
+ test("a non-lexicon package is never followed, even when it is installed right next to one that is", async () => {
1864
+ const { lexicon } = await installLexiconPackage(LEXICON_SOURCE);
1865
+ const vendorDir = join(testDir, "node_modules", "some-vendor-pkg");
1866
+ await mkdir(vendorDir, { recursive: true });
1867
+ await writeFile(
1868
+ join(vendorDir, "package.json"),
1869
+ JSON.stringify({ name: "some-vendor-pkg", version: "0.0.0", type: "module", exports: { ".": "./index.js" } }),
1870
+ );
1871
+ await writeFile(join(vendorDir, "index.js"), `export const SETTINGS = { region: "us-east-1" };`);
1872
+
1873
+ const file = join(testDir, "main.ts");
1874
+ await writeFile(
1875
+ file,
1876
+ `
1877
+ import { SETTINGS } from "some-vendor-pkg";
1878
+ export const region = SETTINGS.region;
1879
+ `,
1880
+ );
1881
+
1882
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, [lexicon]));
1883
+
1884
+ expect(result.ok).toBe(false);
1885
+ if (result.ok) return;
1886
+ expect(result.reason).toContain("unresolved identifier: SETTINGS");
1887
+ });
1888
+
1889
+ test("a lexicon package's CALLABLE export is not bound as an identifier value", async () => {
1890
+ const { lexicon, specifier } = await installLexiconPackage(LEXICON_SOURCE);
1891
+ const file = join(testDir, "main.ts");
1892
+ await writeFile(
1893
+ file,
1894
+ `
1895
+ import { defaultTags } from ${JSON.stringify(specifier)};
1896
+ export const tags = defaultTags;
1897
+ `,
1898
+ );
1899
+
1900
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, [lexicon]));
1901
+
1902
+ expect(result.ok).toBe(false);
1903
+ if (result.ok) return;
1904
+ expect(result.reason).toContain("unresolved identifier: defaultTags");
1905
+ });
1906
+
1907
+ test("process.env still rejects, with the build-parameter guidance, even with an active lexicon package in scope", async () => {
1908
+ const { lexicon, specifier } = await installLexiconPackage(LEXICON_SOURCE);
1909
+ const file = join(testDir, "main.ts");
1910
+ await writeFile(
1911
+ file,
1912
+ `
1913
+ import { CI } from ${JSON.stringify(specifier)};
1914
+ export const branch = CI.CommitBranch;
1915
+ export const region = process.env.AWS_REGION;
1916
+ `,
1917
+ );
1918
+
1919
+ const result = await tryFoldFile(file, [], createFoldSession([], undefined, [lexicon]));
1920
+
1921
+ expect(result.ok).toBe(false);
1922
+ if (result.ok) return;
1923
+ expect(result.reason).toContain(`ambient "process" read is not foldable`);
1924
+ });
1925
+ });
@@ -7,6 +7,7 @@ import { createRequire } from "node:module";
7
7
  import { isDeclarable, type Declarable } from "../declarable";
8
8
  import { isCompositeInstance, type CompositeInstance } from "../composite";
9
9
  import { isAttrRefLike } from "../utils";
10
+ import { isIntrinsic } from "../intrinsic";
10
11
  import {
11
12
  collectConsts,
12
13
  foldResource,
@@ -20,6 +21,7 @@ import {
20
21
  type SymbolicValue,
21
22
  } from "../fold/fold";
22
23
  import { isChantOwnedSpecifier } from "../fold/foldable-helpers";
24
+ import { briefNodeText, callExpressionMessage } from "../fold/subset";
23
25
  import { importModule } from "./import";
24
26
  import type { IntrinsicDef } from "../lexicon";
25
27
  import type { BuildParamValue } from "../build-params";
@@ -171,14 +173,58 @@ export interface FoldSession {
171
173
  * doesn't use build-time parameters pays nothing extra here.
172
174
  */
173
175
  readonly buildParams?: Readonly<Record<string, BuildParamValue>>;
176
+ /**
177
+ * chant #1063 — the exact package specifiers of the lexicons LOADED for
178
+ * this build (`@intentius/chant-lexicon-aws`, …), derived from the lexicon
179
+ * names the build already resolved (`resolveProjectLexicons` ->
180
+ * `loadPlugins`, see ../cli/plugins.ts). This is the entire allowlist
181
+ * {@link buildExternals} will follow a bare import specifier into — see
182
+ * {@link activeLexiconPackage} for why the set is matched by TEXT and
183
+ * built from names the build already knows, rather than by resolving
184
+ * specifiers to find out what they are.
185
+ *
186
+ * Empty when the caller supplied no lexicon list, which disables
187
+ * lexicon-package resolution entirely rather than falling back to
188
+ * something more permissive: "an active lexicon of this build" is the
189
+ * boundary, and a build that can't say what its lexicons are hasn't
190
+ * established one.
191
+ */
192
+ readonly lexiconPackages: ReadonlySet<string>;
193
+ }
194
+
195
+ /**
196
+ * chant #1063 — the package specifier a lexicon NAME (`"aws"`, `"gitlab"`)
197
+ * is installed under. The one naming convention the whole CLI already
198
+ * depends on: `loadPlugin(name)` imports exactly this
199
+ * (../cli/plugins.ts), `detectLexicons` scans source for exactly this
200
+ * (../detectLexicon.ts), and `chant init` writes exactly this into
201
+ * package.json.
202
+ */
203
+ export function lexiconPackageName(lexiconName: string): string {
204
+ return `@intentius/chant-lexicon-${lexiconName}`;
174
205
  }
175
206
 
176
- /** Create a fresh, empty {@link FoldSession}. */
207
+ /**
208
+ * Create a fresh, empty {@link FoldSession}.
209
+ *
210
+ * @param lexicons - chant #1063: the lexicon NAMES active for this build
211
+ * (`["aws", "k8s"]`). Converted to package specifiers via
212
+ * {@link lexiconPackageName}; see {@link FoldSession.lexiconPackages}.
213
+ */
177
214
  export function createFoldSession(
178
215
  intrinsics: readonly IntrinsicDef[] = [],
179
216
  buildParams?: Readonly<Record<string, BuildParamValue>>,
217
+ lexicons: readonly string[] = [],
180
218
  ): FoldSession {
181
- return { intrinsics, cache: new Map(), stack: [], importCache: new Map(), resolvePathCache: new Map(), buildParams };
219
+ return {
220
+ intrinsics,
221
+ cache: new Map(),
222
+ stack: [],
223
+ importCache: new Map(),
224
+ resolvePathCache: new Map(),
225
+ buildParams,
226
+ lexiconPackages: new Set(lexicons.map(lexiconPackageName)),
227
+ };
182
228
  }
183
229
 
184
230
  /**
@@ -805,6 +851,100 @@ function paramsModulePath(): string | null {
805
851
  return paramsModulePathMemo;
806
852
  }
807
853
 
854
+ /**
855
+ * chant #1063 — is `specifier` a bare import of a package that is an ACTIVE
856
+ * LEXICON of this build? Returns the specifier itself when so, `undefined`
857
+ * otherwise.
858
+ *
859
+ * Three deliberate restrictions, each of which is the point rather than an
860
+ * omission:
861
+ *
862
+ * - **Text only, no resolution.** The answer is a `Set.has` on a set built
863
+ * from the lexicon names the build ALREADY resolved before discovery ran
864
+ * (`resolveProjectLexicons` -> `loadPlugins`). Nothing is probed, read, or
865
+ * resolved to decide whether a specifier is in scope — so an import of
866
+ * some unrelated package costs a string comparison and is then left alone,
867
+ * never resolved "just to find out what it is". That matters here more
868
+ * than anywhere: `resolveModulePath`'s bare branch can fall through to
869
+ * `createRequire(fromFile).resolve(specifier)`, measured at up to ~361s
870
+ * for the first resolution of a genuinely new bare specifier in a process
871
+ * (see {@link bareSpecifierPathCache}/{@link fastResolveBareSpecifier} —
872
+ * this exact class of cost regressed twice during chant#1020).
873
+ *
874
+ * - **Exact package specifier, no subpaths.** `@intentius/chant-lexicon-aws`
875
+ * matches; `@intentius/chant-lexicon-aws/actions` does not. Every lexicon
876
+ * re-exports its whole public surface from its barrel and every example
877
+ * imports it that way, so subpaths buy nothing — and they would cost
878
+ * something real: {@link fastResolveBareSpecifier} only recognizes a
879
+ * package ROOT (it looks for `<node_modules>/<specifier>/package.json`),
880
+ * so a subpath specifier falls through to exactly the slow
881
+ * `createRequire().resolve()` path this restriction exists to avoid.
882
+ *
883
+ * - **Lexicons of THIS build only.** Not "any `@intentius/chant-lexicon-*`
884
+ * package on disk", and emphatically not "any bare specifier". A lexicon
885
+ * the build did not load is as out of scope as `node:fs`.
886
+ */
887
+ function activeLexiconPackage(specifier: string, lexiconPackages: ReadonlySet<string>): string | undefined {
888
+ return lexiconPackages.has(specifier) ? specifier : undefined;
889
+ }
890
+
891
+ /**
892
+ * chant #1063 — resolve one named import binding against an active lexicon
893
+ * package's REAL exports, for {@link buildExternals}.
894
+ *
895
+ * The lexicon module is imported (through the session-wide
896
+ * {@link FoldSession.importCache}, so at most one real `import()` per package
897
+ * per build) and the requested export read straight off it. That is the same
898
+ * module object the run path gets — `importModule` is a plain dynamic
899
+ * `import()` with no cache-busting — so what fold captures here is not a
900
+ * reconstruction of the lexicon's data but the identical value, down to
901
+ * object identity for `Azure.ResourceGroupLocation`-style singletons. It is
902
+ * also the same two-step (resolve path, then import) that
903
+ * `resolveImportedExport` has always used to reach a lexicon's constructors
904
+ * and intrinsic functions; the only thing new is that a plain DATA export is
905
+ * now reachable too.
906
+ *
907
+ * Callable exports are deliberately excluded. A lexicon's functions — its
908
+ * resource classes, composite factories, intrinsic implementations — already
909
+ * have dedicated resolution paths that know how to INVOKE them
910
+ * (`resolveResourceEntity`, `resolveCallExpression`, `reviveFoldedValue`), and
911
+ * binding them as plain identifier values here would widen what folds in ways
912
+ * this issue neither needs nor measured: none of the references #1063 exists
913
+ * to unblock (`Azure`, `GCP`, `S3Actions`, gitlab's `CI`) is a function.
914
+ *
915
+ * Returns `undefined` — never throws — for a package that isn't an active
916
+ * lexicon, an export the package doesn't have, a callable export, or an
917
+ * import that fails. The binding is then simply absent from `externals`,
918
+ * exactly as before, and `fold()`'s ordinary "unresolved identifier" failure
919
+ * still fires if the name is actually referenced.
920
+ */
921
+ async function resolveActiveLexiconExport(
922
+ binding: ImportBinding,
923
+ fromFile: string,
924
+ session: FoldSession,
925
+ ): Promise<{ value: unknown } | undefined> {
926
+ if (!activeLexiconPackage(binding.specifier, session.lexiconPackages)) return undefined;
927
+
928
+ let modulePath: string;
929
+ try {
930
+ modulePath = resolveModulePathMemoized(binding.specifier, fromFile, session.resolvePathCache);
931
+ } catch {
932
+ return undefined;
933
+ }
934
+
935
+ let mod: Record<string, unknown>;
936
+ try {
937
+ mod = await importModuleMemoized(modulePath, session.importCache);
938
+ } catch {
939
+ return undefined;
940
+ }
941
+
942
+ if (!(binding.imported in mod)) return undefined;
943
+ const value = mod[binding.imported];
944
+ if (typeof value === "function") return undefined;
945
+ return { value };
946
+ }
947
+
808
948
  // ─────────────────────────────────────────────────────────────────────────
809
949
  // Resolution: given the scan + import map, compute the REAL runtime value
810
950
  // (Declarable | CompositeInstance) each foldable export would have had if
@@ -962,13 +1102,18 @@ async function resolveLiveValue(node: ts.Expression, ctx: ResolveCtx): Promise<L
962
1102
  * `isDeclarable`/`isCompositeInstance` value for a top-level export).
963
1103
  */
964
1104
  async function resolveCallExpression(node: ts.CallExpression, ctx: ResolveCtx): Promise<unknown> {
1105
+ // chant #1054 — reuses ../fold/subset's `callExpressionMessage` (the SAME
1106
+ // builder `fold()` throws with for a call used as a prop value) rather
1107
+ // than a hand-written "call expression as a value" copy: the two used to
1108
+ // say different things for the identical rejection, which silently broke
1109
+ // any tooling grouping fallback reasons by text.
965
1110
  if (!ts.isIdentifier(node.expression)) {
966
- throw cheapError(`call expression as a value is not foldable: ${node.expression.getText()}(...)`);
1111
+ throw cheapError(callExpressionMessage(node));
967
1112
  }
968
1113
  const calleeName = node.expression.text;
969
1114
  const binding = ctx.imports.get(calleeName);
970
1115
  if (!binding) {
971
- throw cheapError(`call expression as a value is not foldable: ${calleeName}(...)`);
1116
+ throw cheapError(callExpressionMessage(node));
972
1117
  }
973
1118
 
974
1119
  let modulePath: string;
@@ -1161,7 +1306,17 @@ async function reviveFoldedValue(value: FoldedValue, ctx: ResolveCtx, requireLiv
1161
1306
  // destroying the very identity #1020 exists to preserve. Passed through
1162
1307
  // completely unchanged, exactly like `resolveCallExpression`'s own
1163
1308
  // `live.value` passthrough for a composite-call argument.
1164
- if (isAttrRefLike(value) || isDeclarable(value) || isCompositeInstance(value)) {
1309
+ // chant #1063 adds the third kind of real object cross-file resolution can
1310
+ // now put here: a live `Intrinsic` instance read off an active lexicon
1311
+ // package (`Azure.ResourceGroupLocation`, `GCP.ProjectId` — see
1312
+ // `resolveActiveLexiconExport`). Same hazard, same fix: the generic walk
1313
+ // below would rebuild it as a plain `{}` copy, dropping the prototype that
1314
+ // carries `toJSON()` and so serializing `{}` where the run path emits
1315
+ // `[resourceGroup().location]`. `isIntrinsic` keys off
1316
+ // `Symbol.for("chant.intrinsic")` (../intrinsic.ts), a GLOBAL symbol, so it
1317
+ // holds across separately-loaded copies of chant-core the way a bare
1318
+ // `instanceof` would not.
1319
+ if (isAttrRefLike(value) || isDeclarable(value) || isCompositeInstance(value) || isIntrinsic(value)) {
1165
1320
  return value;
1166
1321
  }
1167
1322
 
@@ -1443,6 +1598,18 @@ function describeFoldFailure(err: unknown, ctx: ResolveCtx): string {
1443
1598
  return err.message;
1444
1599
  }
1445
1600
 
1601
+ /**
1602
+ * chant #1054 — a short, single-line label for a destructured export's
1603
+ * source expression, for a fold fallback reason: the callee plus `(...)`
1604
+ * for the common composite-call source (`GkeCluster(...)`), or a brief,
1605
+ * bounded rendering of whatever else it is otherwise. Never the source's own
1606
+ * `getText()` — for a real composite call that's the entire multi-line
1607
+ * argument list.
1608
+ */
1609
+ function describeDestructureSource(node: ts.Expression): string {
1610
+ return ts.isCallExpression(node) ? `${briefNodeText(node.expression)}(...)` : briefNodeText(node);
1611
+ }
1612
+
1446
1613
  /** Build a located `FoldError`'s formatted "line:col - message" string anchored at `node` — for a cross-file failure detected here in fold-import.ts (an import cycle, a name genuinely absent from the target module's exports) rather than inside `fold()` itself. */
1447
1614
  function locatedMessage(node: ts.Node, message: string): string {
1448
1615
  const { line, column } = locate(node);
@@ -1585,10 +1752,36 @@ async function buildExternals(
1585
1752
  }
1586
1753
 
1587
1754
  if (!isProjectFileSpecifier(binding.specifier)) {
1588
- // Every other bare specifier (a lexicon/vendor package) is left alone
1589
- // here, exactly as before #1064: it resolves lazily, through the
1590
- // pre-existing `importModule` mechanism, only once a constructor/
1591
- // composite-factory/intrinsic tag actually consumes it.
1755
+ // chant #1063 — a bare specifier naming one of THIS BUILD's active
1756
+ // lexicon packages resolves to that package's real export, so a plain
1757
+ // data export a lexicon publishes (`Azure`/`GCP`'s pseudo-parameter
1758
+ // namespaces, AWS's `S3Actions`, gitlab's `CI`) is an ordinary
1759
+ // identifier value here rather than fold's most common remaining
1760
+ // "unresolved identifier" failure. See
1761
+ // {@link resolveActiveLexiconExport} for the allowlist, the no-cold-
1762
+ // resolution rule, and why callable exports stay out.
1763
+ //
1764
+ // No `liveSources` edge is recorded for what comes back, unlike the
1765
+ // project-file case just below. `liveSources` (chant #1044) exists so
1766
+ // that a folded file which captured ANOTHER FILE's objects is
1767
+ // invalidated when that file is forced back to run — a fold/run
1768
+ // disagreement about identity. A lexicon package has no such duality:
1769
+ // it is not a discovered source file, `planFoldTaint` never considers
1770
+ // it (it filters to the discovered `files` set), it never falls back to
1771
+ // run, and both paths reach it through the identical un-cache-busted
1772
+ // `import()` of the identical resolved path — so the object fold
1773
+ // captures IS the object the run path holds. There is nothing for the
1774
+ // two sides to disagree about, hence nothing to taint.
1775
+ const lexiconExport = await resolveActiveLexiconExport(binding, file, session);
1776
+ if (lexiconExport) {
1777
+ externals.set(localName, lexiconExport.value);
1778
+ continue;
1779
+ }
1780
+ // Every other bare specifier (a non-lexicon vendor package, a lexicon
1781
+ // this build didn't load) is left alone here, exactly as before #1064:
1782
+ // it resolves lazily, through the pre-existing `importModule`
1783
+ // mechanism, only once a constructor/composite-factory/intrinsic tag
1784
+ // actually consumes it.
1592
1785
  continue;
1593
1786
  }
1594
1787
  let targetPath: string;
@@ -1736,18 +1929,26 @@ async function tryFoldFileCore(file: string, session: FoldSession): Promise<Fold
1736
1929
 
1737
1930
  if (decl.kind === "destructure") {
1738
1931
  let value: unknown;
1932
+ // chant #1054 — identify the destructured export by its BINDING
1933
+ // NAMES and the source's callee (`"cluster, nodePool" (destructured
1934
+ // from GkeCluster(...))`), never `decl.node.getText()`: for a real
1935
+ // composite call that's the entire multi-line source, which buries
1936
+ // the actual error after it and breaks any line-oriented consumer of
1937
+ // `[fold:run]` output.
1938
+ const boundNames = decl.elements.map((el) => el.bindingName).join(", ");
1939
+ const source = describeDestructureSource(decl.node);
1739
1940
  try {
1740
1941
  value = (await resolveDeclaratorValue(decl.node, ctx)).value;
1741
1942
  } catch (err) {
1742
1943
  return {
1743
1944
  ok: false,
1744
- reason: `destructured export from "${decl.node.getText()}" is not foldable: ${describeFoldFailure(err, ctx)}`,
1945
+ reason: `"${boundNames}" (destructured from ${source}) is not foldable: ${describeFoldFailure(err, ctx)}`,
1745
1946
  };
1746
1947
  }
1747
1948
  if (!isIndexableObject(value)) {
1748
1949
  return {
1749
1950
  ok: false,
1750
- reason: `destructured export from "${decl.node.getText()}" is not foldable (not a composite call or object)`,
1951
+ reason: `"${boundNames}" (destructured from ${source}) is not foldable: not a composite call or object`,
1751
1952
  };
1752
1953
  }
1753
1954
  for (const { propKey, bindingName } of decl.elements) {
@@ -56,6 +56,19 @@ export interface DiscoveryOptions {
56
56
  */
57
57
  intrinsics?: IntrinsicDef[];
58
58
 
59
+ /**
60
+ * chant #1063 — the lexicon NAMES loaded for this build (`["aws", "k8s"]`),
61
+ * i.e. what `resolveProjectLexicons()` returned and `loadPlugins()` then
62
+ * imported. Threaded into the fold session as the ALLOWLIST of packages a
63
+ * bare import specifier may be resolved into, so a lexicon's plain data
64
+ * exports (`Azure`/`GCP`'s pseudo-parameter namespaces, AWS's `S3Actions`,
65
+ * gitlab's `CI`) fold as identifier values instead of failing the file.
66
+ * Only meaningful when {@link fold} is set. Default: none — a caller that
67
+ * doesn't say which lexicons are active gets no bare-specifier resolution
68
+ * at all, rather than a looser fallback.
69
+ */
70
+ lexicons?: readonly string[];
71
+
59
72
  /**
60
73
  * chant #1045 Phase 2 — opt-in: whatever would otherwise reach the
61
74
  * in-process `importModule` step (every file, when {@link fold} isn't set;
@@ -156,7 +169,9 @@ export async function discover(path: string, options?: DiscoveryOptions): Promis
156
169
  // a project file imported by several others is folded exactly once, so
157
170
  // every referrer shares the identical constructed Declarable/
158
171
  // CompositeInstance objects rather than each building its own copy.
159
- const foldSession = options?.fold ? createFoldSession(options.intrinsics, buildParamValuesMap) : undefined;
172
+ const foldSession = options?.fold
173
+ ? createFoldSession(options.intrinsics, buildParamValuesMap, options.lexicons)
174
+ : undefined;
160
175
  if (options?.fold) {
161
176
  for (const file of files) {
162
177
  foldAttempts.set(file, await tryFoldFile(file, options.intrinsics, foldSession));
package/src/fold/fold.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  SUPPORTED_UNARY_OPERATORS,
6
6
  UNSUPPORTED_OBJECT_MEMBER_MESSAGE,
7
7
  UNSUPPORTED_UNARY_MESSAGE,
8
+ briefNodeText,
8
9
  callExpressionMessage,
9
10
  computedPropertyNameMessage,
10
11
  dynamicElementAccessMessage,
@@ -396,7 +397,7 @@ function foldTaggedTemplate(
396
397
  const tagName = node.tag.getText();
397
398
  const isRegistered = intrinsics.some((i) => i.name === tagName && intrinsicTagFolds(i));
398
399
  if (!isRegistered) {
399
- throw foldError(node, `unregistered tagged template intrinsic: ${tagName}\`...\``);
400
+ throw foldError(node, `unregistered tagged template intrinsic: ${briefNodeText(node.tag)}\`...\``);
400
401
  }
401
402
 
402
403
  const template = node.template;
@@ -635,7 +636,10 @@ export function fold(
635
636
  // Reject so the file falls back to run, which constructs and serializes it
636
637
  // correctly. EVL permits this statically — it's a documented fold/EVL
637
638
  // divergence, like identifier resolution and spread runtime type.
638
- throw foldError(node, `nested \`new ${node.expression.getText()}(...)\` as a value is not foldable — falls back to run`);
639
+ throw foldError(
640
+ node,
641
+ `nested \`new ${briefNodeText(node.expression)}(...)\` as a value is not foldable — falls back to run`,
642
+ );
639
643
  }
640
644
 
641
645
  if (ts.isCallExpression(node)) {
@@ -1,7 +1,7 @@
1
1
  import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { fold, foldResource, collectConsts, FoldError } from "./fold";
4
- import { findSubsetViolation } from "./subset";
4
+ import { briefNodeText, callExpressionMessage, findSubsetViolation } from "./subset";
5
5
  import { evl001NonLiteralExpressionRule } from "../lint/rules/evl001-non-literal-expression";
6
6
  import { evl003DynamicPropertyAccessRule } from "../lint/rules/evl003-dynamic-property-access";
7
7
  import { evl004SpreadNonConstRule } from "../lint/rules/evl004-spread-non-const";
@@ -350,3 +350,69 @@ describe("findSubsetViolation — optional intrinsic registry (#1044)", () => {
350
350
  expect(evl001NonLiteralExpressionRule.check(context).length).toBeGreaterThan(0);
351
351
  });
352
352
  });
353
+
354
+ /**
355
+ * chant #1054 — `briefNodeText` is what keeps every fold fallback reason
356
+ * that used to embed a node's raw `getText()` down to one bounded line. A
357
+ * real composite call's source is many lines; a fold reason that reproduces
358
+ * it verbatim buries the actual error after all of it (the bug this issue
359
+ * reports) and breaks any line-oriented consumer of `[fold:run]` output.
360
+ */
361
+ describe("briefNodeText — single-line, bounded diagnostic text (chant #1054)", () => {
362
+ function initializerOf(source: string): ts.Expression {
363
+ const sourceFile = ts.createSourceFile("t.ts", source, ts.ScriptTarget.Latest, true);
364
+ const consts = collectConsts(sourceFile);
365
+ const init = consts.get("x");
366
+ if (!init) throw new Error(`fixture error: "x" did not parse in ${JSON.stringify(source)}`);
367
+ return init;
368
+ }
369
+
370
+ test("a short, single-line node passes through unchanged", () => {
371
+ expect(briefNodeText(initializerOf(`const x = GkeCluster;`))).toBe("GkeCluster");
372
+ });
373
+
374
+ test("a multi-line node's newlines collapse to spaces — the result is always one line", () => {
375
+ const text = briefNodeText(
376
+ initializerOf(`
377
+ const x = GkeCluster({
378
+ name: config.clusterName,
379
+ location: config.region,
380
+ });
381
+ `),
382
+ );
383
+ expect(text).not.toContain("\n");
384
+ expect(text.split("\n")).toHaveLength(1);
385
+ });
386
+
387
+ test("text over the length cap is truncated with a trailing marker rather than left unbounded", () => {
388
+ const text = briefNodeText(
389
+ initializerOf(`const x = { aVeryLongPropertyNameNumberOne: 1, aVeryLongPropertyNameNumberTwo: 2 };`),
390
+ 20,
391
+ );
392
+ expect(text.length).toBe(20);
393
+ expect(text.endsWith("...")).toBe(true);
394
+ });
395
+ });
396
+
397
+ describe("callExpressionMessage — one line regardless of the call's own argument list (chant #1054)", () => {
398
+ test("only the callee is embedded — a multi-line argument list never leaks into the message", () => {
399
+ const sourceFile = ts.createSourceFile(
400
+ "t.ts",
401
+ `
402
+ const x = GkeCluster({
403
+ name: config.clusterName,
404
+ location: config.region,
405
+ machineType: "n2-standard-2",
406
+ });
407
+ `,
408
+ ts.ScriptTarget.Latest,
409
+ true,
410
+ );
411
+ const consts = collectConsts(sourceFile);
412
+ const call = consts.get("x") as ts.CallExpression;
413
+
414
+ const message = callExpressionMessage(call);
415
+
416
+ expect(message).toBe("function call as a value is not foldable: GkeCluster(...)");
417
+ });
418
+ });
@@ -141,6 +141,22 @@ export function isLiteralElementKey(node: ts.Expression): node is ts.StringLiter
141
141
  return ts.isStringLiteral(node) || ts.isNumericLiteral(node);
142
142
  }
143
143
 
144
+ /**
145
+ * A short, single-line rendering of `node`'s source text for embedding in a
146
+ * diagnostic message — never the raw `getText()`, which reproduces the
147
+ * node's ENTIRE source verbatim and can span dozens of lines for a real
148
+ * composite call or object literal (chant #1054: a fold fallback reason that
149
+ * embeds one of these buries the actual error after it, and breaks any
150
+ * line-oriented consumer of `[fold:run]` output). Internal whitespace
151
+ * (including newlines) collapses to a single space, and the result is capped
152
+ * to a bounded length so one pathological node can't blow out an otherwise
153
+ * one-line reason either.
154
+ */
155
+ export function briefNodeText(node: ts.Node, maxLength = 60): string {
156
+ const collapsed = node.getText().replace(/\s+/g, " ").trim();
157
+ return collapsed.length > maxLength ? `${collapsed.slice(0, maxLength - 3)}...` : collapsed;
158
+ }
159
+
144
160
  // ---------------------------------------------------------------------------
145
161
  // Shared message builders — `fold()` and `findSubsetViolation` both call
146
162
  // these so the diagnostic text for the same violation kind is the same
@@ -148,11 +164,11 @@ export function isLiteralElementKey(node: ts.Expression): node is ts.StringLiter
148
164
  // ---------------------------------------------------------------------------
149
165
 
150
166
  export function computedPropertyNameMessage(node: ts.PropertyName): string {
151
- return `computed/dynamic property name not foldable: ${node.getText()}`;
167
+ return `computed/dynamic property name not foldable: ${briefNodeText(node)}`;
152
168
  }
153
169
 
154
170
  export function dynamicElementAccessMessage(keyNode: ts.Expression): string {
155
- return `dynamic property access — computed key must be a string or numeric literal: ${keyNode.getText()}`;
171
+ return `dynamic property access — computed key must be a string or numeric literal: ${briefNodeText(keyNode)}`;
156
172
  }
157
173
 
158
174
  export const UNSUPPORTED_OBJECT_MEMBER_MESSAGE = "unsupported object member";
@@ -163,8 +179,19 @@ export function unsupportedBinaryMessage(opKind: ts.SyntaxKind): string {
163
179
  return `unsupported binary operator: ${ts.SyntaxKind[opKind]}`;
164
180
  }
165
181
 
182
+ /**
183
+ * chant #1054 — the ONE wording for "a bare function/method call used where
184
+ * chant needs a value it can fold." Before this, `fold()` (this message) and
185
+ * `../discovery/fold-import.ts`'s `resolveCallExpression` (a top-level
186
+ * export's own call-as-a-value check) had each grown their own hand-written
187
+ * copy — "function call as a value" here, "call expression as a value"
188
+ * there — for the identical rejection, which meant a tool grouping fallback
189
+ * reasons by text had to match both to avoid silently under-counting one of
190
+ * them. `resolveCallExpression` now calls this function directly instead of
191
+ * building its own string.
192
+ */
166
193
  export function callExpressionMessage(node: ts.CallExpression): string {
167
- return `function call as a value is not foldable: ${node.expression.getText()}(...)`;
194
+ return `function call as a value is not foldable: ${briefNodeText(node.expression)}(...)`;
168
195
  }
169
196
 
170
197
  export function unsupportedExpressionMessage(node: ts.Node): string {
@@ -61,6 +61,20 @@ export function walkValue(
61
61
  if (name) {
62
62
  return visitor.resourceRef(name);
63
63
  }
64
+ // A resource-kind Declarable constructed inline rather than exported as
65
+ // its own top-level entity (e.g. K8s `new PersistentVolumeClaim({...})`
66
+ // embedded directly in a StatefulSet's `volumeClaimTemplates`) has no
67
+ // logical name to Ref — it was never a key in `entities`, so
68
+ // resolveAttrRefs() never assigns one. Falling through to the generic
69
+ // "object" branch below would walk the Declarable's own enumerable
70
+ // properties, which for a Declarable are its self-referencing attribute
71
+ // accessors (AttrRef instances whose parent is the Declarable itself,
72
+ // still unresolved) — never its authored `.props`. That either threw
73
+ // "logical name not set" (when the resource type declares any
74
+ // attributes) or silently serialized as `{}` (when it doesn't), instead
75
+ // of the embedded spec the caller wrote. Embed its own props inline
76
+ // instead, exactly like a property-kind Declarable already does.
77
+ return visitor.propertyDeclarable(decl, (v) => walkValue(v, entityNames, visitor));
64
78
  }
65
79
 
66
80
  // Handle arrays