@intentius/chant 0.67.0 → 0.68.1

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/attrref.d.ts CHANGED
@@ -19,6 +19,27 @@ export declare class AttrRef implements Intrinsic {
19
19
  * Get the logical name assigned to this attribute reference.
20
20
  */
21
21
  getLogicalName(): string | undefined;
22
+ /**
23
+ * Refuse to become a string (#2349).
24
+ *
25
+ * An `AttrRef` stands for a value the build resolves later, so it has no
26
+ * string form here. Without this, `` `${bucket.arn}-suffix` `` produced
27
+ * `"[object Object]-suffix"` and shipped it — and the fold path produced
28
+ * exactly the same wrong string from the `{__attrRef}` envelope, so the two
29
+ * paths agreed and the differential harness reported nothing. Agreement on a
30
+ * wrong value is the failure this class of check exists to catch, which is
31
+ * why this throws rather than returning something more helpful-looking.
32
+ *
33
+ * `toJSON` below is the honest serialization and is untouched: a serializer
34
+ * that wants the envelope asks for it by name.
35
+ */
36
+ toString(): never;
37
+ /**
38
+ * The same refusal for `+` and for anything else that coerces, so
39
+ * `"prefix" + bucket.arn` fails where `` `${bucket.arn}` `` fails rather
40
+ * than taking a different path to the same wrong string.
41
+ */
42
+ [Symbol.toPrimitive](): never;
22
43
  /**
23
44
  * Serialize to a generic envelope. Lexicon-specific serializers should
24
45
  * read `getLogicalName()` and `attribute` directly instead of relying
@@ -1 +1 @@
1
- {"version":3,"file":"attrref.d.ts","sourceRoot":"","sources":["../src/attrref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,OAAQ,YAAW,SAAS;IACvC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAG,IAAI,CAAU;IAC5C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,WAAW,CAAC,CAAS;gBAEjB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAK7C;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,SAAS;IAIpC;;;;;OAKG;IACH,MAAM,IAAI;QAAE,SAAS,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAU/D"}
1
+ {"version":3,"file":"attrref.d.ts","sourceRoot":"","sources":["../src/attrref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,OAAQ,YAAW,SAAS;IACvC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAG,IAAI,CAAU;IAC5C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,WAAW,CAAC,CAAS;gBAEjB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAK7C;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,SAAS;IAIpC;;;;;;;;;;;;;OAaG;IACH,QAAQ,IAAI,KAAK;IAUjB;;;;OAIG;IACH,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK;IAI7B;;;;;OAKG;IACH,MAAM,IAAI;QAAE,SAAS,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAU/D"}
@@ -1 +1 @@
1
- {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"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"}
@@ -121,6 +121,16 @@ export type FoldedValue = string | number | boolean | null | undefined | FoldedV
121
121
  * invented shape: it's the existing envelope, produced without running the
122
122
  * module that would otherwise construct the real `AttrRef`.
123
123
  */
124
+ /**
125
+ * Which symbolic envelope a folded value is, in words a message can use — or
126
+ * `undefined` for a value that has an honest string form.
127
+ *
128
+ * These are the shapes `fold()` produces for things the build resolves later:
129
+ * a resource attribute, a lexicon intrinsic in either of its two forms, and a
130
+ * registered authoring helper. None of them can be concatenated into a string
131
+ * here, because what they stand for is not known until the build runs.
132
+ */
133
+ export declare function symbolicEnvelopeKind(value: unknown): string | undefined;
124
134
  export interface AttrRefValue {
125
135
  __attrRef: {
126
136
  entity: string;
@@ -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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"}
@@ -0,0 +1,3 @@
1
+ import type { LintRule } from "../rule.js";
2
+ export declare const evl011SymbolicInTemplateRule: LintRule;
3
+ //# sourceMappingURL=evl011-symbolic-in-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evl011-symbolic-in-template.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/evl011-symbolic-in-template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAA+B,MAAM,SAAS,CAAC;AAwFrE,eAAO,MAAM,4BAA4B,EAAE,QAU1C,CAAC"}
@@ -21,6 +21,7 @@ export { evl005ResourceBlockBodyRule } from "./evl005-resource-block-body.js";
21
21
  export { evl007InvalidSiblingsRule } from "./evl007-invalid-siblings.js";
22
22
  export { evl009CompositeNoConstantRule } from "./evl009-composite-no-constant.js";
23
23
  export { evl010CompositeNoTransformRule } from "./evl010-composite-no-transform.js";
24
+ export { evl011SymbolicInTemplateRule } from "./evl011-symbolic-in-template.js";
24
25
  export { cor017CompositeNameMatchRule } from "./cor017-composite-name-match.js";
25
26
  export { cor018CompositePreferLexiconTypeRule } from "./cor018-composite-prefer-lexicon-type.js";
26
27
  export { cor021EnvLiteralNameRule } from "./cor021-env-literal-name.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3G,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AA2B7D;;GAEG;AACH,wBAAgB,aAAa,IAAI,QAAQ,EAAE,CA2B1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3G,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AA4B7D;;GAEG;AACH,wBAAgB,aAAa,IAAI,QAAQ,EAAE,CA4B1C"}
@@ -66,6 +66,16 @@ export declare const sanitizeOneLine: typeof sanitizeLedgerText;
66
66
  * The gate a gated `chant run` stopped at, read off its JSON result (#2119) —
67
67
  * pure, unit-tested directly rather than only through `dispatchOp`'s
68
68
  * subprocess plumbing. `undefined` when the output says nothing about a gate.
69
+ *
70
+ * Reads `gate.name`, matching a real `OpRunStatus`/`OpRunRecord`
71
+ * (`../runtime.ts`'s own `gate?: { name: string; since: string }`) — a gated
72
+ * run's record never carries a nested field literally named `gate`. Checking
73
+ * `gate.gate` instead (chant#2396) is `typeof undefined === "string"`, always
74
+ * false, so every gated dispatch fell through to the regex below, which also
75
+ * never matches a `--json` result: the phrase it looks for belongs to the
76
+ * human-readable render `--json` mode suppresses. The regex stays as the
77
+ * fallback for exactly that human-mode case, where the caller's output is
78
+ * prose rather than JSON.
69
79
  */
70
80
  export declare function classifyDispatchFailure(raw: string): {
71
81
  gateName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../../../src/op/activities/converge.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AAQzC,+JAA+J;AAC/J,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACxC,mHAAmH;IACnH,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,gIAAgI;IAChI,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,2BAAqB,CAAC;AA0BlD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAerF;AA0CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAKtH;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,SAAS,EAAE,WAAW,GAAG,SAAS,GACjC,mBAAmB,CAWrB;AAaD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,sBAAsB,EAAE,EAC/B,YAAY,EAAE,kBAAkB,EAAE,EAClC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,GACb,gBAAgB,CAmDlB;AAoBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyF5G"}
1
+ {"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../../../src/op/activities/converge.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AAQzC,+JAA+J;AAC/J,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACxC,mHAAmH;IACnH,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,gIAAgI;IAChI,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,2BAAqB,CAAC;AA0BlD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAerF;AA0CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAKtH;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,SAAS,EAAE,WAAW,GAAG,SAAS,GACjC,mBAAmB,CAWrB;AAaD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,sBAAsB,EAAE,EAC/B,YAAY,EAAE,kBAAkB,EAAE,EAClC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,GACb,gBAAgB,CAmDlB;AAoBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyF5G"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.67.0",
3
+ "version": "0.68.1",
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",
@@ -146,3 +146,34 @@ describe("AttrRef", () => {
146
146
  });
147
147
  });
148
148
  });
149
+
150
+ describe("stringification is refused (#2349)", () => {
151
+ test("a template literal throws instead of yielding \"[object Object]\"", () => {
152
+ const ref = new AttrRef({}, "arn");
153
+ expect(() => `${ref}`).toThrow(/no string form/);
154
+ });
155
+
156
+ test("concatenation takes the same path, not a different one to the same wrong string", () => {
157
+ const ref = new AttrRef({}, "arn");
158
+ expect(() => "prefix-" + (ref as unknown as string)).toThrow(/no string form/);
159
+ });
160
+
161
+ test("the message names the attribute and points at the remedy", () => {
162
+ const ref = new AttrRef({}, "arn");
163
+ ref._setLogicalName("Bucket");
164
+ try {
165
+ `${ref}`;
166
+ throw new Error("expected a refusal");
167
+ } catch (e) {
168
+ const m = (e as Error).message;
169
+ expect(m).toContain("Bucket.arn");
170
+ expect(m).toMatch(/Sub|intrinsic/);
171
+ }
172
+ });
173
+
174
+ test("toJSON is untouched — a serializer that wants the envelope asks by name", () => {
175
+ const ref = new AttrRef({}, "arn");
176
+ ref._setLogicalName("Bucket");
177
+ expect(ref.toJSON()).toEqual({ __attrRef: { entity: "Bucket", attribute: "arn" } });
178
+ });
179
+ });
package/src/attrref.ts CHANGED
@@ -31,6 +31,39 @@ export class AttrRef implements Intrinsic {
31
31
  return this.logicalName;
32
32
  }
33
33
 
34
+ /**
35
+ * Refuse to become a string (#2349).
36
+ *
37
+ * An `AttrRef` stands for a value the build resolves later, so it has no
38
+ * string form here. Without this, `` `${bucket.arn}-suffix` `` produced
39
+ * `"[object Object]-suffix"` and shipped it — and the fold path produced
40
+ * exactly the same wrong string from the `{__attrRef}` envelope, so the two
41
+ * paths agreed and the differential harness reported nothing. Agreement on a
42
+ * wrong value is the failure this class of check exists to catch, which is
43
+ * why this throws rather than returning something more helpful-looking.
44
+ *
45
+ * `toJSON` below is the honest serialization and is untouched: a serializer
46
+ * that wants the envelope asks for it by name.
47
+ */
48
+ toString(): never {
49
+ const where = this.logicalName ? `${this.logicalName}.${this.attribute}` : `.${this.attribute}`;
50
+ throw new Error(
51
+ `A resource attribute reference (${where}) has no string form: it stands for a value the build ` +
52
+ "resolves later, and interpolating it into a plain template literal would produce " +
53
+ '"[object Object]". Use the lexicon\'s own intrinsic, whose interior handles references — ' +
54
+ "`Sub`${…}`` for CloudFormation — or move the reference out of the template.",
55
+ );
56
+ }
57
+
58
+ /**
59
+ * The same refusal for `+` and for anything else that coerces, so
60
+ * `"prefix" + bucket.arn` fails where `` `${bucket.arn}` `` fails rather
61
+ * than taking a different path to the same wrong string.
62
+ */
63
+ [Symbol.toPrimitive](): never {
64
+ return this.toString();
65
+ }
66
+
34
67
  /**
35
68
  * Serialize to a generic envelope. Lexicon-specific serializers should
36
69
  * read `getLogicalName()` and `attribute` directly instead of relying
@@ -197,6 +197,76 @@ describe("composite factory interpretation (chant #1023)", () => {
197
197
  expect([...result.entities.keys()].sort()).toEqual(["webBucket", "webRole"]);
198
198
  });
199
199
 
200
+
201
+ // ───────────────────────────────────────────────────────────────────────
202
+ // The interpretation depth bound (#2370).
203
+ // ───────────────────────────────────────────────────────────────────────
204
+
205
+ /**
206
+ * A chain of composites each calling the next, `depth` links long, across
207
+ * separate modules so every link is a fresh `resolveInterpretableFactory`.
208
+ * Link 0 is the one `main.ts` calls; the last link builds a real resource.
209
+ */
210
+ async function writeChain(depth: number): Promise<void> {
211
+ for (let i = 0; i < depth; i++) {
212
+ const isLast = i === depth - 1;
213
+ const body = isLast
214
+ ? `(props) => ({ bucket: new Bucket({ BucketName: props.name }) })`
215
+ : `(props) => ({ inner: Link${i + 1}({ name: props.name }) })`;
216
+ await writeFile(
217
+ join(testDir, `link${i}.ts`),
218
+ `
219
+ import { Bucket } from ${JSON.stringify(LEXICON)};
220
+ import { Composite } from ${JSON.stringify(compositePath)};
221
+ ${isLast ? "" : `import { Link${i + 1} } from "./link${i + 1}";`}
222
+ export const Link${i} = Composite(${body}, "Link${i}");
223
+ `,
224
+ );
225
+ }
226
+ await writeFile(
227
+ join(srcDir, "main.ts"),
228
+ `
229
+ import { Link0 } from ${JSON.stringify(join(testDir, "link0"))};
230
+ export const top = Link0({ name: "deep" });
231
+ `,
232
+ );
233
+ }
234
+
235
+ test("a chain within the bound interprets all the way down", async () => {
236
+ // The control. Without this, a test asserting the deep chain falls back
237
+ // proves only that something went wrong somewhere.
238
+ await writeChain(4);
239
+
240
+ const result = await discover(srcDir, { fold: true, lexicons: [LEXICON_NAME] });
241
+
242
+ expect(result.errors).toEqual([]);
243
+ expect(result.foldDecisions.find((d) => d.file.endsWith("main.ts"))?.mode).toBe("fold");
244
+ expect(foldExecutionCounts()).toMatchObject({ factoryInterpretations: 4, projectFactoryInvocations: 0 });
245
+ });
246
+
247
+ test("exhausting the bound falls the file back to run, naming the bound", async () => {
248
+ // 17 links against a bound of 16. Before #2370 this returned the "not
249
+ // interpretable" answer, so the factory was invoked and the file was
250
+ // still reported folded — a different evaluation than the one reported,
251
+ // with nothing in the output saying so.
252
+ await writeChain(17);
253
+
254
+ const result = await discover(srcDir, { fold: true, lexicons: [LEXICON_NAME] });
255
+
256
+ const decision = result.foldDecisions.find((d) => d.file.endsWith("main.ts"));
257
+ expect(decision?.mode).toBe("run");
258
+ expect(decision?.reason).toMatch(/interpretation depth exceeded 16/);
259
+ // The remedy half of the message: what a reader should suspect.
260
+ expect(decision?.reason).toMatch(/recursive/);
261
+ // Falling back means the estate is still built, by the other path. F-Depth
262
+ // asks for a fallback, not a failure.
263
+ expect(result.errors).toEqual([]);
264
+ // And it is a fallback rather than a degradation: the factory was not
265
+ // invoked instead. Before #2370 this read `projectFactoryInvocations: 1`
266
+ // with the file still reported folded.
267
+ expect(foldExecutionCounts()).toMatchObject({ projectFactoryInvocations: 0, factoryInvocations: 0 });
268
+ });
269
+
200
270
  test("a sibling reference inside the body is a LIVE AttrRef on the real instance", async () => {
201
271
  await writeComposite(ADMISSIBLE_BODY);
202
272
  await writeMain(CALL_WEBAPP);
@@ -1769,9 +1769,39 @@ async function resolveCallArguments(
1769
1769
  * inside one module's source, crossing no file boundary — so this is what
1770
1770
  * terminates it. Deliberately small: real composite nesting is 2-3 deep, and a
1771
1771
  * chain past this is a bug, not a design.
1772
+ *
1773
+ * Exhausting it falls the file back to run, naming this bound (#2370). That is
1774
+ * the second half of the specification's `F-Depth`: an implementation states
1775
+ * its bounds and, on exhaustion, falls back rather than fails. The other two —
1776
+ * {@link MAX_RESOLUTION_DEPTH} and `fold()`'s `MAX_FUNCTION_CALL_DEPTH` —
1777
+ * already did.
1778
+ *
1779
+ * It previously returned `undefined` here, which
1780
+ * {@link resolveInterpretableFactory}'s contract defines as "not
1781
+ * interpretable", so the caller invoked the factory instead and the file was
1782
+ * still reported as folded. That conflated two different facts: a factory
1783
+ * whose shape is outside the subset (invoking it is correct) and a factory we
1784
+ * stopped looking at (invoking it is a different evaluation than the one being
1785
+ * reported). The first is a verdict; the second was a silent degradation, and
1786
+ * a reader comparing chant's output against the reference implementation's
1787
+ * "fell back at depth 16" had nothing to explain the difference.
1772
1788
  */
1773
1789
  const MAX_INTERPRETATION_DEPTH = 16;
1774
1790
 
1791
+ /**
1792
+ * Exhaustion of {@link MAX_INTERPRETATION_DEPTH}, as its own type so it can
1793
+ * pass through {@link interpretCompositeFactory}'s decline.
1794
+ *
1795
+ * That decline — a blanket `catch { return undefined }` — is right for every
1796
+ * other failure inside a factory body: the body turned out not to interpret,
1797
+ * the caller invokes it instead, and the file still folds. It is wrong for
1798
+ * this one, because giving up at a depth bound is not a statement about the
1799
+ * body. Without a type to test, the depth error was caught by the *enclosing*
1800
+ * interpretation, declined, and the factory invoked — which is how the bound
1801
+ * came to be silent (#2370).
1802
+ */
1803
+ class InterpretationDepthError extends FoldError {}
1804
+
1775
1805
  /**
1776
1806
  * The static scope of a module that DEFINES composites — everything
1777
1807
  * interpreting one of its factory bodies needs, computed once per module per
@@ -1969,7 +1999,18 @@ async function resolveInterpretableFactory(
1969
1999
  // Rule 1 — project files only. A text check; no resolution performed for a
1970
2000
  // bare specifier, so this costs nothing for the (common) lexicon case.
1971
2001
  if (!isProjectFileSpecifier(binding.specifier)) return undefined;
1972
- if (ctx.interpretDepth >= MAX_INTERPRETATION_DEPTH) return undefined;
2002
+ // Not `undefined`: that answer means "not interpretable" and would invoke
2003
+ // the factory while still reporting the file folded. Giving up is a
2004
+ // different fact and falls the file back to run, naming the bound (#2370).
2005
+ if (ctx.interpretDepth >= MAX_INTERPRETATION_DEPTH) {
2006
+ throw new InterpretationDepthError(
2007
+ `interpretation depth exceeded ${MAX_INTERPRETATION_DEPTH} at "${binding.imported}" — a composite ` +
2008
+ "chain this deep is almost certainly recursive. Falling back to run rather than invoking the " +
2009
+ "factory, which would have reported this file as folded while evaluating it a different way.",
2010
+ 0,
2011
+ 0,
2012
+ );
2013
+ }
1973
2014
 
1974
2015
  let modulePath: string;
1975
2016
  try {
@@ -2346,7 +2387,12 @@ async function interpretCompositeFactory(
2346
2387
  const instance = definition();
2347
2388
  executionCounts.factoryInterpretations += 1;
2348
2389
  return { value: instance };
2349
- } catch {
2390
+ } catch (err) {
2391
+ // Every other failure here means "this body did not interpret" and the
2392
+ // caller invokes instead. Exhausting the depth bound means "we stopped
2393
+ // looking", which has to reach the file's fold verdict rather than be
2394
+ // answered with an invocation (#2370).
2395
+ if (err instanceof InterpretationDepthError) throw err;
2350
2396
  return undefined;
2351
2397
  }
2352
2398
  }
@@ -66,6 +66,59 @@ describe("fold — template interpolation", () => {
66
66
  });
67
67
  });
68
68
 
69
+ describe("fold — a symbolic value in a plain template (#2349)", () => {
70
+ // The bug this replaces: both paths produced "[object Object]" and agreed,
71
+ // so the differential harness — the thing that catches everything else —
72
+ // saw agreement and said nothing.
73
+ test("an attribute reference is refused, located, and names the entity", () => {
74
+ const src = `
75
+ const bucket = new S3Bucket({ name: "my-bucket" });
76
+ const x = \`\${bucket.arn}-suffix\`;
77
+ `;
78
+ expect(() => foldConst(src, "x")).toThrow(FoldError);
79
+ try {
80
+ foldConst(src, "x");
81
+ } catch (e) {
82
+ const err = e as FoldError;
83
+ expect(err.message).toContain("bucket.arn");
84
+ expect(err.message).toContain("[object Object]");
85
+ // The remedy, not just the complaint.
86
+ expect(err.message).toMatch(/Sub|intrinsic/);
87
+ // Located on the span, so an editor can point at it.
88
+ expect(err.line).toBeGreaterThan(0);
89
+ expect(err.column).toBeGreaterThan(0);
90
+ }
91
+ });
92
+
93
+ test("the run path refuses the same program rather than producing the wrong string", () => {
94
+ // The other half of #2349: a file that falls back to run must not quietly
95
+ // succeed where fold refused. `AttrRef.toString` throws, so the two paths
96
+ // now refuse together instead of agreeing on a wrong value.
97
+ const Bucket = createResource("S3Bucket", "aws", { arn: "arn" });
98
+ const bucket = new Bucket({ name: "my-bucket" }) as unknown as Declarable & { arn: AttrRef };
99
+ expect(() => `${bucket.arn}-suffix`).toThrow(/no string form/);
100
+ expect(() => "prefix" + (bucket.arn as unknown as string)).toThrow(/no string form/);
101
+ });
102
+
103
+ test("an ordinary value in a template still interpolates", () => {
104
+ const src = `
105
+ const region = "us-east-1";
106
+ const x = \`bucket-\${region}\`;
107
+ `;
108
+ expect(foldConst(src, "x")).toBe("bucket-us-east-1");
109
+ });
110
+
111
+ test("a tagged template is untouched — that is the documented idiom", () => {
112
+ // The refusal is about *plain* templates. The intrinsic form handles
113
+ // envelopes in its interior and must keep doing so.
114
+ const src = `
115
+ const bucket = new S3Bucket({ name: "my-bucket" });
116
+ const x = Sub\`\${bucket.arn}-suffix\`;
117
+ `;
118
+ expect(() => foldConst(src, "x")).not.toThrow(/no string form/);
119
+ });
120
+ });
121
+
69
122
  describe("fold — objects and spread", () => {
70
123
  test("object literal with property and shorthand assignment", () => {
71
124
  const src = `
package/src/fold/fold.ts CHANGED
@@ -151,6 +151,31 @@ export type FoldedValue =
151
151
  * invented shape: it's the existing envelope, produced without running the
152
152
  * module that would otherwise construct the real `AttrRef`.
153
153
  */
154
+ /**
155
+ * Which symbolic envelope a folded value is, in words a message can use — or
156
+ * `undefined` for a value that has an honest string form.
157
+ *
158
+ * These are the shapes `fold()` produces for things the build resolves later:
159
+ * a resource attribute, a lexicon intrinsic in either of its two forms, and a
160
+ * registered authoring helper. None of them can be concatenated into a string
161
+ * here, because what they stand for is not known until the build runs.
162
+ */
163
+ export function symbolicEnvelopeKind(value: unknown): string | undefined {
164
+ if (typeof value !== "object" || value === null) return undefined;
165
+ const v = value as Record<string, unknown>;
166
+ if ("__attrRef" in v) {
167
+ const ref = v.__attrRef as { entity?: unknown; attribute?: unknown } | undefined;
168
+ const named =
169
+ typeof ref?.entity === "string" && typeof ref?.attribute === "string"
170
+ ? ` (${ref.entity}.${ref.attribute})`
171
+ : "";
172
+ return `a resource attribute reference${named}`;
173
+ }
174
+ if ("__intrinsic" in v && typeof v.__intrinsic === "string") return `the intrinsic \`${v.__intrinsic}\``;
175
+ if ("__helper" in v && typeof v.__helper === "string") return `the helper \`${v.__helper}\``;
176
+ return undefined;
177
+ }
178
+
154
179
  export interface AttrRefValue {
155
180
  __attrRef: { entity: string; attribute: string };
156
181
  }
@@ -1028,7 +1053,24 @@ export function fold(
1028
1053
  if (ts.isTemplateExpression(node)) {
1029
1054
  let out = node.head.text;
1030
1055
  for (const span of node.templateSpans) {
1031
- out += String(fold(span.expression, consts, intrinsics, externals)) + span.literal.text;
1056
+ const value = fold(span.expression, consts, intrinsics, externals);
1057
+ // A symbolic envelope has no string form. `String({__attrRef: …})` is
1058
+ // `"[object Object]"`, and so is `String(attrRef)` on the run path,
1059
+ // because `../attrref.ts` defines no `toString` — so the two paths
1060
+ // agreed on a wrong answer and the differential saw nothing (#2349).
1061
+ // Refused here rather than stringified, for the same reason the
1062
+ // eager-intrinsic branch refuses a deferred envelope (#1966).
1063
+ const symbolic = symbolicEnvelopeKind(value);
1064
+ if (symbolic) {
1065
+ throw foldError(
1066
+ span.expression,
1067
+ `${symbolic} interpolated into a plain template literal, which would stringify it as ` +
1068
+ '"[object Object]". A symbolic value has no string form until the build resolves it, so a ' +
1069
+ "plain template cannot carry one. Use the lexicon's own intrinsic, whose interior handles " +
1070
+ "envelopes — `Sub`${…}`` for CloudFormation — or move the reference out of the template.",
1071
+ );
1072
+ }
1073
+ out += String(value) + span.literal.text;
1032
1074
  }
1033
1075
  return out;
1034
1076
  }
@@ -0,0 +1,88 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import * as ts from "typescript";
3
+ import { evl011SymbolicInTemplateRule } from "./evl011-symbolic-in-template";
4
+ import type { LintContext } from "../rule";
5
+
6
+ function createContext(code: string, filePath = "test.ts"): LintContext {
7
+ const sourceFile = ts.createSourceFile(filePath, code, ts.ScriptTarget.Latest, true);
8
+ return { sourceFile, entities: [], filePath, lexicon: undefined };
9
+ }
10
+
11
+ describe("EVL011: a symbolic reference in a plain template", () => {
12
+ test("rule metadata", () => {
13
+ expect(evl011SymbolicInTemplateRule.id).toBe("EVL011");
14
+ expect(evl011SymbolicInTemplateRule.severity).toBe("error");
15
+ expect(evl011SymbolicInTemplateRule.category).toBe("correctness");
16
+ });
17
+
18
+ test("flags a resource attribute in a plain template, at the reference", () => {
19
+ const ctx = createContext(`
20
+ const bucket = new S3Bucket({ name: "b" });
21
+ const x = \`\${bucket.arn}-suffix\`;
22
+ `);
23
+ const found = evl011SymbolicInTemplateRule.check(ctx);
24
+ expect(found).toHaveLength(1);
25
+ expect(found[0].ruleId).toBe("EVL011");
26
+ expect(found[0].message).toContain("bucket.arn");
27
+ // The remedy, not just the complaint — the whole reason this rule exists
28
+ // alongside a refusal that already fails the build.
29
+ expect(found[0].message).toMatch(/Sub|intrinsic/);
30
+ expect(found[0].line).toBe(3);
31
+ });
32
+
33
+ test("flags every offending span, not just the first", () => {
34
+ const ctx = createContext(`
35
+ const bucket = new S3Bucket({ name: "b" });
36
+ const queue = new Queue({ name: "q" });
37
+ const x = \`\${bucket.arn}/\${queue.url}\`;
38
+ `);
39
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(2);
40
+ });
41
+
42
+ test("allows a tagged template — that is the documented remedy", () => {
43
+ const ctx = createContext(`
44
+ const bucket = new S3Bucket({ name: "b" });
45
+ const x = Sub\`\${bucket.arn}-suffix\`;
46
+ `);
47
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(0);
48
+ });
49
+
50
+ test("allows an ordinary const in a template", () => {
51
+ const ctx = createContext(`
52
+ const region = "us-east-1";
53
+ const x = \`bucket-\${region}\`;
54
+ `);
55
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(0);
56
+ });
57
+
58
+ test("allows a property access on something that is not a resource", () => {
59
+ // The false positive worth avoiding: this code works, and flagging it
60
+ // would train people to suppress the rule.
61
+ const ctx = createContext(`
62
+ const config = { region: "us-east-1" };
63
+ const x = \`bucket-\${config.region}\`;
64
+ `);
65
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(0);
66
+ });
67
+
68
+ test("says nothing about a reference outside a template", () => {
69
+ const ctx = createContext(`
70
+ const bucket = new S3Bucket({ name: "b" });
71
+ const x = bucket.arn;
72
+ `);
73
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(0);
74
+ });
75
+
76
+ test("a missed shape is a cost the refusal already covers", () => {
77
+ // Reached through an array rather than a plain identifier: lint sees
78
+ // syntax, not values, so this is not flagged — and `fold()` still refuses
79
+ // it (#2349). Documented as a deliberate limit rather than left to be
80
+ // discovered as a gap.
81
+ const ctx = createContext(`
82
+ const bucket = new S3Bucket({ name: "b" });
83
+ const all = [bucket];
84
+ const x = \`\${all[0].arn}-suffix\`;
85
+ `);
86
+ expect(evl011SymbolicInTemplateRule.check(ctx)).toHaveLength(0);
87
+ });
88
+ });
@@ -0,0 +1,100 @@
1
+ import * as ts from "typescript";
2
+ import type { LintRule, LintContext, LintDiagnostic } from "../rule";
3
+
4
+ /**
5
+ * EVL011: a symbolic reference inside a plain template literal
6
+ *
7
+ * `` `${bucket.arn}-suffix` `` cannot be evaluated to a string. A resource
8
+ * attribute stands for a value the build resolves later, so there is nothing
9
+ * to interpolate yet, and JavaScript's answer — `"[object Object]"` — is
10
+ * wrong on both of chant's paths.
11
+ *
12
+ * This rule is the friendly half of #2349. The unfriendly half already landed:
13
+ * `fold()` refuses the span with a located error and `AttrRef.toString` throws,
14
+ * so the program fails either way. What a rule adds is finding it at lint time
15
+ * with the remedy attached, rather than at build time with a stack.
16
+ *
17
+ * ## Why it is a heuristic, and why that is acceptable here
18
+ *
19
+ * Lint sees syntax, not values. `foo.bar` inside a template is a resource
20
+ * attribute only if `foo` is a resource, which is a fact `fold()` has and this
21
+ * rule does not — so the check is: a property access whose object is a
22
+ * plain identifier bound in this file by `new`. That is the shape #2349 was
23
+ * reported against and the shape a lexicon's own docs show.
24
+ *
25
+ * It therefore misses a reference reached some other way (through a parameter,
26
+ * an array, a helper's return) and does not flag an access on a plain object.
27
+ * Missing a case costs nothing, because `fold()` still refuses it; flagging a
28
+ * plain object would be a false positive on code that works, which is the
29
+ * error worth avoiding. This is the same asymmetry `../../fold/subset.ts`
30
+ * documents for EVL generally, pointed the other way: there EVL may be
31
+ * stricter than fold, here it is deliberately looser.
32
+ */
33
+
34
+ /** Identifiers bound by `const x = new T(...)` at any depth in this file. */
35
+ function resourceBindings(sourceFile: ts.SourceFile): Set<string> {
36
+ const names = new Set<string>();
37
+ const visit = (node: ts.Node): void => {
38
+ if (
39
+ ts.isVariableDeclaration(node) &&
40
+ ts.isIdentifier(node.name) &&
41
+ node.initializer &&
42
+ ts.isNewExpression(node.initializer)
43
+ ) {
44
+ names.add(node.name.text);
45
+ }
46
+ ts.forEachChild(node, visit);
47
+ };
48
+ visit(sourceFile);
49
+ return names;
50
+ }
51
+
52
+ function checkNode(
53
+ node: ts.Node,
54
+ context: LintContext,
55
+ bound: Set<string>,
56
+ diagnostics: LintDiagnostic[],
57
+ ): void {
58
+ // Untagged only: a tagged template is the documented remedy, and its
59
+ // interior handles envelopes.
60
+ if (ts.isTemplateExpression(node) && !ts.isTaggedTemplateExpression(node.parent)) {
61
+ for (const span of node.templateSpans) {
62
+ const expr = span.expression;
63
+ if (
64
+ ts.isPropertyAccessExpression(expr) &&
65
+ ts.isIdentifier(expr.expression) &&
66
+ bound.has(expr.expression.text)
67
+ ) {
68
+ const { line, character } = context.sourceFile.getLineAndCharacterOfPosition(
69
+ expr.getStart(context.sourceFile),
70
+ );
71
+ diagnostics.push({
72
+ file: context.filePath,
73
+ line: line + 1,
74
+ column: character + 1,
75
+ ruleId: "EVL011",
76
+ severity: "error",
77
+ message:
78
+ `\`${expr.expression.text}.${expr.name.text}\` is a resource attribute and has no string ` +
79
+ "form until the build resolves it — a plain template would stringify it as " +
80
+ "\"[object Object]\". Use the lexicon's own intrinsic, whose interior handles references " +
81
+ "(`Sub`${…}`` for CloudFormation), or move the reference out of the template.",
82
+ });
83
+ }
84
+ }
85
+ }
86
+
87
+ ts.forEachChild(node, (child) => checkNode(child, context, bound, diagnostics));
88
+ }
89
+
90
+ export const evl011SymbolicInTemplateRule: LintRule = {
91
+ id: "EVL011",
92
+ severity: "error",
93
+ category: "correctness",
94
+ description: "A resource attribute cannot be interpolated into a plain template literal",
95
+ check(context: LintContext): LintDiagnostic[] {
96
+ const diagnostics: LintDiagnostic[] = [];
97
+ checkNode(context.sourceFile, context, resourceBindings(context.sourceFile), diagnostics);
98
+ return diagnostics;
99
+ },
100
+ };
@@ -23,6 +23,7 @@ export { evl005ResourceBlockBodyRule } from "./evl005-resource-block-body";
23
23
  export { evl007InvalidSiblingsRule } from "./evl007-invalid-siblings";
24
24
  export { evl009CompositeNoConstantRule } from "./evl009-composite-no-constant";
25
25
  export { evl010CompositeNoTransformRule } from "./evl010-composite-no-transform";
26
+ export { evl011SymbolicInTemplateRule } from "./evl011-symbolic-in-template";
26
27
  export { cor017CompositeNameMatchRule } from "./cor017-composite-name-match";
27
28
  export { cor018CompositePreferLexiconTypeRule } from "./cor018-composite-prefer-lexicon-type";
28
29
  export { cor021EnvLiteralNameRule } from "./cor021-env-literal-name";
@@ -49,6 +50,7 @@ import { evl005ResourceBlockBodyRule } from "./evl005-resource-block-body";
49
50
  import { evl007InvalidSiblingsRule } from "./evl007-invalid-siblings";
50
51
  import { evl009CompositeNoConstantRule } from "./evl009-composite-no-constant";
51
52
  import { evl010CompositeNoTransformRule } from "./evl010-composite-no-transform";
53
+ import { evl011SymbolicInTemplateRule } from "./evl011-symbolic-in-template";
52
54
  import { cor017CompositeNameMatchRule } from "./cor017-composite-name-match";
53
55
  import { cor018CompositePreferLexiconTypeRule } from "./cor018-composite-prefer-lexicon-type";
54
56
  import { cor021EnvLiteralNameRule } from "./cor021-env-literal-name";
@@ -79,6 +81,7 @@ export function loadCoreRules(): LintRule[] {
79
81
  evl007InvalidSiblingsRule,
80
82
  evl009CompositeNoConstantRule,
81
83
  evl010CompositeNoTransformRule,
84
+ evl011SymbolicInTemplateRule,
82
85
  cor017CompositeNameMatchRule,
83
86
  cor018CompositePreferLexiconTypeRule,
84
87
  cor021EnvLiteralNameRule,
@@ -307,12 +307,38 @@ describe("classifyDispatchFailure", () => {
307
307
  const raw = JSON.stringify({
308
308
  op: "fountain-apply",
309
309
  status: "gated",
310
- gate: { version: 1, kind: "pending", op: "fountain-apply", gate: "rollout-gate", timestamp: "t", expiresAt: "t2" },
310
+ gate: { name: "rollout-gate", since: "t2" },
311
311
  records: [],
312
312
  });
313
313
  expect(classifyDispatchFailure(raw)).toEqual({ gateName: "rollout-gate" });
314
314
  });
315
315
 
316
+ // chant#2396: a real gated `OpRunRecord` (`../runtime.ts`'s own
317
+ // `gate?: { name: string; since: string }`) never carries a nested field
318
+ // literally named `gate` — `parsed.gate?.gate` is always `undefined`, so
319
+ // this used to fall through to a regex that never matches `--json` output
320
+ // either, and a `ConvergeOp` tick recorded every gated dispatch as an
321
+ // ordinary "reported" failure. This is the exact record shape
322
+ // `TerraformApplyOp`'s own `chant run dev-apply --json` printed while
323
+ // building `examples/converge-operator` against a live floci.
324
+ test("reads the gate off a real gated Op run record — gate.name, not gate.gate (#2396)", () => {
325
+ const raw = JSON.stringify({
326
+ version: 1,
327
+ id: "local-abc123",
328
+ op: "dev-apply",
329
+ env: "dev",
330
+ started: "2026-09-11T05:39:16.000Z",
331
+ ended: "2026-09-11T05:39:16.058Z",
332
+ status: "gated",
333
+ labels: {},
334
+ outcomes: {},
335
+ phases: [],
336
+ gate: { name: "approve-dev-apply", since: "2026-09-11T05:39:16.058Z" },
337
+ approve: "chant approve dev-apply approve-dev-apply",
338
+ });
339
+ expect(classifyDispatchFailure(raw)).toEqual({ gateName: "approve-dev-apply" });
340
+ });
341
+
316
342
  test("falls back to the human summary line, wherever it appears in the output", () => {
317
343
  const raw = 'some earlier noise\nOp "prod-apply" is gated on "prod-approval" after 0.3s\n approve : chant approve prod-apply prod-approval';
318
344
  expect(classifyDispatchFailure(raw)).toEqual({ gateName: "prod-approval" });
@@ -153,15 +153,25 @@ const GATED_EXIT_CODE = 3;
153
153
  * The gate a gated `chant run` stopped at, read off its JSON result (#2119) —
154
154
  * pure, unit-tested directly rather than only through `dispatchOp`'s
155
155
  * subprocess plumbing. `undefined` when the output says nothing about a gate.
156
+ *
157
+ * Reads `gate.name`, matching a real `OpRunStatus`/`OpRunRecord`
158
+ * (`../runtime.ts`'s own `gate?: { name: string; since: string }`) — a gated
159
+ * run's record never carries a nested field literally named `gate`. Checking
160
+ * `gate.gate` instead (chant#2396) is `typeof undefined === "string"`, always
161
+ * false, so every gated dispatch fell through to the regex below, which also
162
+ * never matches a `--json` result: the phrase it looks for belongs to the
163
+ * human-readable render `--json` mode suppresses. The regex stays as the
164
+ * fallback for exactly that human-mode case, where the caller's output is
165
+ * prose rather than JSON.
156
166
  */
157
167
  export function classifyDispatchFailure(raw: string): { gateName: string } | undefined {
158
168
  for (const line of raw.split("\n")) {
159
169
  const trimmed = line.trim();
160
170
  if (!trimmed.startsWith("{")) continue;
161
171
  try {
162
- const parsed = JSON.parse(trimmed) as { status?: string; gate?: { gate?: string } };
163
- if (parsed.status === "gated" && typeof parsed.gate?.gate === "string") {
164
- return { gateName: parsed.gate.gate };
172
+ const parsed = JSON.parse(trimmed) as { status?: string; gate?: { name?: string } };
173
+ if (parsed.status === "gated" && typeof parsed.gate?.name === "string") {
174
+ return { gateName: parsed.gate.name };
165
175
  }
166
176
  } catch {
167
177
  // Not this line's JSON — keep looking.