@intentius/behold 0.29.11 → 0.29.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/behold",
3
- "version": "0.29.11",
3
+ "version": "0.29.13",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "description": "behold — a live control plane on chant. See your whole estate (every substrate in one graph), coloured by drift; act through delegated, gated Ops.",
@@ -38,8 +38,8 @@ describe("a colour per root (behold#571)", () => {
38
38
 
39
39
  describe("root names in a line (behold#571)", () => {
40
40
  it("finds whole-word names, possessives and names in brackets, and keeps the line's text", () => {
41
- const line = "app reads subnet_id from network, known only after network applies: the review does not show the value app gets.";
42
- expect(names(line)).toEqual(["app", "network", "network", "app"]);
41
+ const line = "app reads subnet_id from network, set when network applies.";
42
+ expect(names(line)).toEqual(["app", "network", "network"]);
43
43
  expect(rootSegments(line, ROOTS).map((s) => s.text).join("")).toBe(line);
44
44
  expect(names("approves wave 2 (app) with network's key")).toEqual(["app", "network"]);
45
45
  expect(names("app: Plan: 0 to add, 1 to change, 0 to destroy.")).toEqual(["app"]);
package/web/kiosk.js CHANGED
@@ -223,7 +223,7 @@ export function unreviewedLines(answer) {
223
223
  if (!pr) return [];
224
224
  return pr.reads
225
225
  .filter((r) => r.outputs === "planned" && r.unknown && r.unknown.length)
226
- .map((r) => `${r.root} reads ${r.unknown.join(", ")} from ${r.upstream}, known only after ${r.upstream} applies: the review does not show the value ${r.root} gets.`);
226
+ .map((r) => `${r.root} reads ${r.unknown.join(", ")} from ${r.upstream}, set when ${r.upstream} applies.`);
227
227
  }
228
228
 
229
229
  /**
@@ -457,7 +457,7 @@ export function factLines(demo, answer) {
457
457
  if (totals) out.push(`pull request #${pr.run.pull_request} changes ${rootsCount(pr.totals_roots) || "across roots"}: ${totals}`);
458
458
  const b = blastRows(answer);
459
459
  if (b && b.changed.length) out.push(`blast radius: ${b.changed.join(", ")}${b.downstream.length ? `; downstream, nearest first: ${b.downstream.join(", ")}` : ""}`);
460
- if (b && b.unplanned.length) out.push(`not touched: ${b.unplanned.join(", ")}`);
460
+ if (b && b.unplanned.length) out.push(`unchanged: ${b.unplanned.join(", ")}`);
461
461
  const cost = costLine(pr.cost);
462
462
  if (cost) out.push(cost);
463
463
  return out;
package/web/kiosk.test.js CHANGED
@@ -49,7 +49,7 @@ describe("frameSrc (#569)", () => {
49
49
 
50
50
  describe("factLines (#569)", () => {
51
51
  it("says the pull request's totals and blast radius", () => {
52
- expect(factLines(demo("planned"), answer)).toEqual(["pull request #7 changes across 3 roots: 3 update", "blast radius: app, edge, network", "not touched: other"]);
52
+ expect(factLines(demo("planned"), answer)).toEqual(["pull request #7 changes across 3 roots: 3 update", "blast radius: app, edge, network", "unchanged: other"]);
53
53
  });
54
54
  });
55
55
 
@@ -23,7 +23,7 @@
23
23
  import { ago, clock, hrefOf } from "./terragucci.js";
24
24
 
25
25
  export const STATE_WORDS = {
26
- "not-started": "not started",
26
+ "not-started": "queued",
27
27
  planned: "planned",
28
28
  waiting: "waiting for an approval",
29
29
  applying: "applying",
@@ -119,13 +119,13 @@ export function readCardIds(answer, e) {
119
119
  return [`${r.member}/${r.name}/data.terraform_remote_state.${data}`, `${r.member}/${r.name}/data.terraform_estate_outputs.${data}`];
120
120
  }
121
121
 
122
- /** "5 create · 1 update", no-ops and zeros left out; "no changes" when nothing moves. */
122
+ /** "5 create · 1 update", no-ops and zeros left out; "unchanged" when nothing moves. */
123
123
  export function totalsLine(totals) {
124
124
  if (!totals) return null;
125
125
  const order = ["create", "update", "replace", "delete", "forget", "import", "read"];
126
126
  const keys = [...order.filter((k) => k in totals), ...Object.keys(totals).filter((k) => !order.includes(k) && k !== "no-op").sort()];
127
127
  const parts = keys.filter((k) => totals[k] > 0).map((k) => `${totals[k]} ${k}`);
128
- return parts.length ? parts.join(" · ") : "no changes";
128
+ return parts.length ? parts.join(" · ") : "unchanged";
129
129
  }
130
130
 
131
131
  /** #568 step 2: "across 3 roots", from `totals_roots` (report minor 35); null on an older report, which has no count. */
@@ -216,7 +216,7 @@ export function composeLine(pr) {
216
216
  return null;
217
217
  }
218
218
 
219
- const APPLY_WORDS = { applied: "applied", partial: "applied in part", failed: "failed", "not-started": "not started", "no-changes": "no changes" };
219
+ const APPLY_WORDS = { applied: "applied", partial: "applied in part", failed: "failed", "not-started": "queued", "no-changes": "unchanged" };
220
220
  const STATE_AS = { written: "state written", unchanged: "state as it was, nothing to write", "not-written": "state not written" };
221
221
 
222
222
  /** One member of a composed run as planned: "app as module.app: 1 create". */
@@ -333,7 +333,7 @@ export function changeHead(answer, progress, now = new Date()) {
333
333
  const stage = changeStage(answer, progress);
334
334
  if (stage === "pull-request") {
335
335
  const r = answer.pull_request.run;
336
- return { text: `pull request #${r.pull_request}, planned ${clock(r.finished, now)}, ${ago(r.finished, now)}; not merged yet, so no run view`, href: hrefOf(answer, r.report), pr: r.pull_request_url || null };
336
+ return { text: `pull request #${r.pull_request}, planned ${clock(r.finished, now)}, ${ago(r.finished, now)}; the run view follows the merge`, href: hrefOf(answer, r.report), pr: r.pull_request_url || null };
337
337
  }
338
338
  if (stage === "apply") {
339
339
  const r = progress.run;
@@ -494,7 +494,7 @@ export function rootStates(answer, progress) {
494
494
  const blast = pr.blast && Array.isArray(pr.blast.roots) ? pr.blast.roots : null;
495
495
  const readsUnknown = (pr.reads || []).some((r) => r.root === root && r.unknown && r.unknown.length) || !!(c && c.held_by_unknown && c.held_by_unknown.includes(root));
496
496
  if (blast && !blast.includes(root) && !readsUnknown) {
497
- roots[root] = { wave: w.number, state: "unchanged", tone: STATE_TONE.unchanged, words: `wave ${w.number} · no changes`, facts: [] };
497
+ roots[root] = { wave: w.number, state: "unchanged", tone: STATE_TONE.unchanged, words: `wave ${w.number} · unchanged`, facts: [] };
498
498
  continue;
499
499
  }
500
500
  const facts = [];
@@ -505,7 +505,7 @@ export function rootStates(answer, progress) {
505
505
  roots[root] = { wave: w.number, state: "planned", tone: STATE_TONE.planned, words: `wave ${w.number} · planned${c ? ", composed" : ""}`, facts };
506
506
  }
507
507
  }
508
- for (const root of known) if (!roots[root]) roots[root] = { wave: null, state: "outside", tone: STATE_TONE.outside, words: "not in this change", facts: [] };
508
+ for (const root of known) if (!roots[root]) roots[root] = { wave: null, state: "outside", tone: STATE_TONE.outside, words: "unchanged", facts: [] };
509
509
  return { stage, roots };
510
510
  }
511
511
  if (stage === "apply") {
@@ -515,7 +515,7 @@ export function rootStates(answer, progress) {
515
515
  const inRun = [...composedOf].filter(([, n]) => n === w.number).map(([r]) => r);
516
516
  for (const root of [...new Set([...w.roots, ...(c ? c.roots : []), ...inRun])]) {
517
517
  if (!rootChanges(w, root)) {
518
- roots[root] = { wave: w.number, state: "unchanged", tone: STATE_TONE.unchanged, words: `wave ${w.number} · no changes`, facts: [] };
518
+ roots[root] = { wave: w.number, state: "unchanged", tone: STATE_TONE.unchanged, words: `wave ${w.number} · unchanged`, facts: [] };
519
519
  continue;
520
520
  }
521
521
  const m = c && c.members ? c.members.find((x) => x.root === root) : null;
@@ -529,7 +529,7 @@ export function rootStates(answer, progress) {
529
529
  if (m && m.apply) facts.push(memberApplyLine(m).replace(`${root}: `, "")); // this root's own part, not the wave's
530
530
  else if (c && !composedHere) {
531
531
  // Beside a composed run in its wave: the wave's figures are the run's, not this root's.
532
- } else if (totals && state !== "not-started") facts.push(totals === "no changes" ? `${together ? "the wave: " : ""}no changes` : `${together ? "the wave " : ""}${state === "applied" ? "applied" : state === "failed" || state === "refused" ? "planned" : "plans"} ${totals}`);
532
+ } else if (totals && state !== "not-started") facts.push(totals === "unchanged" ? `${together ? "the wave: " : ""}unchanged` : `${together ? "the wave " : ""}${state === "applied" ? "applied" : state === "failed" || state === "refused" ? "planned" : "plans"} ${totals}`);
533
533
  if (state === "failed" || state === "refused") {
534
534
  const before = progress.states.filter((x) => x.number < w.number && x.state === "applied").map((x) => x.number);
535
535
  if (before.length) facts.push(`wave ${list(before)} stays applied`);
@@ -544,12 +544,12 @@ export function rootStates(answer, progress) {
544
544
  return { stage, roots };
545
545
  }
546
546
 
547
- /** The short label on a read's line: "reads network's planned http_proxy_port, unknown until network applies". */
547
+ /** The short label on a read's line: "reads network's planned http_proxy_port, set when network applies". */
548
548
  export function readLabel(e) {
549
549
  if (e.composed !== undefined) {
550
550
  return `reads ${e.to} in wave ${e.composed}'s composed run${e.unknown.length ? `: ${list(e.unknown)} known once ${e.to}'s part applies` : ""}`;
551
551
  }
552
- if (e.outputs === "planned") return e.unknown.length ? `reads ${list(e.unknown)} from ${e.to}: unknown until ${e.to} applies` : `reads ${e.to}'s planned outputs`;
552
+ if (e.outputs === "planned") return e.unknown.length ? `reads ${list(e.unknown)} from ${e.to}, set when ${e.to} applies` : `reads ${e.to}'s planned outputs`;
553
553
  return `reads ${e.to}'s applied state`;
554
554
  }
555
555
 
@@ -607,7 +607,7 @@ export function viewCaption(answer, progress, now = new Date()) {
607
607
  const stage = changeStage(answer, progress);
608
608
  if (stage === "pull-request") {
609
609
  const r = answer.pull_request.run;
610
- return `the plan of pull request #${r.pull_request} at ${clock(r.finished, now)}: not merged yet, nothing applied`;
610
+ return `the plan of pull request #${r.pull_request} at ${clock(r.finished, now)}, before the merge`;
611
611
  }
612
612
  if (stage === "apply") {
613
613
  const r = progress.run;
@@ -23,7 +23,7 @@ describe("rootStates (#569)", () => {
23
23
  expect(stage).toBe("pull-request");
24
24
  expect(r.network).toMatchObject({ wave: 1, state: "planned", tone: "plan", words: "wave 1 · planned", facts: ["plan f8851fb61921"] });
25
25
  expect(r.app.facts).toEqual(["plans again once wave 1 applies", "will wait for an approval"]);
26
- expect(r.other).toMatchObject({ state: "outside", words: "not in this change" });
26
+ expect(r.other).toMatchObject({ state: "outside", words: "unchanged" });
27
27
  });
28
28
  it("shows a failed wave's roots failed and the waves before it applied", () => {
29
29
  const p = run(
@@ -60,7 +60,7 @@ describe("rootStates, a root that plans no change (#569 review)", () => {
60
60
  const p = run([{ number: 1, state: "waiting", roots: ["network", "other"], reads: [], digest: "jcs1-sha256:365a4f0d54d7aa", totals: { create: 5 }, changed: ["network"] }], []);
61
61
  const { roots: r } = rootStates(prAnswer, p);
62
62
  expect(r.network.state).toBe("waiting");
63
- expect(r.other).toMatchObject({ state: "unchanged", tone: "idle", words: "wave 1 · no changes", facts: [] });
63
+ expect(r.other).toMatchObject({ state: "unchanged", tone: "idle", words: "wave 1 · unchanged", facts: [] });
64
64
  });
65
65
  it("takes a composed member's own no-changes over the wave's state", () => {
66
66
  const p = run([{ number: 1, state: "failed", roots: ["network"], reads: [], composed: { roots: ["network", "edge"], members: [{ root: "network", module: "m", apply: "failed" }, { root: "edge", module: "e", apply: "no-changes" }] } }], []);
@@ -76,7 +76,7 @@ describe("rootStates, a root that plans no change (#569 review)", () => {
76
76
 
77
77
  describe("readLabel (#569)", () => {
78
78
  it("says what is read and when it is known", () => {
79
- expect(readLabel({ from: "app", to: "network", outputs: "planned", unknown: ["http_proxy_port"] })).toBe("reads http_proxy_port from network: unknown until network applies");
79
+ expect(readLabel({ from: "app", to: "network", outputs: "planned", unknown: ["http_proxy_port"] })).toBe("reads http_proxy_port from network, set when network applies");
80
80
  expect(readLabel({ from: "app", to: "network", outputs: "planned", unknown: [] })).toBe("reads network's planned outputs");
81
81
  expect(readLabel({ from: "app", to: "network", outputs: "applied", unknown: [] })).toBe("reads network's applied state");
82
82
  expect(readLabel({ from: "app", to: "network", outputs: "planned", unknown: ["subnet_id"], composed: 1 })).toBe("reads network in wave 1's composed run: subnet_id known once network's part applies");
@@ -93,7 +93,7 @@ describe("readCardIds (#569)", () => {
93
93
  describe("viewCaption (#569)", () => {
94
94
  it("says which run the marks come from", () => {
95
95
  const now = new Date("2026-10-15T03:30:00Z");
96
- expect(viewCaption(prAnswer, null, now)).toBe("the plan of pull request #201 at 03:11 UTC: not merged yet, nothing applied");
96
+ expect(viewCaption(prAnswer, null, now)).toBe("the plan of pull request #201 at 03:11 UTC, before the merge");
97
97
  expect(viewCaption(prAnswer, run([{ number: 1, state: "applied", roots: ["network"], reads: [] }], []), now)).toBe("the run of merge 6b9f7e25, as of 03:20 UTC");
98
98
  });
99
99
  });
@@ -30,13 +30,13 @@ export const JOB_TONE = { queued: "idle", running: "busy", waiting: "wait", succ
30
30
  /** A card's state in one or two words, when the full words don't fit the card. */
31
31
  export const SHORT_WORDS = {
32
32
  planned: "planned",
33
- "not-started": "not started",
33
+ "not-started": "queued",
34
34
  waiting: "waiting",
35
35
  applying: "applying",
36
36
  applied: "applied",
37
37
  refused: "refused",
38
38
  failed: "failed",
39
- unchanged: "no changes",
39
+ unchanged: "unchanged",
40
40
  outside: "not in this run",
41
41
  };
42
42
 
@@ -98,7 +98,7 @@ describe("the component marks (#571)", () => {
98
98
  network: ["applied", "ok", "applied"],
99
99
  other: ["outside", "idle", "not in this run"],
100
100
  app: ["waiting", "wait", "waiting for an approval"],
101
- edge: ["not-started", "idle", "not started"],
101
+ edge: ["not-started", "idle", "queued"],
102
102
  });
103
103
  expect(m.cards.app.short).toBe("waiting");
104
104
  expect(m.waves[2]).toMatchObject({ job: "apply-wave-2", state: "waiting", tone: "wait", title: "apply-wave-2 · held at the gate" });
@@ -120,7 +120,7 @@ describe("the component marks (#571)", () => {
120
120
  const m = componentMarks(answer, null, facets, { runs: runs(run(11, MERGE, [job("apply-wave-2", "waiting")])), pin: `pull-41-a1b2c3d4` });
121
121
  expect(m.stage).toBe("pull-request");
122
122
  expect(m.cards.network).toMatchObject({ state: "planned", words: "planned" });
123
- expect(m.cards.other).toMatchObject({ state: "outside", words: "not in this change" });
123
+ expect(m.cards.other).toMatchObject({ state: "outside", words: "unchanged" });
124
124
  expect(m.waves[2]).toMatchObject({ state: "planned", status: null, title: "apply-wave-2" });
125
125
  expect(m.waves[1].facts).toEqual(["plan aaaaaaaaaaaa"]);
126
126
  });
@@ -211,7 +211,7 @@ export function renderEstateSvg(answer, now = new Date(), doc = document) {
211
211
  const run = runLine(p, now);
212
212
  g.appendChild(titled(doc, svgEl(doc, "text", { x: b.x + PAD, y: b.y + 55, class: `tg-project-run tg-${run.tone}` }, run.text), run.title));
213
213
  for (const w of b.waves) {
214
- g.appendChild(svgEl(doc, "text", { x: w.x, y: w.y + 14, class: `tg-wave-label tg-wave-${w.state}`, "data-wave": w.number }, `wave ${w.number} · ${w.state === "not-started" ? "not started" : w.state}`));
214
+ g.appendChild(svgEl(doc, "text", { x: w.x, y: w.y + 14, class: `tg-wave-label tg-wave-${w.state}`, "data-wave": w.number }, `wave ${w.number} · ${w.state === "not-started" ? "queued" : w.state}`));
215
215
  for (const r of w.roots) {
216
216
  const node = svgEl(doc, "g", { class: "tg-root-node", "data-root": r.root });
217
217
  node.appendChild(svgEl(doc, "rect", { x: r.x, y: r.y, width: r.w, height: r.h, rx: 4 }));
package/web/terragucci.js CHANGED
@@ -86,7 +86,7 @@ export function stageCell(verdict, stage, now = new Date()) {
86
86
  if (verdict.approval === "waiting") return { text: `wave ${verdict.run.wave} waiting, ${age}`, tone: "wave", title };
87
87
  return { text: `wave ${verdict.run.wave} ${verdict.applied ? "applied" : verdict.approval || "ran"}, ${age}`, tone: "ok", title };
88
88
  }
89
- if (verdict.changes === 0) return { text: `${stage === "tf-drift" ? "none" : "no changes"}, ${age}`, tone: "ok", title };
89
+ if (verdict.changes === 0) return { text: `${stage === "tf-drift" ? "none" : "unchanged"}, ${age}`, tone: "ok", title };
90
90
  const noun = stage === "tf-drift" ? "drifted" : `change${verdict.changes === 1 ? "" : "s"}`;
91
91
  const pr = verdict.run.pull_request ? ` (PR #${verdict.run.pull_request})` : "";
92
92
  return { text: `${verdict.changes} ${noun}${pr}, ${age}`, tone: stage === "tf-drift" ? "drift" : "plan", title };