scrum-skills 0.3.2 → 0.3.4
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/.agents/skills/diagram-design/LICENSE +4 -0
- package/.agents/skills/diagram-design/SKILL.md +423 -0
- package/.agents/skills/diagram-design/UPSTREAM.json +88 -0
- package/.agents/skills/diagram-design/UPSTREAM.md +23 -0
- package/.agents/skills/diagram-design/assets/example-architecture-containment.html +205 -0
- package/.agents/skills/diagram-design/assets/example-architecture-delta.html +193 -0
- package/.agents/skills/diagram-design/assets/example-architecture.html +183 -0
- package/.agents/skills/diagram-design/assets/example-axonometric-plan-campus.html +108 -0
- package/.agents/skills/diagram-design/assets/example-axonometric-plan-coffee-shop.html +121 -0
- package/.agents/skills/diagram-design/assets/example-axonometric-plan-warehouse.html +127 -0
- package/.agents/skills/diagram-design/assets/example-axonometric-plan.html +114 -0
- package/.agents/skills/diagram-design/assets/example-bar.html +129 -0
- package/.agents/skills/diagram-design/assets/example-beeswarm.html +384 -0
- package/.agents/skills/diagram-design/assets/example-box-plot.html +127 -0
- package/.agents/skills/diagram-design/assets/example-bubble.html +147 -0
- package/.agents/skills/diagram-design/assets/example-bump.html +142 -0
- package/.agents/skills/diagram-design/assets/example-data-flow.html +143 -0
- package/.agents/skills/diagram-design/assets/example-datalake.html +269 -0
- package/.agents/skills/diagram-design/assets/example-db-schema.html +302 -0
- package/.agents/skills/diagram-design/assets/example-dependency.html +224 -0
- package/.agents/skills/diagram-design/assets/example-deployment.html +190 -0
- package/.agents/skills/diagram-design/assets/example-dp-integration.html +81 -0
- package/.agents/skills/diagram-design/assets/example-dp-security-matrix.html +88 -0
- package/.agents/skills/diagram-design/assets/example-er.html +202 -0
- package/.agents/skills/diagram-design/assets/example-exploded-ai-stack.html +85 -0
- package/.agents/skills/diagram-design/assets/example-exploded-keyboard.html +84 -0
- package/.agents/skills/diagram-design/assets/example-exploded-phone.html +83 -0
- package/.agents/skills/diagram-design/assets/example-exploded-unboxing.html +84 -0
- package/.agents/skills/diagram-design/assets/example-exploded.html +83 -0
- package/.agents/skills/diagram-design/assets/example-fishbone.html +152 -0
- package/.agents/skills/diagram-design/assets/example-flowchart.html +163 -0
- package/.agents/skills/diagram-design/assets/example-gantt.html +137 -0
- package/.agents/skills/diagram-design/assets/example-heatmap.html +224 -0
- package/.agents/skills/diagram-design/assets/example-high-level-vertical.html +325 -0
- package/.agents/skills/diagram-design/assets/example-high-level.html +301 -0
- package/.agents/skills/diagram-design/assets/example-import-drawio.html +185 -0
- package/.agents/skills/diagram-design/assets/example-import-excalidraw.html +70 -0
- package/.agents/skills/diagram-design/assets/example-import-mermaid.html +70 -0
- package/.agents/skills/diagram-design/assets/example-it-state.html +128 -0
- package/.agents/skills/diagram-design/assets/example-journey.html +148 -0
- package/.agents/skills/diagram-design/assets/example-kanban.html +174 -0
- package/.agents/skills/diagram-design/assets/example-layers.html +123 -0
- package/.agents/skills/diagram-design/assets/example-line.html +111 -0
- package/.agents/skills/diagram-design/assets/example-loop.html +100 -0
- package/.agents/skills/diagram-design/assets/example-marimekko.html +148 -0
- package/.agents/skills/diagram-design/assets/example-medallion.html +159 -0
- package/.agents/skills/diagram-design/assets/example-nested.html +136 -0
- package/.agents/skills/diagram-design/assets/example-org-chart.html +45 -0
- package/.agents/skills/diagram-design/assets/example-polar.html +116 -0
- package/.agents/skills/diagram-design/assets/example-process.html +64 -0
- package/.agents/skills/diagram-design/assets/example-pyramid.html +119 -0
- package/.agents/skills/diagram-design/assets/example-quadrant-consultant.html +166 -0
- package/.agents/skills/diagram-design/assets/example-quadrant.html +135 -0
- package/.agents/skills/diagram-design/assets/example-radar.html +139 -0
- package/.agents/skills/diagram-design/assets/example-ridgeline.html +104 -0
- package/.agents/skills/diagram-design/assets/example-sankey.html +150 -0
- package/.agents/skills/diagram-design/assets/example-scatter.html +141 -0
- package/.agents/skills/diagram-design/assets/example-sequence-oauth.html +227 -0
- package/.agents/skills/diagram-design/assets/example-sequence.html +222 -0
- package/.agents/skills/diagram-design/assets/example-service-blueprint.html +185 -0
- package/.agents/skills/diagram-design/assets/example-slopegraph.html +119 -0
- package/.agents/skills/diagram-design/assets/example-state-lifecycle.html +92 -0
- package/.agents/skills/diagram-design/assets/example-state.html +147 -0
- package/.agents/skills/diagram-design/assets/example-story-map.html +184 -0
- package/.agents/skills/diagram-design/assets/example-streamgraph.html +99 -0
- package/.agents/skills/diagram-design/assets/example-swimlane.html +172 -0
- package/.agents/skills/diagram-design/assets/example-timeline.html +135 -0
- package/.agents/skills/diagram-design/assets/example-tree-block-decomposition.html +151 -0
- package/.agents/skills/diagram-design/assets/example-tree.html +173 -0
- package/.agents/skills/diagram-design/assets/example-treemap.html +107 -0
- package/.agents/skills/diagram-design/assets/example-uml-class.html +188 -0
- package/.agents/skills/diagram-design/assets/example-venn.html +110 -0
- package/.agents/skills/diagram-design/assets/example-wardley.html +153 -0
- package/.agents/skills/diagram-design/assets/example-waterfall.html +129 -0
- package/.agents/skills/diagram-design/assets/template-dark.html +99 -0
- package/.agents/skills/diagram-design/assets/template-full.html +421 -0
- package/.agents/skills/diagram-design/assets/template-motion.html +448 -0
- package/.agents/skills/diagram-design/assets/template-terminal.html +188 -0
- package/.agents/skills/diagram-design/assets/template.html +100 -0
- package/.agents/skills/diagram-design/references/animation.md +143 -0
- package/.agents/skills/diagram-design/references/export-registry.md +78 -0
- package/.agents/skills/diagram-design/references/export.md +376 -0
- package/.agents/skills/diagram-design/references/import-drawio.md +181 -0
- package/.agents/skills/diagram-design/references/import-excalidraw.md +130 -0
- package/.agents/skills/diagram-design/references/import-mermaid.md +137 -0
- package/.agents/skills/diagram-design/references/layout-budget.md +97 -0
- package/.agents/skills/diagram-design/references/onboarding.md +368 -0
- package/.agents/skills/diagram-design/references/output-spec.md +277 -0
- package/.agents/skills/diagram-design/references/primitive-annotation.md +36 -0
- package/.agents/skills/diagram-design/references/primitive-icons.md +827 -0
- package/.agents/skills/diagram-design/references/primitive-sketchy.md +43 -0
- package/.agents/skills/diagram-design/references/primitive-terminal.md +76 -0
- package/.agents/skills/diagram-design/references/primitives-core.md +150 -0
- package/.agents/skills/diagram-design/references/profiles.md +183 -0
- package/.agents/skills/diagram-design/references/semantic-patterns.md +154 -0
- package/.agents/skills/diagram-design/references/style-guide.md +236 -0
- package/.agents/skills/diagram-design/references/style-vivid.md +148 -0
- package/.agents/skills/diagram-design/references/type-architecture-delta.md +143 -0
- package/.agents/skills/diagram-design/references/type-architecture.md +117 -0
- package/.agents/skills/diagram-design/references/type-axonometric-plan.md +83 -0
- package/.agents/skills/diagram-design/references/type-bar.md +108 -0
- package/.agents/skills/diagram-design/references/type-data-flow.md +371 -0
- package/.agents/skills/diagram-design/references/type-db-schema.md +48 -0
- package/.agents/skills/diagram-design/references/type-dependency.md +44 -0
- package/.agents/skills/diagram-design/references/type-deployment.md +45 -0
- package/.agents/skills/diagram-design/references/type-dp-integration.md +407 -0
- package/.agents/skills/diagram-design/references/type-dp-security-matrix.md +379 -0
- package/.agents/skills/diagram-design/references/type-er.md +25 -0
- package/.agents/skills/diagram-design/references/type-exploded.md +115 -0
- package/.agents/skills/diagram-design/references/type-fishbone.md +75 -0
- package/.agents/skills/diagram-design/references/type-flowchart.md +23 -0
- package/.agents/skills/diagram-design/references/type-gantt.md +45 -0
- package/.agents/skills/diagram-design/references/type-heatmap.md +80 -0
- package/.agents/skills/diagram-design/references/type-high-level.md +470 -0
- package/.agents/skills/diagram-design/references/type-it-state.md +468 -0
- package/.agents/skills/diagram-design/references/type-journey.md +55 -0
- package/.agents/skills/diagram-design/references/type-kanban.md +49 -0
- package/.agents/skills/diagram-design/references/type-layers.md +26 -0
- package/.agents/skills/diagram-design/references/type-line.md +337 -0
- package/.agents/skills/diagram-design/references/type-loop.md +223 -0
- package/.agents/skills/diagram-design/references/type-medallion.md +356 -0
- package/.agents/skills/diagram-design/references/type-nested.md +22 -0
- package/.agents/skills/diagram-design/references/type-org-chart.md +44 -0
- package/.agents/skills/diagram-design/references/type-polar.md +136 -0
- package/.agents/skills/diagram-design/references/type-process.md +490 -0
- package/.agents/skills/diagram-design/references/type-pyramid.md +33 -0
- package/.agents/skills/diagram-design/references/type-quadrant.md +81 -0
- package/.agents/skills/diagram-design/references/type-radar.md +82 -0
- package/.agents/skills/diagram-design/references/type-sankey.md +75 -0
- package/.agents/skills/diagram-design/references/type-scatter.md +276 -0
- package/.agents/skills/diagram-design/references/type-sequence.md +130 -0
- package/.agents/skills/diagram-design/references/type-service-blueprint.md +103 -0
- package/.agents/skills/diagram-design/references/type-state.md +30 -0
- package/.agents/skills/diagram-design/references/type-story-map.md +46 -0
- package/.agents/skills/diagram-design/references/type-swimlane.md +22 -0
- package/.agents/skills/diagram-design/references/type-timeline.md +20 -0
- package/.agents/skills/diagram-design/references/type-tree.md +24 -0
- package/.agents/skills/diagram-design/references/type-treemap.md +137 -0
- package/.agents/skills/diagram-design/references/type-uml-class.md +65 -0
- package/.agents/skills/diagram-design/references/type-venn.md +26 -0
- package/.agents/skills/diagram-design/references/type-wardley.md +39 -0
- package/.agents/skills/diagram-design/references/type-waterfall.md +75 -0
- package/.agents/skills/scrum-meta/SKILL.md +36 -36
- package/.agents/skills/scrum-planning/SKILL.md +61 -61
- package/.agents/skills/scrum-planning/references/schema.md +384 -336
- package/.agents/skills/scrum-report/SKILL.md +42 -42
- package/.agents/skills/scrum-sprint/SKILL.md +49 -49
- package/.agents/skills/scrum-tdd/SKILL.md +140 -127
- package/README.md +24 -1
- package/assets/board/200.html +1 -1
- package/assets/board/404.html +1 -1
- package/assets/board/_nuxt/4gQF_HS3.js +1 -0
- package/assets/board/_nuxt/5okfNy5D.js +1 -0
- package/assets/board/_nuxt/{Bb3Limos.js → B0C2jsdk.js} +1 -1
- package/assets/board/_nuxt/B1j6UC4U.js +1 -0
- package/assets/board/_nuxt/B3LKy6o2.js +1 -0
- package/assets/board/_nuxt/BAQQngAq.js +13 -0
- package/assets/board/_nuxt/BE6t7Q2m.js +1 -0
- package/assets/board/_nuxt/BGwhkDRl.js +1 -0
- package/assets/board/_nuxt/BLvbupFS.js +1 -0
- package/assets/board/_nuxt/BQgzP7ur.js +1 -0
- package/assets/board/_nuxt/BRZIF_wo.js +1 -0
- package/assets/board/_nuxt/BU8vdZUs.js +95 -0
- package/assets/board/_nuxt/BW3xJdEx.js +1 -0
- package/assets/board/_nuxt/{Cm9lkUvP.js → BY36DFyj.js} +1 -1
- package/assets/board/_nuxt/BZlZD94i.js +1 -0
- package/assets/board/_nuxt/BZvXNwev.js +3 -0
- package/assets/board/_nuxt/BiWrMOsL.js +1 -0
- package/assets/board/_nuxt/BkoKCNUY.js +1 -0
- package/assets/board/_nuxt/BlKmZhhF.js +1 -0
- package/assets/board/_nuxt/BmBpmU73.js +1 -0
- package/assets/board/_nuxt/BmrSh0rL.js +1 -0
- package/assets/board/_nuxt/BrWE0up6.js +1 -0
- package/assets/board/_nuxt/Bs52qkgk.js +1 -0
- package/assets/board/_nuxt/BuBzMkFZ.js +1 -0
- package/assets/board/_nuxt/Bubk0xn-.js +1 -0
- package/assets/board/_nuxt/BxuBMtk_.js +3 -0
- package/assets/board/_nuxt/By1KXXLR.js +1 -0
- package/assets/board/_nuxt/BygIGL69.js +2 -0
- package/assets/board/_nuxt/C-fx-vFO.js +1 -0
- package/assets/board/_nuxt/C1iO5KH3.js +1 -0
- package/assets/board/_nuxt/C2YPmTzt.js +1 -0
- package/assets/board/_nuxt/C3SpAhCW.js +1 -0
- package/assets/board/_nuxt/C3ZRWz5L.js +1 -0
- package/assets/board/_nuxt/C4WdPP6K.js +1 -0
- package/assets/board/_nuxt/C6o03JHe.js +1 -0
- package/assets/board/_nuxt/C8qB5llI.js +1 -0
- package/assets/board/_nuxt/C9MgRdhu.js +1 -0
- package/assets/board/_nuxt/CCA81-4P.js +1 -0
- package/assets/board/_nuxt/{D2O8Q8x9.js → CFCM18fF.js} +1 -1
- package/assets/board/_nuxt/CGXljzd_.js +1 -0
- package/assets/board/_nuxt/CI0scS-N.js +1 -0
- package/assets/board/_nuxt/CJs9B42o.js +1 -0
- package/assets/board/_nuxt/COmtTtfB.js +1 -0
- package/assets/board/_nuxt/CPYm4J_K.js +1 -0
- package/assets/board/_nuxt/CXG7GZes.js +1 -0
- package/assets/board/_nuxt/CYGiZn-X.js +1 -0
- package/assets/board/_nuxt/CaE8VlUp.js +1 -0
- package/assets/board/_nuxt/Cajxc4Dw.js +1 -0
- package/assets/board/_nuxt/CcGiNUgA.js +1 -0
- package/assets/board/_nuxt/Ccgv3lDj.js +1 -0
- package/assets/board/_nuxt/CdPGFZyy.js +1 -0
- package/assets/board/_nuxt/{DfR3IZN_.js → Cdf_T8Xa.js} +1 -1
- package/assets/board/_nuxt/CgQ30j_6.js +1 -0
- package/assets/board/_nuxt/Ck0-FqVI.js +1 -0
- package/assets/board/_nuxt/CkWKLtjO.js +1 -0
- package/assets/board/_nuxt/CoipdpDu.js +1 -0
- package/assets/board/_nuxt/Cq7hsCKB.js +1 -0
- package/assets/board/_nuxt/D166WVUG.js +1 -0
- package/assets/board/_nuxt/D1V1gysQ.js +1 -0
- package/assets/board/_nuxt/D4Dpzo9e.js +1 -0
- package/assets/board/_nuxt/D5i92OZO.js +1 -0
- package/assets/board/_nuxt/D6dUp4Nm.js +9 -0
- package/assets/board/_nuxt/DFQDFspC.js +1 -0
- package/assets/board/_nuxt/DHX2tw9J.js +1 -0
- package/assets/board/_nuxt/DJM7u8P3.js +1 -0
- package/assets/board/_nuxt/{BPTrRhcw.js → DLr85ebo.js} +1 -1
- package/assets/board/_nuxt/DOMM1wfl.js +1 -0
- package/assets/board/_nuxt/DU6ArlUN.js +1 -0
- package/assets/board/_nuxt/{B_SlFcWp.js → DUgGsde6.js} +1 -1
- package/assets/board/_nuxt/DV4ti-Pq.js +1 -0
- package/assets/board/_nuxt/D_ct-Stz.js +2 -0
- package/assets/board/_nuxt/DbWAComO.js +1 -0
- package/assets/board/_nuxt/DbwlcHAt.js +1 -0
- package/assets/board/_nuxt/Dki9VkAL.js +3 -0
- package/assets/board/_nuxt/DlNJhOoc.js +1 -0
- package/assets/board/_nuxt/Dmg78zOY.js +3 -0
- package/assets/board/_nuxt/DqG7CtD4.js +1 -0
- package/assets/board/_nuxt/DqUSsCJ2.js +1 -0
- package/assets/board/_nuxt/Du2F4WXh.js +1 -0
- package/assets/board/_nuxt/DuRiEXn4.js +1 -0
- package/assets/board/_nuxt/DwCE3305.js +1 -0
- package/assets/board/_nuxt/DwzGxoX2.js +1 -0
- package/assets/board/_nuxt/DxBwVNyP.js +2 -0
- package/assets/board/_nuxt/DzmVW5-D.js +1 -0
- package/assets/board/_nuxt/I-sGtDIB.js +6 -0
- package/assets/board/_nuxt/JU9-x68N.js +1 -0
- package/assets/board/_nuxt/Lozm7hhE.js +1 -0
- package/assets/board/_nuxt/MMsTMkcB.js +1 -0
- package/assets/board/_nuxt/MS7CGmCB.js +1 -0
- package/assets/board/_nuxt/OKKaKILz.js +1 -0
- package/assets/board/_nuxt/{Csqgy925.js → P6qlvBHA.js} +1 -1
- package/assets/board/_nuxt/SrNUvNwO.js +1 -0
- package/assets/board/_nuxt/{DSaWoFHS.js → SywdkA98.js} +1 -1
- package/assets/board/_nuxt/TBIRpVLG.js +1 -0
- package/assets/board/_nuxt/TlTrMIMm.js +1 -0
- package/assets/board/_nuxt/Utb4TVOl.js +1 -0
- package/assets/board/_nuxt/Zv9-SOQF.js +1 -0
- package/assets/board/_nuxt/_id_.B6iqDPxe.css +1 -0
- package/assets/board/_nuxt/b7xtxFRl.js +1 -0
- package/assets/board/_nuxt/builds/latest.json +1 -1
- package/assets/board/_nuxt/builds/meta/08bebe14-0f1b-4d2a-8de4-e84e122d10e9.json +1 -0
- package/assets/board/_nuxt/diagrams.pyhqNtmr.css +1 -0
- package/assets/board/_nuxt/{entry.CKHePurH.css → entry.BBv-sBnP.css} +1 -1
- package/assets/board/_nuxt/error-404.CgJNdpB5.css +1 -0
- package/assets/board/_nuxt/error-500.WYSoH44y.css +1 -0
- package/assets/board/_nuxt/jbri6q1p.js +1 -0
- package/assets/board/_nuxt/q_8bxRMt.js +1 -0
- package/assets/board/burndown/index.html +1 -1
- package/assets/board/diagrams/index.html +1 -0
- package/assets/board/epics/index.html +1 -1
- package/assets/board/gantt/index.html +1 -1
- package/assets/board/index.html +1 -1
- package/assets/board/last-change/index.html +1 -1
- package/assets/board/milestones/index.html +1 -1
- package/assets/board/tests/index.html +1 -1
- package/bin/scrum-skills.mjs +13 -0
- package/package.json +2 -1
- package/templates/AGENTS.md +10 -0
- package/tools/diagram-import.mjs +238 -0
- package/tools/diagram-lint.mjs +518 -0
- package/tools/diagram.mjs +299 -0
- package/tools/last-change.mjs +326 -326
- package/tools/projects.mjs +29 -4
- package/tools/serve.mjs +27 -1
- package/tools/validate.mjs +781 -664
- package/assets/board/_nuxt/1eqboJxR.js +0 -1
- package/assets/board/_nuxt/2K7ag6ES.js +0 -1
- package/assets/board/_nuxt/51OWHj8c.js +0 -2
- package/assets/board/_nuxt/6gFtTBwm.js +0 -1
- package/assets/board/_nuxt/B3jkABw9.js +0 -1
- package/assets/board/_nuxt/B5n2_jZN.js +0 -1
- package/assets/board/_nuxt/BDK2Hj7B.js +0 -1
- package/assets/board/_nuxt/BDcnzXHq.js +0 -1
- package/assets/board/_nuxt/BaG8y0Wt.js +0 -1
- package/assets/board/_nuxt/BbwJq5pb.js +0 -1
- package/assets/board/_nuxt/BgLeKwx0.js +0 -1
- package/assets/board/_nuxt/Bi9Axj3V.js +0 -1
- package/assets/board/_nuxt/BmxvtaMq.js +0 -1
- package/assets/board/_nuxt/BodFvto3.js +0 -1
- package/assets/board/_nuxt/BpWeHLuN.js +0 -1
- package/assets/board/_nuxt/BuOKDFiJ.js +0 -1
- package/assets/board/_nuxt/C40iTe-x.js +0 -1
- package/assets/board/_nuxt/C7K0R7F-.js +0 -2
- package/assets/board/_nuxt/C8vL692X.js +0 -1
- package/assets/board/_nuxt/C9StZL3D.js +0 -3
- package/assets/board/_nuxt/CGI_ZV79.js +0 -1
- package/assets/board/_nuxt/CJ2mz0WY.js +0 -1
- package/assets/board/_nuxt/CJMBJQuf.js +0 -1
- package/assets/board/_nuxt/CK-lOYG9.js +0 -1
- package/assets/board/_nuxt/CK9_veoz.js +0 -1
- package/assets/board/_nuxt/CLBcBrYf.js +0 -1
- package/assets/board/_nuxt/CMUi2-Lj.js +0 -1
- package/assets/board/_nuxt/COf6E6h4.js +0 -1
- package/assets/board/_nuxt/CPCUMJnF.js +0 -1
- package/assets/board/_nuxt/CPcKlmSm.js +0 -1
- package/assets/board/_nuxt/CQTvWh4i.js +0 -1
- package/assets/board/_nuxt/CSEEUF8S.js +0 -1
- package/assets/board/_nuxt/CSSb154I.js +0 -13
- package/assets/board/_nuxt/CgDTd7jS.js +0 -1
- package/assets/board/_nuxt/ChG76uh9.js +0 -1
- package/assets/board/_nuxt/Ci0qbkgh.js +0 -1
- package/assets/board/_nuxt/CqoQ__I_.js +0 -1
- package/assets/board/_nuxt/CuJUHLl8.js +0 -1
- package/assets/board/_nuxt/CvLiA4_O.js +0 -1
- package/assets/board/_nuxt/Cvs12oA0.js +0 -3
- package/assets/board/_nuxt/CyEXFe3V.js +0 -1
- package/assets/board/_nuxt/Cz6rZcLK.js +0 -1
- package/assets/board/_nuxt/D2FhHl1o.js +0 -1
- package/assets/board/_nuxt/D3YCAmfu.js +0 -1
- package/assets/board/_nuxt/D5CE81jK.js +0 -1
- package/assets/board/_nuxt/D75vbfSb.js +0 -1
- package/assets/board/_nuxt/D99LbGfb.js +0 -9
- package/assets/board/_nuxt/DEfLc7p3.js +0 -6
- package/assets/board/_nuxt/DF-nsa1Z.js +0 -1
- package/assets/board/_nuxt/DIc8yx98.js +0 -1
- package/assets/board/_nuxt/DLkAKotw.js +0 -1
- package/assets/board/_nuxt/DRPlYvb3.js +0 -1
- package/assets/board/_nuxt/DRlQgul3.js +0 -1
- package/assets/board/_nuxt/DSLbmoWa.js +0 -1
- package/assets/board/_nuxt/DWO9c9yp.js +0 -1
- package/assets/board/_nuxt/DZo3dYLJ.js +0 -3
- package/assets/board/_nuxt/D_S6N7_b.js +0 -1
- package/assets/board/_nuxt/DajA-Tkt.js +0 -1
- package/assets/board/_nuxt/DbHiyab-.js +0 -1
- package/assets/board/_nuxt/Dc7Ql6eE.js +0 -1
- package/assets/board/_nuxt/Dd9ZukPU.js +0 -1
- package/assets/board/_nuxt/Dg2LiqmN.js +0 -1
- package/assets/board/_nuxt/DhuleNnm.js +0 -1
- package/assets/board/_nuxt/DkI1Qxpp.js +0 -95
- package/assets/board/_nuxt/DnDHGSYI.js +0 -1
- package/assets/board/_nuxt/DpXJ_tCU.js +0 -1
- package/assets/board/_nuxt/DqZgF3hU.js +0 -1
- package/assets/board/_nuxt/DqcxvfbD.js +0 -1
- package/assets/board/_nuxt/DsA2lVci.js +0 -1
- package/assets/board/_nuxt/Dtsa-1NS.js +0 -1
- package/assets/board/_nuxt/Du91iq0p.js +0 -1
- package/assets/board/_nuxt/Dx1wcYFo.js +0 -1
- package/assets/board/_nuxt/EYTShbt4.js +0 -1
- package/assets/board/_nuxt/MaXJprwN.js +0 -1
- package/assets/board/_nuxt/P9x67aq2.js +0 -1
- package/assets/board/_nuxt/S08nFESZ.js +0 -3
- package/assets/board/_nuxt/V0uynWE2.js +0 -1
- package/assets/board/_nuxt/Vo4wMbnS.js +0 -1
- package/assets/board/_nuxt/ZVTqot-_.js +0 -1
- package/assets/board/_nuxt/ZngEd3HB.js +0 -1
- package/assets/board/_nuxt/_id_.B2NDKSlX.css +0 -1
- package/assets/board/_nuxt/assMu_Wn.js +0 -1
- package/assets/board/_nuxt/builds/meta/8e23aec9-5b67-4569-b8bf-d4f07e50ffdf.json +0 -1
- package/assets/board/_nuxt/error-404.BFmXOnCT.css +0 -1
- package/assets/board/_nuxt/error-500.BZ-DdjQ6.css +0 -1
- package/assets/board/_nuxt/rlePnzpc.js +0 -1
- package/assets/board/_nuxt/uKzCKCTq.js +0 -1
- package/assets/board/_nuxt/vwxaNGfc.js +0 -1
- package/assets/board/_nuxt/yh6sf_D5.js +0 -1
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# DP security matrix
|
|
2
|
+
|
|
3
|
+
**Best for:** documenting per-role / per-component access permissions for a data platform — a grid where each row is a platform component (Keycloak, MinIO bucket, Trino catalog, JupyterHub, NiFi, …) and each column is a role / AD group (Data Administrators, Data Engineers, Data Scientists, Data Consumers, …). Each intersection cell holds a permission value (Admin / Full / R/W / Read / SELECT / Login / No access) with a visual category that matches the permission level. One cell may be marked focal to flag a critical access rule (e.g., "Data Consumers can ONLY `SELECT` from the aggregated catalog — sole consumer access").
|
|
4
|
+
|
|
5
|
+
Use when stakeholders need to audit *who can do what* across the platform. Prefer **DP integration** when the question is *who can talk to what* (topology/protocol) rather than *who can write/read what* (permissions).
|
|
6
|
+
|
|
7
|
+
This type is **parametric** — the inputs schema in §1 drives every coordinate via the formulas in §2. The rule shape mirrors `type-medallion.md` / `type-process.md` / `type-data-flow.md` so the focal rule, color override, dark mode, and reproducibility checklist read identically across types.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Inputs — the parameter contract
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
title: "Platform Access Matrix"
|
|
15
|
+
subtitle: "Four canonical groups × platform components"
|
|
16
|
+
|
|
17
|
+
roles: # 2..6 columns, ordered left → right
|
|
18
|
+
- { name: "Data Administrators", code: "DL-DataAdmins" }
|
|
19
|
+
- { name: "Data Engineers", code: "DL-DataEngineers" }
|
|
20
|
+
- { name: "Data Scientists", code: "DL-DataScientists" }
|
|
21
|
+
- { name: "Data Consumers", code: "DL-DataConsumers" }
|
|
22
|
+
|
|
23
|
+
components: # 2..14 rows, ordered top → bottom
|
|
24
|
+
- { name: "Keycloak", hint: "SSO" } # `hint` = right-aligned aside in label cell
|
|
25
|
+
- { name: "MinIO · raw bucket" }
|
|
26
|
+
- { name: "MinIO · anon · staging · agg" }
|
|
27
|
+
- { name: "Trino · raw catalog" }
|
|
28
|
+
- { name: "Trino · anon-staging" }
|
|
29
|
+
- { name: "Trino · aggregated" }
|
|
30
|
+
- { name: "JupyterHub" }
|
|
31
|
+
- { name: "NiFi" }
|
|
32
|
+
|
|
33
|
+
cells: # explicit (row, col) entries; omitted → defaults to "none"
|
|
34
|
+
# value = displayed text (free-form)
|
|
35
|
+
# level = visual category: full | rw | read | none (closed vocabulary, drives styling)
|
|
36
|
+
# focal: true (max 1) — overrides level to focal styling
|
|
37
|
+
# sub: "second-line text" — used inside focal cell
|
|
38
|
+
# color: "#hex" — optional per-cell color override (§4)
|
|
39
|
+
- { row: 0, col: 0, value: "Admin", level: "full" }
|
|
40
|
+
- { row: 0, col: 1, value: "Login", level: "read" }
|
|
41
|
+
- { row: 0, col: 2, value: "Login", level: "read" }
|
|
42
|
+
- { row: 0, col: 3, value: "Login", level: "read" }
|
|
43
|
+
|
|
44
|
+
- { row: 1, col: 0, value: "Full", level: "full" }
|
|
45
|
+
- { row: 1, col: 1, value: "R/W", level: "rw" }
|
|
46
|
+
- { row: 1, col: 2, value: "No access", level: "none" }
|
|
47
|
+
- { row: 1, col: 3, value: "No access", level: "none" }
|
|
48
|
+
|
|
49
|
+
# ... rows 2..4 follow the same pattern ...
|
|
50
|
+
|
|
51
|
+
- { row: 5, col: 0, value: "Full", level: "full" }
|
|
52
|
+
- { row: 5, col: 1, value: "R/W", level: "rw" }
|
|
53
|
+
- { row: 5, col: 2, value: "SELECT", level: "read" }
|
|
54
|
+
- { row: 5, col: 3, value: "SELECT only", sub: "sole consumer access", focal: true }
|
|
55
|
+
|
|
56
|
+
# ... rows 6..7 ...
|
|
57
|
+
|
|
58
|
+
none_label: "No access" # default text rendered when a cell is omitted
|
|
59
|
+
dark: false
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Reserved field semantics:**
|
|
63
|
+
- `roles[j].name` — primary role label (`node-name` role at 11px, white text on the ink banner)
|
|
64
|
+
- `roles[j].code` — secondary AD-group identifier (`sublabel` role, white text at 0.85 opacity)
|
|
65
|
+
- `components[i].hint` — optional right-aligned `sublabel` text in the label cell (e.g., `"SSO"`, `"S3 API"`)
|
|
66
|
+
- `cells[k].level` — closed vocabulary `full | rw | read | none`. Drives fill/stroke/text-color per §2.4.
|
|
67
|
+
- `cells[k].value` — free-form display text. Domain-specific labels (`"R/W"`, `"SELECT"`, `"Login"`) work without inventing new levels.
|
|
68
|
+
- `cells[k].focal: true` — exactly **one** cell may declare this. Overrides `level` to focal styling.
|
|
69
|
+
- `cells[k].sub` — optional 2nd-line text (used with focal). Renders in the `sublabel` role at 8px below the primary value.
|
|
70
|
+
- `cells[k].color: "#hex"` — optional per-cell color override (§4).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Layout formulas — deterministic geometry
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
# Constants
|
|
78
|
+
left_pad = 12
|
|
79
|
+
right_pad = 48
|
|
80
|
+
comp_col_w = 208
|
|
81
|
+
comp_role_gap = 12
|
|
82
|
+
role_col_w = 148
|
|
83
|
+
role_col_gap = 16
|
|
84
|
+
header_h = 52
|
|
85
|
+
row_h = 36
|
|
86
|
+
row_stride = 40
|
|
87
|
+
|
|
88
|
+
# Counts
|
|
89
|
+
n_roles = len(roles) # 2..6
|
|
90
|
+
n_components = len(components) # 2..14
|
|
91
|
+
|
|
92
|
+
# Canvas
|
|
93
|
+
viewBox_w = left_pad + comp_col_w + comp_role_gap
|
|
94
|
+
+ n_roles * role_col_w + (n_roles - 1) * role_col_gap
|
|
95
|
+
+ right_pad
|
|
96
|
+
# 4 roles → 12 + 208 + 12 + 592 + 48 + 48 = 920
|
|
97
|
+
|
|
98
|
+
header_y = 72
|
|
99
|
+
row_y(k) = 140 + k * row_stride # 140, 180, 220, ...
|
|
100
|
+
rows_bottom = row_y(n_components - 1) + row_h # 8 rows → 456
|
|
101
|
+
legend_y_top = rows_bottom + 20 # 476 for 8-row canonical
|
|
102
|
+
viewBox_h = legend_y_top + 44 # 520 for 8-row canonical
|
|
103
|
+
|
|
104
|
+
# Column positions
|
|
105
|
+
comp_col_x = left_pad # 12
|
|
106
|
+
role_col_x(j) = left_pad + comp_col_w + comp_role_gap
|
|
107
|
+
+ j * (role_col_w + role_col_gap)
|
|
108
|
+
# 232, 396, 560, 724
|
|
109
|
+
role_col_cx(j) = role_col_x(j) + role_col_w / 2 # 306, 470, 634, 798
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 2.1 Background
|
|
113
|
+
|
|
114
|
+
Solid paper fill across the full viewBox. No dot pattern.
|
|
115
|
+
|
|
116
|
+
### 2.2 Header row (`y = 72, h = 52`)
|
|
117
|
+
|
|
118
|
+
**Component-column header cell:**
|
|
119
|
+
- Rect: `(comp_col_x, header_y, comp_col_w, header_h)`, fill white, stroke `ink @ 0.12` 0.8, `rx=6`
|
|
120
|
+
- Two-line label centered at `(comp_col_x + comp_col_w/2, header_y+24)` and `(…, header_y+40)`:
|
|
121
|
+
- Line 1: `"Component"` — `node-name` role at 11px, ink
|
|
122
|
+
- Line 2: `"vs. AD group"` — `sublabel` role, muted
|
|
123
|
+
|
|
124
|
+
**Role banners (one per role):**
|
|
125
|
+
- Rect: `(role_col_x(j), header_y, role_col_w, header_h)`, fill `ink`, `rx=6`
|
|
126
|
+
- Two-line label centered:
|
|
127
|
+
- Line 1 at `y=92`: `roles[j].name` — `node-name` role at 11px, white
|
|
128
|
+
- Line 2 at `y=108`: `roles[j].code` — `sublabel` role, white at opacity 0.85
|
|
129
|
+
|
|
130
|
+
### 2.3 Data row (`y = row_y(k), h = 36`)
|
|
131
|
+
|
|
132
|
+
**Component label cell:**
|
|
133
|
+
- Rect: `(comp_col_x, row_y(k), comp_col_w, row_h)`, fill white, stroke `ink @ 0.12` 0.8, `rx=4`
|
|
134
|
+
- Name at `(comp_col_x + 12, row_y(k) + 22)`: `node-name` role at 11px, ink, left-aligned
|
|
135
|
+
- Hint (if present) at `(comp_col_x + comp_col_w − 12, row_y(k) + 22)`: `sublabel` role, muted, right-aligned
|
|
136
|
+
|
|
137
|
+
**Value cells (one per role × component):**
|
|
138
|
+
- Rect: `(role_col_x(j), row_y(k), role_col_w, row_h)`, `rx=4`, stroke `ink @ 0.12` 0.6
|
|
139
|
+
- Fill and text-color depend on `level` (or focal flag) — see §2.4
|
|
140
|
+
- Value text centered at `(role_col_cx(j), row_y(k) + 22)`: `node-name` role at 10px
|
|
141
|
+
- Focal cell uses a slightly raised primary text at `y=18` and a sub-line at `y=30` (`sublabel` role at 8px)
|
|
142
|
+
|
|
143
|
+
### 2.4 Cell style table
|
|
144
|
+
|
|
145
|
+
| `level` | Fill | Stroke | Text color | Text weight |
|
|
146
|
+
|---|---|---|---|---|
|
|
147
|
+
| `full` | `ink @ 0.08` | `ink @ 0.12` | `ink` | 600 |
|
|
148
|
+
| `rw` | `#FFFFFF` | `ink @ 0.12` | `ink` | 400 |
|
|
149
|
+
| `read` | `muted @ 0.08` | `ink @ 0.12` | `muted` | 400 |
|
|
150
|
+
| `none` | `paper` | `ink @ 0.12` | `soft` | 400 |
|
|
151
|
+
| **focal** | `accent @ 0.07` | `accent` (1.4) | `accent` | 600 |
|
|
152
|
+
|
|
153
|
+
The focal cell can carry a 2nd line (`sub:`) rendered in `accent` with the `sublabel` role at 8px and 0.85 opacity.
|
|
154
|
+
|
|
155
|
+
### 2.5 Legend (`y_top = legend_y_top, h ≈ 30`)
|
|
156
|
+
|
|
157
|
+
Hairline separator at `legend_y_top`. Below the separator, one row of style swatches with their labels — only the styles actually used in the diagram appear in the legend.
|
|
158
|
+
|
|
159
|
+
- "LEGEND" eyebrow at `(left_pad, legend_y_top + 20)`: `eyebrow` role, muted, letter-spacing 0.14em
|
|
160
|
+
- Each style: swatch rect (14×12 `rx=2`) followed by a `sublabel` role label
|
|
161
|
+
- Item x-positions are tabulated left-to-right with ~120-px stride; legend wraps onto a second visual row only if `n_roles ≥ 6` (otherwise fits in one line)
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 3. Cells, not connectors
|
|
166
|
+
|
|
167
|
+
A matrix diagram has **no connectors** — there are no arrows between cells, no flow lines. The diagram's information is entirely in the cell content + cell styling. The only "connector-like" element is the focal cell's accent border, which visually "calls out" a specific intersection.
|
|
168
|
+
|
|
169
|
+
Cells emit **no edges**. Don't add arrows pointing into cells or between cells — they belong in a different diagram type.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 4. Color overrides
|
|
174
|
+
|
|
175
|
+
Three independent override axes — per-cell, per-component (row), per-role (column). All optional, all use the same `color: "#hex"` field, all draw from the same recommended palette. Mirrors §3.4 of `type-high-level.md`, §4 of `type-process.md`, §4 of `type-medallion.md`.
|
|
176
|
+
|
|
177
|
+
### 4.1 Per-cell `color`
|
|
178
|
+
|
|
179
|
+
Tints a specific intersection cell. Applied to:
|
|
180
|
+
|
|
181
|
+
| Element | Light | Dark |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| Cell fill | `rgba(C, 0.08)` | `rgba(C_light, 0.12)` |
|
|
184
|
+
| Cell stroke | `rgba(C, 0.45)` width 1.0 | `rgba(C_light, 0.55)` width 1.0 |
|
|
185
|
+
| Value text | `C` | `C_light` |
|
|
186
|
+
| Sub text (if present) | `rgba(C, 0.85)` | `rgba(C_light, 0.95)` |
|
|
187
|
+
|
|
188
|
+
`C_light` = the same hex lightened ~15% for dark-mode contrast.
|
|
189
|
+
|
|
190
|
+
### 4.2 Per-component `color` (`components[i].color`)
|
|
191
|
+
|
|
192
|
+
Tints the row's **label cell only** (left column). The data cells in that row keep their per-cell `level` styling — the row color flags *what* this component is, not *what permissions live in it*.
|
|
193
|
+
|
|
194
|
+
| Element | Light | Dark |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| Label cell fill | `rgba(C, 0.06)` | `rgba(C_light, 0.10)` |
|
|
197
|
+
| Label cell stroke | `rgba(C, 0.45)` width 0.8 | `rgba(C_light, 0.55)` width 0.8 |
|
|
198
|
+
| Component name | `C` | `C_light` |
|
|
199
|
+
| Hint text | unchanged (muted) | unchanged (muted) |
|
|
200
|
+
|
|
201
|
+
### 4.3 Per-role `color` (`roles[j].color`)
|
|
202
|
+
|
|
203
|
+
Tints the **column banner only** (top row). Cells underneath keep their `level` styling. Replaces the default navy banner fill with the chosen hex.
|
|
204
|
+
|
|
205
|
+
| Element | Light & Dark (banner is the same in both modes) |
|
|
206
|
+
|---|---|
|
|
207
|
+
| Banner fill | `C` |
|
|
208
|
+
| Role name + code text | `#FFFFFF` if `C` is dark (luminance ≤ 0.5), else `ink` |
|
|
209
|
+
|
|
210
|
+
If you pick a mid-luminance hex (e.g., yellow `#c9a23a`), the text auto-flips to ink for contrast. Pair `roles[j].text_color: "#hex"` to override this auto-pick.
|
|
211
|
+
|
|
212
|
+
### 4.4 Rules
|
|
213
|
+
|
|
214
|
+
- **Focal cell wins.** A focal cell ignores `color` overrides — accent always.
|
|
215
|
+
- **Per-cell `color` overrides `level` styling** for that one cell.
|
|
216
|
+
- **Per-component / per-role overrides are scoped:** component → row label only; role → banner only. They do **not** spread into the matrix body. To flag a specific intersection, use per-cell.
|
|
217
|
+
- **Cap:** keep total custom-colored entities ≤ 5 per diagram (combining cells + components + roles). Above 5, the matrix reads as colored noise — split into multiple diagrams or rethink which color carries which concern.
|
|
218
|
+
|
|
219
|
+
### 4.5 Recommended palette (same as the other parametric types)
|
|
220
|
+
|
|
221
|
+
- `#b85450` rust-red — Security elevation / break-glass / SoX-flagged
|
|
222
|
+
- `#5a7d9a` slate-blue — Quality / monitoring / observability gate
|
|
223
|
+
- `#7a8c47` olive-green — Approved / governance-cleared / publication-ready
|
|
224
|
+
- `#c9a23a` warm yellow — Working / sandbox / data-scientist zone
|
|
225
|
+
- `#8c6d3f` warm-brown — Archive / cold / DR
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 5. Focal rule
|
|
230
|
+
|
|
231
|
+
Exactly **one** focal cell per diagram (or zero). The focal cell:
|
|
232
|
+
- Uses focal styling (accent fill + accent stroke 1.4 + accent text bold)
|
|
233
|
+
- May carry a 2-line content: primary `value` at `y = row_y(k) + 18`, `sub` at `y = row_y(k) + 30`
|
|
234
|
+
- Calls out the diagram's central security claim — the *one* access rule that distinguishes this platform's posture from a generic permissions table
|
|
235
|
+
|
|
236
|
+
If zero or >1 `focal: true` cells are declared, halt and ask the user.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 6. Dark mode
|
|
241
|
+
|
|
242
|
+
| Token | Light | Dark |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| Paper | `paper` | `ink` |
|
|
245
|
+
| Ink | `ink` | `paper` |
|
|
246
|
+
| Muted | `muted` | `soft` |
|
|
247
|
+
| Soft (no-access text) | `soft` | `muted` |
|
|
248
|
+
| Accent | `accent` | `accent` |
|
|
249
|
+
| Role-banner fill | `ink` | `ink` |
|
|
250
|
+
| Header / row stroke | `ink @ 0.12` | `paper @ 0.18` |
|
|
251
|
+
| Full / Admin fill | `ink @ 0.08` | `paper @ 0.10` |
|
|
252
|
+
| R/W fill | `#FFFFFF` | `paper @ 0.06` |
|
|
253
|
+
| Read fill | `muted @ 0.08` | `soft @ 0.12` |
|
|
254
|
+
| No-access fill | `paper` | `paper @ 0.02` |
|
|
255
|
+
| Focal fill | `accent @ 0.07` | `accent @ 0.12` |
|
|
256
|
+
| Focal stroke | `accent` | `accent` |
|
|
257
|
+
| Custom component colors | `C` | `C_light` (lighten ~15%) |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 7. Reproducibility checklist (taste gate)
|
|
262
|
+
|
|
263
|
+
Before emitting SVG, verify **every** item:
|
|
264
|
+
|
|
265
|
+
1. `viewBox = "0 0 {viewBox_w} {viewBox_h}"` derived via §2 (4 roles × 8 components → 920 × 520).
|
|
266
|
+
2. Header row at `y=72 h=52`. Component header cell white-filled with two-line `Component / vs. AD group` label. Role banners filled `ink` with name + AD-group code in white.
|
|
267
|
+
3. Data rows start at `y=140`, stride 40, height 36. `rows_bottom = 140 + (n_components−1)·40 + 36`.
|
|
268
|
+
4. Component label cell `rx=4`, name left-aligned at `x=24`, optional `hint` right-aligned at `x = comp_col_x + comp_col_w − 12`.
|
|
269
|
+
5. Every value cell `rx=4`, stroke `ink @ 0.12` 0.6, fill + text matching §2.4 for its `level`.
|
|
270
|
+
6. Exactly **one** focal cell (or zero). Focal cell stroke `accent` width 1.4. Primary value at `y = row_y(k) + 18`; `sub` (if present) at `y = row_y(k) + 30`.
|
|
271
|
+
7. Cells omitted from `cells:` render as `level: "none"` with `none_label` text (default `"No access"`).
|
|
272
|
+
8. Custom-colored cells ≤ 2 (in addition to the focal cell).
|
|
273
|
+
9. No connector elements anywhere in the SVG.
|
|
274
|
+
10. Legend strip at `legend_y_top`, one swatch per `level` actually used, hairline separator above.
|
|
275
|
+
11. `viewBox_h` grows with `n_components`; `viewBox_w` grows with `n_roles`.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 8. Anti-patterns
|
|
280
|
+
|
|
281
|
+
- **More than one focal cell** — focal exists to mark *the* critical access rule; >1 erases the signal.
|
|
282
|
+
- **Connectors anywhere** — matrix is value-driven; arrows belong in DP integration / process diagrams.
|
|
283
|
+
- **Freeform `level` values** — closed vocabulary is `full | rw | read | none`. Use `value` for free-form displayed text + `color` override for arbitrary tinting.
|
|
284
|
+
- **Per-row or per-column color tints** — apply `color` per cell only. Whole-row or whole-column highlighting tends to over-emphasize and collapses the matrix into a list.
|
|
285
|
+
- **Using `none_label` as a placeholder for "TBD"** — `none` means *no access*. If the permission is unknown, leave the cell empty in inputs but document it elsewhere; don't render an ambiguous state.
|
|
286
|
+
- **More than 6 roles** — split into two matrices (e.g., human roles vs service accounts) before exceeding 6 columns.
|
|
287
|
+
- **More than 14 components** — split by domain (storage / compute / observability / governance) before exceeding 14 rows.
|
|
288
|
+
- **Using the matrix to document *how* permissions are granted** — that belongs in a process or sequence diagram. The matrix shows *what* each role can do, not the grant flow.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 9. Examples
|
|
293
|
+
|
|
294
|
+
- `assets/example-dp-security-matrix.html` — minimal light (NatStat canonical: 4 roles × 8 components, focal at Data Consumers × Trino aggregated). Gallery default.
|
|
295
|
+
- `assets/example-dp-security-matrix-dark.html` — same, dark skin.
|
|
296
|
+
- `assets/example-dp-security-matrix-full.html` — same, editorial-card frame with subtitle + summary cards.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## 10. Worked YAML — full inputs for `example-dp-security-matrix.html`
|
|
301
|
+
|
|
302
|
+
The complete inputs that map to the shipped canonical example. Every coordinate in that SVG is derivable from §2 applied to these inputs.
|
|
303
|
+
|
|
304
|
+
```yaml
|
|
305
|
+
title: "Platform Access Matrix"
|
|
306
|
+
subtitle: "Four canonical groups × platform components"
|
|
307
|
+
|
|
308
|
+
roles:
|
|
309
|
+
- { name: "Data Administrators", code: "DL-DataAdmins" }
|
|
310
|
+
- { name: "Data Engineers", code: "DL-DataEngineers" }
|
|
311
|
+
- { name: "Data Scientists", code: "DL-DataScientists" }
|
|
312
|
+
- { name: "Data Consumers", code: "DL-DataConsumers" }
|
|
313
|
+
|
|
314
|
+
components:
|
|
315
|
+
- { name: "Keycloak", hint: "SSO" }
|
|
316
|
+
- { name: "MinIO · raw bucket" }
|
|
317
|
+
- { name: "MinIO · anon · staging · agg" }
|
|
318
|
+
- { name: "Trino · raw catalog" }
|
|
319
|
+
- { name: "Trino · anon-staging" }
|
|
320
|
+
- { name: "Trino · aggregated" }
|
|
321
|
+
- { name: "JupyterHub" }
|
|
322
|
+
- { name: "NiFi" }
|
|
323
|
+
|
|
324
|
+
cells:
|
|
325
|
+
# Row 0 — Keycloak
|
|
326
|
+
- { row: 0, col: 0, value: "Admin", level: "full" }
|
|
327
|
+
- { row: 0, col: 1, value: "Login", level: "read" }
|
|
328
|
+
- { row: 0, col: 2, value: "Login", level: "read" }
|
|
329
|
+
- { row: 0, col: 3, value: "Login", level: "read" }
|
|
330
|
+
# Row 1 — MinIO raw
|
|
331
|
+
- { row: 1, col: 0, value: "Full", level: "full" }
|
|
332
|
+
- { row: 1, col: 1, value: "R/W", level: "rw" }
|
|
333
|
+
- { row: 1, col: 2, value: "No access", level: "none" }
|
|
334
|
+
- { row: 1, col: 3, value: "No access", level: "none" }
|
|
335
|
+
# Row 2 — MinIO anon/staging/agg
|
|
336
|
+
- { row: 2, col: 0, value: "Full", level: "full" }
|
|
337
|
+
- { row: 2, col: 1, value: "R/W", level: "rw" }
|
|
338
|
+
- { row: 2, col: 2, value: "Read", level: "read" }
|
|
339
|
+
- { row: 2, col: 3, value: "No access", level: "none" }
|
|
340
|
+
# Row 3 — Trino raw catalog
|
|
341
|
+
- { row: 3, col: 0, value: "Full", level: "full" }
|
|
342
|
+
- { row: 3, col: 1, value: "R/W", level: "rw" }
|
|
343
|
+
- { row: 3, col: 2, value: "No access", level: "none" }
|
|
344
|
+
- { row: 3, col: 3, value: "No access", level: "none" }
|
|
345
|
+
# Row 4 — Trino anon-staging
|
|
346
|
+
- { row: 4, col: 0, value: "Full", level: "full" }
|
|
347
|
+
- { row: 4, col: 1, value: "R/W", level: "rw" }
|
|
348
|
+
- { row: 4, col: 2, value: "SELECT", level: "read" }
|
|
349
|
+
- { row: 4, col: 3, value: "No access", level: "none" }
|
|
350
|
+
# Row 5 — Trino aggregated (focal cell at col 3)
|
|
351
|
+
- { row: 5, col: 0, value: "Full", level: "full" }
|
|
352
|
+
- { row: 5, col: 1, value: "R/W", level: "rw" }
|
|
353
|
+
- { row: 5, col: 2, value: "SELECT", level: "read" }
|
|
354
|
+
- { row: 5, col: 3, value: "SELECT only", sub: "sole consumer access", focal: true }
|
|
355
|
+
# Row 6 — JupyterHub
|
|
356
|
+
- { row: 6, col: 0, value: "Admin", level: "full" }
|
|
357
|
+
- { row: 6, col: 1, value: "R/W", level: "rw" }
|
|
358
|
+
- { row: 6, col: 2, value: "R/W", level: "rw" }
|
|
359
|
+
- { row: 6, col: 3, value: "No access", level: "none" }
|
|
360
|
+
# Row 7 — NiFi
|
|
361
|
+
- { row: 7, col: 0, value: "Admin", level: "full" }
|
|
362
|
+
- { row: 7, col: 1, value: "R/W", level: "rw" }
|
|
363
|
+
- { row: 7, col: 2, value: "Read", level: "read" }
|
|
364
|
+
- { row: 7, col: 3, value: "No access", level: "none" }
|
|
365
|
+
|
|
366
|
+
dark: false
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### 10.1 What this YAML proves
|
|
370
|
+
|
|
371
|
+
Run §2 with these inputs:
|
|
372
|
+
- `n_roles = 4`, `n_components = 8`, no color overrides, one focal cell.
|
|
373
|
+
- `viewBox_w = 12 + 208 + 12 + 4·148 + 3·16 + 48 = 920` ✓
|
|
374
|
+
- `row_y(k)` produces `140, 180, 220, 260, 300, 340, 380, 420` ✓
|
|
375
|
+
- `rows_bottom = 420 + 36 = 456`; `legend_y_top = 476`; `viewBox_h = 520` ✓
|
|
376
|
+
- `role_col_x(j) = [232, 396, 560, 724]` ✓
|
|
377
|
+
- Focal cell at `(row=5, col=3)` → rect `(724, 340, 148, 36)` with accent stroke 1.4 ✓
|
|
378
|
+
|
|
379
|
+
A fresh generation from this YAML produces a diagram visually indistinguishable from the shipped `example-dp-security-matrix.html`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ER / Data Model
|
|
2
|
+
|
|
3
|
+
**Best for:** conceptual and logical data models, API resource relationships, domain models — anything where the story is *entities and cardinality*.
|
|
4
|
+
|
|
5
|
+
**Not for the physical schema.** ER is entity-level: relationship lines join *boxes* and carry cardinality at each end. When the point is real tables with SQL types, constraint chips, indexes, and foreign keys that anchor **column to column**, use [`type-db-schema.md`](type-db-schema.md) instead.
|
|
6
|
+
|
|
7
|
+
## Layout conventions
|
|
8
|
+
- Each entity is a two-section box:
|
|
9
|
+
- **Header**: type tag (`ENTITY`) + entity name in the `node-name` role.
|
|
10
|
+
- **Body**: field list in the `sublabel` role, one per line. PK prefixed with `#`, FK prefixed with `→`.
|
|
11
|
+
- Relationships: lines between entities with cardinality at each end:
|
|
12
|
+
- `1`, `N`, `0..1`, `1..*` in the `arrow-label` role, 8px, placed 10–12px from the entity edge.
|
|
13
|
+
- Optional relationship label ("has", "belongs to") centered on the line.
|
|
14
|
+
- Group related entities close; lay out so most relationships are straight lines, not tangles.
|
|
15
|
+
- Coral on the aggregate root or central entity of the model.
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
- Drawing an arrow for every FK on a model with dozens — lay out by cluster instead.
|
|
19
|
+
- Inconsistent cardinality notation between ends of the same relationship.
|
|
20
|
+
- Fields padded to equal-height boxes — natural height by content is fine.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
- `assets/example-er.html` — minimal light
|
|
24
|
+
- `assets/example-er-dark.html` — minimal dark
|
|
25
|
+
- `assets/example-er-full.html` — full editorial
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Exploded axonometric
|
|
2
|
+
|
|
3
|
+
**Best for:** one object or system drawn in parallel projection with its parts pulled apart along one axis and labelled. A device teardown (what is inside a phone), an unboxing (lid, product, insert, box), assembly order, or the layers of a stack when the reader should see them as physical parts of one thing.
|
|
4
|
+
|
|
5
|
+
**Not this type:**
|
|
6
|
+
|
|
7
|
+
- Ordered abstraction levels with a note on each row → **layer stack** (`type-layers.md`). A layer stack is flat bands of text; an exploded view is the parts of one object. If nothing in the figure has a footprint or a thickness, use the layer stack.
|
|
8
|
+
- Components and the connections between them → **architecture** (`type-architecture.md`). An exploded view has no arrows; position along the axis is the only relationship.
|
|
9
|
+
- Containment without an order → **nested** (`type-nested.md`).
|
|
10
|
+
- Where software runs → **deployment** (`type-deployment.md`).
|
|
11
|
+
|
|
12
|
+
## Projection
|
|
13
|
+
|
|
14
|
+
2:1 dimetric. The ground axes run at 26.565 degrees, so every edge lands on whole pixels when model units are multiples of 4. World x runs right and down, y runs left and down, z runs up. Project every point with one function and never place a coordinate by hand:
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from math import sqrt
|
|
18
|
+
|
|
19
|
+
def iso(x, y, z, ox, oy):
|
|
20
|
+
"""Model point to SVG point. (ox, oy) is where model (0, 0, 0) lands."""
|
|
21
|
+
return ox + x - y, oy + (x + y) / 2 - z
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A rounded-rectangle footprint of corner radius `r` projects to straight edges joined by quarter arcs of one ellipse with `rx = r * sqrt(2)` and `ry = r / sqrt(2)`. Use that one shape for everything: `r = 0` is a box or slab, a small `r` is a product corner, and `r = w / 2 = d / 2` is a cylinder. Corner centres stay fixed when you inset an outline, so an inner rim is the same four centres at a smaller radius.
|
|
25
|
+
|
|
26
|
+
Draw faces as plain SVG `<path>` and `<polygon>` elements with the projected points written in. No CSS 3D, no canvas, no WebGL, and no `transform` to place geometry. If content ever has to sit flat on a face, the matrices that agree with `iso()` are `matrix(1,0.5,-1,0.5,tx,ty)` for the top face, `matrix(1,0.5,0,-1,tx,ty)` for the left face, and `matrix(-1,0.5,0,-1,tx,ty)` for the right face. Labels never use them: labels stay horizontal.
|
|
27
|
+
|
|
28
|
+
`scripts/build-exploded-examples.py` in the repository builds every shipped example from this function and is the worked reference for the helpers below.
|
|
29
|
+
|
|
30
|
+
## Layout conventions
|
|
31
|
+
|
|
32
|
+
- **Parts:** 2 to 5, listed bottom to top. Each part is a rounded prism (`rect`, thickness `t`) plus at most two levels of detail on its top face, because the top face is the one the reader sees.
|
|
33
|
+
- **Explode axis:** Vertical by default. Parts move straight up, nothing rotates, and the bottom part stays at `z = 0`.
|
|
34
|
+
- **Levels:** Parts that sit side by side in the assembled object share a level and explode together. A phone's logic board and battery sit next to each other inside the housing, so they lift as one level instead of stacking two gaps apart.
|
|
35
|
+
- **Gap:** One gap between every pair of levels, `gap = max(k x top-face height, 3 x thickness of the thickest solid part)`, rounded up to a multiple of 4. `k = 0.5` is the floor; raise it to `0.75` when a tall part would hide the focal part below it. Top-face height is `(w + d) / 2` of the largest footprint. Containers (a housing, a box) do not count toward thickness.
|
|
36
|
+
- **Clearance:** If a leader would cross another part, or two labels would sit closer than 36px, raise the gap in steps of 4 until neither happens. Two parts on one level that collide cannot be fixed by the gap: move one of them in plan.
|
|
37
|
+
- **Paint order:** Bottom level first. Inside a level, parts farther back (smaller `x + y`) paint first. A container is split: its back half (silhouette, rim, cavity, floor) paints before the parts that sit inside it, and its outer walls and front rim paint after them. This is the only way an assembled frame shows the parts inside a tray correctly, and it stays correct throughout an explode.
|
|
38
|
+
- **Frame:** The canvas is 1000 wide. The object and a 240px label column are centred together; the viewBox height follows the exploded object plus a 40px top margin. Nothing is clipped at the closed frame either, because the closed object fits inside the exploded one.
|
|
39
|
+
|
|
40
|
+
### Faces and lines
|
|
41
|
+
|
|
42
|
+
| Element | Light | Dark |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| Face base (opaque, under every face) | `#ffffff` | `paper-2` |
|
|
45
|
+
| Top face | base | base + `ink @ 0.10` |
|
|
46
|
+
| Left face (lit side) | base + `ink @ 0.07` | base |
|
|
47
|
+
| Right face (shade side) | base + `ink @ 0.15` | base + `paper @ 0.45` |
|
|
48
|
+
| Focal part, top / left / right | `accent` at 0.10 / 0.20 / 0.32 over base | `accent` at 0.18 top, neutral sides |
|
|
49
|
+
| Silhouette | `ink`, 1.2 (`stroke-strong`) | `ink`, 1.2 |
|
|
50
|
+
| Inner edges (top-front rim, front corner) | `ink` at 0.55, 0.8 (`stroke-thin`) | `ink` at 0.45, 0.8 |
|
|
51
|
+
| Detail lines on a face | `ink` at 0.55, 0.6 to 0.8 | same |
|
|
52
|
+
| Trace lines | `ink` at 0.30, 0.8, dashed `4,3` | `ink` at 0.30, 0.8, dashed `4,3` |
|
|
53
|
+
|
|
54
|
+
Light comes from the top left, so the left face is lighter than the right. Always shade: an outline-only box flips between two readings like a Necker cube. Faces are an opaque base plus an `ink` overlay, never a translucent fill on its own, so parts behind never show through. Trace lines run straight up through the left and right extremes of the bottom part's outline to the underside of the top part, and paint before every part so the parts cover them.
|
|
55
|
+
|
|
56
|
+
### Labels
|
|
57
|
+
|
|
58
|
+
- One label per part, in one column to the right of the object. A label is the part name (`node-name` role, 600, 16px, one or two words) above a technical sublabel (`sublabel` role, 10px, `muted`, tracked 0.08em).
|
|
59
|
+
- A horizontal leader (0.8px, `ink` at 0.40) runs from 6px right of a 2px dot on the part's right extreme, at mid-thickness, to 12px left of the column. Leaders never bend, never cross a part, and never cross each other; horizontal leaders from distinct heights cannot cross each other, and the gap rule above keeps them clear of parts.
|
|
60
|
+
- The focal part's dot, leader, and sublabel take the accent. Its name stays `ink`.
|
|
61
|
+
- No numbered callouts and no legend. The label is on the part it names.
|
|
62
|
+
|
|
63
|
+
### Detail
|
|
64
|
+
|
|
65
|
+
Three levels at most: the form (the rounded prism), insets on its top face (a screen, a cell outline, a moulded well), and micro detail (chips, lenses, a logo mark). A part made of many identical pieces, such as keycaps or switches, declares the envelope of its grid as its box and paints one small prism per piece instead of the envelope; the silhouette path is still there for the verifier, with no fill. Clip any inset that could reach a face edge to that face, keep it 4 units or more inside the edge, and stop at three levels. No contact shadow: shadows are out in this skin (SKILL.md §4). If the object needs grounding, the bottom part already provides it.
|
|
66
|
+
|
|
67
|
+
### Focal part
|
|
68
|
+
|
|
69
|
+
One part at most wears the accent, under the SKILL.md rule of 1 to 2 focal elements. The other parts stay neutral; do not fade them with opacity, because a translucent part shows the edges behind it.
|
|
70
|
+
|
|
71
|
+
## Optional motion
|
|
72
|
+
|
|
73
|
+
An exploded view may open as the assembled object and explode once, because watching the parts lift shows how they fit together. Use the pinned controller from `assets/template-motion.html` in `reveal` mode, per `animation.md`:
|
|
74
|
+
|
|
75
|
+
- The source file is the exploded frame. Every part group carries `data-motion-item`, a `data-step` counted from the top level down (top level lifts first), and `style="--lift:Npx"` where `N` is the part's exploded `z` minus its assembled `z`. In this projection a straight-up move in model space is a straight-up move on screen, so one `translateY(var(--lift))` is the whole explode.
|
|
76
|
+
- The bottom level does not move. Its label and the trace lines arrive together as the last step.
|
|
77
|
+
- Each part's label hides at the closed frame and fades in after its part settles. Hide instantly and delay only the reveal, or labels pile up on the closed object for the first half second.
|
|
78
|
+
- No JavaScript, `prefers-reduced-motion: reduce`, print, `?motion=static`, and export all show the exploded frame.
|
|
79
|
+
- The lift is the one scoped exception to the 24px translation limit in `animation.md`, recorded in the repository as ADR 0013. Nothing else in the figure moves.
|
|
80
|
+
|
|
81
|
+
## Metadata contract
|
|
82
|
+
|
|
83
|
+
`scripts/verify-exploded.py` reprojects each part from what it declares:
|
|
84
|
+
|
|
85
|
+
- The figure: one `<g data-exploded data-origin="ox oy" data-gap="g">` wrapping every part.
|
|
86
|
+
- Each part: a `<g>` with `data-part` (key), `data-name` (the label text), `data-rect="x0 y0 x1 y1 r"`, `data-z`, `data-t`, `data-level`, optional `data-kind="housing"` for a container and `data-focal` for the focal part. Animated parts add `data-closed-z`.
|
|
87
|
+
- Inside each part: the first `<path data-role="silhouette">` is the part's outline at its declared box, and a `<g data-role="label">` holds a `<line data-role="leader">` and a `<text data-role="name">`. Its complete text, including inline `<tspan>` descendants, must match the part's `data-name`.
|
|
88
|
+
- Trace lines carry `data-role="trace"`.
|
|
89
|
+
|
|
90
|
+
The silhouette verifier accepts signed decimal and scientific-notation coordinates within the existing absolute M/L/A/Z path contract. Every operand must be finite; projected vertices, corner radii, and arc flags are still checked. This does not add relative path commands.
|
|
91
|
+
|
|
92
|
+
## Anti-patterns
|
|
93
|
+
|
|
94
|
+
- Hand-placed coordinates, or a CSS `transform` standing in for geometry.
|
|
95
|
+
- Outline-only parts with no face shading.
|
|
96
|
+
- Parts that rotate, slide sideways, or explode along two axes in one figure.
|
|
97
|
+
- Unequal gaps, or a gap shrunk to fit the canvas. Raise `k` or cut a part.
|
|
98
|
+
- Labels on the parts, angled with a face, or spread across two columns.
|
|
99
|
+
- Numbered callouts with a key underneath.
|
|
100
|
+
- More than one part in the accent, or the other parts faded to show which one matters.
|
|
101
|
+
- Blurred contact shadows, gradients on solid faces, or glow.
|
|
102
|
+
- An exploded view of something with no physical sense of parts. If the layers are just a list, use the layer stack.
|
|
103
|
+
|
|
104
|
+
## Examples
|
|
105
|
+
|
|
106
|
+
- `assets/example-exploded.html`: app stack, minimal light
|
|
107
|
+
- `assets/example-exploded-dark.html`: app stack, minimal dark
|
|
108
|
+
- `assets/example-exploded-full.html`: app stack, full editorial
|
|
109
|
+
- `assets/example-exploded-phone.html`, `-dark`, `-full`: phone teardown with a housing, a shared board and battery level, and a display
|
|
110
|
+
- `assets/example-exploded-unboxing.html`, `-dark`, `-full`: packaging with a telescoping lid, a product and cable on one level, an insert, and a box
|
|
111
|
+
- `assets/example-exploded-ai-stack.html`, `-dark`, `-full`: an AI agent stack with a secrets vault, tools, skills as small cards on one layer, the agent harness around the model, and the interface
|
|
112
|
+
- `assets/example-exploded-keyboard.html`, `-dark`, `-full`: a mechanical keyboard with a case tray, PCB, plate, a grid of switches, and a grid of keycaps
|
|
113
|
+
- `assets/example-exploded-phone-animated.html`: the phone assembled, then exploded once
|
|
114
|
+
- `assets/example-exploded-unboxing-animated.html`: the box closed, then unpacked once
|
|
115
|
+
- `assets/example-exploded-ai-stack-animated.html`, `assets/example-exploded-keyboard-animated.html`: the stack and the keyboard assembled, then exploded once
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Fishbone / Ishikawa (root-cause)
|
|
2
|
+
|
|
3
|
+
**Best for:** structured root-cause analysis. One observed effect, causes grouped by category, sub-causes hanging off each category. The standard artefact of an incident post-mortem — use it when a reader needs to see *what was investigated*, not just the conclusion.
|
|
4
|
+
|
|
5
|
+
## Layout conventions
|
|
6
|
+
|
|
7
|
+
- **Spine.** A horizontal line (`ink`, 1.2px) runs left→right at the vertical centre `CY`, terminating with an arrowhead into an **effect box** at the right head — the node-box pattern from SKILL.md §6 ([primitives-core.md](primitives-core.md#node-box--full-pattern)), the observed-effect statement inside.
|
|
8
|
+
- **Bones.** Category lines are straight diagonals at a fixed **60°** to the spine, alternating above and below, evenly spaced along it. Each bone carries its category name at the outer end in a small tag-style box (`rx=4`, not a pill) — `node-name` role, 12px, weight 600.
|
|
9
|
+
- **Sub-causes.** Short horizontal ticks (32px, `soft`) branch off each bone at fixed points along its length, each with a sub-cause label in the `sublabel` role at 9px sitting past the open end of the tick.
|
|
10
|
+
- **Diagonal exemption.** SKILL.md §6 rule 1 (mandatory rounded right-angle elbows) does not apply to the 60° bones — they are this type's defining grammar. The exemption covers **bones and sub-cause ticks only**; any other connector in a fishbone diagram (e.g. a callout leader, a cross-reference arrow) still uses rounded right-angle elbows.
|
|
11
|
+
- **Focal rule.** Exactly one bone is the confirmed root cause: its line is `accent`, and its category tag uses `accent-tint` fill + `accent` stroke. The effect box is styled the same way (`accent-tint` fill, `accent` stroke) since it's the diagram's headline. That pair — root-cause bone and effect box — is the full 2-accent budget; every other bone, tag, and tick stays `ink` / `muted` / `soft`.
|
|
12
|
+
- **Drawing order:** background → spine → bones → sub-cause ticks → category tag boxes → effect box → legend. Lines before boxes, so box fills cap the line ends cleanly.
|
|
13
|
+
|
|
14
|
+
## Math
|
|
15
|
+
|
|
16
|
+
For a spine at `y = CY` with the effect box's left edge at `x = HEAD`, bone `k` (1-indexed, k = 1..6) attaches to the spine at:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
attach_x(k) = HEAD - 160 - k * 160
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Bones alternate above (`k` odd) and below (`k` even) the spine. A bone's far endpoint — where the category tag sits — is the integer-rounded 60° offset from its attach point:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
dx = -96
|
|
26
|
+
dy = ∓168 (minus = above, plus = below)
|
|
27
|
+
far_x(k) = attach_x(k) + dx
|
|
28
|
+
far_y(k) = CY ∓ 168
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Pre-computed reference (5-bone layout, HEAD=1200, CY=320)
|
|
32
|
+
|
|
33
|
+
| Bone `k` | Category slot | Side | `attach_x` | `far_x, far_y` |
|
|
34
|
+
|---|---|---|---|---|
|
|
35
|
+
| 1 | first | above | 880 | 784, 152 |
|
|
36
|
+
| 2 | second | below | 720 | 624, 488 |
|
|
37
|
+
| 3 | third | above | 560 | 464, 152 |
|
|
38
|
+
| 4 | fourth | below | 400 | 304, 488 |
|
|
39
|
+
| 5 | fifth | above | 240 | 144, 152 |
|
|
40
|
+
|
|
41
|
+
A 6th bone (below) would attach at `x=80`, far endpoint `(-16, 488)`, and its category tag would run from `x=-76` to `x=44` against a viewBox that starts at `x=-40`. It clips. **Five is the ceiling at `HEAD=1200`**: to draw a 6th, widen `HEAD` *and* the viewBox width by at least 160 each, keeping the viewBox origin at `-40`. Both have to move together — widening `HEAD` alone pushes the 200px effect box to `1360..1560` past the `1440` right edge, trading a clipped tag on the left for a clipped effect on the right. Or drop a category.
|
|
42
|
+
|
|
43
|
+
**Sub-cause ticks** sit at fractions `m/6` along the bone (`m = 2, 4` for two ticks; `m = 3` for one), so their coordinates stay on the 4px grid:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
tick_x(k, m) = attach_x(k) - 16 * m
|
|
47
|
+
tick_y(k, m) = CY ∓ 28 * m
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The tick itself is a 32px horizontal line from `(tick_x, tick_y)` to `(tick_x - 32, tick_y)`; the label sits past its open end, `text-anchor="end"` at `x = tick_x - 36`, `y = tick_y - 4` (above-bones) or `tick_y + 12` (below-bones).
|
|
51
|
+
|
|
52
|
+
## Complexity budget
|
|
53
|
+
|
|
54
|
+
| Limit | Rule |
|
|
55
|
+
|---|---|
|
|
56
|
+
| Max categories (bones) | 5 at `HEAD=1200`. A 6th requires a widened canvas — see Geometry |
|
|
57
|
+
| Max sub-causes per bone | 3 |
|
|
58
|
+
| Max sub-causes total | 18 |
|
|
59
|
+
| Max accent elements | 2 (root-cause bone+tag, effect box) |
|
|
60
|
+
|
|
61
|
+
## Anti-patterns
|
|
62
|
+
|
|
63
|
+
- **More than 5 bones on the default canvas.** The 6th tag clips the viewBox. Widen `HEAD` and the viewBox width together and deliberately, or split by subsystem into two fishbones.
|
|
64
|
+
- **Sub-causes that restate the category.** A "Deploy" bone with a sub-cause labeled "deployment issue" adds a node without adding information.
|
|
65
|
+
- **A bone with zero sub-causes.** An empty category is a placeholder, not a finding — delete the bone or don't draw it until there's something under it.
|
|
66
|
+
- **Accenting more than one root cause.** If two categories are both confirmed, that's two diagrams (or a merged cause) — not two accent bones. The 2-accent budget is load-bearing for the "this is the answer" signal.
|
|
67
|
+
- **Using fishbone for a sequence of failures.** A chain of things that happened in order is a timeline or sequence diagram — fishbone is for causes of *one* effect, not a chronology.
|
|
68
|
+
- **Pasting in the classic 6M template (Man/Machine/Material/Method/Measurement/Environment) with empty categories.** Name categories from the actual investigation, not a generic checklist waiting to be filled in later.
|
|
69
|
+
- **Effect box phrased as a solution.** "Add a p99 alert" is a fix, not an observed effect. The box states what was seen — a symptom, a measurement, an incident — never the remedy.
|
|
70
|
+
|
|
71
|
+
## Examples
|
|
72
|
+
|
|
73
|
+
- `assets/example-fishbone.html` — minimal light. Checkout p99 latency incident, 5 categories, Data confirmed as root cause.
|
|
74
|
+
- `assets/example-fishbone-dark.html` — minimal dark, same data.
|
|
75
|
+
- `assets/example-fishbone-full.html` — full editorial: container framing + 3 summary cards of varied widths + footer.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Flowchart
|
|
2
|
+
|
|
3
|
+
**Best for:** decision logic, algorithms, user-facing branching flows ("Should I…?"), onboarding routing, support-triage trees.
|
|
4
|
+
|
|
5
|
+
## Layout conventions
|
|
6
|
+
- Shape carries type, not color:
|
|
7
|
+
- **Oval** (`rx=20`) — start / end
|
|
8
|
+
- **Rectangle** (`rx=6`) — step / action
|
|
9
|
+
- **Diamond** — decision (≤3 exits)
|
|
10
|
+
- **Small filled ink dot** (`r=4`) — merge point where branches rejoin
|
|
11
|
+
- Flow runs top→down. From a diamond, conventional exits: Yes to the right, No below — but label every outgoing arrow regardless.
|
|
12
|
+
- Use coral on the happy path *or* on the single most consequential decision — never on every decision.
|
|
13
|
+
- If two arrows must cross, use a small arc jump on one so the crossing is readable.
|
|
14
|
+
|
|
15
|
+
## Anti-patterns
|
|
16
|
+
- Using fill color to signal node type (shape does that).
|
|
17
|
+
- Decision diamond with 4+ exits — refactor into nested diamonds.
|
|
18
|
+
- Unlabeled decision branches.
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
- `assets/example-flowchart.html` — minimal light
|
|
22
|
+
- `assets/example-flowchart-dark.html` — minimal dark
|
|
23
|
+
- `assets/example-flowchart-full.html` — full editorial
|