@ansible-flow/core 0.87.0 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ai/describe.js +5 -5
- package/dist/ai/handlers.js +21 -20
- package/dist/ai/handlers.js.map +1 -1
- package/dist/ai/ops.js +4 -4
- package/dist/ai/reference.js +2 -2
- package/dist/ai/scenarios.js +8 -6
- package/dist/awx/import.js +3 -3
- package/dist/chunks/{chunk-IZJPLWDY.js → chunk-2KB3J3R5.js} +2 -2
- package/dist/chunks/{chunk-EAJFZKPB.js → chunk-37FKZNRN.js} +3 -3
- package/dist/chunks/{chunk-BNMW6KWK.js → chunk-57KJYXWA.js} +3 -3
- package/dist/chunks/{chunk-2P3JEHLH.js → chunk-7ALTNZCI.js} +3 -3
- package/dist/chunks/{chunk-WSARMPYU.js → chunk-APBEHKCF.js} +2 -2
- package/dist/chunks/{chunk-W2CSOAIB.js → chunk-BSX6G7QY.js} +5 -5
- package/dist/chunks/{chunk-3Z4WABFK.js → chunk-CATQHJS6.js} +4 -4
- package/dist/chunks/{chunk-HPRG2672.js → chunk-CCWUUVSG.js} +2 -2
- package/dist/chunks/{chunk-C6SQEXL5.js → chunk-CNQ7M7HA.js} +2 -2
- package/dist/chunks/{chunk-IXW7A4M7.js → chunk-CNYGDBID.js} +2 -2
- package/dist/chunks/{chunk-DL4LYODQ.js → chunk-J5LYSQ3L.js} +2 -2
- package/dist/chunks/{chunk-72LO6GQE.js → chunk-KXD6FX2Z.js} +2 -2
- package/dist/chunks/{chunk-4RMWFRWG.js → chunk-LELKMVJG.js} +45 -7
- package/dist/chunks/chunk-LELKMVJG.js.map +7 -0
- package/dist/chunks/{chunk-QMIXDOU6.js → chunk-OGNFHW5O.js} +4 -10
- package/dist/chunks/chunk-OGNFHW5O.js.map +7 -0
- package/dist/chunks/chunk-OJZSZBHW.js +45 -0
- package/dist/chunks/chunk-OJZSZBHW.js.map +7 -0
- package/dist/chunks/{chunk-R4MW3DRT.js → chunk-OW32YCZ6.js} +2 -2
- package/dist/chunks/{chunk-76T45V37.js → chunk-TBFB7A2Z.js} +5 -1
- package/dist/chunks/{chunk-76T45V37.js.map → chunk-TBFB7A2Z.js.map} +2 -2
- package/dist/chunks/{chunk-BXJOUAXV.js → chunk-TEJARYAE.js} +3 -3
- package/dist/chunks/{chunk-KZALUEFT.js → chunk-TPMACJFA.js} +3 -3
- package/dist/chunks/{chunk-2MJKBPGG.js → chunk-WTVGCMGV.js} +7 -3
- package/dist/chunks/chunk-WTVGCMGV.js.map +7 -0
- package/dist/chunks/{chunk-6MLYGFT6.js → chunk-XJAMBKE3.js} +6 -2
- package/dist/chunks/chunk-XJAMBKE3.js.map +7 -0
- package/dist/chunks/{chunk-FMCBTYUM.js → chunk-ZXUXX3YY.js} +2 -2
- package/dist/engine/binding.js +3 -1
- package/dist/engine/engines.js +5 -3
- package/dist/engine/files.js +5 -3
- package/dist/engine/optionA.js +4 -2
- package/dist/engine/preview.js +5 -3
- package/dist/engine/preview.js.map +1 -1
- package/dist/engine/writePlan.js +7 -5
- package/dist/export/drawio.js +3 -3
- package/dist/export/layoutCheck.js +3 -3
- package/dist/export/scene.js +2 -2
- package/dist/export/svg.js +4 -4
- package/dist/flow/findingCodes.js +1 -1
- package/dist/flow/localFiles.d.ts +17 -0
- package/dist/flow/localFiles.js +14 -0
- package/dist/flow/localFiles.js.map +7 -0
- package/dist/import/outline.js +5 -4
- package/dist/import/playbook.js +2 -2
- package/dist/import/source.js +2 -1
- package/dist/protocol.d.ts +12 -0
- package/dist/run/command.d.ts +13 -4
- package/dist/run/command.js +19 -0
- package/dist/run/command.js.map +3 -3
- package/dist/scenario/live.js +7 -5
- package/dist/scenario/simulate.js +6 -4
- package/dist/view/flowFacts.js +7 -5
- package/dist/view/flowFacts.js.map +1 -1
- package/dist/view/jinjaComplete.js +3 -3
- package/dist/view/route.d.ts +3 -1
- package/dist/view/route.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-2MJKBPGG.js.map +0 -7
- package/dist/chunks/chunk-4RMWFRWG.js.map +0 -7
- package/dist/chunks/chunk-6MLYGFT6.js.map +0 -7
- package/dist/chunks/chunk-QMIXDOU6.js.map +0 -7
- /package/dist/chunks/{chunk-IZJPLWDY.js.map → chunk-2KB3J3R5.js.map} +0 -0
- /package/dist/chunks/{chunk-EAJFZKPB.js.map → chunk-37FKZNRN.js.map} +0 -0
- /package/dist/chunks/{chunk-BNMW6KWK.js.map → chunk-57KJYXWA.js.map} +0 -0
- /package/dist/chunks/{chunk-2P3JEHLH.js.map → chunk-7ALTNZCI.js.map} +0 -0
- /package/dist/chunks/{chunk-WSARMPYU.js.map → chunk-APBEHKCF.js.map} +0 -0
- /package/dist/chunks/{chunk-W2CSOAIB.js.map → chunk-BSX6G7QY.js.map} +0 -0
- /package/dist/chunks/{chunk-3Z4WABFK.js.map → chunk-CATQHJS6.js.map} +0 -0
- /package/dist/chunks/{chunk-HPRG2672.js.map → chunk-CCWUUVSG.js.map} +0 -0
- /package/dist/chunks/{chunk-C6SQEXL5.js.map → chunk-CNQ7M7HA.js.map} +0 -0
- /package/dist/chunks/{chunk-IXW7A4M7.js.map → chunk-CNYGDBID.js.map} +0 -0
- /package/dist/chunks/{chunk-DL4LYODQ.js.map → chunk-J5LYSQ3L.js.map} +0 -0
- /package/dist/chunks/{chunk-72LO6GQE.js.map → chunk-KXD6FX2Z.js.map} +0 -0
- /package/dist/chunks/{chunk-R4MW3DRT.js.map → chunk-OW32YCZ6.js.map} +0 -0
- /package/dist/chunks/{chunk-BXJOUAXV.js.map → chunk-TEJARYAE.js.map} +0 -0
- /package/dist/chunks/{chunk-KZALUEFT.js.map → chunk-TPMACJFA.js.map} +0 -0
- /package/dist/chunks/{chunk-FMCBTYUM.js.map → chunk-ZXUXX3YY.js.map} +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/core/view/route.ts
|
|
2
|
-
import { getSmoothStepPath, Position as Side } from "@xyflow/system";
|
|
2
|
+
import { getBezierPath, getSmoothStepPath, Position as Side } from "@xyflow/system";
|
|
3
3
|
var OFFSET = 20;
|
|
4
4
|
var RADIUS = 5;
|
|
5
|
+
var CURVE_RADIUS = 40;
|
|
5
6
|
var INSET = 2;
|
|
6
7
|
var CLEAR = 25;
|
|
7
8
|
var GAP = 8;
|
|
@@ -68,7 +69,25 @@ function labelBox(text, at) {
|
|
|
68
69
|
const w = [...text].length * 6 + 8;
|
|
69
70
|
return { x: at.x - w / 2, y: at.y - 8, width: w, height: 16 };
|
|
70
71
|
}
|
|
71
|
-
function routeWire(a, from, b, to, boxes, label) {
|
|
72
|
+
function routeWire(a, from, b, to, boxes, label, style = "stepped") {
|
|
73
|
+
if (style === "curved") {
|
|
74
|
+
const [curve, cx, cy] = getBezierPath({
|
|
75
|
+
sourceX: a.x,
|
|
76
|
+
sourceY: a.y,
|
|
77
|
+
sourcePosition: from,
|
|
78
|
+
targetX: b.x,
|
|
79
|
+
targetY: b.y,
|
|
80
|
+
targetPosition: to
|
|
81
|
+
});
|
|
82
|
+
if (!runsThrough(bezierPoints(curve), boxes)) return { path: curve, label: { x: cx, y: cy } };
|
|
83
|
+
const around = roundBoxes(a, DIR_OF[from], b, DIR_OF[to], boxes);
|
|
84
|
+
if (!around) return { path: curve, label: { x: cx, y: cy } };
|
|
85
|
+
return {
|
|
86
|
+
path: pathOf(around, CURVE_RADIUS),
|
|
87
|
+
label: labelOn(around, boxes, label),
|
|
88
|
+
bends: around.slice(1, -1)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
72
91
|
const [path, x, y] = getSmoothStepPath({
|
|
73
92
|
sourceX: a.x,
|
|
74
93
|
sourceY: a.y,
|
|
@@ -269,19 +288,38 @@ function corners(points) {
|
|
|
269
288
|
}
|
|
270
289
|
return out;
|
|
271
290
|
}
|
|
272
|
-
function pathOf(points) {
|
|
291
|
+
function pathOf(points, radius = RADIUS) {
|
|
273
292
|
const first = points[0];
|
|
274
293
|
const last = points.at(-1);
|
|
275
294
|
let path = `M${first.x} ${first.y}`;
|
|
276
295
|
for (let i = 1; i < points.length - 1; i++)
|
|
277
|
-
path += bendAt(
|
|
296
|
+
path += bendAt(
|
|
297
|
+
points[i - 1],
|
|
298
|
+
points[i],
|
|
299
|
+
points[i + 1],
|
|
300
|
+
radius
|
|
301
|
+
);
|
|
278
302
|
return `${path}L${last.x} ${last.y}`;
|
|
279
303
|
}
|
|
280
|
-
function
|
|
304
|
+
function bezierPoints(path) {
|
|
305
|
+
const [p0, c1, c2, p1] = pointsOf(path);
|
|
306
|
+
if (!p0 || !c1 || !c2 || !p1) return pointsOf(path);
|
|
307
|
+
const out = [];
|
|
308
|
+
for (let i = 0; i <= 24; i++) {
|
|
309
|
+
const t = i / 24;
|
|
310
|
+
const u = 1 - t;
|
|
311
|
+
out.push({
|
|
312
|
+
x: u * u * u * p0.x + 3 * u * u * t * c1.x + 3 * u * t * t * c2.x + t * t * t * p1.x,
|
|
313
|
+
y: u * u * u * p0.y + 3 * u * u * t * c1.y + 3 * u * t * t * c2.y + t * t * t * p1.y
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
return out;
|
|
317
|
+
}
|
|
318
|
+
function bendAt(a, b, c, radius = RADIUS) {
|
|
281
319
|
const size = Math.min(
|
|
282
320
|
Math.hypot(a.x - b.x, a.y - b.y) / 2,
|
|
283
321
|
Math.hypot(b.x - c.x, b.y - c.y) / 2,
|
|
284
|
-
|
|
322
|
+
radius
|
|
285
323
|
);
|
|
286
324
|
const { x, y } = b;
|
|
287
325
|
if (a.x === x && x === c.x || a.y === y && y === c.y) return `L${x} ${y}`;
|
|
@@ -388,4 +426,4 @@ export {
|
|
|
388
426
|
labelBox,
|
|
389
427
|
routeWire
|
|
390
428
|
};
|
|
391
|
-
//# sourceMappingURL=chunk-
|
|
429
|
+
//# sourceMappingURL=chunk-LELKMVJG.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/core/view/route.ts"],
|
|
4
|
+
"sourcesContent": ["// Wires that step round nodes (AFD-70). A wire is React Flow's smooth step from port to port, as\n// before, wherever that clears every node box. Where it would run through one (a wire that skips a\n// step, or one back up the flow), it takes an orthogonal route round the boxes instead: short, few\n// turns, clear of the boxes, drawn with the same stubs and rounded corners. The canvas edge, the\n// export scenes and the layout check all route here, so every picture of a level shows the same\n// wires. AFD-294: the canvas may draw them curved instead: a bezier from port to port where that\n// clears every node, else the same route round the boxes with wide round bends.\nimport { getBezierPath, getSmoothStepPath, Position as Side } from '@xyflow/system';\nimport type { Position } from '../flow/types';\n\nexport interface Box {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface Route {\n /** SVG path in canvas pixels. */\n path: string;\n /** Where the wire's label sits. */\n label: Position;\n /** A route round boxes: its corners between the two ends (draw.io waypoints). */\n bends?: Position[];\n}\n\n/** getSmoothStepPath's defaults: the stub out of a port and the corner radius. */\nconst OFFSET = 20;\nconst RADIUS = 5;\n/** AFD-294: how a wire is drawn: stepped (right angles, small round corners) or curved. */\nexport type WireStyle = 'stepped' | 'curved';\n/** A curved route's bends: as round as the stretches either side allow, up to this. */\nconst CURVE_RADIUS = 40;\n/** A wire that only grazes a box edge is not through it: boxes shrink by this much first. */\nexport const INSET = 2;\n/** Routes keep as far from a box as a stub keeps from its node (handle face 5 + stub 20)... */\nconst CLEAR = 25;\n/** ...and, in a narrow gap, never come closer than this. */\nconst GAP = 8;\n/** A bend costs as much as this much more wire... */\nconst BEND = 40;\n/** ...and wire closer to a box than CLEAR costs this much more again... */\nconst NEAR = 1;\n/**\n * ...and wire off the two lines through its stub ends a little more, so of equal routes it takes\n * the one that turns onto its stubs: wires into one port then share their last stretch.\n */\nconst DRIFT = 0.01;\n\n/** Directions of travel, clockwise from up; a port's side is the way its stub leaves. */\nconst DIRS: Position[] = [\n { x: 0, y: -1 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n];\nconst DIR_OF: Record<Side, number> = {\n [Side.Top]: 0,\n [Side.Right]: 1,\n [Side.Bottom]: 2,\n [Side.Left]: 3,\n};\n\n// ---- geometry shared with the layout check ------------------------------------------------------\n\n/** The corners a stepped path passes: its M, L and Q points in order (Q's control is a corner). */\nexport function pointsOf(path: string): Position[] {\n const n = path.match(/-?\\d+(\\.\\d+)?(e-?\\d+)?/g)?.map(Number) ?? [];\n const out: Position[] = [];\n for (let i = 0; i + 1 < n.length; i += 2) out.push({ x: n[i] as number, y: n[i + 1] as number });\n return out;\n}\n\nexport const overlaps = (a: Box, b: Box) =>\n a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;\n\n/** The box shrunk by `by` on every side (grown when negative). */\nexport const inset = (b: Box, by: number): Box => ({\n x: b.x + by,\n y: b.y + by,\n width: Math.max(0, b.width - 2 * by),\n height: Math.max(0, b.height - 2 * by),\n});\n\n/** Whether segment a\u2013b passes through the box (Liang\u2013Barsky clipping). */\nexport function segmentHits(a: Position, b: Position, r: Box): boolean {\n let t0 = 0;\n let t1 = 1;\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const edges: [number, number][] = [\n [-dx, a.x - r.x],\n [dx, r.x + r.width - a.x],\n [-dy, a.y - r.y],\n [dy, r.y + r.height - a.y],\n ];\n for (const [p, q] of edges) {\n if (p === 0) {\n if (q < 0) return false;\n continue;\n }\n const t = q / p;\n if (p < 0) t0 = Math.max(t0, t);\n else t1 = Math.min(t1, t);\n if (t0 > t1) return false;\n }\n return true;\n}\n\n/** Whether a polyline runs through any of the boxes. */\nexport function runsThrough(points: Position[], boxes: readonly Box[]): boolean {\n for (const box of boxes) {\n const r = inset(box, INSET);\n for (let i = 0; i + 1 < points.length; i++)\n if (segmentHits(points[i] as Position, points[i + 1] as Position, r)) return true;\n }\n return false;\n}\n\n/** A wire label as the canvas draws it: 10 px mono text (6 px a character) on a padded background. */\nexport function labelBox(text: string, at: Position): Box {\n const w = [...text].length * 6 + 8;\n return { x: at.x - w / 2, y: at.y - 8, width: w, height: 16 };\n}\n\n// ---- routing ------------------------------------------------------------------------------------\n\n/**\n * The wire from `a` (leaving by side `from`) to `b` (entered by side `to`) among the node boxes of\n * its level, its own two included. `label` is the text it shows, kept off the boxes on a route.\n */\nexport function routeWire(\n a: Position,\n from: Side,\n b: Position,\n to: Side,\n boxes: readonly Box[],\n label?: string,\n style: WireStyle = 'stepped',\n): Route {\n if (style === 'curved') {\n const [curve, cx, cy] = getBezierPath({\n sourceX: a.x,\n sourceY: a.y,\n sourcePosition: from,\n targetX: b.x,\n targetY: b.y,\n targetPosition: to,\n });\n if (!runsThrough(bezierPoints(curve), boxes)) return { path: curve, label: { x: cx, y: cy } };\n const around = roundBoxes(a, DIR_OF[from], b, DIR_OF[to], boxes);\n // Boxed in: the curve, as a stepped wire would keep its smooth step.\n if (!around) return { path: curve, label: { x: cx, y: cy } };\n return {\n path: pathOf(around, CURVE_RADIUS),\n label: labelOn(around, boxes, label),\n bends: around.slice(1, -1),\n };\n }\n const [path, x, y] = getSmoothStepPath({\n sourceX: a.x,\n sourceY: a.y,\n sourcePosition: from,\n targetX: b.x,\n targetY: b.y,\n targetPosition: to,\n });\n const step = { path, label: { x, y } };\n if (!runsThrough(pointsOf(path), boxes)) return step;\n // Boxed in (a node on a port, or no gap wide enough): the smooth step, as before.\n const points = roundBoxes(a, DIR_OF[from], b, DIR_OF[to], boxes);\n if (!points) return step;\n return { path: pathOf(points), label: labelOn(points, boxes, label), bends: points.slice(1, -1) };\n}\n\n/** Grid lines: the stub ends, the lines CLEAR off each box edge, and the middle of a gap too narrow for those. */\nfunction lines(s: number, t: number, edges: [number, number][]): number[] {\n const all = edges.flat().sort((p, q) => p - q);\n const out = [s, t];\n for (const [lo, hi] of edges) out.push(lo - CLEAR, hi + CLEAR);\n for (let i = 0; i + 1 < all.length; i++) {\n const gap = (all[i + 1] as number) - (all[i] as number);\n if (gap > 2 * GAP && gap < 2 * CLEAR)\n out.push(((all[i] as number) + (all[i + 1] as number)) / 2);\n }\n return [...new Set(out)].sort((p, q) => p - q);\n}\n\n/**\n * The route's corners, from `a` to `b`, keeping the smooth step's stubs: it leaves the source stub\n * heading out and enters the target stub heading in. Nodes far off the two ends are left out of\n * the search; when that finds nothing, it runs again with every node.\n */\nfunction roundBoxes(\n a: Position,\n from: number,\n b: Position,\n to: number,\n boxes: readonly Box[],\n): Position[] | undefined {\n const out = DIRS[from] as Position;\n const back = DIRS[to] as Position;\n const s = { x: a.x + out.x * OFFSET, y: a.y + out.y * OFFSET };\n const t = { x: b.x + back.x * OFFSET, y: b.y + back.y * OFFSET };\n if (runsThrough([a, s], boxes) || runsThrough([t, b], boxes)) return undefined;\n for (const reach of [REACH, Number.POSITIVE_INFINITY]) {\n const near = nearby(s, t, boxes, reach);\n const found = search(s, from, t, (to + 2) % 4, near);\n if (found) return corners([a, ...found, b]);\n if (near.length === boxes.length) break;\n }\n return undefined;\n}\n\n/** How far round the two ends a first search looks: about two node widths. */\nconst REACH = 400;\n\n/**\n * The boxes within `reach` of the box spanning s and t, and then every box the search grid they\n * make would reach, so a grid segment can never jump a box it does not know.\n */\nfunction nearby(s: Position, t: Position, boxes: readonly Box[], reach: number): readonly Box[] {\n if (!Number.isFinite(reach)) return boxes;\n const span = (pts: Position[], pad: number): Box => {\n const xs = pts.map((p) => p.x);\n const ys = pts.map((p) => p.y);\n const [x, y] = [Math.min(...xs) - pad, Math.min(...ys) - pad];\n return { x, y, width: Math.max(...xs) + pad - x, height: Math.max(...ys) + pad - y };\n };\n let near = boxes.filter((r) => overlaps(r, span([s, t], reach)));\n for (;;) {\n const grid = span(\n [s, t, ...near.flatMap((r) => [r, { x: r.x + r.width, y: r.y + r.height }])],\n CLEAR + GAP,\n );\n const more = boxes.filter((r) => near.includes(r) || overlaps(r, grid));\n if (more.length === near.length) return near;\n near = more;\n }\n}\n\n/**\n * A* over a grid of lines in (point, direction) states: cost is length (more near a box) plus\n * BEND a turn, and no U-turns. A stretch into a box is not taken. From s heading `from` to t heading `into`; the grid points passed.\n */\nfunction search(\n s: Position,\n from: number,\n t: Position,\n into: number,\n boxes: readonly Box[],\n): Position[] | undefined {\n const xs = lines(\n s.x,\n t.x,\n boxes.map((r) => [r.x, r.x + r.width]),\n );\n const ys = lines(\n s.y,\n t.y,\n boxes.map((r) => [r.y, r.y + r.height]),\n );\n const nx = xs.length;\n const ny = ys.length;\n // Per stretch between neighbouring grid points, across (i,j)-(i+1,j) and down (i,j)-(i,j+1):\n // -1 when it enters a box grown by GAP, else how much of it runs closer to a box than CLEAR.\n const across = new Float32Array(nx * ny);\n const down = new Float32Array(nx * ny);\n const mark = (\n to: Float32Array,\n k: number,\n lo: number,\n hi: number,\n g0: number,\n g1: number,\n c0: number,\n c1: number,\n inside: boolean,\n ) => {\n if (hi <= c0 || lo >= c1 || (to[k] as number) < 0) return;\n if (inside && hi > g0 && lo < g1) to[k] = -1;\n else to[k] = Math.max(to[k] as number, Math.min(hi, c1) - Math.max(lo, c0));\n };\n for (const r of boxes) {\n const [gx0, gx1, gy0, gy1] = [r.x - GAP, r.x + r.width + GAP, r.y - GAP, r.y + r.height + GAP];\n const [cx0, cx1, cy0, cy1] = [\n r.x - CLEAR,\n r.x + r.width + CLEAR,\n r.y - CLEAR,\n r.y + r.height + CLEAR,\n ];\n for (let j = 0; j < ny; j++) {\n const y = ys[j] as number;\n if (y <= cy0 || y >= cy1) continue;\n for (let i = 0; i + 1 < nx; i++)\n mark(\n across,\n i * ny + j,\n xs[i] as number,\n xs[i + 1] as number,\n gx0,\n gx1,\n cx0,\n cx1,\n y > gy0 && y < gy1,\n );\n }\n for (let i = 0; i < nx; i++) {\n const x = xs[i] as number;\n if (x <= cx0 || x >= cx1) continue;\n for (let j = 0; j + 1 < ny; j++)\n mark(\n down,\n i * ny + j,\n ys[j] as number,\n ys[j + 1] as number,\n gy0,\n gy1,\n cy0,\n cy1,\n x > gx0 && x < gx1,\n );\n }\n }\n const inBox = (p: Position) =>\n boxes.some(\n (r) =>\n p.x > r.x - GAP &&\n p.x < r.x + r.width + GAP &&\n p.y > r.y - GAP &&\n p.y < r.y + r.height + GAP,\n );\n if (inBox(s) || inBox(t)) return undefined;\n const si = xs.indexOf(s.x);\n const sj = ys.indexOf(s.y);\n const ti = xs.indexOf(t.x);\n const tj = ys.indexOf(t.y);\n const states = nx * ny * 4;\n const cost = new Float64Array(states).fill(Number.POSITIVE_INFINITY);\n const prev = new Int32Array(states).fill(-1);\n // Distance left, plus the turns any route from here must still make (a lower bound, so A*\n // stays exact): none straight ahead in the right heading, one from a heading across it, else two.\n // At t itself none: the step onto t paid for its last turn.\n const h = (i: number, j: number, d: number) => {\n const dx = t.x - (xs[i] as number);\n const dy = t.y - (ys[j] as number);\n if (dx === 0 && dy === 0) return 0;\n const step = DIRS[d] as Position;\n const turns =\n d === into\n ? dx * step.y === dy * step.x && dx * step.x + dy * step.y >= 0\n ? 0\n : 2\n : d === (into + 2) % 4\n ? 2\n : 1;\n return Math.abs(dx) + Math.abs(dy) + turns * BEND;\n };\n const heap = new Heap();\n const start = (si * ny + sj) * 4 + from;\n cost[start] = 0;\n heap.push(h(si, sj, from), 0, start);\n let goal = -1;\n while (heap.size > 0) {\n const { key: f, value: k } = heap.pop();\n const d = k % 4;\n const p = (k - d) / 4;\n const i = Math.floor(p / ny);\n const j = p % ny;\n if (f > (cost[k] as number) + h(i, j, d)) continue;\n if (i === ti && j === tj) {\n goal = k;\n break;\n }\n for (let nd = 0; nd < 4; nd++) {\n if (nd === (d + 2) % 4) continue;\n const step = DIRS[nd] as Position;\n const ni = i + step.x;\n const nj = j + step.y;\n if (ni < 0 || nj < 0 || ni >= nx || nj >= ny) continue;\n const flat = nd % 2 === 1;\n const near = flat\n ? (across[Math.min(i, ni) * ny + j] as number)\n : (down[i * ny + Math.min(j, nj)] as number);\n if (near < 0) continue;\n const x = xs[i] as number;\n const y = ys[j] as number;\n const len = flat ? Math.abs((xs[ni] as number) - x) : Math.abs((ys[nj] as number) - y);\n const stub = flat ? y === s.y || y === t.y : x === s.x || x === t.x;\n let c =\n (cost[k] as number) + len * (stub ? 1 : 1 + DRIFT) + near * NEAR + (nd === d ? 0 : BEND);\n const nk = (ni * ny + nj) * 4 + nd;\n if (ni === ti && nj === tj) {\n if (nd === (into + 2) % 4) continue;\n if (nd !== into) c += BEND;\n }\n if (c < (cost[nk] as number)) {\n cost[nk] = c;\n prev[nk] = k;\n heap.push(c + h(ni, nj, nd), c, nk);\n }\n }\n }\n if (goal < 0) return undefined;\n const path: Position[] = [];\n for (let k = goal; k >= 0; k = prev[k] as number) {\n const p = (k - (k % 4)) / 4;\n path.push({ x: xs[Math.floor(p / ny)] as number, y: ys[p % ny] as number });\n }\n return path.reverse();\n}\n\n/** The points where the route turns, with its two ends. */\nfunction corners(points: Position[]): Position[] {\n const out: Position[] = [];\n for (const p of points) {\n const q = out.at(-1);\n if (q && q.x === p.x && q.y === p.y) continue;\n const o = out.at(-2);\n if (o && q && ((o.x === q.x && q.x === p.x) || (o.y === q.y && q.y === p.y))) out.pop();\n out.push(p);\n }\n return out;\n}\n\n/** The route as getSmoothStepPath draws its own points: rounded corners of radius RADIUS. */\nfunction pathOf(points: Position[], radius = RADIUS): string {\n const first = points[0] as Position;\n const last = points.at(-1) as Position;\n let path = `M${first.x} ${first.y}`;\n for (let i = 1; i < points.length - 1; i++)\n path += bendAt(\n points[i - 1] as Position,\n points[i] as Position,\n points[i + 1] as Position,\n radius,\n );\n return `${path}L${last.x} ${last.y}`;\n}\n\n/**\n * AFD-294: points along a bezier wire (`M x,y C c1 c2 end`), close enough to tell whether it\n * crosses a node box.\n */\nfunction bezierPoints(path: string): Position[] {\n const [p0, c1, c2, p1] = pointsOf(path);\n if (!p0 || !c1 || !c2 || !p1) return pointsOf(path);\n const out: Position[] = [];\n for (let i = 0; i <= 24; i++) {\n const t = i / 24;\n const u = 1 - t;\n out.push({\n x: u * u * u * p0.x + 3 * u * u * t * c1.x + 3 * u * t * t * c2.x + t * t * t * p1.x,\n y: u * u * u * p0.y + 3 * u * u * t * c1.y + 3 * u * t * t * c2.y + t * t * t * p1.y,\n });\n }\n return out;\n}\n\n/** @xyflow/system's getBend (not exported), so a route's corners match a smooth step's. */\nfunction bendAt(a: Position, b: Position, c: Position, radius = RADIUS): string {\n const size = Math.min(\n Math.hypot(a.x - b.x, a.y - b.y) / 2,\n Math.hypot(b.x - c.x, b.y - c.y) / 2,\n radius,\n );\n const { x, y } = b;\n if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) return `L${x} ${y}`;\n if (a.y === y) {\n const xDir = a.x < c.x ? -1 : 1;\n const yDir = a.y < c.y ? 1 : -1;\n return `L ${x + size * xDir},${y}Q ${x},${y} ${x},${y + size * yDir}`;\n }\n const xDir = a.x < c.x ? 1 : -1;\n const yDir = a.y < c.y ? -1 : 1;\n return `L ${x},${y + size * yDir}Q ${x},${y} ${x + size * xDir},${y}`;\n}\n\n/** Length of a straight stretch. */\nconst length = (p: Position, q: Position) => Math.abs(q.x - p.x) + Math.abs(q.y - p.y);\n\n/**\n * Where a route's label goes: on the first stretch from the source that holds it clear of every\n * box, as near that stretch's middle as it can, so a label names the port its wire leaves by.\n * Without a clear spot, half way along.\n */\nfunction labelOn(points: Position[], boxes: readonly Box[], text: string | undefined): Position {\n for (let i = 0; text && i + 1 < points.length; i++) {\n const p = points[i] as Position;\n const q = points[i + 1] as Position;\n const len = length(p, q);\n const along = p.y === q.y ? labelBox(text, p).width : 16;\n const room = (len - along - 8) / 2;\n const ux = Math.sign(q.x - p.x);\n const uy = Math.sign(q.y - p.y);\n for (let k = 0; k <= room; k += 8)\n for (const sign of k ? [-1, 1] : [1]) {\n const o = len / 2 + sign * k;\n const at = { x: p.x + ux * o, y: p.y + uy * o };\n const box = labelBox(text, at);\n if (!boxes.some((r) => overlaps(box, r))) return at;\n }\n }\n const legs = points.slice(1).map((q, i) => length(points[i] as Position, q));\n let rest = legs.reduce((sum, len) => sum + len, 0) / 2;\n for (let i = 0; i + 1 < points.length; i++) {\n const p = points[i] as Position;\n const q = points[i + 1] as Position;\n const len = legs[i] as number;\n if (rest <= len)\n return { x: p.x + Math.sign(q.x - p.x) * rest, y: p.y + Math.sign(q.y - p.y) * rest };\n rest -= len;\n }\n return points[0] as Position;\n}\n\n/**\n * A binary min-heap of states by priority. Of equal priorities the one furthest along goes first\n * (else A* widens over every equally short path on a grid), then the first pushed, so a route is\n * the same wherever it is drawn. The heap holds entry numbers; an entry's fields are stored once.\n */\nclass Heap {\n private heap: number[] = [];\n private keys: number[] = [];\n private depths: number[] = [];\n private values: number[] = [];\n\n get size(): number {\n return this.heap.length;\n }\n\n push(key: number, depth: number, value: number): void {\n const e = this.keys.length;\n this.keys.push(key);\n this.depths.push(depth);\n this.values.push(value);\n const h = this.heap;\n let i = h.length;\n h.push(e);\n while (i > 0) {\n const up = (i - 1) >> 1;\n if (!this.before(e, h[up] as number)) break;\n h[i] = h[up] as number;\n i = up;\n }\n h[i] = e;\n }\n\n /** Takes the first entry off: its priority and value. */\n pop(): { key: number; value: number } {\n const h = this.heap;\n const top = h[0] as number;\n const last = h.pop() as number;\n if (h.length > 0) {\n let i = 0;\n for (;;) {\n const l = 2 * i + 1;\n if (l >= h.length) break;\n const r = l + 1;\n const c = r < h.length && this.before(h[r] as number, h[l] as number) ? r : l;\n if (!this.before(h[c] as number, last)) break;\n h[i] = h[c] as number;\n i = c;\n }\n h[i] = last;\n }\n return { key: this.keys[top] as number, value: this.values[top] as number };\n }\n\n private before(a: number, b: number): boolean {\n const ka = this.keys[a] as number;\n const kb = this.keys[b] as number;\n if (ka !== kb) return ka < kb;\n const da = this.depths[a] as number;\n const db = this.depths[b] as number;\n return da !== db ? da > db : a < b;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["xDir", "yDir"]
|
|
7
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LOCAL_FILES
|
|
3
|
+
} from "./chunk-OJZSZBHW.js";
|
|
1
4
|
import {
|
|
2
5
|
basename,
|
|
3
6
|
dirname,
|
|
@@ -241,15 +244,6 @@ function moduleOf(raw) {
|
|
|
241
244
|
return { module: keys[0], value: raw[keys[0]], local: false };
|
|
242
245
|
}
|
|
243
246
|
var INCLUDES = /* @__PURE__ */ new Set(["include_tasks", "import_tasks", "include"]);
|
|
244
|
-
var LOCAL_FILES = {
|
|
245
|
-
template: { param: "src", sub: "templates" },
|
|
246
|
-
win_template: { param: "src", sub: "templates" },
|
|
247
|
-
copy: { param: "src", sub: "files" },
|
|
248
|
-
win_copy: { param: "src", sub: "files" },
|
|
249
|
-
unarchive: { param: "src", sub: "files" },
|
|
250
|
-
script: { param: "cmd", sub: "files" },
|
|
251
|
-
include_vars: { param: "file", sub: "vars" }
|
|
252
|
-
};
|
|
253
247
|
var ROLE_INCLUDES = /* @__PURE__ */ new Set(["include_role", "import_role"]);
|
|
254
248
|
var Reader = class {
|
|
255
249
|
constructor(io, opts) {
|
|
@@ -833,4 +827,4 @@ export {
|
|
|
833
827
|
readPlaybook,
|
|
834
828
|
scanFolder
|
|
835
829
|
};
|
|
836
|
-
//# sourceMappingURL=chunk-
|
|
830
|
+
//# sourceMappingURL=chunk-OGNFHW5O.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/core/import/source.ts"],
|
|
4
|
+
"sourcesContent": ["// Playbooks, task files and roles as import sources (AFD-26): one normalized tree per playbook.\n// Tasks take their module and arguments apart (action:, local_action:, free-form and k=v forms),\n// inherit their play's and blocks' keywords as Ansible does, and literal includes and imports are\n// read in. What a flow cannot hold is listed per item, so the mapper can say so.\n// Ansible's own loader (the probe, ADR-0012) needs an environment, flattens blocks and drops\n// arguments, conditions and loops; this reader works anywhere and keeps them.\nimport { templated } from '../flow/jinja';\nimport { isAllowedKeyword } from '../flow/keywords';\nimport { LOCAL_FILES } from '../flow/localFiles';\nimport { builtinFqcn, shortName } from './builtins';\nimport {\n type AnsibleConfig,\n basename,\n dirname,\n exists,\n isMapping,\n isTemplated,\n isVaultFile,\n join,\n lineOf,\n normalize,\n type Plain,\n type PlainMap,\n parseAnsible,\n parseConfig,\n type SourceIO,\n toValue,\n} from './read';\n\nexport interface Origin {\n path: string;\n line?: number;\n}\n\nexport interface TaskForm {\n kind: 'task';\n name: string;\n /** As written (`copy`, `cisco.ios.ios_config`). */\n module: string;\n /** Fully qualified when known. */\n fqcn?: string;\n params: Record<string, unknown>;\n /** Task keywords a binding carries (impl.keywords), inherited ones included. */\n keywords: Record<string, unknown>;\n register?: string;\n notify: string[];\n /** Handlers: the topics they listen to besides their name. */\n listen: string[];\n tags: string[];\n become?: boolean;\n /** Whole seconds, or a template given at run time (AFD-112). */\n timeout?: number | string;\n retries?: number | string;\n delay?: number | string;\n until?: string;\n ignoreUnreachable?: boolean;\n /** Keywords with no place in a flow. */\n dropped: string[];\n /** Local files the task reads (template src, ...): where Ansible finds them, or missing. */\n files: LocalFile[];\n origin: Origin;\n}\n\nexport interface LocalFile {\n /** The parameter, or `cmd` for a script's first word. */\n param: string;\n written: string;\n /** Repository path, when found. */\n path?: string;\n}\n\nexport interface VarsFile {\n file: string;\n path?: string;\n /** Top-level variable names in it (none when encrypted or missing). */\n keys: string[];\n}\n\nexport interface BlockForm {\n kind: 'block';\n name: string;\n items: Item[];\n rescue: Item[];\n always: Item[];\n origin: Origin;\n}\n\nexport interface IncludeForm {\n kind: 'include';\n name: string;\n /** The file as written. */\n file: string;\n /** Read in: the file's items (a literal path that exists). */\n path?: string;\n items?: Item[];\n /** Why it is not read in (a templated path, a loop, missing). */\n dynamic?: string;\n /**\n * AFD-149: an include_tasks' own `when`, which Ansible checks once for the include (not on each\n * task in the file, as for import_tasks). Its parts are ANDed.\n */\n when?: unknown[];\n keywords: Record<string, unknown>;\n tags: string[];\n /** AFD-187: the include's own vars (they also reach every task read in). */\n vars?: Record<string, unknown>;\n /**\n * AFD-177: what keeps a file that runs as include_tasks from working in generated/ (it reads\n * playbook_dir, or includes files found only next to the playbook).\n */\n portability?: string[];\n origin: Origin;\n}\n\n/** A task file of a split role: one step per file (decision 2). */\nexport interface RoleStep {\n /** include_role tasks_from: the file under tasks/ without its extension. */\n tasksFrom: string;\n name: string;\n keywords: Record<string, unknown>;\n tags: string[];\n}\n\nexport interface RoleForm {\n kind: 'role';\n name: string;\n /** What include_role names: the role name, or an FQCN for a collection role. */\n ref: string;\n /** Folder of the role, when found. */\n dir?: string;\n /** Whether generated plays find it (roles_path of the repository's ansible.cfg, collections). */\n onRolesPath: boolean;\n /** Role variables and include options (tasks_from, vars_from, ...). */\n params: Record<string, unknown>;\n keywords: Record<string, unknown>;\n tags: string[];\n become?: boolean;\n split?: RoleStep[];\n /** Variables the role registers or sets (read statically), so later steps can read them. */\n outputs: string[];\n dropped: string[];\n origin: Origin;\n}\n\nexport interface MetaForm {\n kind: 'meta';\n name: string;\n action: string;\n keywords: Record<string, unknown>;\n origin: Origin;\n}\n\nexport type Item = TaskForm | BlockForm | IncludeForm | RoleForm | MetaForm;\n\nexport interface VarPrompt {\n name: string;\n private: boolean;\n default?: unknown;\n prompt?: string;\n}\n\nexport interface PlayForm {\n kind: 'play';\n name: string;\n hosts: string;\n gatherFacts: boolean;\n gatherParams: Record<string, unknown>;\n become?: boolean;\n serial?: string | number;\n maxFailPercentage?: number;\n anyErrorsFatal?: boolean;\n collections: string[];\n vars: Record<string, unknown>;\n varsFiles: VarsFile[];\n varsPrompt: VarPrompt[];\n preTasks: Item[];\n roles: Item[];\n tasks: Item[];\n postTasks: Item[];\n handlers: Item[];\n dropped: string[];\n origin: Origin;\n}\n\nexport interface ImportPlaybookForm {\n kind: 'import_playbook';\n name: string;\n file: string;\n playbook?: PlaybookForm;\n /** Why it is not read in. */\n missing?: string;\n keywords: Record<string, unknown>;\n origin: Origin;\n}\n\nexport interface PlaybookForm {\n path: string;\n plays: (PlayForm | ImportPlaybookForm)[];\n}\n\nexport interface ReadOptions {\n /** Short module name + the play's collections \u2192 FQCN (the catalog, when the host has one). */\n resolveModule?(name: string, collections: string[]): string | undefined;\n}\n\nexport interface ReadResult {\n playbook?: PlaybookForm;\n /** What did not read one to one, for the user. */\n notes: string[];\n /** Every file read, repository paths. */\n files: string[];\n config?: AnsibleConfig;\n}\n\n// ---- keywords ------------------------------------------------------------------------------------\n\n/** Every key a task may have besides its module (Ansible's Task attributes). */\nconst TASK_KEYS = new Set([\n 'name',\n 'action',\n 'local_action',\n 'args',\n 'async',\n 'poll',\n 'become',\n 'become_exe',\n 'become_flags',\n 'become_method',\n 'become_user',\n 'changed_when',\n 'check_mode',\n 'collections',\n 'connection',\n 'debugger',\n 'delay',\n 'delegate_facts',\n 'delegate_to',\n 'diff',\n 'environment',\n 'failed_when',\n 'ignore_errors',\n 'ignore_unreachable',\n 'loop',\n 'loop_control',\n 'module_defaults',\n 'no_log',\n 'notify',\n 'listen',\n 'port',\n 'register',\n 'remote_user',\n 'retries',\n 'run_once',\n 'tags',\n 'throttle',\n 'timeout',\n 'until',\n 'vars',\n 'when',\n 'any_errors_fatal',\n 'block',\n 'rescue',\n 'always',\n]);\n\nconst isTaskKey = (k: string) => TASK_KEYS.has(k) || /^with_[a-z_]+$/.test(k);\n\n/** What blocks and plays hand down to their tasks. */\ninterface Scope {\n keywords: Record<string, unknown>;\n when: unknown[];\n tags: string[];\n become?: boolean;\n ignoreUnreachable?: boolean;\n /** Keywords that have no place, inherited. */\n dropped: string[];\n}\n\nconst EMPTY_SCOPE: Scope = { keywords: {}, when: [], tags: [], dropped: [] };\n\n/** Keywords a block or play hands down (their own `when`, tags and become are kept apart). */\nconst INHERITED = new Set([\n 'become_user',\n 'become_method',\n 'become_flags',\n 'become_exe',\n 'environment',\n 'connection',\n 'remote_user',\n 'port',\n 'ignore_errors',\n 'no_log',\n 'check_mode',\n 'diff',\n 'delegate_to',\n 'delegate_facts',\n 'run_once',\n 'throttle',\n 'module_defaults',\n 'debugger',\n 'vars',\n]);\n\nconst asList = (v: unknown): string[] =>\n v === undefined || v === null\n ? []\n : (Array.isArray(v) ? v : String(v).split(',')).map((x) => String(x).trim()).filter(Boolean);\n\nconst asBool = (v: unknown): boolean | undefined =>\n typeof v === 'boolean'\n ? v\n : typeof v === 'string' && /^(yes|true|on|1)$/i.test(v)\n ? true\n : typeof v === 'string' && /^(no|false|off|0)$/i.test(v)\n ? false\n : undefined;\n\nconst asInt = (v: unknown): number | undefined =>\n typeof v === 'number' && Number.isInteger(v)\n ? v\n : typeof v === 'string' && /^[0-9]+$/.test(v.trim())\n ? Number(v)\n : undefined;\n\n/**\n * A number, or a whole template the flow keeps as a value given at run time (AFD-112: a templated\n * retries, delay or timeout used to be dropped on import).\n */\nconst asIntOrTemplate = (v: unknown): number | string | undefined =>\n asInt(v) ?? (templated(v) ? v.trim() : undefined);\n\n/** A block's or play's own keys added to what its parent handed down. */\nfunction narrow(parent: Scope, raw: PlainMap, own: 'block' | 'play'): Scope {\n const keywords = { ...parent.keywords };\n // A play's vars become flow inputs; a block's vars reach its tasks.\n for (const k of INHERITED)\n if (raw[k] !== undefined && !(own === 'play' && k === 'vars')) {\n const v = toValue(raw[k] as Plain);\n keywords[k] =\n k === 'vars' && isMapping(keywords.vars) && isMapping(v) ? { ...keywords.vars, ...v } : v;\n }\n const dropped = [...parent.dropped];\n if (own === 'block' && raw.any_errors_fatal !== undefined) dropped.push('any_errors_fatal');\n return {\n keywords,\n when: own === 'block' && raw.when !== undefined ? [...parent.when, raw.when] : parent.when,\n tags: [...parent.tags, ...asList(raw.tags)],\n become: asBool(raw.become) ?? parent.become,\n ignoreUnreachable: asBool(raw.ignore_unreachable) ?? parent.ignoreUnreachable,\n dropped,\n };\n}\n\n/** A task's keywords over what it inherits; `when` lists are ANDed in order. */\nfunction taskKeywords(\n scope: Scope,\n raw: PlainMap,\n): { keywords: Record<string, unknown>; dropped: string[] } {\n const keywords: Record<string, unknown> = { ...scope.keywords };\n const dropped = [...scope.dropped];\n for (const [k, v] of Object.entries(raw)) {\n if (!isTaskKey(k) || k === 'when') continue;\n if (\n [\n 'name',\n 'action',\n 'local_action',\n 'args',\n 'register',\n 'notify',\n 'listen',\n 'tags',\n 'become',\n 'timeout',\n 'retries',\n 'delay',\n 'until',\n 'ignore_unreachable',\n 'block',\n 'rescue',\n 'always',\n 'collections',\n ].includes(k)\n )\n continue;\n if (k === 'with_items' || k === 'with_list') keywords.loop = toValue(v);\n else if (k === 'vars' && isMapping(keywords.vars) && isMapping(v))\n keywords.vars = { ...keywords.vars, ...(toValue(v) as Record<string, unknown>) };\n else if (isAllowedKeyword(k)) keywords[k] = toValue(v);\n else dropped.push(k);\n }\n const when = [...scope.when, ...(raw.when !== undefined ? [raw.when] : [])]\n .flatMap((w) => (Array.isArray(w) ? w : [w]))\n .map((w) => toValue(w as Plain));\n if (when.length === 1) keywords.when = when[0];\n else if (when.length > 1) keywords.when = when;\n return { keywords, dropped: [...new Set(dropped)] };\n}\n\n// ---- module arguments ----------------------------------------------------------------------------\n\n/** `src=a dest=\"b c\" mode=0644` \u2192 {src, dest, mode}; quotes and `{{ }}` keep their spaces. */\nexport function parseKv(text: string): { args: Record<string, string>; rest: string } {\n const args: Record<string, string> = {};\n const rest: string[] = [];\n const tokens: string[] = [];\n let cur = '';\n let quote = '';\n let depth = 0;\n for (let i = 0; i < text.length; i++) {\n const c = text[i] as string;\n if (quote) {\n cur += c;\n if (c === quote && text[i - 1] !== '\\\\') quote = '';\n } else if (c === '\"' || c === \"'\") {\n quote = c;\n cur += c;\n } else if (text.startsWith('{{', i) || text.startsWith('{%', i)) {\n depth++;\n cur += text.slice(i, i + 2);\n i++;\n } else if ((text.startsWith('}}', i) || text.startsWith('%}', i)) && depth > 0) {\n depth--;\n cur += text.slice(i, i + 2);\n i++;\n } else if (/\\s/.test(c) && depth === 0) {\n if (cur) tokens.push(cur);\n cur = '';\n } else cur += c;\n }\n if (cur) tokens.push(cur);\n // Ansible's parse_kv drops the quotes and decodes escapes (`content=\"done\\n\"` ends in a newline).\n const ESC: Record<string, string> = { n: '\\n', t: '\\t', r: '\\r', '\\\\': '\\\\', '\"': '\"', \"'\": \"'\" };\n const unquote = (s: string) =>\n (/^([\"']).*\\1$/s.test(s) ? s.slice(1, -1) : s).replace(\n /\\\\([ntr\\\\\"'])/g,\n (_, c: string) => ESC[c] ?? c,\n );\n for (const t of tokens) {\n const m = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/s.exec(t);\n if (m?.[1]) args[m[1]] = unquote(m[2] ?? '');\n else rest.push(t);\n }\n return { args, rest: rest.join(' ') };\n}\n\n/** Modules whose arguments are a command line, and the options Ansible takes out of it. */\nconst FREE_FORM: Record<string, string> = {\n command: 'cmd',\n shell: 'cmd',\n script: 'cmd',\n raw: '_raw_params',\n win_command: '_raw_params',\n win_shell: '_raw_params',\n};\nconst FREE_OPTIONS = new Set(['chdir', 'creates', 'removes', 'executable', 'stdin', 'warn']);\n\n/** Module arguments from the task value: a map, k=v text, or a free-form command line. */\nfunction moduleArgs(module: string, value: unknown, extra: unknown): Record<string, unknown> {\n const short = shortName(module).replace(/^ansible\\.windows\\./, '');\n let params: Record<string, unknown> = {};\n if (isMapping(value)) params = toValue(value) as Record<string, unknown>;\n else if (typeof value === 'string' && value.trim()) {\n const free = FREE_FORM[short];\n if (free) {\n const { args, rest } = parseKv(value);\n const options = Object.fromEntries(Object.entries(args).filter(([k]) => FREE_OPTIONS.has(k)));\n const kept = Object.entries(args)\n .filter(([k]) => !FREE_OPTIONS.has(k))\n .map(([k, v]) => `${k}=${v}`);\n params = { [free]: [rest, ...kept].filter(Boolean).join(' '), ...options };\n } else if (short === 'include_vars') params = { file: value.trim() };\n else {\n const { args, rest } = parseKv(value);\n params = rest ? { ...args, _raw_params: rest } : args;\n }\n }\n if (isMapping(extra)) params = { ...params, ...(toValue(extra) as Record<string, unknown>) };\n return params;\n}\n\n/** The module key and its value: a lone non-keyword key, or action / local_action. */\nfunction moduleOf(raw: PlainMap): { module: string; value: unknown; local: boolean } | undefined {\n for (const key of ['action', 'local_action'] as const) {\n const a = raw[key];\n if (a === undefined) continue;\n if (typeof a === 'string') {\n const [module = '', ...rest] = a.trim().split(/\\s+/);\n return { module, value: rest.join(' '), local: key === 'local_action' };\n }\n if (isMapping(a) && typeof a.module === 'string') {\n const { module, ...rest } = a;\n return { module: module as string, value: rest, local: key === 'local_action' };\n }\n }\n const keys = Object.keys(raw).filter((k) => !isTaskKey(k));\n if (!keys[0]) return undefined;\n return { module: keys[0], value: raw[keys[0]], local: false };\n}\n\nconst INCLUDES = new Set(['include_tasks', 'import_tasks', 'include']);\n\nconst ROLE_INCLUDES = new Set(['include_role', 'import_role']);\n// ---- the reader ----------------------------------------------------------------------------------\n\ninterface RoleInfo {\n dir?: string;\n onRolesPath: boolean;\n split?: RoleStep[];\n outputs: string[];\n}\n\nclass Reader {\n readonly notes: string[] = [];\n readonly files = new Set<string>();\n private readonly roles = new Map<string, Promise<RoleInfo>>();\n /** Task files being read in, to stop an include cycle. */\n private readonly including: string[] = [];\n /** AFD-179: task files that include themselves, at any depth; they run as include_tasks. */\n private readonly cyclic = new Set<string>();\n private config?: AnsibleConfig;\n private collections: string[] = [];\n\n constructor(\n private readonly io: SourceIO,\n private readonly opts: ReadOptions,\n ) {}\n\n /** The repository's ansible.cfg (the one runs use, ADR-0005). */\n async loadConfig(): Promise<AnsibleConfig | undefined> {\n const text = await this.io.read('ansible.cfg');\n if (text !== undefined) this.config = parseConfig(text, '');\n return this.config;\n }\n\n private async readYaml(path: string): Promise<Plain | undefined> {\n const text = await this.io.read(path);\n if (text === undefined) return undefined;\n this.files.add(path);\n if (isVaultFile(text)) {\n this.notes.push(`${path} is encrypted with Ansible Vault as a whole: not read.`);\n return undefined;\n }\n const { value, error } = parseAnsible(text);\n if (error) {\n this.notes.push(`${path} is not valid YAML (${error}): not read.`);\n return undefined;\n }\n return value;\n }\n\n async playbook(path: string, stack: string[] = []): Promise<PlaybookForm | undefined> {\n const data = await this.readYaml(path);\n if (data === undefined) return undefined;\n if (!Array.isArray(data)) {\n this.notes.push(`${path} is not a playbook (no list of plays).`);\n return undefined;\n }\n const plays: PlaybookForm['plays'] = [];\n for (const raw of data) {\n if (!isMapping(raw)) continue;\n const origin = { path, line: lineOf(raw) };\n const imp = raw.import_playbook ?? raw['ansible.builtin.import_playbook'];\n if (imp !== undefined) {\n plays.push(await this.importPlaybook(raw, String(imp), path, origin, stack));\n continue;\n }\n if (raw.hosts === undefined) {\n this.notes.push(`${path}:${origin.line ?? '?'}: a play without hosts was skipped.`);\n continue;\n }\n plays.push(await this.play(raw, path, origin));\n }\n return { path, plays };\n }\n\n private async importPlaybook(\n raw: PlainMap,\n file: string,\n from: string,\n origin: Origin,\n stack: string[],\n ): Promise<ImportPlaybookForm> {\n const keywords: Record<string, unknown> = {};\n if (raw.vars !== undefined) keywords.vars = toValue(raw.vars);\n if (raw.when !== undefined) keywords.when = toValue(raw.when);\n const form: ImportPlaybookForm = {\n kind: 'import_playbook',\n name: typeof raw.name === 'string' ? raw.name : basename(file).replace(/\\.ya?ml$/, ''),\n file,\n keywords,\n origin,\n };\n if (isTemplated(file)) {\n form.missing = 'its path is templated';\n return form;\n }\n const path = join(dirname(from), file);\n if (stack.includes(path) || stack.length >= 8) {\n form.missing = stack.includes(path) ? 'it imports itself' : 'imports nest deeper than 8';\n return form;\n }\n form.playbook = await this.playbook(path, [...stack, from]);\n if (!form.playbook) form.missing = `${path} was not found or not read`;\n return form;\n }\n\n private async play(raw: PlainMap, path: string, origin: Origin): Promise<PlayForm> {\n this.collections = asList(raw.collections);\n const scope = narrow(EMPTY_SCOPE, raw, 'play');\n const dropped = ['strategy', 'order', 'force_handlers'].filter((k) => raw[k] !== undefined);\n const gather = asBool(raw.gather_facts);\n const gatherParams: Record<string, unknown> = {};\n if (raw.gather_subset !== undefined) gatherParams.gather_subset = toValue(raw.gather_subset);\n if (raw.gather_timeout !== undefined) gatherParams.gather_timeout = toValue(raw.gather_timeout);\n const dir = dirname(path);\n const section = async (key: string) =>\n this.items(Array.isArray(raw[key]) ? (raw[key] as Plain[]) : [], scope, dir, dir, path);\n const prompts = Array.isArray(raw.vars_prompt) ? raw.vars_prompt : [];\n return {\n kind: 'play',\n name: typeof raw.name === 'string' ? raw.name : '',\n hosts: Array.isArray(raw.hosts)\n ? raw.hosts.map(String).join(',')\n : String(raw.hosts ?? 'all'),\n gatherFacts: gather ?? this.config?.gathering !== 'explicit',\n gatherParams,\n become: scope.become,\n serial:\n typeof raw.serial === 'number' || typeof raw.serial === 'string' ? raw.serial : undefined,\n maxFailPercentage: asInt(raw.max_fail_percentage),\n anyErrorsFatal: asBool(raw.any_errors_fatal),\n collections: this.collections,\n vars: isMapping(raw.vars) ? (toValue(raw.vars) as Record<string, unknown>) : {},\n varsFiles: await this.varsFiles(raw.vars_files, dir),\n varsPrompt: prompts.filter(isMapping).map((p) => ({\n name: String(p.name ?? ''),\n private: asBool(p.private) ?? true,\n ...(p.default !== undefined ? { default: toValue(p.default) } : {}),\n ...(typeof p.prompt === 'string' ? { prompt: p.prompt } : {}),\n })),\n preTasks: await section('pre_tasks'),\n roles: await this.playRoles(raw.roles, scope, path),\n tasks: await section('tasks'),\n postTasks: await section('post_tasks'),\n handlers: await section('handlers'),\n dropped: [...new Set([...dropped, ...scope.dropped])],\n origin,\n };\n }\n\n /** The `roles:` section: strings or maps with role/name, vars, keywords and old-style vars. */\n private async playRoles(value: Plain | undefined, scope: Scope, path: string): Promise<Item[]> {\n const out: Item[] = [];\n for (const entry of Array.isArray(value) ? value : []) {\n const raw: PlainMap = isMapping(entry) ? entry : { role: entry as Plain };\n const name = String(raw.role ?? raw.name ?? '');\n if (!name) continue;\n const params: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(raw))\n if (!['role', 'name'].includes(k) && !isTaskKey(k)) params[k] = toValue(v);\n if (isMapping(raw.vars)) Object.assign(params, toValue(raw.vars));\n out.push(\n await this.role(name, params, { ...raw, vars: null } as PlainMap, scope, path, {\n path,\n line: lineOf(entry),\n }),\n );\n }\n return out;\n }\n\n async items(\n list: Plain[],\n scope: Scope,\n dir: string,\n playDir: string,\n file: string,\n depth = 0,\n ): Promise<Item[]> {\n const out: Item[] = [];\n for (const raw of list) {\n if (!isMapping(raw)) continue;\n const item = await this.item(raw, scope, dir, playDir, file, depth);\n if (item) out.push(item);\n }\n return out;\n }\n\n private async item(\n raw: PlainMap,\n scope: Scope,\n dir: string,\n playDir: string,\n file: string,\n depth: number,\n ): Promise<Item | undefined> {\n const origin = { path: file, line: lineOf(raw) };\n const name = typeof raw.name === 'string' ? raw.name : '';\n if (Array.isArray(raw.block)) {\n const inner = narrow(scope, raw, 'block');\n const list = async (key: string) =>\n this.items(\n Array.isArray(raw[key]) ? (raw[key] as Plain[]) : [],\n inner,\n dir,\n playDir,\n file,\n depth,\n );\n return {\n kind: 'block',\n name,\n items: await list('block'),\n rescue: await list('rescue'),\n always: await list('always'),\n origin,\n };\n }\n const found = moduleOf(raw);\n if (!found) {\n this.notes.push(`${file}:${origin.line ?? '?'}: a task without a module was skipped.`);\n return undefined;\n }\n const short = shortName(found.module);\n const { keywords, dropped } = taskKeywords(scope, raw);\n if (found.local) keywords.delegate_to = 'localhost';\n const tags = [...scope.tags, ...asList(raw.tags)];\n if (INCLUDES.has(short))\n return this.include(\n raw,\n found.value,\n name,\n keywords,\n tags,\n dir,\n playDir,\n origin,\n scope,\n depth,\n short === 'import_tasks',\n );\n if (ROLE_INCLUDES.has(short)) {\n const args = moduleArgs(found.module, found.value, raw.args);\n const roleName = String(args.name ?? '');\n const params: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(args)) if (k !== 'name' && k !== 'apply') params[k] = v;\n if (isMapping(raw.vars)) Object.assign(params, toValue(raw.vars));\n const apply = isMapping(args.apply) ? (args.apply as PlainMap) : {};\n const role = await this.role(\n roleName,\n params,\n { ...raw, ...apply, vars: null } as PlainMap,\n scope,\n file,\n origin,\n );\n role.name = name || role.name;\n return role;\n }\n if (short === 'meta') {\n return { kind: 'meta', name, action: String(found.value ?? '').trim(), keywords, origin };\n }\n const params = moduleArgs(found.module, found.value, raw.args);\n const fqcn =\n builtinFqcn(found.module) ?? this.opts.resolveModule?.(found.module, this.collections);\n const become = asBool(raw.become) ?? scope.become;\n return {\n kind: 'task',\n name,\n module: found.module,\n ...(fqcn ? { fqcn } : {}),\n params,\n keywords,\n ...(typeof raw.register === 'string' && raw.register ? { register: raw.register } : {}),\n notify: asList(raw.notify),\n listen: asList(raw.listen),\n tags,\n ...(become !== undefined ? { become } : {}),\n ...(asIntOrTemplate(raw.timeout) ? { timeout: asIntOrTemplate(raw.timeout) } : {}),\n ...(asIntOrTemplate(raw.retries) !== undefined\n ? { retries: asIntOrTemplate(raw.retries) }\n : {}),\n ...(asIntOrTemplate(raw.delay) !== undefined ? { delay: asIntOrTemplate(raw.delay) } : {}),\n ...(typeof raw.until === 'string' ? { until: raw.until } : {}),\n ...((asBool(raw.ignore_unreachable) ?? scope.ignoreUnreachable)\n ? { ignoreUnreachable: true }\n : {}),\n dropped: [\n ...dropped,\n ...(raw.retries !== undefined && asIntOrTemplate(raw.retries) === undefined\n ? ['retries']\n : []),\n ...(raw.delay !== undefined && asIntOrTemplate(raw.delay) === undefined ? ['delay'] : []),\n ...(raw.timeout !== undefined && !asIntOrTemplate(raw.timeout) ? ['timeout'] : []),\n ],\n files: await this.localFiles(found.module, params, dir, playDir),\n origin,\n };\n }\n\n /** Where Ansible would find the local files a task names, searched as it does. */\n private async localFiles(\n module: string,\n params: Record<string, unknown>,\n dir: string,\n playDir: string,\n ): Promise<LocalFile[]> {\n const short = shortName(module).replace(/^ansible\\.windows\\./, '');\n const spec = LOCAL_FILES[short];\n if (!spec || asBool(params.remote_src)) return [];\n let written = params[spec.param];\n if (short === 'script' && typeof written === 'string') written = written.trim().split(/\\s+/)[0];\n if (typeof written !== 'string' || !written || isTemplated(written) || written.startsWith('/'))\n return [];\n const bases = [...new Set([dir, playDir])];\n const candidates = bases.flatMap((b) => [join(b, spec.sub, written), join(b, written)]);\n for (const path of candidates)\n if (await exists(this.io, path)) return [{ param: spec.param, written, path }];\n return [{ param: spec.param, written }];\n }\n\n private async varsFiles(value: Plain | undefined, dir: string): Promise<VarsFile[]> {\n const out: VarsFile[] = [];\n for (const entry of Array.isArray(value) ? value : []) {\n const file = Array.isArray(entry) ? entry[0] : entry;\n if (typeof file !== 'string') continue;\n if (isTemplated(file) || file.startsWith('/')) {\n out.push({ file, keys: [] });\n continue;\n }\n const path = join(dir, file);\n const data = (await exists(this.io, path)) ? await this.readYaml(path) : undefined;\n out.push({\n file,\n ...(data !== undefined ? { path } : {}),\n keys: isMapping(data) ? Object.keys(data) : [],\n });\n }\n return out;\n }\n\n private async include(\n raw: PlainMap,\n value: unknown,\n name: string,\n keywords: Record<string, unknown>,\n tags: string[],\n dir: string,\n playDir: string,\n origin: Origin,\n scope: Scope,\n depth: number,\n /** import_tasks: static; include_tasks (and the old include): dynamic (AFD-149). */\n isStatic = false,\n ): Promise<IncludeForm> {\n const args = isMapping(value) ? (toValue(value) as Record<string, unknown>) : {};\n const target =\n typeof value === 'string' ? value.trim() : String(args.file ?? args._raw_params ?? '');\n const form: IncludeForm = { kind: 'include', name, file: target, keywords, tags, origin };\n if (isMapping(raw.vars)) form.vars = toValue(raw.vars) as Record<string, unknown>;\n if (!target || isTemplated(target)) {\n form.dynamic = 'its file name is templated';\n return form;\n }\n // AFD-179: the file is found first, so an include that cannot be read in can still run it.\n const candidates = [...new Set([join(dir, target), join(playDir, target)])];\n let path: string | undefined;\n for (const c of candidates)\n if (await exists(this.io, c)) {\n path = c;\n break;\n }\n const runAsIs = async (why: string) => {\n form.dynamic = why;\n if (path) {\n form.path = path;\n form.portability = await this.portability(path, playDir);\n }\n return form;\n };\n if (keywords.loop !== undefined || Object.keys(keywords).some((k) => k.startsWith('with_')))\n return runAsIs('it runs in a loop');\n if (depth >= 8) return runAsIs('includes nest deeper than 8');\n if (path && this.including.includes(path)) {\n this.cyclic.add(path);\n return runAsIs(`${path} includes itself`);\n }\n for (const p of path ? [path] : []) {\n const data = await this.readYaml(p);\n if (data === undefined) break;\n form.path = p;\n // import_tasks: its keywords reach every task in the file. include_tasks (AFD-149): its own\n // `when` is checked once and its tags select the include itself; only its vars and `apply`\n // (keywords for the tasks inside) reach them.\n let inner: Scope;\n if (isStatic) inner = narrow(scope, raw, 'block');\n else {\n const base = narrow(\n scope,\n (raw.vars !== undefined ? { vars: raw.vars } : {}) as PlainMap,\n 'block',\n );\n inner = isMapping(args.apply) ? narrow(base, args.apply as PlainMap, 'block') : base;\n if (raw.when !== undefined)\n form.when = (Array.isArray(raw.when) ? raw.when : [raw.when]).map((w) =>\n toValue(w as Plain),\n );\n }\n this.including.push(p);\n const items = await this.items(\n Array.isArray(data) ? data : [],\n inner,\n dirname(p),\n playDir,\n p,\n depth + 1,\n );\n this.including.pop();\n // A file that includes itself, here or deeper, runs as include_tasks: a copy read in one\n // level deep would not run as the source does.\n if (this.cyclic.has(p)) return runAsIs(`${p} includes itself`);\n form.items = items;\n form.keywords = {};\n return form;\n }\n form.dynamic = `${candidates[0]} was not found`;\n return form;\n }\n\n /**\n * AFD-177: why a task file would not work from generated/: it reads playbook_dir, or includes a\n * file Ansible finds only next to the playbook (not next to the file itself).\n */\n private async portability(path: string, playDir: string): Promise<string[]> {\n const text = (await this.io.read(path)) ?? '';\n const found: string[] = [];\n if (/\\bplaybook_dir\\b/.test(text)) found.push('reads playbook_dir');\n const data = await this.readYaml(path);\n const nested = new Set<string>();\n const walk = (v: unknown) => {\n if (Array.isArray(v)) v.forEach(walk);\n else if (isMapping(v))\n for (const [k, x] of Object.entries(v)) {\n if (INCLUDES.has(shortName(k))) {\n const f = typeof x === 'string' ? x : isMapping(x) ? (x.file ?? x._raw_params) : '';\n if (typeof f === 'string' && f && !isTemplated(f) && !f.startsWith('/'))\n nested.add(f.trim());\n } else walk(x);\n }\n };\n walk(data);\n for (const f of nested)\n if (\n !(await exists(this.io, join(dirname(path), f))) &&\n (await exists(this.io, join(playDir, f)))\n )\n found.push(`includes ${f} relative to the playbook`);\n return found;\n }\n\n private async role(\n name: string,\n params: Record<string, unknown>,\n raw: PlainMap,\n scope: Scope,\n file: string,\n origin: Origin,\n ): Promise<RoleForm> {\n // Role variables are params; every other keyword applies to the role's tasks.\n const { keywords, dropped } = taskKeywords(scope, raw);\n delete keywords.vars;\n const info = await this.roleInfo(name, dirname(file));\n const tags = [...scope.tags, ...asList(raw.tags)];\n const become = asBool(raw.become) ?? scope.become;\n return {\n kind: 'role',\n name: name.includes('/') ? basename(name) : name,\n ref: name.includes('/') && info.dir ? basename(info.dir) : name,\n ...(info.dir ? { dir: info.dir } : {}),\n onRolesPath: info.onRolesPath,\n params,\n keywords,\n tags,\n ...(become !== undefined ? { become } : {}),\n ...(info.split && !params.tasks_from ? { split: info.split } : {}),\n outputs: info.outputs,\n dropped,\n origin,\n };\n }\n\n /** Where a role lives, whether runs find it, its split and what it registers. */\n roleInfo(name: string, fromDir: string): Promise<RoleInfo> {\n const key = `${fromDir}|${name}`;\n let found = this.roles.get(key);\n if (!found) {\n found = this.findRole(name, fromDir);\n this.roles.set(key, found);\n }\n return found;\n }\n\n private async findRole(name: string, fromDir: string): Promise<RoleInfo> {\n const parts = name.split('.');\n const cfgRoles = this.config?.rolesPath ?? [];\n let candidates: { dir: string; onRolesPath: boolean }[];\n if (!name.includes('/') && parts.length === 3) {\n const [ns, coll, role] = parts;\n const bases = [\n 'collections',\n ...(this.config?.collectionsPath ?? []).map((p) => normalize(p)),\n ];\n candidates = [...new Set([...bases, join(fromDir, 'collections')])].map((b) => ({\n dir: join(b, 'ansible_collections', ns ?? '', coll ?? '', 'roles', role ?? ''),\n onRolesPath: true,\n }));\n } else {\n // Ansible's order: roles/ next to the playbook, then roles_path, then the playbook's folder.\n candidates = [\n { dir: join(fromDir, 'roles', name), onRolesPath: false },\n ...cfgRoles.map((p) => ({ dir: join(p, name), onRolesPath: true })),\n { dir: join('roles', name), onRolesPath: false },\n { dir: join(fromDir, name), onRolesPath: false },\n ];\n }\n for (const c of candidates) {\n for (const main of ['tasks/main.yml', 'tasks/main.yaml', 'meta/main.yml'])\n if (await exists(this.io, join(c.dir, main))) {\n const onRolesPath = c.onRolesPath || cfgRoles.includes(dirname(c.dir));\n return { dir: c.dir, onRolesPath, ...(await this.roleTasks(c.dir)) };\n }\n }\n // A collection role not in the repository is still bound by name: the EE may have it.\n return { onRolesPath: parts.length === 3, outputs: [] };\n }\n\n /** A split role (main only includes literal files) and the variables its tasks set. */\n private async roleTasks(dir: string): Promise<{ split?: RoleStep[]; outputs: string[] }> {\n const tasksDir = join(dir, 'tasks');\n const outputs = new Set<string>();\n const seen = new Set<string>();\n const walk = async (path: string, depth: number): Promise<Plain[] | undefined> => {\n if (seen.has(path) || depth > 4) return undefined;\n seen.add(path);\n const text = await this.io.read(path);\n if (text === undefined || isVaultFile(text)) return undefined;\n const { value } = parseAnsible(text);\n if (!Array.isArray(value)) return undefined;\n const visit = async (list: Plain[]) => {\n for (const t of list) {\n if (!isMapping(t)) continue;\n if (typeof t.register === 'string') outputs.add(t.register);\n for (const b of ['block', 'rescue', 'always'])\n if (Array.isArray(t[b])) await visit(t[b] as Plain[]);\n const m = moduleOf(t);\n const short = m ? shortName(m.module) : '';\n if (short === 'set_fact' && isMapping(m?.value))\n for (const k of Object.keys(m.value)) if (k !== 'cacheable') outputs.add(k);\n const target = INCLUDES.has(short)\n ? typeof m?.value === 'string'\n ? m.value\n : (m?.value as PlainMap)?.file\n : undefined;\n if (typeof target === 'string' && !isTemplated(target))\n await walk(join(dirname(path), target), depth + 1);\n }\n };\n await visit(value);\n return value;\n };\n let mainPath = join(tasksDir, 'main.yml');\n if (!(await exists(this.io, mainPath))) mainPath = join(tasksDir, 'main.yaml');\n const main = await walk(mainPath, 0);\n let split: RoleStep[] | undefined;\n if (main && main.length >= 2) {\n split = [];\n for (const t of main) {\n const m = isMapping(t) ? moduleOf(t) : undefined;\n const short = m ? shortName(m.module) : '';\n const target =\n typeof m?.value === 'string' ? m.value.trim() : (m?.value as PlainMap | undefined)?.file;\n const extra = isMapping(t)\n ? Object.keys(t).filter((k) => isTaskKey(k) && !['name', 'tags', 'when'].includes(k))\n : ['?'];\n if (\n !m ||\n !INCLUDES.has(short) ||\n typeof target !== 'string' ||\n isTemplated(target) ||\n extra.length\n ) {\n split = undefined;\n break;\n }\n const rel = normalize(join(dirname(mainPath.slice(tasksDir.length + 1)), target));\n split.push({\n tasksFrom: rel.replace(/\\.ya?ml$/, ''),\n name:\n typeof (t as PlainMap).name === 'string'\n ? ((t as PlainMap).name as string)\n : basename(rel).replace(/\\.ya?ml$/, ''),\n keywords:\n (t as PlainMap).when !== undefined\n ? { when: toValue((t as PlainMap).when as Plain) }\n : {},\n tags: asList((t as PlainMap).tags),\n });\n }\n }\n return { ...(split ? { split } : {}), outputs: [...outputs].sort() };\n }\n}\n\n/** Reads a playbook with everything it imports and includes. */\nexport async function readPlaybook(\n io: SourceIO,\n path: string,\n opts: ReadOptions = {},\n): Promise<ReadResult> {\n const reader = new Reader(io, opts);\n const config = await reader.loadConfig();\n const playbook = await reader.playbook(normalize(path));\n return { playbook, notes: reader.notes, files: [...reader.files], ...(config ? { config } : {}) };\n}\n\n// ---- folders -------------------------------------------------------------------------------------\n\n/** Folders a scan never enters: tooling, generated code, and Ansible content that is not a playbook. */\nconst SKIP_DIRS = new Set([\n 'node_modules',\n 'generated',\n 'out',\n 'dist',\n 'venv',\n 'roles',\n 'group_vars',\n 'host_vars',\n 'collections',\n 'flows',\n 'molecule',\n '__pycache__',\n]);\n\nconst PLAY_HINT = /^[ \\t]*-?[ \\t]*(hosts|(ansible\\.builtin\\.)?import_playbook)[ \\t]*:/m;\n\nexport interface FolderPlaybook {\n path: string;\n /** The first play's name, else the file name. */\n title: string;\n /** Not imported by another playbook in the folder: offered first. */\n entry: boolean;\n /** Who imports it, when not an entry. */\n importedBy?: string;\n}\n\nexport interface FolderScan {\n playbooks: FolderPlaybook[];\n /** Roles under roles/ (and roles_path) with whether each is split. */\n roles: { name: string; dir: string; split: boolean }[];\n truncated: boolean;\n}\n\n/** The playbooks of a folder (and below), which ones are entries, and its roles. */\nexport async function scanFolder(io: SourceIO, dir: string, maxFiles = 2000): Promise<FolderScan> {\n const files: string[] = [];\n let truncated = false;\n const walk = async (d: string, depth: number) => {\n if (depth > 6) return;\n for (const e of await io.list(d)) {\n if (files.length >= maxFiles) {\n truncated = true;\n return;\n }\n if (e.name.startsWith('.')) continue;\n const path = join(d, e.name);\n if (e.dir) {\n if (!SKIP_DIRS.has(e.name)) await walk(path, depth + 1);\n } else if (/\\.ya?ml$/.test(e.name) && !e.name.endsWith('.flow.yaml')) files.push(path);\n }\n };\n await walk(normalize(dir), 0);\n const playbooks: FolderPlaybook[] = [];\n const imports = new Map<string, string>();\n for (const path of files) {\n const text = await io.read(path);\n if (text === undefined || !PLAY_HINT.test(text) || isVaultFile(text)) continue;\n const { value } = parseAnsible(text);\n if (!Array.isArray(value)) continue;\n const items = value.filter(isMapping);\n const plays = items.filter((p) => p.hosts !== undefined);\n const imported = items\n .map((p) => p.import_playbook ?? p['ansible.builtin.import_playbook'])\n .filter((f): f is string => typeof f === 'string' && !isTemplated(f));\n if (!plays.length && !imported.length) continue;\n for (const f of imported) imports.set(join(dirname(path), f), path);\n const first = plays.find((p) => typeof p.name === 'string');\n playbooks.push({\n path,\n title: typeof first?.name === 'string' ? first.name : basename(path),\n entry: true,\n });\n }\n for (const p of playbooks) {\n const by = imports.get(p.path);\n if (by) {\n p.entry = false;\n p.importedBy = by;\n }\n }\n const roles: FolderScan['roles'] = [];\n const reader = new Reader(io, {});\n const config = await reader.loadConfig();\n const roleDirs = [...new Set([join(dir, 'roles'), 'roles', ...(config?.rolesPath ?? [])])];\n for (const base of roleDirs)\n for (const e of await io.list(base))\n if (e.dir && !e.name.startsWith('.') && !roles.some((r) => r.dir === join(base, e.name))) {\n const r = await reader.roleInfo(e.name, dirname(base));\n if (r.dir) roles.push({ name: e.name, dir: r.dir, split: !!r.split });\n }\n playbooks.sort((a, b) => Number(b.entry) - Number(a.entry) || a.path.localeCompare(b.path));\n return { playbooks, roles, truncated };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["params"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shortName
|
|
3
|
+
} from "./chunk-LNFMYJUJ.js";
|
|
4
|
+
|
|
5
|
+
// src/core/flow/localFiles.ts
|
|
6
|
+
var LOCAL_FILES = {
|
|
7
|
+
template: { param: "src", sub: "templates" },
|
|
8
|
+
win_template: { param: "src", sub: "templates" },
|
|
9
|
+
copy: { param: "src", sub: "files" },
|
|
10
|
+
win_copy: { param: "src", sub: "files" },
|
|
11
|
+
unarchive: { param: "src", sub: "files" },
|
|
12
|
+
script: { param: "cmd", sub: "files" },
|
|
13
|
+
include_vars: { param: "file", sub: "vars" }
|
|
14
|
+
};
|
|
15
|
+
var REPO_ROOT_VAR = "afd_repo_root";
|
|
16
|
+
var truthy = (v) => v === true || typeof v === "string" && /^(yes|true|on|1)$/i.test(v.trim());
|
|
17
|
+
function localFileOf(module, params) {
|
|
18
|
+
const spec = LOCAL_FILES[shortName(module).replace(/^ansible\.windows\./, "")];
|
|
19
|
+
if (!spec || !params || typeof params !== "object" || Array.isArray(params)) return void 0;
|
|
20
|
+
const map = params;
|
|
21
|
+
if (truthy(map.remote_src)) return void 0;
|
|
22
|
+
let written = map[spec.param];
|
|
23
|
+
if (spec.param === "cmd" && typeof written === "string") written = written.trim().split(/\s+/)[0];
|
|
24
|
+
if (typeof written !== "string" || !written.trim()) return void 0;
|
|
25
|
+
const path = written.trim();
|
|
26
|
+
if (path.includes("{{") || path.includes("{%") || /^([/~\\]|[A-Za-z]:)/.test(path))
|
|
27
|
+
return void 0;
|
|
28
|
+
return { param: spec.param, path: path.replace(/^\.\//, "") };
|
|
29
|
+
}
|
|
30
|
+
function rootedParams(module, params) {
|
|
31
|
+
const file = localFileOf(module, params);
|
|
32
|
+
if (!file) return params;
|
|
33
|
+
const map = { ...params };
|
|
34
|
+
const rooted = `{{ ${REPO_ROOT_VAR} }}/${file.path}`;
|
|
35
|
+
map[file.param] = file.param === "cmd" && typeof map.cmd === "string" ? map.cmd.replace(/^\s*\S+/, rooted) : rooted;
|
|
36
|
+
return map;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
LOCAL_FILES,
|
|
41
|
+
REPO_ROOT_VAR,
|
|
42
|
+
localFileOf,
|
|
43
|
+
rootedParams
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=chunk-OJZSZBHW.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/core/flow/localFiles.ts"],
|
|
4
|
+
"sourcesContent": ["// Files a step reads from the repository (AFD-291): a template's or a copy's source, a script, a\n// vars file. Generated plays run from flows/<key>/generated, where Ansible would look for them, so a\n// relative path in a step means the repository root: the generator writes it from\n// `{{ afd_repo_root }}`, and the host warns when the file is not there. Import (AFD-176) already\n// writes the paths it finds that way, searched as Ansible does from the source playbook.\nimport { shortName } from '../import/builtins';\n\n/** Modules that read a local file, the parameter naming it and the subfolder Ansible looks in. */\nexport const LOCAL_FILES: Record<string, { param: string; sub: string }> = {\n template: { param: 'src', sub: 'templates' },\n win_template: { param: 'src', sub: 'templates' },\n copy: { param: 'src', sub: 'files' },\n win_copy: { param: 'src', sub: 'files' },\n unarchive: { param: 'src', sub: 'files' },\n script: { param: 'cmd', sub: 'files' },\n include_vars: { param: 'file', sub: 'vars' },\n};\n\n/** The variable generated plays set to the repository root. */\nexport const REPO_ROOT_VAR = 'afd_repo_root';\n\nconst truthy = (v: unknown) =>\n v === true || (typeof v === 'string' && /^(yes|true|on|1)$/i.test(v.trim()));\n\n/**\n * The repository file a module step names by a relative path, as written; undefined when it names\n * none (another module, a remote source, an absolute or templated path).\n */\nexport function localFileOf(\n module: string,\n params: unknown,\n): { param: string; path: string } | undefined {\n const spec = LOCAL_FILES[shortName(module).replace(/^ansible\\.windows\\./, '')];\n if (!spec || !params || typeof params !== 'object' || Array.isArray(params)) return undefined;\n const map = params as Record<string, unknown>;\n if (truthy(map.remote_src)) return undefined;\n let written = map[spec.param];\n if (spec.param === 'cmd' && typeof written === 'string') written = written.trim().split(/\\s+/)[0];\n if (typeof written !== 'string' || !written.trim()) return undefined;\n const path = written.trim();\n if (path.includes('{{') || path.includes('{%') || /^([/~\\\\]|[A-Za-z]:)/.test(path))\n return undefined;\n return { param: spec.param, path: path.replace(/^\\.\\//, '') };\n}\n\n/** The params with a relative repository file written from `{{ afd_repo_root }}`. */\nexport function rootedParams(module: string, params: unknown): unknown {\n const file = localFileOf(module, params);\n if (!file) return params;\n const map = { ...(params as Record<string, unknown>) };\n const rooted = `{{ ${REPO_ROOT_VAR} }}/${file.path}`;\n map[file.param] =\n file.param === 'cmd' && typeof map.cmd === 'string'\n ? map.cmd.replace(/^\\s*\\S+/, rooted)\n : rooted;\n return map;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAQO,IAAM,cAA8D;AAAA,EACzE,UAAU,EAAE,OAAO,OAAO,KAAK,YAAY;AAAA,EAC3C,cAAc,EAAE,OAAO,OAAO,KAAK,YAAY;AAAA,EAC/C,MAAM,EAAE,OAAO,OAAO,KAAK,QAAQ;AAAA,EACnC,UAAU,EAAE,OAAO,OAAO,KAAK,QAAQ;AAAA,EACvC,WAAW,EAAE,OAAO,OAAO,KAAK,QAAQ;AAAA,EACxC,QAAQ,EAAE,OAAO,OAAO,KAAK,QAAQ;AAAA,EACrC,cAAc,EAAE,OAAO,QAAQ,KAAK,OAAO;AAC7C;AAGO,IAAM,gBAAgB;AAE7B,IAAM,SAAS,CAAC,MACd,MAAM,QAAS,OAAO,MAAM,YAAY,qBAAqB,KAAK,EAAE,KAAK,CAAC;AAMrE,SAAS,YACd,QACA,QAC6C;AAC7C,QAAM,OAAO,YAAY,UAAU,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AAC7E,MAAI,CAAC,QAAQ,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO;AACpF,QAAM,MAAM;AACZ,MAAI,OAAO,IAAI,UAAU,EAAG,QAAO;AACnC,MAAI,UAAU,IAAI,KAAK,KAAK;AAC5B,MAAI,KAAK,UAAU,SAAS,OAAO,YAAY,SAAU,WAAU,QAAQ,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC;AAChG,MAAI,OAAO,YAAY,YAAY,CAAC,QAAQ,KAAK,EAAG,QAAO;AAC3D,QAAM,OAAO,QAAQ,KAAK;AAC1B,MAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,sBAAsB,KAAK,IAAI;AAC/E,WAAO;AACT,SAAO,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,QAAQ,SAAS,EAAE,EAAE;AAC9D;AAGO,SAAS,aAAa,QAAgB,QAA0B;AACrE,QAAM,OAAO,YAAY,QAAQ,MAAM;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,MAAM,EAAE,GAAI,OAAmC;AACrD,QAAM,SAAS,MAAM,aAAa,OAAO,KAAK,IAAI;AAClD,MAAI,KAAK,KAAK,IACZ,KAAK,UAAU,SAAS,OAAO,IAAI,QAAQ,WACvC,IAAI,IAAI,QAAQ,WAAW,MAAM,IACjC;AACN,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-X3DEH47B.js";
|
|
13
13
|
import {
|
|
14
14
|
scenesOf
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KXD6FX2Z.js";
|
|
16
16
|
import {
|
|
17
17
|
NODE_TYPE_LABEL,
|
|
18
18
|
flowDetails,
|
|
@@ -454,4 +454,4 @@ export {
|
|
|
454
454
|
drawioPages,
|
|
455
455
|
drawioFile
|
|
456
456
|
};
|
|
457
|
-
//# sourceMappingURL=chunk-
|
|
457
|
+
//# sourceMappingURL=chunk-OW32YCZ6.js.map
|
|
@@ -192,6 +192,10 @@ var FINDING_CODES = {
|
|
|
192
192
|
meaning: "Another step sets the input's own name (set_fact, register, an output of that name) where it runs after the from: step, or before the reader when the from: step does not set that name. The generated play passes the input as a play var, and Ansible ranks set_fact and register above play vars: the step reads the value set last, not the one from: names.",
|
|
193
193
|
fix: "Rename the input (the binding then reads the new name), or read from: the step that sets the name last. If the value set last is what the step should get, accept it with that reason."
|
|
194
194
|
},
|
|
195
|
+
"binding-file-missing": {
|
|
196
|
+
meaning: "A step reads a repository file (a template or copy source, a script, a vars file) that is not there. Generated plays read a relative path from the repository root.",
|
|
197
|
+
fix: "Write the path from the repository root (templates/motd.j2), or add the file there."
|
|
198
|
+
},
|
|
195
199
|
"binding-playbook-dir": {
|
|
196
200
|
meaning: "A binding reads playbook_dir. Generated plays run from the flow's generated/ folder, so paths next to the source playbook are not found there.",
|
|
197
201
|
fix: "Write repository paths from {{ afd_repo_root }}, the repository root the generated play sets; a shared task file can use {{ afd_repo_root | default(playbook_dir) }} so it works from the source playbook too."
|
|
@@ -326,4 +330,4 @@ var FINDING_CODES = {
|
|
|
326
330
|
export {
|
|
327
331
|
FINDING_CODES
|
|
328
332
|
};
|
|
329
|
-
//# sourceMappingURL=chunk-
|
|
333
|
+
//# sourceMappingURL=chunk-TBFB7A2Z.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/core/flow/findingCodes.ts"],
|
|
4
|
-
"sourcesContent": ["// Every problem the designer reports, with what it means and how to fix it (AFD-19): shown by AI\n// tools next to each finding and listed in the skill's generated reference.\nexport interface FindingCode {\n meaning: string;\n fix: string;\n}\n\nexport const FINDING_CODES: Record<string, FindingCode> = {\n schema: {\n meaning: 'The file breaks the flow schema (a field of the wrong type or an unknown field).',\n fix: 'Correct the field named in the message; see the format reference.',\n },\n 'input-default-type': {\n meaning:\n 'A host_list or list flow input has a string default; the generated code joins it letter by letter.',\n fix: 'Write the default as a list: default: [edge] (set_io on flow with field {type: host_list, default: [edge]}).',\n },\n 'keyword-reserved': {\n meaning:\n 'A task keyword in impl.keywords that the flow models itself (register, tags, become, timeout, retries, until, notify, block) or that is no task keyword.',\n fix: 'Move it where the message says (impl.register, settings, a handler step, a subflow), or remove it.',\n },\n 'keyword-ignored': {\n meaning:\n 'Task keywords that cannot apply: on a playbook binding, or vars on a role binding (role variables belong in params).',\n fix: 'Remove them, or bind a module or role; move role variables to params.',\n },\n 'missing-id': {\n meaning:\n 'Written by hand: a node, wire or the flow has no ID, or a reference names a node by key.',\n fix: 'Run Complete IDs (designer banner or quick fix, or flow_complete_ids). Never invent IDs.',\n },\n 'unknown-key': {\n meaning: 'A reference names a key no node has (or several nodes have).',\n fix: 'Use an existing key; inside subflows keys are per level.',\n },\n 'duplicate-id': {\n meaning: 'Two items share an ID.',\n fix: 'Remove the id of the copy and run Complete IDs.',\n },\n 'duplicate-key': {\n meaning: 'Two nodes on one level share a key.',\n fix: 'Rename one (update_node key); from: references follow.',\n },\n 'edge-missing-node': {\n meaning: 'A wire names a node that does not exist.',\n fix: 'Delete the wire or point it at an existing node.',\n },\n 'edge-cross-level': {\n meaning: 'A wire joins nodes on different levels.',\n fix: 'Wires stay on one level; use the subflow entry (set_entry) or an exit (add_exit).',\n },\n 'edge-bad-port': {\n meaning: 'A wire uses a port the node type does not have.',\n fix: 'Use one of the ports of that type (port catalog).',\n },\n 'edge-direction': {\n meaning: 'A wire starts at an input or ends at an output.',\n fix: 'Wires go from an output port to an input port (usually in).',\n },\n 'edge-port-not-enabled': {\n meaning: 'A wire uses an optional port the node has not enabled.',\n fix: 'enable_port for that node and port.',\n },\n 'port-multiple-edges': {\n meaning: 'An output port has more than one wire.',\n fix: 'One wire per output: fan out with a parallel node.',\n },\n 'port-not-supported': {\n meaning: 'The port is enabled on a node type that does not support it.',\n fix: 'disable_port, or change the node type.',\n },\n 'port-role-unroutable': {\n meaning: 'A role binding gives no signal for this port (e.g. unchanged).',\n fix: 'Bind a module instead, or do not use the port.',\n },\n 'open-fail-port': {\n meaning:\n 'A fail port (failed_hosts, unreachable, timeout, rejected) is not wired: its hosts fail the run.',\n fix: 'Wire it to a handler (apply_pattern), or leave_open with a reason.',\n },\n 'decision-no-reason': {\n meaning: 'A port is left open on purpose without a reason.',\n fix: 'Give a reason (leave_open again with reason).',\n },\n 'decision-not-fail': {\n meaning: 'Only fail ports can be left open on purpose.',\n fix: 'reopen it; wire the port instead.',\n },\n 'decision-on-connected': {\n meaning: 'A port marked open on purpose is wired.',\n fix: 'reopen it (the wire decides).',\n },\n 'duplicate-decision': {\n meaning: 'The same port has two decisions.',\n fix: 'Keep one: reopen, then leave_open once.',\n },\n 'annotation-target-missing': {\n meaning:\n 'A note is on a node that is not on its level (or gone), a section or text is on a node, or the file is format 1.',\n fix: 'Detach the note (its menu, or remove `on`), or attach it again; for format 1, Upgrade Flow Format.',\n },\n 'stale-decision': {\n meaning:\n 'A decision refers to a node, port or item that is gone, or an accepted check that no warning matches any more.',\n fix: 'Remove the decision (reopen, or unaccept).',\n },\n 'layout-orphan': {\n meaning: 'A position for a node that does not exist.',\n fix: 'Harmless; tidy_up or a move rewrites positions.',\n },\n 'status-overclaim': {\n meaning: 'A status claims more than the node has (e.g. implemented without impl).',\n fix: 'Lower the status, or add what it needs (contract for specified, impl for implemented).',\n },\n 'setting-on-flow': {\n meaning:\n 'Format 2: credential or execution_environment on a node; the AWX template has one set, on the flow.',\n fix: 'Set them on the flow (runtime.credentials, runtime.execution_environment), or let Set Up AWX Template ask.',\n },\n 'bad-name': {\n meaning:\n 'An input, output or register name Ansible cannot use as a variable: not a letter or _ then letters, digits and _, or a Python or Jinja keyword (in, not, true, none, class).',\n fix: 'Rename it, e.g. retry_count for retry-count; the readers of an output follow a rename made in the designer.',\n },\n 'keyword-is-setting': {\n meaning: 'Format 2: a task keyword the flow now models as a setting (become_user).',\n fix: 'Set it in Execution \u203A Privilege instead; on a subflow it applies to the steps inside.',\n },\n 'renamed-field': {\n meaning:\n 'Format 2: a node keeps a format 1 field name (handler, now purpose: it is not an Ansible handler).',\n fix: 'Rename the key to purpose, or pick the purpose again in Details \u203A General.',\n },\n 'status-out-of-step': {\n meaning:\n 'Format 2: the stored status is not the one the node\u2019s content gives (a hand edit of the file).',\n fix: 'Any edit of the node in the designer sets it again; or write the status the message names.',\n },\n 'tested-without-record': {\n meaning: 'Format 2: a node is tested but has no `tested` record (a run, or a reason).',\n fix: 'Mark Tested\u2026 with a reason, or run the flow; else set the status it has.',\n },\n 'import-gone': {\n meaning:\n 'Re-import from Source found that the task this step was imported from is no longer in the source; the step stays.',\n fix: \"Delete the step, or keep it: remove its origin to make it this flow's own.\",\n },\n 'shared-edited': {\n meaning:\n \"A shared subflow (a copy of another flow's subflow) was changed here, so it no longer matches the version it was copied from; or it sits in a format 1 flow.\",\n fix: \"Edit the source flow and Update, or Unlink to make the copy this flow's own.\",\n },\n 'shared-source': {\n meaning:\n \"A shared subflow's source is missing (the file or the subflow key), is not a .flow.yaml inside the workspace folder, or has a newer version than the copy.\",\n fix: 'Update Shared Subflow for a newer version; fix ref.from or Unlink when the source is gone.',\n },\n 'rolling-unsupported': {\n meaning:\n 'A rolling subflow has a step that needs plays of its own (a subflow, approval, parallel, join, playbook binding, inventory_target, or its own serial or max_fail_percentage), or rolling is set on a node that is not a subflow.',\n fix: 'Move that step out of the subflow, or remove rolling: without it the steps run play by play.',\n },\n 'legacy-port': {\n meaning:\n 'A node has the undo or cancelled port, which were never built: Rollback wires explicit undo steps, and a cancelled job routes no host.',\n fix: 'Upgrade Flow Format removes them and their wires (format 2: remove them); apply Rollback for undo steps.',\n },\n 'timeout-unreadable': {\n meaning:\n 'settings.timeout is not a duration the generated code can read, so the step runs without a timeout. A template ({{ \u2026 }}) is read at run time on a step, but not on an approval, whose AWX template needs a number.',\n fix: 'Write it as 30s, 15m or 1h30m (update_node settings.timeout); on a step, a template of whole seconds reading an input works too.',\n },\n 'timeout-without-setting': {\n meaning: 'The timeout port is enabled but settings.timeout is not set.',\n fix: 'Set settings.timeout (update_node settings).',\n },\n 'inventory-target-ignored': {\n meaning: 'inventory_target is set where it has no effect.',\n fix: 'Remove it, or move it to a task or a subflow without inner steps.',\n },\n 'host-list-input': {\n meaning: 'A node-level host_list input is informational: hosts come from the wire.',\n fix: 'Usually nothing; the arriving hosts decide.',\n },\n 'no-targets': {\n meaning: 'No flow input seeds the hosts entering the start node.',\n fix: 'Add a host_list flow input with targets: true (set_io flow).',\n },\n 'reads-disabled': {\n meaning:\n 'A from: reads an output of a disabled node (or of a step inside a disabled subflow), which runs nothing and so makes nothing.',\n fix: 'Give the input a default, read the value from another step, or enable the node (update_node with disabled: null).',\n },\n 'disabled-ends-path': {\n meaning:\n 'A disabled node the hosts cannot pass through: it does not go on to one next step (no main output is wired, or a decision or parallel has several), so the hosts that reach it stop there.',\n fix: 'Wire exactly one of its main outputs, or enable the node; to take a branching step out, delete it and wire the path by hand.',\n },\n 'disabled-not-allowed': {\n meaning: 'disabled: true on a start or an end node, which are the ends of the path.',\n fix: 'Remove disabled from the node.',\n },\n 'from-unresolved': {\n meaning: 'A from: names nothing this node can read.',\n fix: 'Use <node_key>.<output> of a node that runs before, flow.<input>, or inside a subflow <subflow_key>.<input>; give a path (sub/step.output) to set_io to lift a step inside another subflow.',\n },\n 'register-collision': {\n meaning:\n 'A from: reads a register (impl.register) that another step also registers, or that a flow input also names: the generated code reads whichever ran last, and a flow input always wins.',\n fix: 'Give one of the steps its own register name (Binding \u203A Register result as), or rename the flow input.',\n },\n 'ref-may-be-undefined': {\n meaning:\n \"A from: reads an output of a step that does not run before this one on every path, or that hosts reach after failing in it: some hosts arrive without the value. A step that sets the input's own name (set_fact, register, an output of that name) counts too: the generated play passes the input as a play var, and that fact wins over it.\",\n fix: 'Read it after the paths join on the producing step, or wire the failure path elsewhere. If the step handles a missing value itself (x is defined, | default), guard the read that way or mark the input optional: true; a default makes the value defined, so an \"is defined\" test would always pass.',\n },\n 'input-shadowed': {\n meaning:\n \"Another step sets the input's own name (set_fact, register, an output of that name) where it runs after the from: step, or before the reader when the from: step does not set that name. The generated play passes the input as a play var, and Ansible ranks set_fact and register above play vars: the step reads the value set last, not the one from: names.\",\n fix: 'Rename the input (the binding then reads the new name), or read from: the step that sets the name last. If the value set last is what the step should get, accept it with that reason.',\n },\n 'binding-playbook-dir': {\n meaning:\n \"A binding reads playbook_dir. Generated plays run from the flow's generated/ folder, so paths next to the source playbook are not found there.\",\n fix: 'Write repository paths from {{ afd_repo_root }}, the repository root the generated play sets; a shared task file can use {{ afd_repo_root | default(playbook_dir) }} so it works from the source playbook too.',\n },\n 'binding-unknown-var': {\n meaning: 'A binding parameter (assert that included) uses a variable no input provides.',\n fix: 'Add the input the message names (set_io) or fix the name. A variable set outside the flow at run time (AWX or Kestra extra vars, inventory, a caller) goes into flow.external_vars (update_flow).',\n },\n 'condition-braces': {\n meaning:\n 'A decision condition has {{ }} or {% %} inside it; it is a bare expression, as a when: is, so every host would hit a condition error.',\n fix: 'Write the expression without the braces: x == 1, not {{ x }} == 1.',\n },\n 'condition-unknown-var': {\n meaning:\n 'A decision condition or until uses a variable that is not an input (or, for until, the result).',\n fix: 'Add the input the message names (set_io) or fix the name.',\n },\n 'subflow-output-unset': {\n meaning:\n 'A subflow output names no inner output, and no single inner step has one of that name.',\n fix: 'Set its from to <inner_step>.<output> (set_io).',\n },\n 'input-unfed': {\n meaning:\n 'A step input has no from and no default, so nothing gives it a value; the generated task reads a host variable of that name, if any.',\n fix: 'Set its from to an upstream output or a flow input (set_io), or give it a default; for the result of a step, make it an output there first.',\n },\n 'setting-unknown-var': {\n meaning:\n 'settings.retries, delay or timeout is given at run time ({{ \u2026 }}) and reads a variable that is not an input of the step.',\n fix: 'Add the input the message names (set_io, from: flow.<name>), or use ask_at_run_time, which adds the flow input and the node input.',\n },\n 'setting-input-type': {\n meaning:\n 'settings.retries, delay or timeout reads an input of a type that holds no number (boolean, list, dict, host_list), so the task fails when Ansible renders it.',\n fix: 'Read an integer input (set_io type integer), or write a number.',\n },\n 'until-whole-result': {\n meaning:\n 'settings.until compares the whole registered result with a value (r == \"x\", \"x\" in r); the result is a dict, so the test never holds.',\n fix: 'Test a field of the result, like <register>.stdout or <register>.rc (update_node settings.until).',\n },\n 'until-not-module': {\n meaning: 'settings.until on a role or playbook step, where Ansible cannot retry.',\n fix: 'Move the polling into a module step, or remove until.',\n },\n 'approval-split': {\n meaning: 'Approval outcomes go to different places in a way AWX cannot express.',\n fix: 'Route rejected and timeout the same way.',\n },\n 'approval-fields': {\n meaning:\n 'A node that is not an approval has approval fields (approvers, notify, message): nothing reads them.',\n fix: 'Remove them, or make the node an approval.',\n },\n 'awx-segments': {\n meaning:\n 'Approvals inside subflows, or two that can wait at once, cannot become segments: AWX workflows and Ansible Flow Server wait at top-level approvals, one at a time.',\n fix: 'Keep approvals on the top level, one at a time.',\n },\n 'runtime-kind': {\n meaning:\n 'flow.runtime.kind does not fit the flow (e.g. a job for a flow with approvals); in format 2, it is derived and not written.',\n fix: 'Use awx_workflow with approvals, awx_job without; in format 2, remove it.',\n },\n 'rollback-unreachable': {\n meaning: 'A Rollback node cannot be reached by any failed hosts.',\n fix: 'Wire a fail port to it, or delete it.',\n },\n 'boundary-ref': {\n meaning: 'The subflow entry or an exit names something that is not on its inner level.',\n fix: 'set_entry / add_exit with an inner node of that subflow.',\n },\n 'boundary-no-entry': {\n meaning: 'A subflow has inner steps but no entry: hosts cannot get in.',\n fix: 'set_entry to its first step.',\n },\n 'boundary-port-unfed': {\n meaning: 'A subflow port has wires outside but no inner exit feeds it.',\n fix: 'add_exit from an inner output to that port.',\n },\n 'inner-exit-unmapped': {\n meaning:\n 'A success port of a step inside a subflow is neither wired nor an exit of the subflow: its hosts never reach an outer port.',\n fix: 'Wire it to the next inner step, or add_exit from it to a port of the subflow.',\n },\n 'success-port-unwired': {\n meaning:\n 'A success port on the top level is not wired: its hosts stop there without reaching an end node.',\n fix: 'Wire it to the next step or to an end node (Done).',\n },\n 'codegen-cycle': {\n meaning: 'Wires form a cycle; flows run top-down.',\n fix: 'Remove a wire; retries use apply_pattern retry.',\n },\n 'codegen-no-input': {\n meaning: 'A node gets no hosts: nothing wires into it.',\n fix: 'Wire an output into its in port, or delete it.',\n },\n 'codegen-no-targets': {\n meaning: 'The generated playbook has no hosts to start with.',\n fix: 'Add a host_list flow input with targets: true.',\n },\n 'codegen-playbook-ports': {\n meaning: 'A playbook binding cannot route this port.',\n fix: 'Use ok_hosts/failed_hosts, or bind a role or module.',\n },\n 'codegen-segments': {\n meaning: 'Approval segments cannot be generated for this flow.',\n fix: 'See awx-segments.',\n },\n 'codegen-target-ports': {\n meaning:\n 'A node with inventory_target uses a port that cannot be routed for the arriving hosts.',\n fix: 'Use ok_hosts, failed_hosts or timeout.',\n },\n 'binding-not-in-ee': {\n meaning: 'The bound module or role is not in the execution environment.',\n fix: 'Pick another, or add its collection to the environment.',\n },\n 'binding-removed': { meaning: 'The bound module was removed.', fix: 'Bind its replacement.' },\n 'binding-deprecated': {\n meaning: 'The bound module is deprecated.',\n fix: 'Bind its replacement.',\n },\n 'binding-redirect': {\n meaning: 'The bound name redirects to another module.',\n fix: 'Use the final name.',\n },\n 'binding-unknown-param': {\n meaning: 'A parameter the module does not have.',\n fix: 'Remove or rename it (module docs in the catalog).',\n },\n 'binding-missing-param': {\n meaning: 'A required module parameter is missing.',\n fix: 'Add it to impl.params.',\n },\n 'binding-no-check-mode': {\n meaning: 'The module does not support check mode: skeleton runs skip it.',\n fix: 'Usually fine; real runs only.',\n },\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// Every problem the designer reports, with what it means and how to fix it (AFD-19): shown by AI\n// tools next to each finding and listed in the skill's generated reference.\nexport interface FindingCode {\n meaning: string;\n fix: string;\n}\n\nexport const FINDING_CODES: Record<string, FindingCode> = {\n schema: {\n meaning: 'The file breaks the flow schema (a field of the wrong type or an unknown field).',\n fix: 'Correct the field named in the message; see the format reference.',\n },\n 'input-default-type': {\n meaning:\n 'A host_list or list flow input has a string default; the generated code joins it letter by letter.',\n fix: 'Write the default as a list: default: [edge] (set_io on flow with field {type: host_list, default: [edge]}).',\n },\n 'keyword-reserved': {\n meaning:\n 'A task keyword in impl.keywords that the flow models itself (register, tags, become, timeout, retries, until, notify, block) or that is no task keyword.',\n fix: 'Move it where the message says (impl.register, settings, a handler step, a subflow), or remove it.',\n },\n 'keyword-ignored': {\n meaning:\n 'Task keywords that cannot apply: on a playbook binding, or vars on a role binding (role variables belong in params).',\n fix: 'Remove them, or bind a module or role; move role variables to params.',\n },\n 'missing-id': {\n meaning:\n 'Written by hand: a node, wire or the flow has no ID, or a reference names a node by key.',\n fix: 'Run Complete IDs (designer banner or quick fix, or flow_complete_ids). Never invent IDs.',\n },\n 'unknown-key': {\n meaning: 'A reference names a key no node has (or several nodes have).',\n fix: 'Use an existing key; inside subflows keys are per level.',\n },\n 'duplicate-id': {\n meaning: 'Two items share an ID.',\n fix: 'Remove the id of the copy and run Complete IDs.',\n },\n 'duplicate-key': {\n meaning: 'Two nodes on one level share a key.',\n fix: 'Rename one (update_node key); from: references follow.',\n },\n 'edge-missing-node': {\n meaning: 'A wire names a node that does not exist.',\n fix: 'Delete the wire or point it at an existing node.',\n },\n 'edge-cross-level': {\n meaning: 'A wire joins nodes on different levels.',\n fix: 'Wires stay on one level; use the subflow entry (set_entry) or an exit (add_exit).',\n },\n 'edge-bad-port': {\n meaning: 'A wire uses a port the node type does not have.',\n fix: 'Use one of the ports of that type (port catalog).',\n },\n 'edge-direction': {\n meaning: 'A wire starts at an input or ends at an output.',\n fix: 'Wires go from an output port to an input port (usually in).',\n },\n 'edge-port-not-enabled': {\n meaning: 'A wire uses an optional port the node has not enabled.',\n fix: 'enable_port for that node and port.',\n },\n 'port-multiple-edges': {\n meaning: 'An output port has more than one wire.',\n fix: 'One wire per output: fan out with a parallel node.',\n },\n 'port-not-supported': {\n meaning: 'The port is enabled on a node type that does not support it.',\n fix: 'disable_port, or change the node type.',\n },\n 'port-role-unroutable': {\n meaning: 'A role binding gives no signal for this port (e.g. unchanged).',\n fix: 'Bind a module instead, or do not use the port.',\n },\n 'open-fail-port': {\n meaning:\n 'A fail port (failed_hosts, unreachable, timeout, rejected) is not wired: its hosts fail the run.',\n fix: 'Wire it to a handler (apply_pattern), or leave_open with a reason.',\n },\n 'decision-no-reason': {\n meaning: 'A port is left open on purpose without a reason.',\n fix: 'Give a reason (leave_open again with reason).',\n },\n 'decision-not-fail': {\n meaning: 'Only fail ports can be left open on purpose.',\n fix: 'reopen it; wire the port instead.',\n },\n 'decision-on-connected': {\n meaning: 'A port marked open on purpose is wired.',\n fix: 'reopen it (the wire decides).',\n },\n 'duplicate-decision': {\n meaning: 'The same port has two decisions.',\n fix: 'Keep one: reopen, then leave_open once.',\n },\n 'annotation-target-missing': {\n meaning:\n 'A note is on a node that is not on its level (or gone), a section or text is on a node, or the file is format 1.',\n fix: 'Detach the note (its menu, or remove `on`), or attach it again; for format 1, Upgrade Flow Format.',\n },\n 'stale-decision': {\n meaning:\n 'A decision refers to a node, port or item that is gone, or an accepted check that no warning matches any more.',\n fix: 'Remove the decision (reopen, or unaccept).',\n },\n 'layout-orphan': {\n meaning: 'A position for a node that does not exist.',\n fix: 'Harmless; tidy_up or a move rewrites positions.',\n },\n 'status-overclaim': {\n meaning: 'A status claims more than the node has (e.g. implemented without impl).',\n fix: 'Lower the status, or add what it needs (contract for specified, impl for implemented).',\n },\n 'setting-on-flow': {\n meaning:\n 'Format 2: credential or execution_environment on a node; the AWX template has one set, on the flow.',\n fix: 'Set them on the flow (runtime.credentials, runtime.execution_environment), or let Set Up AWX Template ask.',\n },\n 'bad-name': {\n meaning:\n 'An input, output or register name Ansible cannot use as a variable: not a letter or _ then letters, digits and _, or a Python or Jinja keyword (in, not, true, none, class).',\n fix: 'Rename it, e.g. retry_count for retry-count; the readers of an output follow a rename made in the designer.',\n },\n 'keyword-is-setting': {\n meaning: 'Format 2: a task keyword the flow now models as a setting (become_user).',\n fix: 'Set it in Execution \u203A Privilege instead; on a subflow it applies to the steps inside.',\n },\n 'renamed-field': {\n meaning:\n 'Format 2: a node keeps a format 1 field name (handler, now purpose: it is not an Ansible handler).',\n fix: 'Rename the key to purpose, or pick the purpose again in Details \u203A General.',\n },\n 'status-out-of-step': {\n meaning:\n 'Format 2: the stored status is not the one the node\u2019s content gives (a hand edit of the file).',\n fix: 'Any edit of the node in the designer sets it again; or write the status the message names.',\n },\n 'tested-without-record': {\n meaning: 'Format 2: a node is tested but has no `tested` record (a run, or a reason).',\n fix: 'Mark Tested\u2026 with a reason, or run the flow; else set the status it has.',\n },\n 'import-gone': {\n meaning:\n 'Re-import from Source found that the task this step was imported from is no longer in the source; the step stays.',\n fix: \"Delete the step, or keep it: remove its origin to make it this flow's own.\",\n },\n 'shared-edited': {\n meaning:\n \"A shared subflow (a copy of another flow's subflow) was changed here, so it no longer matches the version it was copied from; or it sits in a format 1 flow.\",\n fix: \"Edit the source flow and Update, or Unlink to make the copy this flow's own.\",\n },\n 'shared-source': {\n meaning:\n \"A shared subflow's source is missing (the file or the subflow key), is not a .flow.yaml inside the workspace folder, or has a newer version than the copy.\",\n fix: 'Update Shared Subflow for a newer version; fix ref.from or Unlink when the source is gone.',\n },\n 'rolling-unsupported': {\n meaning:\n 'A rolling subflow has a step that needs plays of its own (a subflow, approval, parallel, join, playbook binding, inventory_target, or its own serial or max_fail_percentage), or rolling is set on a node that is not a subflow.',\n fix: 'Move that step out of the subflow, or remove rolling: without it the steps run play by play.',\n },\n 'legacy-port': {\n meaning:\n 'A node has the undo or cancelled port, which were never built: Rollback wires explicit undo steps, and a cancelled job routes no host.',\n fix: 'Upgrade Flow Format removes them and their wires (format 2: remove them); apply Rollback for undo steps.',\n },\n 'timeout-unreadable': {\n meaning:\n 'settings.timeout is not a duration the generated code can read, so the step runs without a timeout. A template ({{ \u2026 }}) is read at run time on a step, but not on an approval, whose AWX template needs a number.',\n fix: 'Write it as 30s, 15m or 1h30m (update_node settings.timeout); on a step, a template of whole seconds reading an input works too.',\n },\n 'timeout-without-setting': {\n meaning: 'The timeout port is enabled but settings.timeout is not set.',\n fix: 'Set settings.timeout (update_node settings).',\n },\n 'inventory-target-ignored': {\n meaning: 'inventory_target is set where it has no effect.',\n fix: 'Remove it, or move it to a task or a subflow without inner steps.',\n },\n 'host-list-input': {\n meaning: 'A node-level host_list input is informational: hosts come from the wire.',\n fix: 'Usually nothing; the arriving hosts decide.',\n },\n 'no-targets': {\n meaning: 'No flow input seeds the hosts entering the start node.',\n fix: 'Add a host_list flow input with targets: true (set_io flow).',\n },\n 'reads-disabled': {\n meaning:\n 'A from: reads an output of a disabled node (or of a step inside a disabled subflow), which runs nothing and so makes nothing.',\n fix: 'Give the input a default, read the value from another step, or enable the node (update_node with disabled: null).',\n },\n 'disabled-ends-path': {\n meaning:\n 'A disabled node the hosts cannot pass through: it does not go on to one next step (no main output is wired, or a decision or parallel has several), so the hosts that reach it stop there.',\n fix: 'Wire exactly one of its main outputs, or enable the node; to take a branching step out, delete it and wire the path by hand.',\n },\n 'disabled-not-allowed': {\n meaning: 'disabled: true on a start or an end node, which are the ends of the path.',\n fix: 'Remove disabled from the node.',\n },\n 'from-unresolved': {\n meaning: 'A from: names nothing this node can read.',\n fix: 'Use <node_key>.<output> of a node that runs before, flow.<input>, or inside a subflow <subflow_key>.<input>; give a path (sub/step.output) to set_io to lift a step inside another subflow.',\n },\n 'register-collision': {\n meaning:\n 'A from: reads a register (impl.register) that another step also registers, or that a flow input also names: the generated code reads whichever ran last, and a flow input always wins.',\n fix: 'Give one of the steps its own register name (Binding \u203A Register result as), or rename the flow input.',\n },\n 'ref-may-be-undefined': {\n meaning:\n \"A from: reads an output of a step that does not run before this one on every path, or that hosts reach after failing in it: some hosts arrive without the value. A step that sets the input's own name (set_fact, register, an output of that name) counts too: the generated play passes the input as a play var, and that fact wins over it.\",\n fix: 'Read it after the paths join on the producing step, or wire the failure path elsewhere. If the step handles a missing value itself (x is defined, | default), guard the read that way or mark the input optional: true; a default makes the value defined, so an \"is defined\" test would always pass.',\n },\n 'input-shadowed': {\n meaning:\n \"Another step sets the input's own name (set_fact, register, an output of that name) where it runs after the from: step, or before the reader when the from: step does not set that name. The generated play passes the input as a play var, and Ansible ranks set_fact and register above play vars: the step reads the value set last, not the one from: names.\",\n fix: 'Rename the input (the binding then reads the new name), or read from: the step that sets the name last. If the value set last is what the step should get, accept it with that reason.',\n },\n 'binding-file-missing': {\n meaning:\n 'A step reads a repository file (a template or copy source, a script, a vars file) that is not there. Generated plays read a relative path from the repository root.',\n fix: 'Write the path from the repository root (templates/motd.j2), or add the file there.',\n },\n 'binding-playbook-dir': {\n meaning:\n \"A binding reads playbook_dir. Generated plays run from the flow's generated/ folder, so paths next to the source playbook are not found there.\",\n fix: 'Write repository paths from {{ afd_repo_root }}, the repository root the generated play sets; a shared task file can use {{ afd_repo_root | default(playbook_dir) }} so it works from the source playbook too.',\n },\n 'binding-unknown-var': {\n meaning: 'A binding parameter (assert that included) uses a variable no input provides.',\n fix: 'Add the input the message names (set_io) or fix the name. A variable set outside the flow at run time (AWX or Kestra extra vars, inventory, a caller) goes into flow.external_vars (update_flow).',\n },\n 'condition-braces': {\n meaning:\n 'A decision condition has {{ }} or {% %} inside it; it is a bare expression, as a when: is, so every host would hit a condition error.',\n fix: 'Write the expression without the braces: x == 1, not {{ x }} == 1.',\n },\n 'condition-unknown-var': {\n meaning:\n 'A decision condition or until uses a variable that is not an input (or, for until, the result).',\n fix: 'Add the input the message names (set_io) or fix the name.',\n },\n 'subflow-output-unset': {\n meaning:\n 'A subflow output names no inner output, and no single inner step has one of that name.',\n fix: 'Set its from to <inner_step>.<output> (set_io).',\n },\n 'input-unfed': {\n meaning:\n 'A step input has no from and no default, so nothing gives it a value; the generated task reads a host variable of that name, if any.',\n fix: 'Set its from to an upstream output or a flow input (set_io), or give it a default; for the result of a step, make it an output there first.',\n },\n 'setting-unknown-var': {\n meaning:\n 'settings.retries, delay or timeout is given at run time ({{ \u2026 }}) and reads a variable that is not an input of the step.',\n fix: 'Add the input the message names (set_io, from: flow.<name>), or use ask_at_run_time, which adds the flow input and the node input.',\n },\n 'setting-input-type': {\n meaning:\n 'settings.retries, delay or timeout reads an input of a type that holds no number (boolean, list, dict, host_list), so the task fails when Ansible renders it.',\n fix: 'Read an integer input (set_io type integer), or write a number.',\n },\n 'until-whole-result': {\n meaning:\n 'settings.until compares the whole registered result with a value (r == \"x\", \"x\" in r); the result is a dict, so the test never holds.',\n fix: 'Test a field of the result, like <register>.stdout or <register>.rc (update_node settings.until).',\n },\n 'until-not-module': {\n meaning: 'settings.until on a role or playbook step, where Ansible cannot retry.',\n fix: 'Move the polling into a module step, or remove until.',\n },\n 'approval-split': {\n meaning: 'Approval outcomes go to different places in a way AWX cannot express.',\n fix: 'Route rejected and timeout the same way.',\n },\n 'approval-fields': {\n meaning:\n 'A node that is not an approval has approval fields (approvers, notify, message): nothing reads them.',\n fix: 'Remove them, or make the node an approval.',\n },\n 'awx-segments': {\n meaning:\n 'Approvals inside subflows, or two that can wait at once, cannot become segments: AWX workflows and Ansible Flow Server wait at top-level approvals, one at a time.',\n fix: 'Keep approvals on the top level, one at a time.',\n },\n 'runtime-kind': {\n meaning:\n 'flow.runtime.kind does not fit the flow (e.g. a job for a flow with approvals); in format 2, it is derived and not written.',\n fix: 'Use awx_workflow with approvals, awx_job without; in format 2, remove it.',\n },\n 'rollback-unreachable': {\n meaning: 'A Rollback node cannot be reached by any failed hosts.',\n fix: 'Wire a fail port to it, or delete it.',\n },\n 'boundary-ref': {\n meaning: 'The subflow entry or an exit names something that is not on its inner level.',\n fix: 'set_entry / add_exit with an inner node of that subflow.',\n },\n 'boundary-no-entry': {\n meaning: 'A subflow has inner steps but no entry: hosts cannot get in.',\n fix: 'set_entry to its first step.',\n },\n 'boundary-port-unfed': {\n meaning: 'A subflow port has wires outside but no inner exit feeds it.',\n fix: 'add_exit from an inner output to that port.',\n },\n 'inner-exit-unmapped': {\n meaning:\n 'A success port of a step inside a subflow is neither wired nor an exit of the subflow: its hosts never reach an outer port.',\n fix: 'Wire it to the next inner step, or add_exit from it to a port of the subflow.',\n },\n 'success-port-unwired': {\n meaning:\n 'A success port on the top level is not wired: its hosts stop there without reaching an end node.',\n fix: 'Wire it to the next step or to an end node (Done).',\n },\n 'codegen-cycle': {\n meaning: 'Wires form a cycle; flows run top-down.',\n fix: 'Remove a wire; retries use apply_pattern retry.',\n },\n 'codegen-no-input': {\n meaning: 'A node gets no hosts: nothing wires into it.',\n fix: 'Wire an output into its in port, or delete it.',\n },\n 'codegen-no-targets': {\n meaning: 'The generated playbook has no hosts to start with.',\n fix: 'Add a host_list flow input with targets: true.',\n },\n 'codegen-playbook-ports': {\n meaning: 'A playbook binding cannot route this port.',\n fix: 'Use ok_hosts/failed_hosts, or bind a role or module.',\n },\n 'codegen-segments': {\n meaning: 'Approval segments cannot be generated for this flow.',\n fix: 'See awx-segments.',\n },\n 'codegen-target-ports': {\n meaning:\n 'A node with inventory_target uses a port that cannot be routed for the arriving hosts.',\n fix: 'Use ok_hosts, failed_hosts or timeout.',\n },\n 'binding-not-in-ee': {\n meaning: 'The bound module or role is not in the execution environment.',\n fix: 'Pick another, or add its collection to the environment.',\n },\n 'binding-removed': { meaning: 'The bound module was removed.', fix: 'Bind its replacement.' },\n 'binding-deprecated': {\n meaning: 'The bound module is deprecated.',\n fix: 'Bind its replacement.',\n },\n 'binding-redirect': {\n meaning: 'The bound name redirects to another module.',\n fix: 'Use the final name.',\n },\n 'binding-unknown-param': {\n meaning: 'A parameter the module does not have.',\n fix: 'Remove or rename it (module docs in the catalog).',\n },\n 'binding-missing-param': {\n meaning: 'A required module parameter is missing.',\n fix: 'Add it to impl.params.',\n },\n 'binding-no-check-mode': {\n meaning: 'The module does not support check mode: skeleton runs skip it.',\n fix: 'Usually fine; real runs only.',\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|