diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 9ede86d..e2052e7 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -10,7 +10,8 @@ This directory is a build output plus its sources. `index.html`, | file | what it is | |---|---| -| `index.html` | the viewer. Open it from the filesystem, no server needed. Five views, the rendered diagram above each, click a component for its record. | +| `index.html` | the viewer. Open it from the filesystem, no server needed. Seven views, the rendered diagram above each, click a component for its record. | +| `check_viewer.js` | the viewer's only check. Runs every view against a DOM stub, because a TypeError in a renderer shows as a blank panel and not as an error. | | `findings.md` | the analysis. Kept apart from the facts on purpose. | | `maven-architecture.json` | the inventory. 160 components, 204 relations. The factual source for everything else. | | `anchors.md` | every symbol the inventory names, resolved to `path:line` with the line quoted. | @@ -22,10 +23,18 @@ This directory is a build output plus its sources. `index.html`, ```sh python3 docs/architecture/build_inventory.py # → maven-architecture.json python3 docs/architecture/verify_anchors.py # → anchors.md, exit 1 if stale -sh docs/architecture/render.sh # → diagrams/*.svg, then index.html +sh docs/architecture/render.sh # → diagrams/*.svg, then index.html, then check_viewer.js python3 docs/architecture/build_viewer.py # → index.html alone +node docs/architecture/check_viewer.js # → every view rendered, no throw ``` +Views 6 and 7 read `docs/capabilities/`, not this directory. View 6 is the +capability matrix, 51 rows against seven dimensions. View 7 is the twelve +cross-cutting invariants and the components that participate in each. Both are +inlined by `build_viewer.py`, which reads `ledger.yaml` and `invariants.yaml` +rather than deriving anything itself: the ledger's build is the only thing +allowed to decide a dimension. + `render.sh` drives mermaid-cli through the system chromium rather than letting puppeteer download its own. It is also the only syntax check this repo has for a `.mmd`. diff --git a/docs/architecture/build_viewer.py b/docs/architecture/build_viewer.py index 81511e1..ba463e9 100644 --- a/docs/architecture/build_viewer.py +++ b/docs/architecture/build_viewer.py @@ -12,8 +12,11 @@ Running it alone rebuilds the viewer against whatever SVGs are already there. import json import os +import yaml + HERE = os.path.dirname(os.path.abspath(__file__)) DIA = os.path.join(HERE, "diagrams") +CAPDIR = os.path.join(os.path.dirname(HERE), "capabilities") def main() -> None: @@ -26,8 +29,17 @@ def main() -> None: elif name.endswith(".svg"): svg[name] = open(path).read() + # The capability half. Generated beside this one and read here rather than + # re-derived: the ledger's build is the only thing allowed to decide a + # dimension, and a second derivation would drift from it silently. + ledger = yaml.safe_load(open(os.path.join(CAPDIR, "ledger.yaml"))) + invariants = yaml.safe_load( + open(os.path.join(CAPDIR, "invariants.yaml")))["invariants"] + payload = ( "const ARCH = " + json.dumps(arch, ensure_ascii=False) + ";\n" + "const CAPS = " + json.dumps(ledger, ensure_ascii=False) + ";\n" + "const INV = " + json.dumps(invariants, ensure_ascii=False) + ";\n" "const MERMAID = " + json.dumps(mermaid, ensure_ascii=False) + ";\n" "const SVG = " + json.dumps(svg, ensure_ascii=False) + ";\n" ) @@ -37,9 +49,10 @@ def main() -> None: out = os.path.join(HERE, "index.html") open(out, "w").write(template.replace("/*__DATA__*/", payload)) print( - "index.html: %d bytes, %d components, %d relations, %d diagrams, %d rendered" + "index.html: %d bytes, %d components, %d relations, %d diagrams, " + "%d rendered, %d capabilities, %d invariants" % (os.path.getsize(out), len(arch["components"]), len(arch["edges"]), - len(mermaid), len(svg)) + len(mermaid), len(svg), len(ledger["capabilities"]), len(invariants)) ) diff --git a/docs/architecture/check_viewer.js b/docs/architecture/check_viewer.js new file mode 100644 index 0000000..01ce9e3 --- /dev/null +++ b/docs/architecture/check_viewer.js @@ -0,0 +1,64 @@ +// Smoke test for index.html's renderers, run by render.sh when node is present. +// +// The viewer has no test harness and a TypeError in a renderer produces a blank +// panel, not an error anyone sees. This runs every view's render function +// against a DOM stub and fails loudly on the first throw. It checks that the +// renderers run over the real data, not that the result looks right. +// +// node docs/architecture/check_viewer.js [path/to/index.html] + +const fs = require('fs'); +const path = process.argv[2] || __dirname + '/index.html'; +const src = fs.readFileSync(path, 'utf8'); +const js = src.match(/