@intentius/chant 0.72.5 → 0.74.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/build.d.ts +25 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/index.d.ts +14 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/fold/subset.d.ts +9 -6
- package/dist/fold/subset.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/build.test.ts +54 -1
- package/src/build.ts +52 -21
- package/src/discovery/fold-composite.test.ts +31 -4
- package/src/discovery/fold-import.test.ts +13 -7
- package/src/discovery/fold-import.ts +30 -0
- package/src/discovery/index.test.ts +8 -1
- package/src/discovery/index.ts +28 -1
- package/src/discovery/sandbox/fold-boundary.test.ts +26 -4
- package/src/fold/subset.ts +9 -6
- package/src/fold-provenance.test.ts +16 -1
package/dist/build.d.ts
CHANGED
|
@@ -56,6 +56,22 @@ export interface StackGraph {
|
|
|
56
56
|
* referencing an attribute of a resource in lexicon B ⇒ A depends on B). Returns
|
|
57
57
|
* the edge set plus a topological order, parallel-safe waves, and any cycles.
|
|
58
58
|
*/
|
|
59
|
+
/**
|
|
60
|
+
* Is this entity a member of a lexicon stack?
|
|
61
|
+
*
|
|
62
|
+
* Four kinds are not, and every one of them is serializer-neutral: a
|
|
63
|
+
* `LexiconOutput` is collected separately, a secret provenance declaration
|
|
64
|
+
* (#1828) and a plan scenario (#1292) are data lint and the CLI read off the
|
|
65
|
+
* entity map, and an Op (#2118) builds to its own `op.json` rather than
|
|
66
|
+
* through a lexicon serializer.
|
|
67
|
+
*
|
|
68
|
+
* {@link partitionByLexicon} has skipped all four since each landed, and
|
|
69
|
+
* {@link computeStackGraph}'s walk did not — so an entity with no `lexicon`
|
|
70
|
+
* (a `LexiconOutput`) entered `edges`, `order` and `waves` as `undefined`
|
|
71
|
+
* while `nodes`, built from the partition, could never contain it (#2480).
|
|
72
|
+
* One predicate for both sites, so they cannot drift apart again.
|
|
73
|
+
*/
|
|
74
|
+
export declare function isStackMember(entity: Declarable): boolean;
|
|
59
75
|
export declare function computeStackGraph(entities: Map<string, Declarable>, lexiconNames: string[]): StackGraph;
|
|
60
76
|
/**
|
|
61
77
|
* Result of the build process
|
|
@@ -110,6 +126,15 @@ export interface BuildOptions {
|
|
|
110
126
|
* (unchanged behavior/performance).
|
|
111
127
|
*/
|
|
112
128
|
sandbox?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* spec 2.0, `ι = executing` — invoke project-owned code at `F-Call` step 6
|
|
131
|
+
* instead of falling back. See {@link DiscoveryOptions.executing}.
|
|
132
|
+
*
|
|
133
|
+
* The fold's value is then what a run computes in this process, environment
|
|
134
|
+
* and all, which is why `open` is the default and is strict. Mutually
|
|
135
|
+
* exclusive with {@link sandbox}. Default `false`.
|
|
136
|
+
*/
|
|
137
|
+
executing?: boolean;
|
|
113
138
|
/**
|
|
114
139
|
* chant #1064 — this build's resolved build-time parameter values (see
|
|
115
140
|
* ./build-params.ts's `resolveBuildParams`, driven by the CLI's
|
package/dist/build.d.ts.map
CHANGED
|
@@ -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,EAAyB,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAiC,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAQlE,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,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|
|
@@ -92,6 +92,20 @@ export interface DiscoveryOptions {
|
|
|
92
92
|
* process, no IPC) and fold coverage, is unchanged unless requested.
|
|
93
93
|
*/
|
|
94
94
|
sandbox?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* spec 2.0, `ι = executing` — invoke project-owned code at `F-Call` step 6
|
|
97
|
+
* rather than falling back.
|
|
98
|
+
*
|
|
99
|
+
* `F-Call` step 5 makes a declarator whose callee resolves to a project file
|
|
100
|
+
* `run` under every other mode, so a build that wants the value a run would
|
|
101
|
+
* compute has to say so. The value is then this process's: the factory body
|
|
102
|
+
* and its module's top level execute here, environment and all, which is
|
|
103
|
+
* exactly why it cannot be the default.
|
|
104
|
+
*
|
|
105
|
+
* Mutually exclusive with {@link sandbox}, which refuses to import project
|
|
106
|
+
* code at all. Asking for both is a contradiction rather than a preference.
|
|
107
|
+
*/
|
|
108
|
+
executing?: boolean;
|
|
95
109
|
/**
|
|
96
110
|
* chant #1064 — this build's resolved build-time parameter values (see
|
|
97
111
|
* ../build-params.ts's `resolveBuildParams`, driven by the CLI's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AACA,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;AA8D1D;;;;;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;IACvB;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;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;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AACA,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;AA8D1D;;;;;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;IACvB;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;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;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;;;;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,CA8SjG"}
|
package/dist/fold/subset.d.ts
CHANGED
|
@@ -219,13 +219,16 @@ import { type IntrinsicDef } from "../lexicon.js";
|
|
|
219
219
|
* `sandbox`. `open` stays the default and stays strict (#2453).
|
|
220
220
|
*
|
|
221
221
|
* `scripts/check-docs-citations.ts` refuses to run when this constant and the
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
222
|
+
* rules it loads disagree, so this and the `@intentius/tsad-conformance`
|
|
223
|
+
* devDependency move together. That coupling is deliberate: it is what stops
|
|
224
|
+
* the docs being gated against a rule set nobody writes against — which is
|
|
225
|
+
* exactly what happened while this sat at `1.0` through six versions, passing
|
|
226
|
+
* because both sides were equally stale.
|
|
227
|
+
*
|
|
228
|
+
* Until chant#2470 the rules came from a commit `docs-check.yml` checked out;
|
|
229
|
+
* now they come from the published package, so bumping it is what moves this.
|
|
227
230
|
*/
|
|
228
|
-
export declare const SPEC_VERSION = "1
|
|
231
|
+
export declare const SPEC_VERSION = "2.1";
|
|
229
232
|
/** The two EVL rule ids a shape violation can be attributed to. */
|
|
230
233
|
export type SubsetRuleId = "EVL001" | "EVL003";
|
|
231
234
|
/** A located, shape-level rejection: the offending node, the EVL rule id it maps to, and a message. */
|
|
@@ -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,EAAiD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwKG;AAEH
|
|
1
|
+
{"version":3,"file":"subset.d.ts","sourceRoot":"","sources":["../../src/fold/subset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAiD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,eAAO,MAAM,YAAY,QAAQ,CAAC;AAElC,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;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAoDpF;AAgCD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAkO7B"}
|
package/package.json
CHANGED
package/src/build.test.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { describe, test, expect, beforeEach, afterEach, vi } from "vitest";
|
|
|
2
2
|
import { build, partitionByLexicon, detectCrossLexiconRefs, collectLexiconOutputs, computeStackGraph } from "./build";
|
|
3
3
|
import { output } from "./lexicon-output";
|
|
4
4
|
import { AttrRef } from "./attrref";
|
|
5
|
-
import { INTRINSIC_MARKER } from "./intrinsic";
|
|
5
|
+
import { INTRINSIC_MARKER, type Intrinsic } from "./intrinsic";
|
|
6
6
|
import type { Serializer } from "./serializer";
|
|
7
7
|
import type { Declarable } from "./declarable";
|
|
8
8
|
import { DECLARABLE_MARKER } from "./declarable";
|
|
@@ -793,6 +793,59 @@ describe("computeStackGraph (#200 — cross-stack apply ordering)", () => {
|
|
|
793
793
|
const ent = (lexicon: string, props: Record<string, unknown> = {}): Declarable =>
|
|
794
794
|
({ lexicon, entityType: `${lexicon}::X`, [DECLARABLE_MARKER]: true, props }) as unknown as Declarable;
|
|
795
795
|
|
|
796
|
+
// #2480: the walk took `entity.lexicon` as the consumer for every entity,
|
|
797
|
+
// and four kinds have no place in a stack graph. A LexiconOutput carries no
|
|
798
|
+
// `lexicon` at all, so it produced an edge with `from: undefined`, and that
|
|
799
|
+
// `undefined` then reached `order` and `waves` — while `nodes`, built from
|
|
800
|
+
// the partition, could never contain it. Reproduced on chant's own
|
|
801
|
+
// fan-out-estate and bedrock-agentcore-agent examples, both of which declare
|
|
802
|
+
// outputs built from intrinsics.
|
|
803
|
+
//
|
|
804
|
+
// The invariant these assert is the one a consumer can actually rely on:
|
|
805
|
+
// `nodes` is the roster, and nothing may appear anywhere else that is not
|
|
806
|
+
// named in it.
|
|
807
|
+
const rosterHolds = (g: ReturnType<typeof computeStackGraph>): void => {
|
|
808
|
+
const roster = new Set(g.nodes);
|
|
809
|
+
expect(g.nodes.every((n) => typeof n === "string")).toBe(true);
|
|
810
|
+
for (const e of g.edges) {
|
|
811
|
+
expect(roster.has(e.from)).toBe(true);
|
|
812
|
+
expect(roster.has(e.to)).toBe(true);
|
|
813
|
+
}
|
|
814
|
+
for (const n of g.order) expect(roster.has(n)).toBe(true);
|
|
815
|
+
for (const wave of g.waves) for (const n of wave) expect(roster.has(n)).toBe(true);
|
|
816
|
+
for (const cycle of g.cycles) for (const n of cycle) expect(roster.has(n)).toBe(true);
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
test("a LexiconOutput is not a stack member, so it cannot reach edges, order or waves (#2480)", () => {
|
|
820
|
+
const vpc = ent("aws");
|
|
821
|
+
// An output built from an intrinsic holds real AttrRefs inside it, which
|
|
822
|
+
// is what carried the walk into `addEdge(undefined, "aws")`.
|
|
823
|
+
// Built from an INTRINSIC holding an AttrRef, which is the shape the two
|
|
824
|
+
// reproducing examples have (`Fn::Sub`/`Ref` over a resource attribute).
|
|
825
|
+
// An output built from a bare AttrRef stores only a WeakRef and carries
|
|
826
|
+
// the walk nowhere, so it does not reproduce this.
|
|
827
|
+
const intrinsic: Intrinsic = {
|
|
828
|
+
[INTRINSIC_MARKER]: true as const,
|
|
829
|
+
ref: new AttrRef(vpc, "id"),
|
|
830
|
+
toJSON: () => ({ "Fn::Sub": "x" }),
|
|
831
|
+
} as Intrinsic;
|
|
832
|
+
const out = output(intrinsic, "vpcId");
|
|
833
|
+
|
|
834
|
+
const g = computeStackGraph(new Map([["vpc", vpc], ["vpcId", out as unknown as Declarable]]), ["aws"]);
|
|
835
|
+
|
|
836
|
+
expect(g.nodes).toEqual(["aws"]);
|
|
837
|
+
expect(g.edges).toEqual([]);
|
|
838
|
+
expect(g.order).toEqual(["aws"]);
|
|
839
|
+
expect(g.waves).toEqual([["aws"]]);
|
|
840
|
+
rosterHolds(g);
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
test("the roster invariant holds for an ordinary cross-lexicon graph too", () => {
|
|
844
|
+
const vpc = ent("aws");
|
|
845
|
+
const svc = ent("k8s", { vpcId: new AttrRef(vpc, "id") });
|
|
846
|
+
rosterHolds(computeStackGraph(new Map([["vpc", vpc], ["svc", svc]]), ["aws", "k8s"]));
|
|
847
|
+
});
|
|
848
|
+
|
|
796
849
|
test("infers a consumer→producer edge from a cross-lexicon AttrRef", () => {
|
|
797
850
|
const vpc = ent("aws");
|
|
798
851
|
const svc = ent("k8s", { vpcId: new AttrRef(vpc, "id") });
|
package/src/build.ts
CHANGED
|
@@ -65,6 +65,30 @@ export interface StackGraph {
|
|
|
65
65
|
* referencing an attribute of a resource in lexicon B ⇒ A depends on B). Returns
|
|
66
66
|
* the edge set plus a topological order, parallel-safe waves, and any cycles.
|
|
67
67
|
*/
|
|
68
|
+
/**
|
|
69
|
+
* Is this entity a member of a lexicon stack?
|
|
70
|
+
*
|
|
71
|
+
* Four kinds are not, and every one of them is serializer-neutral: a
|
|
72
|
+
* `LexiconOutput` is collected separately, a secret provenance declaration
|
|
73
|
+
* (#1828) and a plan scenario (#1292) are data lint and the CLI read off the
|
|
74
|
+
* entity map, and an Op (#2118) builds to its own `op.json` rather than
|
|
75
|
+
* through a lexicon serializer.
|
|
76
|
+
*
|
|
77
|
+
* {@link partitionByLexicon} has skipped all four since each landed, and
|
|
78
|
+
* {@link computeStackGraph}'s walk did not — so an entity with no `lexicon`
|
|
79
|
+
* (a `LexiconOutput`) entered `edges`, `order` and `waves` as `undefined`
|
|
80
|
+
* while `nodes`, built from the partition, could never contain it (#2480).
|
|
81
|
+
* One predicate for both sites, so they cannot drift apart again.
|
|
82
|
+
*/
|
|
83
|
+
export function isStackMember(entity: Declarable): boolean {
|
|
84
|
+
return (
|
|
85
|
+
!isLexiconOutput(entity) &&
|
|
86
|
+
!isSecretDeclaration(entity) &&
|
|
87
|
+
!isScenario(entity) &&
|
|
88
|
+
!isOpEntity(entity)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
68
92
|
export function computeStackGraph(
|
|
69
93
|
entities: Map<string, Declarable>,
|
|
70
94
|
lexiconNames: string[],
|
|
@@ -72,6 +96,10 @@ export function computeStackGraph(
|
|
|
72
96
|
const edges: Array<{ from: string; to: string }> = [];
|
|
73
97
|
const edgeSet = new Set<string>();
|
|
74
98
|
const addEdge = (from: string, to: string): void => {
|
|
99
|
+
// A structural guard, not a defensive one: `nodes` comes from the
|
|
100
|
+
// partition, so an endpoint the partition would have dropped can never be
|
|
101
|
+
// a legitimate member of this graph (#2480).
|
|
102
|
+
if (typeof from !== "string" || typeof to !== "string") return;
|
|
75
103
|
if (from === to) return;
|
|
76
104
|
const key = `${from}\0${to}`;
|
|
77
105
|
if (edgeSet.has(key)) return;
|
|
@@ -104,6 +132,9 @@ export function computeStackGraph(
|
|
|
104
132
|
};
|
|
105
133
|
|
|
106
134
|
for (const [, entity] of entities) {
|
|
135
|
+
// #2480: the same four kinds `partitionByLexicon` drops. Walking one as a
|
|
136
|
+
// consumer takes its absent `lexicon` as the edge's `from`.
|
|
137
|
+
if (!isStackMember(entity)) continue;
|
|
107
138
|
const consumer = entity.lexicon;
|
|
108
139
|
const visited = new Set<unknown>();
|
|
109
140
|
for (const val of Object.values(entity as unknown as Record<string, unknown>)) {
|
|
@@ -117,10 +148,10 @@ export function computeStackGraph(
|
|
|
117
148
|
// Dependency map: node → producers it depends on.
|
|
118
149
|
const nodes = lexiconNames.length
|
|
119
150
|
? [...lexiconNames]
|
|
120
|
-
: //
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
[...new Set([...entities.values()].filter(
|
|
151
|
+
: // The same predicate, rather than the partial copy of it this branch
|
|
152
|
+
// carried: it filtered secrets and scenarios but not outputs or Ops, so
|
|
153
|
+
// it could mint a node the partition would have dropped (#2480).
|
|
154
|
+
[...new Set([...entities.values()].filter(isStackMember).map((e) => e.lexicon))];
|
|
124
155
|
const deps = new Map<string, Set<string>>();
|
|
125
156
|
for (const n of nodes) deps.set(n, new Set());
|
|
126
157
|
for (const { from, to } of edges) {
|
|
@@ -209,6 +240,15 @@ export interface BuildOptions {
|
|
|
209
240
|
* (unchanged behavior/performance).
|
|
210
241
|
*/
|
|
211
242
|
sandbox?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* spec 2.0, `ι = executing` — invoke project-owned code at `F-Call` step 6
|
|
245
|
+
* instead of falling back. See {@link DiscoveryOptions.executing}.
|
|
246
|
+
*
|
|
247
|
+
* The fold's value is then what a run computes in this process, environment
|
|
248
|
+
* and all, which is why `open` is the default and is strict. Mutually
|
|
249
|
+
* exclusive with {@link sandbox}. Default `false`.
|
|
250
|
+
*/
|
|
251
|
+
executing?: boolean;
|
|
212
252
|
|
|
213
253
|
/**
|
|
214
254
|
* chant #1064 — this build's resolved build-time parameter values (see
|
|
@@ -316,23 +356,13 @@ export function partitionByLexicon(
|
|
|
316
356
|
const partitions = new Map<string, Map<string, Declarable>>();
|
|
317
357
|
|
|
318
358
|
for (const [name, entity] of entities) {
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
if (
|
|
326
|
-
// Plan scenarios (#1292) are serializer-neutral the same way: a checkable
|
|
327
|
-
// expectation the CLI reads off the entity map, never output.
|
|
328
|
-
if (isScenario(entity)) continue;
|
|
329
|
-
// Op declarations (#2118) too. An Op's build output is its `op.json` IR,
|
|
330
|
-
// and core writes that itself from the entity map (`./cli/commands/build.ts`)
|
|
331
|
-
// rather than routing it through a lexicon serializer — the Op model, the
|
|
332
|
-
// executor and the IR are all core's, and no lexicon renders an Op entity
|
|
333
|
-
// into its own manifest. Keeping them out of every partition means no
|
|
334
|
-
// "No serializer found" warning fires for core's own `chant` lexicon.
|
|
335
|
-
if (isOpEntity(entity)) continue;
|
|
359
|
+
// The four serializer-neutral kinds, each explained on {@link isStackMember}:
|
|
360
|
+
// a LexiconOutput is collected separately, and a secret declaration
|
|
361
|
+
// (#1828), a plan scenario (#1292) and an Op (#2118) are read off the
|
|
362
|
+
// entity map rather than routed through a lexicon serializer. Keeping them
|
|
363
|
+
// out of every partition is what stops a "No serializer found" warning
|
|
364
|
+
// firing for a pseudo-lexicon.
|
|
365
|
+
if (!isStackMember(entity)) continue;
|
|
336
366
|
const lexicon = entity.lexicon;
|
|
337
367
|
if (!partitions.has(lexicon)) {
|
|
338
368
|
partitions.set(lexicon, new Map());
|
|
@@ -676,6 +706,7 @@ export async function build(
|
|
|
676
706
|
intrinsics: options?.intrinsics,
|
|
677
707
|
lexicons: options?.lexicons,
|
|
678
708
|
sandbox: options?.sandbox,
|
|
709
|
+
executing: options?.executing,
|
|
679
710
|
buildParams: options?.buildParams,
|
|
680
711
|
});
|
|
681
712
|
|
|
@@ -167,15 +167,31 @@ describe("composite factory interpretation (chant #1023)", () => {
|
|
|
167
167
|
// The probe fires — an inadmissible factory still invokes, exactly as before.
|
|
168
168
|
// ───────────────────────────────────────────────────────────────────────
|
|
169
169
|
|
|
170
|
-
test("an INADMISSIBLE factory is
|
|
170
|
+
test("an INADMISSIBLE factory is refused rather than invoked (spec 2.0)", async () => {
|
|
171
171
|
await writeComposite(INADMISSIBLE_BODY);
|
|
172
172
|
await writeMain(CALL_WEBAPP);
|
|
173
173
|
|
|
174
174
|
const result = await discover(srcDir, { fold: true, lexicons: [LEXICON_NAME] });
|
|
175
175
|
|
|
176
|
+
// Interpretation declines on the body's shape, which is step 4. `F-Call`
|
|
177
|
+
// step 5 then makes the verdict `run` rather than importing the module and
|
|
178
|
+
// invoking it, because the specifier is a project file.
|
|
179
|
+
expect(result.errors).toEqual([]);
|
|
180
|
+
expect(result.foldDecisions.find((d) => d.file.endsWith("main.ts"))?.mode).toBe("run");
|
|
181
|
+
// The module does run, because `run` means the file is run and this build
|
|
182
|
+
// asked for no sandbox. What the fold no longer does is invoke it.
|
|
183
|
+
expect(foldExecutionCounts()).toMatchObject({ factoryInterpretations: 0, projectFactoryInvocations: 0 });
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("an INADMISSIBLE factory is invoked under `executing` (spec 2.0)", async () => {
|
|
187
|
+
await writeComposite(INADMISSIBLE_BODY);
|
|
188
|
+
await writeMain(CALL_WEBAPP);
|
|
189
|
+
|
|
190
|
+
const result = await discover(srcDir, { fold: true, executing: true, lexicons: [LEXICON_NAME] });
|
|
191
|
+
|
|
176
192
|
expect(result.errors).toEqual([]);
|
|
177
193
|
expect(result.foldDecisions.find((d) => d.file.endsWith("main.ts"))?.mode).toBe("fold");
|
|
178
|
-
expect(moduleRan(), "the defining module
|
|
194
|
+
expect(moduleRan(), "the defining module was imported, because the caller asked").toBe(true);
|
|
179
195
|
expect(foldExecutionCounts()).toMatchObject({ factoryInterpretations: 0, projectFactoryInvocations: 1 });
|
|
180
196
|
expect([...result.entities.keys()]).toEqual(["webBucket"]);
|
|
181
197
|
});
|
|
@@ -416,9 +432,20 @@ describe("composite factory interpretation (chant #1023)", () => {
|
|
|
416
432
|
export const web = makeApp({ name: "data" });
|
|
417
433
|
`);
|
|
418
434
|
|
|
419
|
-
const
|
|
435
|
+
const plain = await discover(srcDir, { fold: true, lexicons: [LEXICON_NAME] });
|
|
436
|
+
|
|
437
|
+
// Rule 2 still holds — a plain function is not a registered composite, so
|
|
438
|
+
// interpretation never applies to it. What changed at spec 2.0 is the arm
|
|
439
|
+
// it falls to: `F-Call` step 5 refuses a project file rather than invoking.
|
|
440
|
+
expect(plain.foldDecisions.find((d) => d.file.endsWith("main.ts"))?.mode).toBe("run");
|
|
441
|
+
expect(foldExecutionCounts(), "the fold invoked nothing; the fallback run is what imported it").toMatchObject({
|
|
442
|
+
factoryInterpretations: 0,
|
|
443
|
+
projectFactoryInvocations: 0,
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
const result = await discover(srcDir, { fold: true, executing: true, lexicons: [LEXICON_NAME] });
|
|
420
447
|
|
|
421
|
-
expect(moduleRan(), "a plain function
|
|
448
|
+
expect(moduleRan(), "a plain function is invoked under `executing`").toBe(true);
|
|
422
449
|
expect(foldExecutionCounts()).toMatchObject({ factoryInterpretations: 0, projectFactoryInvocations: 1 });
|
|
423
450
|
expect([...result.entities.keys()].sort()).toEqual(["webBucket", "webRole"]);
|
|
424
451
|
});
|
|
@@ -104,12 +104,14 @@ describe("tryFoldFile", () => {
|
|
|
104
104
|
expect(result.entities.map(([name]) => name).sort()).toEqual(["a", "b"]);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
// chant #1023 (epic #1019 Phase 5)
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
|
|
107
|
+
// chant #1023 (epic #1019 Phase 5) made this fold by INVOKING the factory
|
|
108
|
+
// for real with statically-folded props. spec 2.0's `F-Call` step 5 moved
|
|
109
|
+
// that invocation behind `ι = executing`, because the factory's body and its
|
|
110
|
+
// module's top level are the project's own code. The body here is admissible
|
|
111
|
+
// in shape but interpretation declines on it — `Bucket` is a module-level
|
|
112
|
+
// const bound to a `createResource(...)` call — so step 4 does not catch it
|
|
113
|
+
// and step 5 decides.
|
|
114
|
+
test("a top-level composite factory call falls back, and folds under `executing`", async () => {
|
|
113
115
|
await writeResourceDefs();
|
|
114
116
|
await writeFile(
|
|
115
117
|
join(testDir, "composites.ts"),
|
|
@@ -133,7 +135,11 @@ describe("tryFoldFile", () => {
|
|
|
133
135
|
`,
|
|
134
136
|
);
|
|
135
137
|
|
|
136
|
-
const
|
|
138
|
+
const refused = await tryFoldFile(file);
|
|
139
|
+
expect(refused.ok).toBe(false);
|
|
140
|
+
if (!refused.ok) expect(refused.reason).toContain("does not invoke project-owned code");
|
|
141
|
+
|
|
142
|
+
const result = await tryFoldFile(file, undefined, createFoldSession(undefined, undefined, undefined, false, [], true));
|
|
137
143
|
|
|
138
144
|
expect(result.ok).toBe(true);
|
|
139
145
|
if (!result.ok) return;
|
|
@@ -1576,6 +1576,36 @@ async function invokeResolvedCallee(
|
|
|
1576
1576
|
const refusal = sandboxedExecutionRefusal(binding, ctx, calleeName, "composite factory");
|
|
1577
1577
|
if (refusal) throw cheapError(refusal);
|
|
1578
1578
|
|
|
1579
|
+
// spec 2.0, `F-Call` step 5 — a callee that resolves to a PROJECT FILE is
|
|
1580
|
+
// not imported and invoked here. Invoking it runs the factory body, and its
|
|
1581
|
+
// whole module's top level, in the CLI's own process, and that is the
|
|
1582
|
+
// project's own code rather than a package's.
|
|
1583
|
+
//
|
|
1584
|
+
// Step 2's project-owned invocation moved behind `ι = executing` at v0.72.3
|
|
1585
|
+
// (chant#2455). Step 6 is the same path and had not moved, which is the
|
|
1586
|
+
// whole of this change. The specification took the decision first: its
|
|
1587
|
+
// rationale says of `executing` that "it is never the default", and
|
|
1588
|
+
// `verdict.md` calls `open` the strict default.
|
|
1589
|
+
//
|
|
1590
|
+
// A package factory still runs here, which is what `F-Host-Admission`
|
|
1591
|
+
// governs. A project-file callee that a `Composite` registered is
|
|
1592
|
+
// INTERPRETED at step 4 and never reaches this line; only one that
|
|
1593
|
+
// interpretation declined does, and for that the verdict is `run`.
|
|
1594
|
+
// "Project file" is the specifier's ORIGIN, not its syntax.
|
|
1595
|
+
// {@link isProjectFileSpecifier} is true of any absolute path, and chant's
|
|
1596
|
+
// own modules are imported by absolute path throughout the tests, so the
|
|
1597
|
+
// shape test alone refuses `propagate` and every other host function chant
|
|
1598
|
+
// publishes. {@link isTrustedExecutableBinding} draws the line the rule
|
|
1599
|
+
// means: an active lexicon package or chant-core's own tree is a package's
|
|
1600
|
+
// code, and everything else reached by a relative or absolute specifier is
|
|
1601
|
+
// the project's.
|
|
1602
|
+
if (!ctx.executing && isProjectFileSpecifier(binding.specifier) && !isTrustedExecutableBinding(binding, ctx)) {
|
|
1603
|
+
throw cheapError(
|
|
1604
|
+
`"${calleeName}" is imported from "${binding.specifier}", which is a project file; ` +
|
|
1605
|
+
"the default mode does not invoke project-owned code (`executing` would run it and fold what it returns)",
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1579
1609
|
let modulePath: string;
|
|
1580
1610
|
try {
|
|
1581
1611
|
modulePath = resolveModulePathMemoized(binding.specifier, ctx.file, ctx.resolvePathCache);
|
|
@@ -372,7 +372,14 @@ describe("discover — fold mode (#1022, epic #1019)", () => {
|
|
|
372
372
|
);
|
|
373
373
|
|
|
374
374
|
const withoutFold = await discover(testDir);
|
|
375
|
-
|
|
375
|
+
// spec 2.0 — the default refuses to invoke the project-file factory, so
|
|
376
|
+
// the file falls back. Output equivalence is what this test is about and
|
|
377
|
+
// it holds either way, because the fallback run computes the same thing.
|
|
378
|
+
const refused = await discover(testDir, { fold: true });
|
|
379
|
+
expect(refused.foldDecisions.find((d) => d.file.endsWith("stack.ts"))?.mode).toBe("run");
|
|
380
|
+
expect([...refused.entities.keys()].sort()).toEqual([...withoutFold.entities.keys()].sort());
|
|
381
|
+
|
|
382
|
+
const withFold = await discover(testDir, { fold: true, executing: true });
|
|
376
383
|
|
|
377
384
|
expect(withFold.errors).toEqual([]);
|
|
378
385
|
expect(withFold.entities.size).toBe(withoutFold.entities.size);
|
package/src/discovery/index.ts
CHANGED
|
@@ -165,6 +165,20 @@ export interface DiscoveryOptions {
|
|
|
165
165
|
* process, no IPC) and fold coverage, is unchanged unless requested.
|
|
166
166
|
*/
|
|
167
167
|
sandbox?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* spec 2.0, `ι = executing` — invoke project-owned code at `F-Call` step 6
|
|
170
|
+
* rather than falling back.
|
|
171
|
+
*
|
|
172
|
+
* `F-Call` step 5 makes a declarator whose callee resolves to a project file
|
|
173
|
+
* `run` under every other mode, so a build that wants the value a run would
|
|
174
|
+
* compute has to say so. The value is then this process's: the factory body
|
|
175
|
+
* and its module's top level execute here, environment and all, which is
|
|
176
|
+
* exactly why it cannot be the default.
|
|
177
|
+
*
|
|
178
|
+
* Mutually exclusive with {@link sandbox}, which refuses to import project
|
|
179
|
+
* code at all. Asking for both is a contradiction rather than a preference.
|
|
180
|
+
*/
|
|
181
|
+
executing?: boolean;
|
|
168
182
|
|
|
169
183
|
/**
|
|
170
184
|
* chant #1064 — this build's resolved build-time parameter values (see
|
|
@@ -263,8 +277,21 @@ export async function discover(path: string, options?: DiscoveryOptions): Promis
|
|
|
263
277
|
// `sandbox` the session refuses those imports and the file demotes to the
|
|
264
278
|
// run path — which, under `sandbox`, is the isolated child. See
|
|
265
279
|
// fold-import.ts's `sandboxedExecutionRefusal`.
|
|
280
|
+
if (options?.sandbox === true && options?.executing === true) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
"discover: `sandbox` and `executing` are mutually exclusive — the first refuses to import " +
|
|
283
|
+
"project code and the second exists to invoke it. Pass one.",
|
|
284
|
+
);
|
|
285
|
+
}
|
|
266
286
|
const foldSession = options?.fold
|
|
267
|
-
? createFoldSession(
|
|
287
|
+
? createFoldSession(
|
|
288
|
+
options.intrinsics,
|
|
289
|
+
buildParamValuesMap,
|
|
290
|
+
options.lexicons,
|
|
291
|
+
options.sandbox === true,
|
|
292
|
+
[],
|
|
293
|
+
options.executing === true,
|
|
294
|
+
)
|
|
268
295
|
: undefined;
|
|
269
296
|
if (options?.fold) {
|
|
270
297
|
for (const file of files) {
|
|
@@ -4,6 +4,7 @@ import { join, dirname, resolve } from "node:path";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { discover } from "../index";
|
|
7
|
+
import { foldExecutionCounts, resetFoldExecutionCounts } from "../fold-import";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* chant #1093 — the security property `--sandbox` is supposed to buy, tested
|
|
@@ -101,16 +102,37 @@ describe("fold under --sandbox never executes project code in the CLI process (c
|
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
test("plain --fold
|
|
105
|
+
test("plain --fold refuses a project-owned composite factory: nothing runs here (spec 2.0)", async () => {
|
|
105
106
|
await writeCompositeFixture();
|
|
107
|
+
resetFoldExecutionCounts();
|
|
106
108
|
|
|
107
109
|
const result = await discover(testDir, { fold: true });
|
|
108
110
|
|
|
109
|
-
//
|
|
111
|
+
// Until spec 2.0 this folded, and folding it ran project code right here.
|
|
112
|
+
// `F-Call` step 5 moved that invocation behind `ι = executing`, so the
|
|
113
|
+
// verdict is `run` and the FOLD invokes nothing.
|
|
114
|
+
const main = result.foldDecisions.find((d) => d.file.endsWith("main.ts"));
|
|
115
|
+
expect(main?.mode).toBe("run");
|
|
116
|
+
expect(foldExecutionCounts()).toMatchObject({ projectFactoryInvocations: 0 });
|
|
117
|
+
// The markers still fire, because a `run` verdict means the file is run,
|
|
118
|
+
// and without --sandbox the run path is this process. That is the fallback
|
|
119
|
+
// doing its job rather than the fold reaching project code, and it is
|
|
120
|
+
// exactly what the next test moves to the child.
|
|
121
|
+
expect(marker(MODULE_MARKER)).toBe(true);
|
|
122
|
+
expect([...result.entities.keys()].sort()).toEqual(["webBucket", "webRole"]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("`executing` invokes it, which is what that mode is for (spec 2.0)", async () => {
|
|
126
|
+
await writeCompositeFixture();
|
|
127
|
+
resetFoldExecutionCounts();
|
|
128
|
+
|
|
129
|
+
const result = await discover(testDir, { fold: true, executing: true });
|
|
130
|
+
|
|
110
131
|
const main = result.foldDecisions.find((d) => d.file.endsWith("main.ts"));
|
|
111
132
|
expect(main?.mode).toBe("fold");
|
|
112
|
-
expect(
|
|
113
|
-
expect(marker(
|
|
133
|
+
expect(foldExecutionCounts()).toMatchObject({ projectFactoryInvocations: 1 });
|
|
134
|
+
expect(marker(MODULE_MARKER), "composites.ts's module top level ran, because the caller asked").toBe(true);
|
|
135
|
+
expect(marker(FACTORY_MARKER), "the factory body ran, because the caller asked").toBe(true);
|
|
114
136
|
expect([...result.entities.keys()].sort()).toEqual(["webBucket", "webRole"]);
|
|
115
137
|
});
|
|
116
138
|
|
package/src/fold/subset.ts
CHANGED
|
@@ -222,13 +222,16 @@ import { intrinsicCallFolds, intrinsicCallFoldsEagerly, type IntrinsicDef } from
|
|
|
222
222
|
* `sandbox`. `open` stays the default and stays strict (#2453).
|
|
223
223
|
*
|
|
224
224
|
* `scripts/check-docs-citations.ts` refuses to run when this constant and the
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
225
|
+
* rules it loads disagree, so this and the `@intentius/tsad-conformance`
|
|
226
|
+
* devDependency move together. That coupling is deliberate: it is what stops
|
|
227
|
+
* the docs being gated against a rule set nobody writes against — which is
|
|
228
|
+
* exactly what happened while this sat at `1.0` through six versions, passing
|
|
229
|
+
* because both sides were equally stale.
|
|
230
|
+
*
|
|
231
|
+
* Until chant#2470 the rules came from a commit `docs-check.yml` checked out;
|
|
232
|
+
* now they come from the published package, so bumping it is what moves this.
|
|
230
233
|
*/
|
|
231
|
-
export const SPEC_VERSION = "1
|
|
234
|
+
export const SPEC_VERSION = "2.1";
|
|
232
235
|
|
|
233
236
|
/** The two EVL rule ids a shape violation can be attributed to. */
|
|
234
237
|
export type SubsetRuleId = "EVL001" | "EVL003";
|
|
@@ -335,10 +335,24 @@ const COMPOSITES = `
|
|
|
335
335
|
|
|
336
336
|
const MAIN = `
|
|
337
337
|
import { Bucket } from ${JSON.stringify(LEXICON)};
|
|
338
|
-
import { WebService
|
|
338
|
+
import { WebService } from "../composites";
|
|
339
339
|
|
|
340
340
|
export const logs = new Bucket({ BucketName: "logs" });
|
|
341
341
|
export const web = WebService({ name: "data", tier: "prod", iam: { path: "/service/" } });
|
|
342
|
+
`;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* `LegacyService` sits in its own file since spec 2.0.
|
|
346
|
+
*
|
|
347
|
+
* It is one `if` outside the subset, so step 4 declines and `F-Call` step 5
|
|
348
|
+
* makes the declarator `run`. A verdict is per file, so leaving it beside
|
|
349
|
+
* `web` took the whole file to run and every field's origin with it — the
|
|
350
|
+
* interpreted composite's provenance is only observable in a file that folds.
|
|
351
|
+
* `executing` is the other way to keep it, and this fixture wants the default.
|
|
352
|
+
*/
|
|
353
|
+
const LEGACY_MAIN = `
|
|
354
|
+
import { LegacyService } from "../composites";
|
|
355
|
+
|
|
342
356
|
export const legacy = LegacyService({ name: "old" });
|
|
343
357
|
`;
|
|
344
358
|
|
|
@@ -361,6 +375,7 @@ describe("fold provenance over a real composite build (#2161)", () => {
|
|
|
361
375
|
await mkdir(srcDir, { recursive: true });
|
|
362
376
|
await writeFile(join(testDir, "composites.ts"), COMPOSITES);
|
|
363
377
|
await writeFile(join(srcDir, "main.ts"), MAIN);
|
|
378
|
+
await writeFile(join(srcDir, "legacy.ts"), LEGACY_MAIN);
|
|
364
379
|
});
|
|
365
380
|
|
|
366
381
|
afterEach(async () => {
|