diff --git a/README.md b/README.md index 1ad4bae..8360e10 100644 --- a/README.md +++ b/README.md @@ -319,6 +319,30 @@ and paints it with `layoutIr` + `renderSvg` (`src/render.ts`); the SPA inlines t SVG and wires click-inspect by `data-node-id` against the IR. pinhole's layout is dagre — pure JS, no native dependency. +Where an official mark exists, a node paints it instead of a generic glyph — a +Deployment gets the Kubernetes wheel-and-helm heptagon, a Kustomization the +Flux mark, a `Helm::Release` the Helm wheel. The corpus is vendored under +`web/icons/` (30 kubernetes/community SVGs, 3 cncf/artwork marks for +Flux/Argo/Helm, licensing in `THIRD_PARTY.md`) and mapped kind by kind in +`src/icon-packs.ts`; a kind with no official icon falls through to pinhole's +keyword heuristic rather than a wrong picture. + +dagre's layout is a good first draft, not a final one: drag a card to move +it, grab a containment box's corner to resize it, and both survive a reload. +What persists is a delta — `{dx,dy}` for a card, `{dw,dh}` for a box, never +an absolute position — keyed by `behold.layout..` +(`web/layout-store.js`), so the graph stays chant's and the arrangement on +top of it is yours. `↺ layout` sits beside `⤢ fit` and shows up only once +something on the current lens is hand-placed. + +Type splits by purpose: mono (system stacks — ui-monospace, SF Mono, +Cascadia, JetBrains, IBM Plex) carries node ids, ARNs, statuses and counts; +sans carries labels only. Colour comes from 552 Ghostty terminal palettes run +through an OKLCH-derived token pipeline (`src/theme.ts`), so a theme switch +re-derives the whole chrome, not just the graph — and a node whose drift +status just changed pulses once in the colour it became, off under +`prefers-reduced-motion`. + ## Local development `just` lists everything. The core loop: diff --git a/example-argo-estate/README.md b/example-argo-estate/README.md index c9a7158..d85d3d4 100644 --- a/example-argo-estate/README.md +++ b/example-argo-estate/README.md @@ -21,18 +21,22 @@ no Docker. It copies out, `npm install`s, and serves. What to look at: both Applications to the AppProject they name (behold#222) — the join chant lints as ARGO002, so an estate whose lint passes cannot be drawn wrong. The entity graph carries them at the attributes tier (`?detail=3`). -- The **logical lens** on the control plane alone - (`behold serve control-plane`, zoom: logical): `namespace app-a` and - `namespace app-b` drawn as boxes even though the control plane declares no - `Namespace` object anywhere. They come from each Application's - `spec.destination.namespace` — a namespace Argo will own objects in is a - namespace the estate is committed to. Serve all three members and the apps' - Deployments and Services sit inside those boxes. - -That last one is the Argo/Flux difference worth noticing: flux-estate's control -plane must declare the app namespaces itself (a Kustomization's -`targetNamespace` must already exist), while here `CreateNamespace=true` means -Argo makes them — so the box exists on the strength of the destination alone. +- The **logical lens** (zoom: logical): cluster ⊃ `namespace app-a` and + `namespace app-b`, each holding that app's Deployment + Service, plus + `namespace argocd` holding both Applications and the AppProject — drawn + even though the control plane declares no `Namespace` object anywhere. The + app namespaces come from each Application's `spec.destination.namespace`; a + namespace Argo will own objects in is a namespace the estate is committed + to, and behold#224 taught the composed estate to draw that projection. + Serve `control-plane` alone (`behold serve control-plane`, zoom: logical) + and the same boxes appear empty — the destination harvest still names them, + but there is nothing from app-a/app-b in the graph to fill them with. + +That alone-vs-composed split is the Argo/Flux difference worth noticing: +flux-estate's control plane must declare the app namespaces itself (a +Kustomization's `targetNamespace` must already exist), while here +`CreateNamespace=true` means Argo makes them — so the box exists on the +strength of the destination alone. Argo's ordering is the `argocd.argoproj.io/sync-wave` annotation, so unlike Flux's `dependsOn` (behold#223) there is no edge to draw for it: app-a is wave diff --git a/package-lock.json b/package-lock.json index d80c2b9..db5f053 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,10 @@ "name": "@intentius/behold", "version": "0.8.0", "dependencies": { - "@hono/node-server": "^1.13.0", + "@hono/node-server": "^2.0.5", "@intentius/chant": "^0.38.0", "@intentius/pinhole": "^0.3.1", - "hono": "^4.6.0" + "hono": "^4.12.34" }, "bin": { "behold": "bin/behold.js" @@ -491,12 +491,12 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.0.tgz", + "integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==", "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=20" }, "peerDependencies": { "hono": "^4" @@ -2074,9 +2074,9 @@ } }, "node_modules/hono": { - "version": "4.12.30", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.30.tgz", - "integrity": "sha512-emn+JoJjrN9YTpRDS5it/UI2SO9BAE37T6I3d963RxcZ81G9A4pr2SZTEiiaiKbzx+NKRg5BZ89fCL7gCJCUog==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz", + "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==", "license": "MIT", "engines": { "node": ">=16.9.0" diff --git a/package.json b/package.json index 7d80163..f0724a6 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "prepublishOnly": "npm run build" }, "dependencies": { - "@hono/node-server": "^1.13.0", + "@hono/node-server": "^2.0.5", "@intentius/chant": "^0.38.0", "@intentius/pinhole": "^0.3.1", - "hono": "^4.6.0" + "hono": "^4.12.34" }, "devDependencies": { "@types/node": "^22.0.0",