@cat-factory/contracts 0.107.0 → 0.108.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.
@@ -0,0 +1,61 @@
1
+ import type { AnalystCitation, AnalystRecipeDraft, AnalystRecipeNote } from './environment-analyst.js';
2
+ import type { ProvisioningDetectionConfidence, ProvisioningRecommendation } from './environments.js';
3
+ import type { StackRecipe } from './stack-recipes.js';
4
+ /** The top-level {@link StackRecipe} fields the merge tracks provenance for, in display order. */
5
+ export declare const MERGEABLE_RECIPE_FIELDS: readonly ["composeFiles", "composeProfiles", "envFiles", "externalNetworks", "sharedStackRefs", "prerequisites", "setupSteps", "healthGate", "teardownSteps"];
6
+ /** A {@link StackRecipe} field whose value + provenance the merge resolves. */
7
+ export type MergeableRecipeField = (typeof MERGEABLE_RECIPE_FIELDS)[number];
8
+ /**
9
+ * Which source supplied the value that landed in the merged recipe for a field:
10
+ * - `detector` — only the deterministic detector produced it (authoritative).
11
+ * - `analyst` — only the analyst produced it (a draft the human edits/confirms).
12
+ * - `both` — both produced it and the DETECTOR's value won (the analyst's is surfaced as a
13
+ * dissenting note via {@link MergedRecipeDraft.analystNotes}, not applied).
14
+ */
15
+ export type RecipeFieldOrigin = 'detector' | 'analyst' | 'both';
16
+ /**
17
+ * Provenance for one populated recipe field. Carries the WINNING source's rationale: the detector
18
+ * confidence + note when a detected fact won (`detector`/`both`), or the analyst rationale +
19
+ * citations when the analyst's draft won (`analyst`). The wizard renders this as the per-field
20
+ * confidence / "suggested by analysis of …" chip.
21
+ */
22
+ export interface MergedRecipeField {
23
+ /** The recipe field this entry describes. */
24
+ field: MergeableRecipeField;
25
+ /** Which source's value landed in the merged recipe. */
26
+ origin: RecipeFieldOrigin;
27
+ /** Detector confidence, present when a detected fact won (`origin` `detector`/`both`). */
28
+ confidence?: ProvisioningDetectionConfidence;
29
+ /** The detector's rationale message, present when a detected fact won. */
30
+ detectorMessage?: string;
31
+ /** The analyst's rationale, present when the analyst's draft won (`origin` `analyst`). */
32
+ analystRationale?: string;
33
+ /** Analyst source citations backing the field, present when the analyst's draft won. */
34
+ citations?: AnalystCitation[];
35
+ }
36
+ /**
37
+ * The merged, reviewable recipe: the detector-wins {@link StackRecipe} plus per-field provenance,
38
+ * the analyst's summary + verbatim notes (so the wizard can render granular per-step provenance
39
+ * such as `setupSteps[2]`), and whether the analyst contributed anything at all.
40
+ */
41
+ export interface MergedRecipeDraft {
42
+ /** The merged recipe (detector facts win on overlap; analyst-only fields fill the gaps). */
43
+ recipe: StackRecipe;
44
+ /** Provenance for each populated recipe field, in {@link MERGEABLE_RECIPE_FIELDS} order. */
45
+ fields: MergedRecipeField[];
46
+ /** The analyst's one-paragraph environment summary, when it ran and returned one. */
47
+ summary?: string;
48
+ /** Every analyst note verbatim (for per-step provenance the field-level view can't hold). */
49
+ analystNotes: AnalystRecipeNote[];
50
+ /** True when an analyst draft contributed a recipe field, a note, or a summary. */
51
+ hasAnalystInput: boolean;
52
+ }
53
+ /**
54
+ * Merge a deterministic {@link ProvisioningRecommendation} with an opt-in
55
+ * {@link AnalystRecipeDraft} into a single {@link MergedRecipeDraft}: detector facts win where
56
+ * both produce a field, analyst-only fields fill the gaps, and every populated field carries the
57
+ * winning source's provenance. `draft` absent (the analyst never ran) ⇒ the detector's recipe
58
+ * verbatim with detector provenance and no analyst input.
59
+ */
60
+ export declare function mergeAnalystRecipeDraft(recommendation: ProvisioningRecommendation, draft?: AnalystRecipeDraft): MergedRecipeDraft;
61
+ //# sourceMappingURL=environment-analyst-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-analyst-merge.d.ts","sourceRoot":"","sources":["../src/environment-analyst-merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EACV,+BAA+B,EAE/B,0BAA0B,EAC3B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAwBrD,kGAAkG;AAClG,eAAO,MAAM,uBAAuB,+JAUe,CAAA;AAEnD,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3E;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,KAAK,EAAE,oBAAoB,CAAA;IAC3B,wDAAwD;IACxD,MAAM,EAAE,iBAAiB,CAAA;IACzB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,+BAA+B,CAAA;IAC5C,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,wFAAwF;IACxF,SAAS,CAAC,EAAE,eAAe,EAAE,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,4FAA4F;IAC5F,MAAM,EAAE,WAAW,CAAA;IACnB,4FAA4F;IAC5F,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,YAAY,EAAE,iBAAiB,EAAE,CAAA;IACjC,mFAAmF;IACnF,eAAe,EAAE,OAAO,CAAA;CACzB;AA+DD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,0BAA0B,EAC1C,KAAK,CAAC,EAAE,kBAAkB,GACzB,iBAAiB,CAgEnB"}
@@ -0,0 +1,152 @@
1
+ // ---------------------------------------------------------------------------
2
+ // ANALYST DRAFT MERGE — combine the DETERMINISTIC provisioning recommendation
3
+ // (`provisioningRecommendationSchema`, read checkout-free by the detector) with the opt-in
4
+ // environment analyst's `AnalystRecipeDraft` (the LLM's read of the imperative bring-up) into a
5
+ // single reviewable recipe, per field, WITH PROVENANCE. This is the "review recipe" input for
6
+ // the setup wizard (slice 7 of docs/initiatives/stack-recipes-and-shared-stacks.md).
7
+ //
8
+ // The rule the initiative fixes (see `environment-analyst.ts`): **deterministic detector facts
9
+ // WIN where both produce a field; analyst-only fields fill the gaps, editable + flagged with the
10
+ // analyst's rationale/citations.** The detector is authoritative because it read the actual
11
+ // compose truth; the analyst only translates the imperative parts a scan can't see (setup steps,
12
+ // health gate, prerequisites) — so it never overrides a mechanically-detected fact, it only adds
13
+ // what the detector couldn't know.
14
+ //
15
+ // PURE + no IO (both inputs are already-parsed contract types), so it lives in @cat-factory/contracts
16
+ // beside the types it merges and is directly consumable by BOTH the SPA wizard (client-side, no
17
+ // extra endpoint) and any backend caller — the same shared-pure-helper shape as
18
+ // `resolveFrontendBindings` / `buildFrontendRunNotes`. The output is a view model, not a wire type:
19
+ // nothing here crosses a boundary, and on save the wizard persists only the resulting `StackRecipe`
20
+ // (re-validated against the STRICT `stackRecipeSchema`) onto the service frame.
21
+ // ---------------------------------------------------------------------------
22
+ /** The top-level {@link StackRecipe} fields the merge tracks provenance for, in display order. */
23
+ export const MERGEABLE_RECIPE_FIELDS = [
24
+ 'composeFiles',
25
+ 'composeProfiles',
26
+ 'envFiles',
27
+ 'externalNetworks',
28
+ 'sharedStackRefs',
29
+ 'prerequisites',
30
+ 'setupSteps',
31
+ 'healthGate',
32
+ 'teardownSteps',
33
+ ];
34
+ /** A produced field = a defined non-array value, or a non-empty array (an empty array is "not produced"). */
35
+ function isProduced(value) {
36
+ if (value === undefined || value === null)
37
+ return false;
38
+ if (Array.isArray(value))
39
+ return value.length > 0;
40
+ return true;
41
+ }
42
+ /**
43
+ * The base field name a note targets, stripping any index/path suffix so a per-step analyst note
44
+ * (`setupSteps[2]`, `healthGate.url`) still maps to the top-level field it explains.
45
+ */
46
+ function baseNoteField(field) {
47
+ const trimmed = field.trim();
48
+ let end = trimmed.length;
49
+ const bracket = trimmed.indexOf('[');
50
+ if (bracket >= 0 && bracket < end)
51
+ end = bracket;
52
+ const dot = trimmed.indexOf('.');
53
+ if (dot >= 0 && dot < end)
54
+ end = dot;
55
+ return trimmed.slice(0, end);
56
+ }
57
+ /** The detector note for a field (exact `field` match), if any. */
58
+ function detectorNoteFor(notes, field) {
59
+ return notes.find((note) => note.field === field);
60
+ }
61
+ /**
62
+ * Deep-clone a JSON-shaped contract value (recipe fields + analyst notes are pure data — strings,
63
+ * numbers, arrays, plain objects, no Date/Map/class instances). Used so the merged view model
64
+ * shares NO mutable reference with the caller's recommendation/draft: the wizard edits the merged
65
+ * recipe/notes in place, and an in-place edit must never reach back and mutate the deterministic
66
+ * detector fact or the non-binding draft. (A `structuredClone` global isn't typed in this pure,
67
+ * browser-shared package's `ES2022` lib, so this stays dependency-free.)
68
+ */
69
+ function cloneData(value) {
70
+ if (Array.isArray(value))
71
+ return value.map((item) => cloneData(item));
72
+ if (value !== null && typeof value === 'object') {
73
+ const out = {};
74
+ for (const [key, nested] of Object.entries(value))
75
+ out[key] = cloneData(nested);
76
+ return out;
77
+ }
78
+ return value;
79
+ }
80
+ /**
81
+ * The analyst note for a field: an exact `field` match wins over an indexed/path-suffixed one
82
+ * (e.g. `setupSteps` is preferred over `setupSteps[0]` for the field-level chip).
83
+ */
84
+ function analystNoteFor(notes, field) {
85
+ return (notes.find((note) => note.field.trim() === field) ??
86
+ notes.find((note) => baseNoteField(note.field) === field));
87
+ }
88
+ /**
89
+ * Merge a deterministic {@link ProvisioningRecommendation} with an opt-in
90
+ * {@link AnalystRecipeDraft} into a single {@link MergedRecipeDraft}: detector facts win where
91
+ * both produce a field, analyst-only fields fill the gaps, and every populated field carries the
92
+ * winning source's provenance. `draft` absent (the analyst never ran) ⇒ the detector's recipe
93
+ * verbatim with detector provenance and no analyst input.
94
+ */
95
+ export function mergeAnalystRecipeDraft(recommendation, draft) {
96
+ const detectorRecipe = recommendation.provisioning.recipe;
97
+ const analystRecipe = draft?.recipe;
98
+ // Clone the analyst notes up front so the returned view model shares no mutable reference with
99
+ // the caller's `draft` — the wizard edits this recipe/notes in place, and an in-place edit must
100
+ // never reach back and mutate the deterministic detector fact or the non-binding draft.
101
+ const analystNotes = draft?.notes ? cloneData(draft.notes) : [];
102
+ const recipe = {};
103
+ const fields = [];
104
+ for (const field of MERGEABLE_RECIPE_FIELDS) {
105
+ const detectorValue = detectorRecipe?.[field];
106
+ const analystValue = analystRecipe?.[field];
107
+ const detectorHas = isProduced(detectorValue);
108
+ const analystHas = isProduced(analystValue);
109
+ if (detectorHas) {
110
+ // The detector read the compose truth — its fact wins even if the analyst also proposed one.
111
+ // Clone the value so an edit to the merged recipe can't mutate the source recommendation.
112
+ Object.assign(recipe, { [field]: cloneData(detectorValue) });
113
+ const note = detectorNoteFor(recommendation.notes, field);
114
+ fields.push({
115
+ field,
116
+ origin: analystHas ? 'both' : 'detector',
117
+ ...(note ? { confidence: note.confidence, detectorMessage: note.message } : {}),
118
+ });
119
+ }
120
+ else if (analystHas) {
121
+ // Analyst-only field (setup steps, health gate, prerequisites the detector can't see).
122
+ // Clone the value so an edit to the merged recipe can't mutate the source draft.
123
+ Object.assign(recipe, { [field]: cloneData(analystValue) });
124
+ const note = analystNoteFor(analystNotes, field);
125
+ fields.push({
126
+ field,
127
+ origin: 'analyst',
128
+ ...(note
129
+ ? {
130
+ analystRationale: note.rationale,
131
+ ...(note.citations ? { citations: note.citations } : {}),
132
+ }
133
+ : {}),
134
+ });
135
+ }
136
+ }
137
+ const summary = draft?.summary;
138
+ // A blank summary (absent, empty, or whitespace-only — the lenient draft schema doesn't trim)
139
+ // is "no summary": it neither counts as analyst input nor rides along in the output, so the
140
+ // `summary` presence and `hasAnalystInput` signals can't disagree for the same draft.
141
+ const hasSummary = summary !== undefined && summary.trim() !== '';
142
+ const analystContributedRecipe = MERGEABLE_RECIPE_FIELDS.some((field) => isProduced(analystRecipe?.[field]));
143
+ const hasAnalystInput = Boolean(draft && (analystContributedRecipe || analystNotes.length > 0 || hasSummary));
144
+ return {
145
+ recipe,
146
+ fields,
147
+ ...(hasSummary ? { summary } : {}),
148
+ analystNotes,
149
+ hasAnalystInput,
150
+ };
151
+ }
152
+ //# sourceMappingURL=environment-analyst-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-analyst-merge.js","sourceRoot":"","sources":["../src/environment-analyst-merge.ts"],"names":[],"mappings":"AAYA,8EAA8E;AAC9E,8EAA8E;AAC9E,2FAA2F;AAC3F,gGAAgG;AAChG,8FAA8F;AAC9F,qFAAqF;AACrF,EAAE;AACF,+FAA+F;AAC/F,iGAAiG;AACjG,4FAA4F;AAC5F,iGAAiG;AACjG,iGAAiG;AACjG,mCAAmC;AACnC,EAAE;AACF,sGAAsG;AACtG,gGAAgG;AAChG,gFAAgF;AAChF,oGAAoG;AACpG,oGAAoG;AACpG,gFAAgF;AAChF,8EAA8E;AAE9E,kGAAkG;AAClG,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,cAAc;IACd,iBAAiB;IACjB,UAAU;IACV,kBAAkB;IAClB,iBAAiB;IACjB,eAAe;IACf,YAAY;IACZ,YAAY;IACZ,eAAe;CACkC,CAAA;AAqDnD,6GAA6G;AAC7G,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IACjD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,CAAA;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACpC,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,GAAG,GAAG;QAAE,GAAG,GAAG,OAAO,CAAA;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,GAAG;QAAE,GAAG,GAAG,GAAG,CAAA;IACpC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC9B,CAAC;AAED,mEAAmE;AACnE,SAAS,eAAe,CACtB,KAA2C,EAC3C,KAA2B;IAE3B,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAA;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAI,KAAQ;IAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAM,CAAA;IAC1E,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,GAAG,GAA4B,EAAE,CAAA;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;QAC/E,OAAO,GAAQ,CAAA;IACjB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CACrB,KAAmC,EACnC,KAA2B;IAE3B,OAAO,CACL,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAC1D,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,cAA0C,EAC1C,KAA0B;IAE1B,MAAM,cAAc,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAA;IACzD,MAAM,aAAa,GAAG,KAAK,EAAE,MAAM,CAAA;IACnC,+FAA+F;IAC/F,gGAAgG;IAChG,wFAAwF;IACxF,MAAM,YAAY,GAAwB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAEpF,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,MAAM,MAAM,GAAwB,EAAE,CAAA;IAEtC,KAAK,MAAM,KAAK,IAAI,uBAAuB,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,cAAc,EAAE,CAAC,KAAK,CAAC,CAAA;QAC7C,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,WAAW,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;QAC7C,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;QAE3C,IAAI,WAAW,EAAE,CAAC;YAChB,6FAA6F;YAC7F,0FAA0F;YAC1F,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;YAC5D,MAAM,IAAI,GAAG,eAAe,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YACzD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;gBACxC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChF,CAAC,CAAA;QACJ,CAAC;aAAM,IAAI,UAAU,EAAE,CAAC;YACtB,uFAAuF;YACvF,iFAAiF;YACjF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;YAC3D,MAAM,IAAI,GAAG,cAAc,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;YAChD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,MAAM,EAAE,SAAS;gBACjB,GAAG,CAAC,IAAI;oBACN,CAAC,CAAC;wBACE,gBAAgB,EAAE,IAAI,CAAC,SAAS;wBAChC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACzD;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,CAAA;IAC9B,8FAA8F;IAC9F,4FAA4F;IAC5F,sFAAsF;IACtF,MAAM,UAAU,GAAG,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;IACjE,MAAM,wBAAwB,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CACtE,UAAU,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,CAAC,CACnC,CAAA;IACD,MAAM,eAAe,GAAG,OAAO,CAC7B,KAAK,IAAI,CAAC,wBAAwB,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,CAC7E,CAAA;IAED,OAAO;QACL,MAAM;QACN,MAAM;QACN,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,YAAY;QACZ,eAAe;KAChB,CAAA;AACH,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -8,6 +8,6 @@
8
8
  * type for `ConflictError`, and the SPA keys an exhaustive `Record<ConflictReason, …>` of
9
9
  * localized titles off it — adding a value without a title trips the frontend typecheck.
10
10
  */
11
- export declare const CONFLICT_REASONS: readonly ['providers_unconfigured', 'preset_unsatisfiable', 'dependencies_unmet', 'task_limit_reached', 'tester_infra_unsupported', 'binary_storage_unconfigured', 'agent_backend_unconfigured', 'run_not_retryable', 'no_pr_to_merge', 'github_not_connected', 'bootstrap_not_retryable', 'bootstrap_reference_missing', 'provision_type_unhandled', 'visual_pipeline_no_frontend'];
11
+ export declare const CONFLICT_REASONS: readonly ['providers_unconfigured', 'preset_unsatisfiable', 'dependencies_unmet', 'task_limit_reached', 'tester_infra_unsupported', 'binary_storage_unconfigured', 'agent_backend_unconfigured', 'run_not_retryable', 'no_pr_to_merge', 'github_not_connected', 'bootstrap_not_retryable', 'bootstrap_reference_missing', 'provision_type_unhandled', 'visual_pipeline_no_frontend', 'deployer_required_before_tester'];
12
12
  export type ConflictReason = (typeof CONFLICT_REASONS)[number];
13
13
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,YAC3B,wBAAwB,EAKxB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,6BAA6B,EAG7B,0BAA0B,EAG1B,6BAA6B,CACrB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,YAC3B,wBAAwB,EAKxB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,6BAA6B,EAG7B,0BAA0B,EAG1B,6BAA6B,EAI7B,iCAAiC,CACzB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA"}
package/dist/errors.js CHANGED
@@ -32,5 +32,9 @@ export const CONFLICT_REASONS = [
32
32
  // A pipeline with visual steps (`tester-ui` / `visual-confirmation`) was started on a frame
33
33
  // with no UI to exercise — neither a `frontend` frame nor a frame a frontend links to.
34
34
  'visual_pipeline_no_frontend',
35
+ // A `kubernetes`/`custom` service's pipeline reaches a Tester / human-test / playwright step
36
+ // with no enabled `deployer` before it, so nothing would provision the env it needs — the run
37
+ // would dead-end inside the consumer. The Deployer is the single environment provisioner.
38
+ 'deployer_required_before_tester',
35
39
  ];
36
40
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,wBAAwB;IACxB,8FAA8F;IAC9F,4FAA4F;IAC5F,+FAA+F;IAC/F,8EAA8E;IAC9E,sBAAsB;IACtB,oBAAoB;IACpB,oBAAoB;IACpB,0BAA0B;IAC1B,6BAA6B;IAC7B,4BAA4B;IAC5B,mBAAmB;IACnB,gBAAgB;IAChB,sBAAsB;IACtB,yBAAyB;IACzB,6BAA6B;IAC7B,kFAAkF;IAClF,kFAAkF;IAClF,0BAA0B;IAC1B,4FAA4F;IAC5F,uFAAuF;IACvF,6BAA6B;CACrB,CAAA"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,wBAAwB;IACxB,8FAA8F;IAC9F,4FAA4F;IAC5F,+FAA+F;IAC/F,8EAA8E;IAC9E,sBAAsB;IACtB,oBAAoB;IACpB,oBAAoB;IACpB,0BAA0B;IAC1B,6BAA6B;IAC7B,4BAA4B;IAC5B,mBAAmB;IACnB,gBAAgB;IAChB,sBAAsB;IACtB,yBAAyB;IACzB,6BAA6B;IAC7B,kFAAkF;IAClF,kFAAkF;IAClF,0BAA0B;IAC1B,4FAA4F;IAC5F,uFAAuF;IACvF,6BAA6B;IAC7B,6FAA6F;IAC7F,8FAA8F;IAC9F,0FAA0F;IAC1F,iCAAiC;CACzB,CAAA"}
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export * from './preflights.js';
21
21
  export * from './stack-recipes.js';
22
22
  export * from './shared-stacks.js';
23
23
  export * from './environment-analyst.js';
24
+ export * from './environment-analyst-merge.js';
24
25
  export * from './runners.js';
25
26
  export * from './bootstrap.js';
26
27
  export * from './env-config-repair.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ export * from './preflights.js';
21
21
  export * from './stack-recipes.js';
22
22
  export * from './shared-stacks.js';
23
23
  export * from './environment-analyst.js';
24
+ export * from './environment-analyst-merge.js';
24
25
  export * from './runners.js';
25
26
  export * from './bootstrap.js';
26
27
  export * from './env-config-repair.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/contracts",
3
- "version": "0.107.0",
3
+ "version": "0.108.0",
4
4
  "description": "Valibot wire contract shared between the Agent Architecture Board frontend and backend.",
5
5
  "repository": {
6
6
  "type": "git",