Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7e1ad1c0c | ||
|
|
714090a83d | ||
|
|
9347de298f | ||
|
|
62d2afc152 | ||
|
|
794f2aa2d6 | ||
|
|
7f40de708c |
No files matched your search
@@ -31,6 +31,10 @@ Top-level sections are Organization, Strategy, and Contribution, each with an in
|
|||||||
|
|
||||||
Archify 3.0.1 is vendored under `vendor/archify/` from commit `d5a1333d7447c866a765adac7d4d062f2f02e4d2`. MIT and third-party notices are preserved. `diagrams/` holds editable JSON; `pnpm diagrams:build` validates and generates local standalone viewers before every site build. The iframe is sandboxed without same-origin permission. See `docs/contribution/diagrams.md` for capability analysis, authoring, boundaries, and upgrade procedure.
|
Archify 3.0.1 is vendored under `vendor/archify/` from commit `d5a1333d7447c866a765adac7d4d062f2f02e4d2`. MIT and third-party notices are preserved. `diagrams/` holds editable JSON; `pnpm diagrams:build` validates and generates local standalone viewers before every site build. The iframe is sandboxed without same-origin permission. See `docs/contribution/diagrams.md` for capability analysis, authoring, boundaries, and upgrade procedure.
|
||||||
|
|
||||||
|
The build checks upstream provenance before applying the portal integration: `scripts/inline-viewer.css` restores compact embed controls, two guarded preset restrictions are removed from generated viewers only, and `scripts/viewer-theme-bridge.js` synchronizes theme with the portal through source-validated messages. Vendor files remain unchanged. Delivery receipts describe the upstream artifact before this integration, not the final served bytes. Theme changes do not reload viewers or discard visual presets. PNG, JPEG, WebP and SVG downloads remain available; browser-dependent exports stay disabled when unsupported.
|
||||||
|
|
||||||
|
For interaction acceptance, serve the production build on port 4173 and run `pnpm test:browser` with an installed Playwright Chromium (or `PLAYWRIGHT_CHROMIUM_EXECUTABLE`). This checks story layouts, portal/diagram theme synchronization, all four presets, actual exported artifact decoding, route changes, and fullscreen click/Escape/focus behavior at desktop and mobile widths. Screenshots, downloads and results are saved under ignored `.cache/` directories.
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
Inspired by https://www.eldorado.gg/: Lato, near-black navigation, charcoal, gold `#ffc950`, light panels, bold headings. Original documentation artwork and square panels; no official marketplace assets or business claims. See `docs/core/reference.md`.
|
Inspired by https://www.eldorado.gg/: Lato, near-black navigation, charcoal, gold `#ffc950`, light panels, bold headings. Original documentation artwork and square panels; no official marketplace assets or business claims. See `docs/core/reference.md`.
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Learn before expanding",
|
||||||
|
"output": "static/diagrams/strategy-adoption-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "choose",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Choose workflow",
|
||||||
|
"sublabel": "Department outcome",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coach",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Coach people",
|
||||||
|
"sublabel": "Verify + recover",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "canary",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Run bounded canary",
|
||||||
|
"sublabel": "Qualified skill + client",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "accept",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Accept real work",
|
||||||
|
"sublabel": "Independent review",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "feedback",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Review feedback",
|
||||||
|
"sublabel": "Usefulness + non-use",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expand",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Expand or revise",
|
||||||
|
"sublabel": "Keep a manual path",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "choose",
|
||||||
|
"to": "coach",
|
||||||
|
"label": "Prepare"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "coach",
|
||||||
|
"to": "canary",
|
||||||
|
"label": "support pilot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "canary",
|
||||||
|
"to": "accept",
|
||||||
|
"label": "Verify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "accept",
|
||||||
|
"to": "feedback",
|
||||||
|
"label": "learn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "feedback",
|
||||||
|
"to": "expand",
|
||||||
|
"label": "decide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "feedback-loop",
|
||||||
|
"from": "expand",
|
||||||
|
"to": "coach",
|
||||||
|
"label": "Review revision",
|
||||||
|
"variant": "dashed",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "right"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Learn before expanding",
|
||||||
|
"output": "static/diagrams/strategy-adoption/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "choose",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Choose workflow",
|
||||||
|
"sublabel": "Department outcome",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coach",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Coach people",
|
||||||
|
"sublabel": "Verify + recover",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "canary",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Run bounded canary",
|
||||||
|
"sublabel": "Qualified skill + client",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "accept",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Accept real work",
|
||||||
|
"sublabel": "Independent review",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "feedback",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Review feedback",
|
||||||
|
"sublabel": "Usefulness + non-use",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expand",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Expand or revise",
|
||||||
|
"sublabel": "Keep a manual path",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "choose",
|
||||||
|
"to": "coach",
|
||||||
|
"label": "Prepare"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "coach",
|
||||||
|
"to": "canary",
|
||||||
|
"label": "support pilot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "canary",
|
||||||
|
"to": "accept",
|
||||||
|
"label": "Verify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "accept",
|
||||||
|
"to": "feedback",
|
||||||
|
"label": "learn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "feedback",
|
||||||
|
"to": "expand",
|
||||||
|
"label": "decide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "feedback-loop",
|
||||||
|
"from": "expand",
|
||||||
|
"to": "coach",
|
||||||
|
"label": "Review revision",
|
||||||
|
"variant": "dashed",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "right"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Independent approval",
|
||||||
|
"output": "static/diagrams/strategy-governance-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "owner",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Owner proposes",
|
||||||
|
"sublabel": "Existing accountable team",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "review",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Independent review",
|
||||||
|
"sublabel": "Quality + risk evidence",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "canary",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Bounded canary",
|
||||||
|
"sublabel": "Qualified client path",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "approve",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Approve revision",
|
||||||
|
"sublabel": "Exact digest + scope",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "publish",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Publish bundle",
|
||||||
|
"sublabel": "Data & AI catalog",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribute",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Verify effective state",
|
||||||
|
"sublabel": "Platform & IT",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "owner",
|
||||||
|
"to": "review",
|
||||||
|
"label": "submit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "review",
|
||||||
|
"to": "canary",
|
||||||
|
"label": "qualify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "canary",
|
||||||
|
"to": "approve",
|
||||||
|
"label": "Accept"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "approve",
|
||||||
|
"to": "publish",
|
||||||
|
"label": "record approval"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "publish",
|
||||||
|
"to": "distribute",
|
||||||
|
"label": "Deliver"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Independent approval",
|
||||||
|
"output": "static/diagrams/strategy-governance/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "owner",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Owner proposes",
|
||||||
|
"sublabel": "Existing accountable team",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "review",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Independent review",
|
||||||
|
"sublabel": "Quality + risk evidence",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "canary",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Bounded canary",
|
||||||
|
"sublabel": "Qualified client path",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "approve",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Approve revision",
|
||||||
|
"sublabel": "Exact digest + scope",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "publish",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Publish bundle",
|
||||||
|
"sublabel": "Data & AI catalog",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribute",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Verify effective state",
|
||||||
|
"sublabel": "Platform & IT",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "owner",
|
||||||
|
"to": "review",
|
||||||
|
"label": "submit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "review",
|
||||||
|
"to": "canary",
|
||||||
|
"label": "qualify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "canary",
|
||||||
|
"to": "approve",
|
||||||
|
"label": "Accept"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "approve",
|
||||||
|
"to": "publish",
|
||||||
|
"label": "record approval"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "publish",
|
||||||
|
"to": "distribute",
|
||||||
|
"label": "Deliver"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Skills before authority",
|
||||||
|
"output": "static/diagrams/strategy-journey-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "skills",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Govern skills",
|
||||||
|
"sublabel": "Owner + pinned revision",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "prove",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Prove quality",
|
||||||
|
"sublabel": "Independent evaluation",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Pilot with people",
|
||||||
|
"sublabel": "Qualified local clients",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribute",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Verify distribution",
|
||||||
|
"sublabel": "Canary + rollback",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordinate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Coordinate delivery",
|
||||||
|
"sublabel": "One logical SDLC agent",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expand",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Expand by evidence",
|
||||||
|
"sublabel": "Department outcomes",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "skills",
|
||||||
|
"to": "prove",
|
||||||
|
"label": "qualify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "prove",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "coach"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "distribute",
|
||||||
|
"label": "Verify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "distribute",
|
||||||
|
"to": "coordinate",
|
||||||
|
"label": "prove recovery"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "coordinate",
|
||||||
|
"to": "expand",
|
||||||
|
"label": "Justify"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Skills before authority",
|
||||||
|
"output": "static/diagrams/strategy-journey/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "skills",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Govern skills",
|
||||||
|
"sublabel": "Owner + pinned revision",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "prove",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Prove quality",
|
||||||
|
"sublabel": "Independent evaluation",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Pilot with people",
|
||||||
|
"sublabel": "Qualified local clients",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribute",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Verify distribution",
|
||||||
|
"sublabel": "Canary + rollback",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordinate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Coordinate delivery",
|
||||||
|
"sublabel": "One logical SDLC agent",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expand",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Expand by evidence",
|
||||||
|
"sublabel": "Department outcomes",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "skills",
|
||||||
|
"to": "prove",
|
||||||
|
"label": "qualify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "prove",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "coach"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "distribute",
|
||||||
|
"label": "Verify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "distribute",
|
||||||
|
"to": "coordinate",
|
||||||
|
"label": "prove recovery"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "coordinate",
|
||||||
|
"to": "expand",
|
||||||
|
"label": "Justify"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Maintain trust over time",
|
||||||
|
"output": "static/diagrams/strategy-maintenance-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "monitor",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Monitor skills",
|
||||||
|
"sublabel": "Usefulness + safety",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "triage",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Triage changes",
|
||||||
|
"sublabel": "Owner + risk review",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "correct",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Correct and test",
|
||||||
|
"sublabel": "Independent regression",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decision",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Approve or hold",
|
||||||
|
"sublabel": "Exact revised bundle",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "promote",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Promote safely",
|
||||||
|
"sublabel": "Verify state + monitor",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "observe",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Quarantine / rollback",
|
||||||
|
"sublabel": "Revoke unsafe revision",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "monitor",
|
||||||
|
"to": "triage",
|
||||||
|
"label": "Detect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "triage",
|
||||||
|
"to": "correct",
|
||||||
|
"label": "scope correction"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "correct",
|
||||||
|
"to": "decision",
|
||||||
|
"label": "Prove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "decision",
|
||||||
|
"to": "promote",
|
||||||
|
"label": "authorize"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "unsafe",
|
||||||
|
"from": "triage",
|
||||||
|
"to": "observe",
|
||||||
|
"label": "Unsafe",
|
||||||
|
"variant": "security",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "review-loop",
|
||||||
|
"from": "observe",
|
||||||
|
"to": "correct",
|
||||||
|
"label": "Requalify",
|
||||||
|
"variant": "dashed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Maintain trust over time",
|
||||||
|
"output": "static/diagrams/strategy-maintenance/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "monitor",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Monitor skills",
|
||||||
|
"sublabel": "Usefulness + safety",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "triage",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Triage changes",
|
||||||
|
"sublabel": "Owner + risk review",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "correct",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Correct and test",
|
||||||
|
"sublabel": "Independent regression",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decision",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Approve or hold",
|
||||||
|
"sublabel": "Exact revised bundle",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "promote",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Promote safely",
|
||||||
|
"sublabel": "Verify state + monitor",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "observe",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Quarantine / rollback",
|
||||||
|
"sublabel": "Revoke unsafe revision",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "monitor",
|
||||||
|
"to": "triage",
|
||||||
|
"label": "Detect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "triage",
|
||||||
|
"to": "correct",
|
||||||
|
"label": "scope correction"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "correct",
|
||||||
|
"to": "decision",
|
||||||
|
"label": "Prove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "decision",
|
||||||
|
"to": "promote",
|
||||||
|
"label": "authorize"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "unsafe",
|
||||||
|
"from": "triage",
|
||||||
|
"to": "observe",
|
||||||
|
"label": "Unsafe",
|
||||||
|
"variant": "security",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "review-loop",
|
||||||
|
"from": "observe",
|
||||||
|
"to": "correct",
|
||||||
|
"label": "Requalify",
|
||||||
|
"variant": "dashed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Evidence before claims",
|
||||||
|
"output": "static/diagrams/strategy-measurement-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "collect",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Collect evidence",
|
||||||
|
"sublabel": "Task / CI / incident",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "validate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Validate sources",
|
||||||
|
"sublabel": "Joins + missingness",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "calculate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Calculate measures",
|
||||||
|
"sublabel": "16 exact contracts",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "balance",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Read balanced signals",
|
||||||
|
"sublabel": "Quality / flow / risk",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "weigh",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Weigh benefit and cost",
|
||||||
|
"sublabel": "Outcomes / cost / people",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Continue or change",
|
||||||
|
"sublabel": "No causal ROI claim",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "collect",
|
||||||
|
"to": "validate",
|
||||||
|
"label": "Check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "validate",
|
||||||
|
"to": "calculate",
|
||||||
|
"label": "apply definitions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "calculate",
|
||||||
|
"to": "balance",
|
||||||
|
"label": "compare"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "balance",
|
||||||
|
"to": "weigh",
|
||||||
|
"label": "consider together"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "weigh",
|
||||||
|
"to": "decide",
|
||||||
|
"label": "decide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Evidence before claims",
|
||||||
|
"output": "static/diagrams/strategy-measurement/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "collect",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Collect evidence",
|
||||||
|
"sublabel": "Task / CI / incident",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "validate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Validate sources",
|
||||||
|
"sublabel": "Joins + missingness",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "calculate",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Calculate measures",
|
||||||
|
"sublabel": "16 exact contracts",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "balance",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Read balanced signals",
|
||||||
|
"sublabel": "Quality / flow / risk",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "weigh",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Weigh benefit and cost",
|
||||||
|
"sublabel": "Outcomes / cost / people",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Continue or change",
|
||||||
|
"sublabel": "No causal ROI claim",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "collect",
|
||||||
|
"to": "validate",
|
||||||
|
"label": "Check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "validate",
|
||||||
|
"to": "calculate",
|
||||||
|
"label": "apply definitions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "calculate",
|
||||||
|
"to": "balance",
|
||||||
|
"label": "compare"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "balance",
|
||||||
|
"to": "weigh",
|
||||||
|
"label": "consider together"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "weigh",
|
||||||
|
"to": "decide",
|
||||||
|
"label": "decide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Risk-tiered qualification",
|
||||||
|
"output": "static/diagrams/strategy-quality-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "risk",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Classify risk",
|
||||||
|
"sublabel": "R1 / R2 / R3",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "plan",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Agree evaluation",
|
||||||
|
"sublabel": "Task mix + thresholds",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "trial",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Repeat trials",
|
||||||
|
"sublabel": "Candidate vs approved",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "verify",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Verify artifacts",
|
||||||
|
"sublabel": "Independent checks",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gate",
|
||||||
|
"type": "security",
|
||||||
|
"label": "All gates pass?",
|
||||||
|
"sublabel": "Safety cannot be traded",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "promote",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Promote or hold",
|
||||||
|
"sublabel": "Owner decision",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "risk",
|
||||||
|
"to": "plan",
|
||||||
|
"label": "Scope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "plan",
|
||||||
|
"to": "trial",
|
||||||
|
"label": "freeze plan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "trial",
|
||||||
|
"to": "verify",
|
||||||
|
"label": "Assess"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "verify",
|
||||||
|
"to": "gate",
|
||||||
|
"label": "review evidence"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "gate",
|
||||||
|
"to": "promote",
|
||||||
|
"label": "decide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Risk-tiered qualification",
|
||||||
|
"output": "static/diagrams/strategy-quality/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "risk",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Classify risk",
|
||||||
|
"sublabel": "R1 / R2 / R3",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "plan",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Agree evaluation",
|
||||||
|
"sublabel": "Task mix + thresholds",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "trial",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Repeat trials",
|
||||||
|
"sublabel": "Candidate vs approved",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "verify",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Verify artifacts",
|
||||||
|
"sublabel": "Independent checks",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gate",
|
||||||
|
"type": "security",
|
||||||
|
"label": "All gates pass?",
|
||||||
|
"sublabel": "Safety cannot be traded",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "promote",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Promote or hold",
|
||||||
|
"sublabel": "Owner decision",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "risk",
|
||||||
|
"to": "plan",
|
||||||
|
"label": "Scope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "plan",
|
||||||
|
"to": "trial",
|
||||||
|
"label": "freeze plan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "trial",
|
||||||
|
"to": "verify",
|
||||||
|
"label": "Assess"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "verify",
|
||||||
|
"to": "gate",
|
||||||
|
"label": "review evidence"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "gate",
|
||||||
|
"to": "promote",
|
||||||
|
"label": "decide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Evidence-gated rollout",
|
||||||
|
"output": "static/diagrams/strategy-roadmap-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "foundation",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "1 \u00b7 Foundation",
|
||||||
|
"sublabel": "People + data + baseline",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "2 \u00b7 Skills pilot",
|
||||||
|
"sublabel": "Qualified, useful work",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribution",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "3 \u00b7 Distribution",
|
||||||
|
"sublabel": "Revocation + recovery",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordination",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "4 \u00b7 Coordination",
|
||||||
|
"sublabel": "Human takeover proven",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expansion",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "5 \u00b7 Departments",
|
||||||
|
"sublabel": "Outcomes + cost + risk",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "foundation",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "Charter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "distribution",
|
||||||
|
"label": "quality + coverage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "distribution",
|
||||||
|
"to": "coordination",
|
||||||
|
"label": "Controls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "coordination",
|
||||||
|
"to": "expansion",
|
||||||
|
"label": "authority drills pass"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: Evidence-gated rollout",
|
||||||
|
"output": "static/diagrams/strategy-roadmap/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "foundation",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "1 \u00b7 Foundation",
|
||||||
|
"sublabel": "People + data + baseline",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "2 \u00b7 Skills pilot",
|
||||||
|
"sublabel": "Qualified, useful work",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "distribution",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "3 \u00b7 Distribution",
|
||||||
|
"sublabel": "Revocation + recovery",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordination",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "4 \u00b7 Coordination",
|
||||||
|
"sublabel": "Human takeover proven",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
150
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "expansion",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "5 \u00b7 Departments",
|
||||||
|
"sublabel": "Outcomes + cost + risk",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
280
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "foundation",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "Charter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "distribution",
|
||||||
|
"label": "quality + coverage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "distribution",
|
||||||
|
"to": "coordination",
|
||||||
|
"label": "Controls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "coordination",
|
||||||
|
"to": "expansion",
|
||||||
|
"label": "authority drills pass"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: coordination without authority transfer",
|
||||||
|
"output": "static/diagrams/strategy-target-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "people",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "People authorize",
|
||||||
|
"sublabel": "Retain accountability",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordinator",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "SDLC coordinator",
|
||||||
|
"sublabel": "Routes approved work",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clients",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Local coding agents",
|
||||||
|
"sublabel": "Propose changes",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gates",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Repository + CI",
|
||||||
|
"sublabel": "Verify exact revision",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "registry",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Governed skills",
|
||||||
|
"sublabel": "Pinned + qualified",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "approval",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Human approval",
|
||||||
|
"sublabel": "Exact artifact + scope",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
620
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "release",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Release service",
|
||||||
|
"sublabel": "Production credentials",
|
||||||
|
"pos": [
|
||||||
|
40,
|
||||||
|
740
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "people",
|
||||||
|
"to": "coordinator",
|
||||||
|
"label": "Authorize scope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "coordinator",
|
||||||
|
"to": "clients",
|
||||||
|
"label": "Route tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "registry",
|
||||||
|
"to": "coordinator",
|
||||||
|
"label": "Guide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "registry",
|
||||||
|
"to": "clients",
|
||||||
|
"label": "Guide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "clients",
|
||||||
|
"to": "gates",
|
||||||
|
"label": "Propose"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-5",
|
||||||
|
"from": "gates",
|
||||||
|
"to": "approval",
|
||||||
|
"label": "Evidence"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-6",
|
||||||
|
"from": "approval",
|
||||||
|
"to": "release",
|
||||||
|
"label": "Authorize"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "TO-BE: coordination without authority transfer",
|
||||||
|
"output": "static/diagrams/strategy-target/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "people",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "People authorize",
|
||||||
|
"sublabel": "Retain accountability",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coordinator",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "SDLC coordinator",
|
||||||
|
"sublabel": "Routes approved work",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clients",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Local coding agents",
|
||||||
|
"sublabel": "Propose changes",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gates",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Repository + CI",
|
||||||
|
"sublabel": "Verify exact revision",
|
||||||
|
"pos": [
|
||||||
|
20,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "registry",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Governed skills",
|
||||||
|
"sublabel": "Pinned + qualified",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "approval",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Human approval",
|
||||||
|
"sublabel": "Exact artifact + scope",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "release",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Release service",
|
||||||
|
"sublabel": "Production credentials",
|
||||||
|
"pos": [
|
||||||
|
260,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
180,
|
||||||
|
60
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "flow-0",
|
||||||
|
"from": "people",
|
||||||
|
"to": "coordinator",
|
||||||
|
"label": "Authorize scope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-1",
|
||||||
|
"from": "coordinator",
|
||||||
|
"to": "clients",
|
||||||
|
"label": "Route tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-2",
|
||||||
|
"from": "registry",
|
||||||
|
"to": "coordinator",
|
||||||
|
"label": "Guide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-3",
|
||||||
|
"from": "registry",
|
||||||
|
"to": "clients",
|
||||||
|
"label": "Guide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-4",
|
||||||
|
"from": "clients",
|
||||||
|
"to": "gates",
|
||||||
|
"label": "Propose"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-5",
|
||||||
|
"from": "gates",
|
||||||
|
"to": "approval",
|
||||||
|
"label": "Evidence"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flow-6",
|
||||||
|
"from": "approval",
|
||||||
|
"to": "release",
|
||||||
|
"label": "Authorize"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,11 +3,28 @@ id: index
|
|||||||
title: AI adoption strategy
|
title: AI adoption strategy
|
||||||
description: Govern skills first; outcomes before activity; explicit target status.
|
description: Govern skills first; outcomes before activity; explicit target status.
|
||||||
slug: /
|
slug: /
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## How do we reach dependable AI-assisted work?
|
||||||
|
|
||||||
|
Start with governed skills, then widen coordination only when evidence supports it. The destination is one logical SDLC coordinator alongside people using qualified local coding agents.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-journey" title="Skills and quality evidence precede wider coordination" story />
|
||||||
|
|
||||||
|
- **Skills first:** reusable working knowledge, not permission to act.
|
||||||
|
- **People stay accountable:** the six departments and eleven teams keep their decisions.
|
||||||
|
- **Outcomes before activity:** quality, risk and total cost determine whether to continue.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Strategy rationale and reading map</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
### Govern skills first, expand authority only with evidence
|
### Govern skills first, expand authority only with evidence
|
||||||
@@ -30,4 +47,8 @@ Success means accepted outcomes with maintained quality, controlled risk and und
|
|||||||
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
|
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
|
||||||
- [Roadmap](./roadmap.mdx) — Evidence-gated phases, no promised dates or budgets.
|
- [Roadmap](./roadmap.mdx) — Evidence-gated phases, no promised dates or budgets.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [See how people, skills and delivery controls connect →](./target-operating-model.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,30 @@
|
|||||||
id: measurement
|
id: measurement
|
||||||
title: Measurement
|
title: Measurement
|
||||||
description: Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
|
description: Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## Is AI-assisted work worth continuing?
|
||||||
|
|
||||||
|
Judge accepted outcomes alongside quality, delivery flow, risk, cost and human experience. Validate source coverage before calculating; missing evidence is unknown, not success.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-measurement" title="Collect evidence, validate it, calculate balanced measures and decide" story />
|
||||||
|
|
||||||
|
**Illustrative only:** 1 accepted task ÷ 4 matured starts × 100 = **25%** confirmed success. One unresolved task stays in the denominator; known-outcome coverage is **75%**. These are synthetic data, not Eldorado results.
|
||||||
|
|
||||||
|
- **16 contracts:** exact definitions below; 9 prototype calculations, 7 explicitly unimplemented metrics.
|
||||||
|
- **Balanced evidence:** no productivity rankings, composite score or causal ROI claim.
|
||||||
|
- **Privacy first:** no raw prompts or code by default; protect small cohorts and agree retention before collection.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Collection, baseline, event and privacy contracts</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
### Decide what counts before counting
|
### Decide what counts before counting
|
||||||
@@ -33,6 +52,11 @@ Many-to-many task/attempt/skill/client associations preserve exact immutable ver
|
|||||||
|
|
||||||
The privacy starting proposal is 30 days for raw structured analytics events and 12 months for aggregated trends, subject to the responsible owners' review. Keep the approved catalog/approval record for the supported revision's lifetime and its required audit period, which must be decided separately. Incident evidence uses a restricted, explicitly authorized hold and deletion schedule, not an indefinite analytics exception. Suppress reports below five people and prohibit drill-down or overlapping cohort slices that reconstruct identities. Five is a proposed minimum, not a guarantee against re-identification. No raw prompts, code, screens, customer cases or secrets are collected by default. Publish the purpose, lawful collection basis, access/deletion route and retention before collecting. Consent is not presumed to be an appropriate employment-law basis.
|
The privacy starting proposal is 30 days for raw structured analytics events and 12 months for aggregated trends, subject to the responsible owners' review. Keep the approved catalog/approval record for the supported revision's lifetime and its required audit period, which must be decided separately. Incident evidence uses a restricted, explicitly authorized hold and deletion schedule, not an indefinite analytics exception. Suppress reports below five people and prohibit drill-down or overlapping cohort slices that reconstruct identities. Five is a proposed minimum, not a guarantee against re-identification. No raw prompts, code, screens, customer cases or secrets are collected by default. Publish the purpose, lawful collection basis, access/deletion route and retention before collecting. Consent is not presumed to be an appropriate employment-law basis.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>All 16 KPI contracts — formulas, populations, owners and limits</summary>
|
||||||
|
|
||||||
## Metric contracts
|
## Metric contracts
|
||||||
|
|
||||||
Each contract is a prospective collection design. No live source or observed baseline is established. N and D refer to the numerator and denominator shown for that metric.
|
Each contract is a prospective collection design. No live source or observed baseline is established. N and D refer to the numerator and denominator shown for that metric.
|
||||||
@@ -341,6 +365,11 @@ Independently accepted domain outcomes against a predeclared business rubric, se
|
|||||||
| Gaming and limits | Weaken rubric or count drafts as customer benefit; lock rubric and independently audit acceptance. Descriptive signal, not causal AI productivity attribution. Source completeness, task mix and sampling limit inference; report uncertainty. Domain owner signs acceptance: Operations service accuracy; Marketing claims/rights; Finance reconciliation accuracy; HR policy correctness; Product usability/value. Not revenue uplift. |
|
| Gaming and limits | Weaken rubric or count drafts as customer benefit; lock rubric and independently audit acceptance. Descriptive signal, not causal AI productivity attribution. Source completeness, task mix and sampling limit inference; report uncertainty. Domain owner signs acceptance: Operations service accuracy; Marketing claims/rights; Finance reconciliation accuracy; HR policy correctness; Product usability/value. Not revenue uplift. |
|
||||||
|
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Run the nine-metric synthetic prototype and inspect omissions</summary>
|
||||||
|
|
||||||
## Run the synthetic measurement example
|
## Run the synthetic measurement example
|
||||||
|
|
||||||
**Executed synthetic example — not Eldorado results.** The bundled fixture produces 1 independently accepted task from 4 matured starts: 25% confirmed success. One unresolved task remains in that denominator; known-outcome coverage is 75%. Selection precision and recall are each 1 / 2 = 50%. Allocated synthetic cost is EUR 60 / 1 accepted outcome = EUR 60 per accepted outcome. These deliberately small samples demonstrate arithmetic and missingness, not a baseline, target or ROI claim.
|
**Executed synthetic example — not Eldorado results.** The bundled fixture produces 1 independently accepted task from 4 matured starts: 25% confirmed success. One unresolved task remains in that denominator; known-outcome coverage is 75%. Selection precision and recall are each 1 / 2 = 50%. Allocated synthetic cost is EUR 60 / 1 accepted outcome = EUR 60 per accepted outcome. These deliberately small samples demonstrate arithmetic and missingness, not a baseline, target or ROI claim.
|
||||||
@@ -349,4 +378,8 @@ From the private documentation checkout, run `node scripts/ai-kpi.mjs` and `node
|
|||||||
|
|
||||||
The executable covers validated success, selection precision/recall, change fail and rework rates, escaped quality, policy effects, cost and human experience. Other catalog metrics remain contracts rather than implemented collectors; output lists the omissions. Snapshot inputs are simplified, pre-reconciled records, not a production ingestion system. Conflicting duplicates reject the calculation rather than silently choosing a value.
|
The executable covers validated success, selection precision/recall, change fail and rework rates, escaped quality, policy effects, cost and human experience. Other catalog metrics remain contracts rather than implemented collectors; output lists the omissions. Snapshot inputs are simplified, pre-reconciled records, not a production ingestion system. Conflicting duplicates reject the calculation rather than silently choosing a value.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Use findings to maintain, quarantine or replace skills →](./skills-maintenance.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,28 @@
|
|||||||
id: roadmap
|
id: roadmap
|
||||||
title: Roadmap
|
title: Roadmap
|
||||||
description: Evidence-gated phases, no promised dates or budgets.
|
description: Evidence-gated phases, no promised dates or budgets.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## What must be true before widening the rollout?
|
||||||
|
|
||||||
|
Advance by exit evidence, not promised dates or usage volume. Each stage can hold, narrow or stop; changed client, data or authority boundaries reopen earlier gates.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-roadmap" title="Foundation, pilot, reliable distribution, coordination and departmental expansion have exit gates" story />
|
||||||
|
|
||||||
|
- **Start bounded:** named people, lawful data handling and a reproducible baseline precede the pilot.
|
||||||
|
- **Prove recovery before coordination:** verified versions, revocation and human takeover are prerequisites.
|
||||||
|
- **Expand by department:** accepted outcomes, guardrails, total cost and experience justify continuation; sensitive decisions remain human.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Stage-by-stage entry evidence, work, exit gates and hold conditions</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
### Foundation
|
### Foundation
|
||||||
@@ -51,4 +68,8 @@ description: Evidence-gated phases, no promised dates or budgets.
|
|||||||
|
|
||||||
There are no invented launch dates, budgets, staffing commitments or guaranteed gains. Phase gates permit narrowing or stopping. Re-evaluate earlier phases when the underlying client, provider, data scope or authority changes.
|
There are no invented launch dates, budgets, staffing commitments or guaranteed gains. Phase gates permit narrowing or stopping. Re-evaluate earlier phases when the underlying client, provider, data scope or authority changes.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Return to the strategy destination →](./index.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,28 @@
|
|||||||
id: skills-adoption
|
id: skills-adoption
|
||||||
title: Skills adoption
|
title: Skills adoption
|
||||||
description: Workflow-led coaching, client choice, feedback, manual path.
|
description: Workflow-led coaching, client choice, feedback, manual path.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## When should a pilot become a team workflow?
|
||||||
|
|
||||||
|
Expand only when a bounded canary produces independently accepted work and useful feedback. Teach people to verify artifacts and recover without AI, not merely invoke a skill.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-adoption" title="Choose a workflow, coach a canary, verify outcomes and improve before expansion" story />
|
||||||
|
|
||||||
|
- **Team-led:** the departmental owner defines the outcome; People & Administration Squad supports learning.
|
||||||
|
- **Choice within support:** qualify the client path instead of promising identical agent behavior.
|
||||||
|
- **No adoption quotas:** retain a manual path; rejected suggestions and non-use are feedback, not poor performance.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Onboarding responsibilities, coaching and feedback safeguards</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
Start with a small set of useful workflows chosen by the existing teams. Product Management and the departmental owner identify the outcome; Data & AI helps turn it into a skill; Quality Engineering establishes acceptance; Platform & IT qualifies the client path; Architecture & Security clears the data boundary. People & Administration Squad coordinates learning and accessible feedback.
|
Start with a small set of useful workflows chosen by the existing teams. Product Management and the departmental owner identify the outcome; Data & AI helps turn it into a skill; Quality Engineering establishes acceptance; Platform & IT qualifies the client path; Architecture & Security clears the data boundary. People & Administration Squad coordinates learning and accessible feedback.
|
||||||
@@ -17,4 +34,8 @@ Use short worked examples, peer pairing, office hours and a clear catalog search
|
|||||||
|
|
||||||
No developer rankings, individual productivity scores, minimum invocation quotas or inference of effort from token counts are part of this strategy. Report cohort-level evidence with privacy protection and balanced quality, flow, risk and cost. A participant may reasonably stop using a skill that creates more work or uncertainty.
|
No developer rankings, individual productivity scores, minimum invocation quotas or inference of effort from token counts are part of this strategy. Report cohort-level evidence with privacy protection and balanced quality, flow, risk and cost. A participant may reasonably stop using a skill that creates more work or uncertainty.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Measure accepted outcomes, not activity →](./measurement.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,28 @@
|
|||||||
id: skills-governance
|
id: skills-governance
|
||||||
title: Skills governance
|
title: Skills governance
|
||||||
description: Contract, lifecycle, decision rights, adapters, locking, exceptions.
|
description: Contract, lifecycle, decision rights, adapters, locking, exceptions.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## Who can approve a skill for use?
|
||||||
|
|
||||||
|
The owning team authors the skill; independent reviewers assess it before exact-revision approval. Data & AI maintains the catalog, while Platform & IT verifies distribution and revocation.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-governance" title="An owner proposes; independent review and canary evidence precede approval" story />
|
||||||
|
|
||||||
|
- **Separate duties:** the author cannot provide the only approval; higher risk involves Architecture & Security.
|
||||||
|
- **Pin the whole bundle:** content, adapters and executable dependencies travel together.
|
||||||
|
- **Keep controls authoritative:** exceptions expire and cannot bypass protected release, payment or identity controls.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Ownership, client qualification, exceptions and rollback</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
### A contract that travels, controls that stay authoritative
|
### A contract that travels, controls that stay authoritative
|
||||||
@@ -33,6 +50,11 @@ A cached verified bundle may support explicitly permitted low-risk work if its m
|
|||||||
|
|
||||||
Rollback restores the approved manifest and dependencies, invalidates affected sessions, revokes unsafe revisions, runs a smoke test and verifies effective state. It cannot undo data disclosure or commands already executed. Those require incident response.
|
Rollback restores the approved manifest and dependencies, invalidates affected sessions, revokes unsafe revisions, runs a smoke test and verifies effective state. It cannot undo data disclosure or commands already executed. Those require incident response.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Catalog contract — required fields</summary>
|
||||||
|
|
||||||
## Catalog contract
|
## Catalog contract
|
||||||
|
|
||||||
| Contract | Definition |
|
| Contract | Definition |
|
||||||
@@ -59,6 +81,11 @@ Rollback restores the approved manifest and dependencies, invalidates affected s
|
|||||||
| procedure | Prerequisites, bounded steps, expected artifacts, verification, failure handling, escalation |
|
| procedure | Prerequisites, bounded steps, expected artifacts, verification, failure handling, escalation |
|
||||||
|
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Lifecycle transitions and required evidence</summary>
|
||||||
|
|
||||||
## Promotion and retirement
|
## Promotion and retirement
|
||||||
|
|
||||||
| Transition | Required evidence |
|
| Transition | Required evidence |
|
||||||
@@ -70,4 +97,8 @@ Rollback restores the approved manifest and dependencies, invalidates affected s
|
|||||||
| any active state → quarantined | Incident or unsafe/unknown provenance; central deny immediately |
|
| any active state → quarantined | Incident or unsafe/unknown provenance; central deny immediately |
|
||||||
| quarantined → experimental | Reviewed correction; new immutable revision; requalify, never auto-restore approval |
|
| quarantined → experimental | Reviewed correction; new immutable revision; requalify, never auto-restore approval |
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [See the evidence needed to qualify a skill →](./skills-quality.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,28 @@
|
|||||||
id: skills-maintenance
|
id: skills-maintenance
|
||||||
title: Skills maintenance
|
title: Skills maintenance
|
||||||
description: Review, drift, deprecation, rollback and incident handling.
|
description: Review, drift, deprecation, rollback and incident handling.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## What happens when a skill drifts or causes harm?
|
||||||
|
|
||||||
|
Monitor usefulness and safety throughout a revision's life. Unsafe behavior triggers containment; a correction returns through independent tests and approval, never automatic reinstatement.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-maintenance" title="Monitor, triage and test corrections; promote safely or contain and roll back" story />
|
||||||
|
|
||||||
|
- **Named ownership:** Data & AI coordinates catalog health with the owning teams.
|
||||||
|
- **Early triggers:** incidents and client, model or dependency changes override the calendar.
|
||||||
|
- **Recovery is verified:** rollback restores a known-good bundle; it cannot undo disclosure or past effects.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Review responsibilities, incident handling and proposed review intervals</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
Every approved skill has an accountable owning team, independent reviewer, review due date, supported client matrix and rollback bundle. Review both usefulness and safety, not just metadata freshness. Proposed maximum review intervals are recorded by risk tier; incidents, dependency changes, model/client drift or repeated failures trigger earlier review.
|
Every approved skill has an accountable owning team, independent reviewer, review due date, supported client matrix and rollback bundle. Review both usefulness and safety, not just metadata freshness. Proposed maximum review intervals are recorded by risk tier; incidents, dependency changes, model/client drift or repeated failures trigger earlier review.
|
||||||
@@ -25,4 +42,8 @@ Owner ratification is required before adoption. Review earlier after incidents o
|
|||||||
| R2 | 60 |
|
| R2 | 60 |
|
||||||
| R3 | 30 |
|
| R3 | 30 |
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Use exit evidence to choose the next rollout stage →](./roadmap.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,11 +2,28 @@
|
|||||||
id: skills-quality
|
id: skills-quality
|
||||||
title: Skills quality
|
title: Skills quality
|
||||||
description: Risk tiers, independent evaluation, repeated trials, adversarial conformance.
|
description: Risk tiers, independent evaluation, repeated trials, adversarial conformance.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## What evidence is enough to promote a skill?
|
||||||
|
|
||||||
|
Risk determines the evaluation depth, not whether safety checks apply. Independent evidence must show useful outcomes and no failed mandatory gate before promotion.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-quality" title="Classify risk, test independently, then pass every mandatory gate" story />
|
||||||
|
|
||||||
|
- **R1:** approved nonsensitive drafting. **R2:** code or customer-impacting material. **R3:** privileged or sensitive effects; human-authorized, outside initial autonomous scope.
|
||||||
|
- **No averaging away harm:** a critical unauthorized effect blocks promotion.
|
||||||
|
- **Proposed floors need owner ratification:** missing coverage or acceptance rules means qualification is incomplete.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Evaluation design, adversarial cases and interpretation</summary>
|
||||||
|
|
||||||
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
|
||||||
|
|
||||||
Quality has four separate questions: was the right skill selected, was the procedure executed safely, did the artifact pass independent checks, and did the workflow produce useful outcomes? A successful invocation answers none of the remaining questions by itself.
|
Quality has four separate questions: was the right skill selected, was the procedure executed safely, did the artifact pass independent checks, and did the workflow produce useful outcomes? A successful invocation answers none of the remaining questions by itself.
|
||||||
@@ -21,6 +38,11 @@ Include adversarial repository text, malicious referenced code, wrong permission
|
|||||||
|
|
||||||
Report denominators, task mix, trial counts, per-client results and uncertainty. A passing benchmark is evidence within a tested envelope, not proof that all future tasks are safe. Material model, client, adapter or dependency changes trigger requalification.
|
Report denominators, task mix, trial counts, per-client results and uncertainty. A passing benchmark is evidence within a tested envelope, not proof that all future tasks are safe. Material model, client, adapter or dependency changes trigger requalification.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Proposed R1 / R2 / R3 sample sizes and thresholds</summary>
|
||||||
|
|
||||||
## Proposed qualification floors
|
## Proposed qualification floors
|
||||||
|
|
||||||
These are local design defaults for responsible-owner ratification, not approved service levels or guarantees. All mandatory checks must pass regardless of aggregate score.
|
These are local design defaults for responsible-owner ratification, not approved service levels or guarantees. All mandatory checks must pass regardless of aggregate score.
|
||||||
@@ -57,4 +79,8 @@ These are local design defaults for responsible-owner ratification, not approved
|
|||||||
|
|
||||||
Artifact success denominator is every planned executed trial, retaining failures and abandonment. Trials of same task are correlated: show per-task and per-client strata; do not inflate independent sample size. Selection floors use independent labels. Report 95% uncertainty intervals clustered by task for outcome comparisons; no regression versus current approved path beyond a preregistered owner-approved margin. Missing margin/precision rule prevents promotion.
|
Artifact success denominator is every planned executed trial, retaining failures and abandonment. Trials of same task are correlated: show per-task and per-client strata; do not inflate independent sample size. Selection floors use independent labels. Report 95% uncertainty intervals clustered by task for outcome comparisons; no regression versus current approved path beyond a preregistered owner-approved margin. Missing margin/precision rule prevents promotion.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Introduce qualified skills through a bounded pilot →](./skills-adoption.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -2,12 +2,28 @@
|
|||||||
id: target-operating-model
|
id: target-operating-model
|
||||||
title: Target operating model
|
title: Target operating model
|
||||||
description: One logical coordinator; local client choice; independent authority; all departments.
|
description: One logical coordinator; local client choice; independent authority; all departments.
|
||||||
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
## Who coordinates, and who can authorize delivery?
|
||||||
|
|
||||||
|
One logical coordinator routes work; people retain authority. Local agents propose changes, while independent CI and human approval govern what the release service can execute.
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-target" title="People authorize; skills guide; independent gates protect release" story />
|
||||||
|
|
||||||
|
- **Local choice:** Copilot, Claude Code and Cline use qualified adapters and pinned skills.
|
||||||
|
- **Central controls:** neither laptops nor the coordinator hold production credentials.
|
||||||
|
- **Existing organization:** six departments, eleven teams; Data & AI owns coordination, not their decisions.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Trust boundaries, recovery and detailed delivery path</summary>
|
||||||
|
|
||||||
## Coordination without transferred authority
|
## Coordination without transferred authority
|
||||||
|
|
||||||
The diagram is an overview; the equivalent delivery path below remains readable on narrow screens. Expand the diagram to inspect its trust boundaries and use its zoom controls for individual relationships.
|
The diagram is an overview; the equivalent delivery path below remains readable on narrow screens. Expand the diagram to inspect its trust boundaries and use its zoom controls for individual relationships.
|
||||||
@@ -38,6 +54,11 @@ The registry distributes reviewed immutable content and adapters, not ambient cr
|
|||||||
|
|
||||||
Central controls verify protected-branch review, actual artifact identity, exact commit and policy revision, required checks and a scoped human approval. Candidate changes cannot edit their own authoritative gate or reuse approval for a different artifact. Deployment credentials belong to the release service, not the local agent. Approval expires or is invalidated by changed content. Emergency stop revokes mutation credentials and stops scheduling independently of the model, preserves evidence and enables human takeover.
|
Central controls verify protected-branch review, actual artifact identity, exact commit and policy revision, required checks and a scoped human approval. Candidate changes cannot edit their own authoritative gate or reuse approval for a different artifact. Deployment credentials belong to the release service, not the local agent. Approval expires or is invalidated by changed content. Emergency stop revokes mutation credentials and stops scheduling independently of the model, preserves evidence and enables human takeover.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Responsibilities and first workflows for all eleven teams</summary>
|
||||||
|
|
||||||
### Department contributions
|
### Department contributions
|
||||||
|
|
||||||
### Product / Product Management
|
### Product / Product Management
|
||||||
@@ -110,4 +131,8 @@ Product keeps two teams; Technology keeps five; the other four departments keep
|
|||||||
|
|
||||||
See the existing [organization structure](/organization/structure/), [department collaboration](/organization/collaboration/) and [SDLC responsibilities](/organization/sdlc/).
|
See the existing [organization structure](/organization/structure/), [department collaboration](/organization/collaboration/) and [SDLC responsibilities](/organization/sdlc/).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [Decide who owns and approves each skill →](./skills-governance.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
+8
-1
@@ -15,11 +15,13 @@
|
|||||||
"verify:build": "node scripts/verify.mjs --build",
|
"verify:build": "node scripts/verify.mjs --build",
|
||||||
"diagrams:build": "node scripts/build-diagrams.mjs",
|
"diagrams:build": "node scripts/build-diagrams.mjs",
|
||||||
"test": "node --test scripts/*.test.mjs",
|
"test": "node --test scripts/*.test.mjs",
|
||||||
|
"test:browser": "node scripts/browser/strategy-story.cjs && node scripts/browser/inline-controls.cjs",
|
||||||
"kpi:example": "node scripts/ai-kpi.mjs"
|
"kpi:example": "node scripts/ai-kpi.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.10.2",
|
"@docusaurus/core": "3.10.2",
|
||||||
"@docusaurus/preset-classic": "3.10.2",
|
"@docusaurus/preset-classic": "3.10.2",
|
||||||
|
"@docusaurus/theme-common": "3.10.2",
|
||||||
"@easyops-cn/docusaurus-search-local": "0.55.3",
|
"@easyops-cn/docusaurus-search-local": "0.55.3",
|
||||||
"@fontsource/lato": "5.2.6",
|
"@fontsource/lato": "5.2.6",
|
||||||
"@mdx-js/react": "3.1.1",
|
"@mdx-js/react": "3.1.1",
|
||||||
@@ -33,9 +35,14 @@
|
|||||||
"@docusaurus/tsconfig": "3.10.2",
|
"@docusaurus/tsconfig": "3.10.2",
|
||||||
"@docusaurus/types": "3.10.2",
|
"@docusaurus/types": "3.10.2",
|
||||||
"@types/react": "19.1.13",
|
"@types/react": "19.1.13",
|
||||||
|
"playwright": "1.63.0",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
"pnpm": {"overrides": {"serialize-javascript": "7.0.5"}},
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"serialize-javascript": "7.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.5%",
|
">0.5%",
|
||||||
|
|||||||
Generated
+22
@@ -17,6 +17,9 @@ importers:
|
|||||||
'@docusaurus/preset-classic':
|
'@docusaurus/preset-classic':
|
||||||
specifier: 3.10.2
|
specifier: 3.10.2
|
||||||
version: 3.10.2(@algolia/client-search@5.59.0)(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(search-insights@2.17.3)(typescript@5.9.3)
|
version: 3.10.2(@algolia/client-search@5.59.0)(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(search-insights@2.17.3)(typescript@5.9.3)
|
||||||
|
'@docusaurus/theme-common':
|
||||||
|
specifier: 3.10.2
|
||||||
|
version: 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
'@easyops-cn/docusaurus-search-local':
|
'@easyops-cn/docusaurus-search-local':
|
||||||
specifier: 0.55.3
|
specifier: 0.55.3
|
||||||
version: 0.55.3(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
|
version: 0.55.3(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
|
||||||
@@ -51,6 +54,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 19.1.13
|
specifier: 19.1.13
|
||||||
version: 19.1.13
|
version: 19.1.13
|
||||||
|
playwright:
|
||||||
|
specifier: 1.63.0
|
||||||
|
version: 1.63.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.9.3
|
specifier: 5.9.3
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
@@ -3962,6 +3968,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-Oo/NZcSWccq8KyoG7gLE9fnltgHns+pNCjCAp/WmjsUySi+sX7y4z4Xqu4fVb42CDHzRPl33fjzT15V1wvcyhA==}
|
resolution: {integrity: sha512-Oo/NZcSWccq8KyoG7gLE9fnltgHns+pNCjCAp/WmjsUySi+sX7y4z4Xqu4fVb42CDHzRPl33fjzT15V1wvcyhA==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
|
|
||||||
|
playwright-core@1.63.0:
|
||||||
|
resolution: {integrity: sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
playwright@1.63.0:
|
||||||
|
resolution: {integrity: sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
postcss-attribute-case-insensitive@7.0.1:
|
postcss-attribute-case-insensitive@7.0.1:
|
||||||
resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==}
|
resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -10793,6 +10809,12 @@ snapshots:
|
|||||||
pvutils: 1.2.0
|
pvutils: 1.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
playwright-core@1.63.0: {}
|
||||||
|
|
||||||
|
playwright@1.63.0:
|
||||||
|
dependencies:
|
||||||
|
playwright-core: 1.63.0
|
||||||
|
|
||||||
postcss-attribute-case-insensitive@7.0.1(postcss@8.5.28):
|
postcss-attribute-case-insensitive@7.0.1(postcss@8.5.28):
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss: 8.5.28
|
postcss: 8.5.28
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
const {chromium} = require('playwright');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
(async () => {
|
||||||
|
const base = process.argv[2] || 'http://127.0.0.1:4173';
|
||||||
|
const output = `.cache/inline-${process.argv[3] || 'local'}`;
|
||||||
|
fs.mkdirSync(output, {recursive: true});
|
||||||
|
const browser = await chromium.launch({headless: true, executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args: ['--no-sandbox']});
|
||||||
|
const results = [];
|
||||||
|
try {
|
||||||
|
for (const width of [1440, 390, 320]) {
|
||||||
|
const context = await browser.newContext({viewport: {width, height: 1000}, colorScheme: 'light'});
|
||||||
|
const page = await context.newPage();
|
||||||
|
await page.goto(`${base}/eldorado-v1/documentation/strategy/`, {waitUntil: 'networkidle'});
|
||||||
|
const panel = page.locator('.archify-panel--story');
|
||||||
|
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
|
||||||
|
await iframe.scrollIntoViewIfNeeded();
|
||||||
|
const frame = await (await iframe.elementHandle()).contentFrame();
|
||||||
|
const theme = async value => {
|
||||||
|
await page.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
||||||
|
await frame.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
||||||
|
};
|
||||||
|
await theme('light');
|
||||||
|
for (const id of ['btn-theme', 'btn-preset', 'btn-export']) {
|
||||||
|
const box = await frame.locator(`#${id}`).boundingBox();
|
||||||
|
assert(box && box.width >= 40 && box.height >= 44, id);
|
||||||
|
}
|
||||||
|
const toolbar = await frame.locator('.toolbar').boundingBox();
|
||||||
|
const exportButton = await frame.locator('#btn-export').boundingBox();
|
||||||
|
const diagram = await frame.locator('.diagram-container > svg').boundingBox();
|
||||||
|
const rightGap = toolbar.x + toolbar.width - exportButton.x - exportButton.width;
|
||||||
|
assert(Math.abs(rightGap - 8) < 1, `toolbar right padding at ${width}: ${rightGap}`);
|
||||||
|
assert(diagram.y >= toolbar.y + toolbar.height, 'toolbar must stay above nodes');
|
||||||
|
const checkMenu = async selector => {
|
||||||
|
await frame.locator(selector).evaluate(n => Promise.all(n.getAnimations().map(a => a.finished)));
|
||||||
|
const menu = await frame.locator(selector).boundingBox();
|
||||||
|
const viewport = await iframe.boundingBox();
|
||||||
|
const currentToolbar = await frame.locator('.toolbar').boundingBox();
|
||||||
|
assert(menu && menu.x >= viewport.x - 1 && menu.y >= currentToolbar.y + currentToolbar.height - 1, selector);
|
||||||
|
assert(menu.x + menu.width <= viewport.x + viewport.width + 1, `${selector} clips horizontally`);
|
||||||
|
assert(menu.y + menu.height <= viewport.y + viewport.height + 1, `${selector} clips vertically`);
|
||||||
|
};
|
||||||
|
const light = await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor);
|
||||||
|
await frame.locator('#btn-theme').click(); await theme('dark');
|
||||||
|
assert.notEqual(await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor), light);
|
||||||
|
await frame.locator('#btn-theme').click(); await theme('light');
|
||||||
|
// Mobile portal theme control lives in the navigation drawer.
|
||||||
|
const portalTheme = async target => {
|
||||||
|
if (width <= 700) await page.getByRole('button', {name: 'Toggle navigation bar'}).click();
|
||||||
|
for (let attempt = 0; attempt < 3; attempt++) {
|
||||||
|
await page.getByRole('button', {name: /Switch between dark and light mode/}).filter({visible: true}).click();
|
||||||
|
if (await page.locator('html').getAttribute('data-theme') === target) break;
|
||||||
|
}
|
||||||
|
if (width <= 700) await page.getByRole('button', {name: 'Close navigation bar'}).click();
|
||||||
|
};
|
||||||
|
await portalTheme('dark'); await theme('dark');
|
||||||
|
await portalTheme('light'); await theme('light');
|
||||||
|
for (const preset of ['signal-flow', 'blueprint', 'editorial', 'classic']) {
|
||||||
|
await frame.locator('#btn-preset').click();
|
||||||
|
await checkMenu('.preset-menu');
|
||||||
|
await frame.locator(`[data-preset-value="${preset}"]`).click();
|
||||||
|
assert.equal(await frame.locator('html').getAttribute('data-preset'), preset);
|
||||||
|
}
|
||||||
|
// A theme change must not reload the iframe or lose the selected visual preset.
|
||||||
|
await frame.locator('#btn-preset').click();
|
||||||
|
await frame.locator('[data-preset-value="blueprint"]').click();
|
||||||
|
await portalTheme('dark'); await theme('dark');
|
||||||
|
assert.equal(await frame.locator('html').getAttribute('data-preset'), 'blueprint');
|
||||||
|
const exports = [];
|
||||||
|
for (const format of ['png', 'jpeg', 'webp', 'svg', 'svg-light', 'svg-dark', 'webm']) {
|
||||||
|
await frame.locator('#btn-export').click();
|
||||||
|
await checkMenu('.export-menu');
|
||||||
|
if (format === 'webm' && await frame.locator('[data-format="webm"]').isDisabled()) {
|
||||||
|
exports.push({format, unsupported: true});
|
||||||
|
await frame.locator('#btn-export').click();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log(`Export ${width} ${format}`);
|
||||||
|
const [download] = await Promise.all([
|
||||||
|
page.waitForEvent('download', {timeout: 60000}),
|
||||||
|
frame.locator(`[data-format="${format}"]`).click(),
|
||||||
|
]);
|
||||||
|
assert.equal(await download.failure(), null);
|
||||||
|
const path = `${output}/${width}-${format}-${download.suggestedFilename()}`;
|
||||||
|
await download.saveAs(path);
|
||||||
|
const bytes = fs.readFileSync(path);
|
||||||
|
assert(bytes.length > 1000);
|
||||||
|
if (format.startsWith('svg')) {
|
||||||
|
const valid = await page.evaluate(xml => {
|
||||||
|
const doc = new DOMParser().parseFromString(xml, 'image/svg+xml');
|
||||||
|
return !doc.querySelector('parsererror') && doc.documentElement.localName === 'svg' && doc.querySelectorAll('text').length > 0;
|
||||||
|
}, bytes.toString());
|
||||||
|
assert(valid, format);
|
||||||
|
} else {
|
||||||
|
const mime = {png:'image/png', jpeg:'image/jpeg', webp:'image/webp', webm:'video/webm'}[format];
|
||||||
|
const dimensions = await page.evaluate(async ({data, mime}) => {
|
||||||
|
const media = document.createElement(mime.startsWith('video') ? 'video' : 'img');
|
||||||
|
const loaded = new Promise((resolve, reject) => {media[mime.startsWith('video') ? 'onloadedmetadata' : 'onload'] = resolve; media.onerror = reject;});
|
||||||
|
media.src = `data:${mime};base64,${data}`; await loaded;
|
||||||
|
return [media.videoWidth || media.naturalWidth, media.videoHeight || media.naturalHeight];
|
||||||
|
}, {data: bytes.toString('base64'), mime});
|
||||||
|
assert(dimensions.every(n => n > 0), format);
|
||||||
|
}
|
||||||
|
exports.push({format, path, bytes:bytes.length});
|
||||||
|
}
|
||||||
|
const opener = panel.getByRole('button', {name:/^Expand /});
|
||||||
|
await opener.click();
|
||||||
|
let full = await (await panel.locator('dialog iframe').elementHandle()).contentFrame();
|
||||||
|
await full.waitForFunction(() => document.documentElement.dataset.theme === 'dark');
|
||||||
|
await full.locator('#btn-theme').click(); await theme('light');
|
||||||
|
const close = panel.getByRole('button', {name:'Close full-screen diagram'});
|
||||||
|
assert.equal(await close.innerText(), '×');
|
||||||
|
await close.click(); assert(await opener.evaluate(n => n === document.activeElement));
|
||||||
|
await opener.click();
|
||||||
|
full = await (await panel.locator('dialog iframe').elementHandle()).contentFrame();
|
||||||
|
await full.waitForFunction(() => document.documentElement.dataset.theme === 'light');
|
||||||
|
await close.focus(); await page.keyboard.press('Escape');
|
||||||
|
assert(await opener.evaluate(n => n === document.activeElement));
|
||||||
|
await iframe.scrollIntoViewIfNeeded();
|
||||||
|
await page.evaluate(() => scrollTo(0, 0));
|
||||||
|
await page.screenshot({path:`${output}/${width}.png`, fullPage:true});
|
||||||
|
await frame.locator('#btn-theme').click(); await theme('dark');
|
||||||
|
await page.locator('.strategy-content a[href$="/strategy/target-operating-model/"]').filter({visible:true}).click();
|
||||||
|
const next = page.locator(`.archify-panel--story[data-diagram="strategy-target"] > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
||||||
|
await next.scrollIntoViewIfNeeded();
|
||||||
|
await (await (await next.elementHandle()).contentFrame()).waitForFunction(() => document.documentElement.dataset.theme === 'dark');
|
||||||
|
assert(!await page.evaluate(() => document.documentElement.scrollWidth > innerWidth));
|
||||||
|
results.push({width, toolbar, rightGap, dropdownsUnclipped:true, themeSync:true, presets:4, exports, fullscreen:true, routeTheme:true});
|
||||||
|
fs.writeFileSync(`${output}/results.json`, JSON.stringify(results,null,2));
|
||||||
|
await context.close();
|
||||||
|
}
|
||||||
|
console.log(`PASS ${results.length} viewports: bidirectional themes, 4 presets, all supported exports decoded, fullscreen and route persistence`);
|
||||||
|
} finally {await browser.close();}
|
||||||
|
})().catch(error => {console.error(error); process.exitCode = 1;});
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
const {chromium}=require('playwright');
|
||||||
|
const assert=require('node:assert/strict');
|
||||||
|
const fs=require('node:fs');
|
||||||
|
(async()=>{
|
||||||
|
const base=process.argv[2]||'http://127.0.0.1:4173';
|
||||||
|
const label=process.argv[3]||'accepted';
|
||||||
|
const browser=await chromium.launch({headless:true,executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});
|
||||||
|
const results=[];fs.mkdirSync(`.cache/story-${label}`,{recursive:true});
|
||||||
|
try{
|
||||||
|
for(const width of [1440,390]){
|
||||||
|
const context=await browser.newContext({viewport:{width,height:1000}});
|
||||||
|
const page=await context.newPage();
|
||||||
|
for(const id of ['index','target-operating-model','skills-governance','skills-quality','skills-adoption','measurement','skills-maintenance','roadmap']){
|
||||||
|
const response=await page.goto(`${base}/eldorado-v1/documentation/strategy/${id==='index'?'':id+'/'}`,{waitUntil:'networkidle'});assert.equal(response.status(),200);
|
||||||
|
const panel=page.locator('.archify-panel--story');
|
||||||
|
const iframe=panel.locator(width===390?'.story-mobile':'.story-desktop');await iframe.scrollIntoViewIfNeeded();
|
||||||
|
const frame=await (await iframe.elementHandle()).contentFrame();await frame.locator('svg[role="img"]').waitFor();
|
||||||
|
const geometry=await frame.locator('svg[role="img"]').evaluate(svg=>{
|
||||||
|
const nodes=[...svg.querySelectorAll('[data-node-id]')].map(n=>{const r=n.getBoundingClientRect();return {id:n.id,x:r.x,y:r.y,right:r.right,bottom:r.bottom};});
|
||||||
|
return {width:innerWidth,height:innerHeight,nodes,svg:svg.getBoundingClientRect().toJSON(),minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n=>parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))};
|
||||||
|
});
|
||||||
|
assert(geometry.nodes.length>=5 && geometry.nodes.length<=7,id);
|
||||||
|
for(const n of geometry.nodes) assert(n.x>=0 && n.y>=0 && n.right<=geometry.width+1 && n.bottom<=geometry.height+1,`${id} ${width} clipped ${JSON.stringify(n)} / ${geometry.height}`);
|
||||||
|
const data=await page.locator('.strategy-content').evaluate(el=>({words:el.innerText.trim().split(/\s+/).length,overflow:document.documentElement.scrollWidth>innerWidth,openDetails:el.querySelectorAll('details[open]').length}));
|
||||||
|
assert(data.words<=200,id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
|
||||||
|
await page.evaluate(()=>scrollTo(0,0));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true});
|
||||||
|
const opener=panel.getByRole('button',{name:/^Expand /});await opener.click();
|
||||||
|
const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
|
||||||
|
assert.equal(await close.innerText(),'×');assert(await close.evaluate(n=>n===document.activeElement));
|
||||||
|
const box=await close.boundingBox();assert.equal(box.width,44);assert.equal(box.height,44);
|
||||||
|
await close.click();assert(await opener.evaluate(n=>n===document.activeElement));
|
||||||
|
await opener.click();await close.waitFor({state:'visible'});await page.keyboard.press('Escape');await page.waitForFunction(()=>!document.querySelector('.archify-panel--story dialog').open);assert(await opener.evaluate(n=>n===document.activeElement));
|
||||||
|
const summary=page.locator('.strategy-content > details > summary').first();await summary.click();assert(await summary.evaluate(n=>n.parentElement.open));await summary.click();
|
||||||
|
results.push({id,width,...data,geometry,modalClick:true,modalEscape:true,focusRestored:true,details:true});fs.writeFileSync(`.cache/story-${label}/results.json`,JSON.stringify(results,null,2));
|
||||||
|
}
|
||||||
|
await page.goto(`${base}/eldorado-v1/documentation/strategy/measurement/#validated-task-success`,{waitUntil:'networkidle'});
|
||||||
|
const heading=page.locator('#validated-task-success');await heading.waitFor({state:'visible'});
|
||||||
|
assert(await heading.evaluate(n=>n.closest('details').open),'hash should open metric reference');
|
||||||
|
await context.close();
|
||||||
|
}
|
||||||
|
console.log(`PASS ${results.length} desktop/mobile cases, clipping, default word count, details, modal click/Escape/focus and KPI hash navigation`);
|
||||||
|
} finally {await browser.close();}
|
||||||
|
})().catch(e=>{console.error(e);process.exitCode=1});
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import {readdirSync, readFileSync, mkdirSync, copyFileSync, renameSync, rmSync} from 'node:fs';
|
import {readdirSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, renameSync, rmSync} from 'node:fs';
|
||||||
import {join} from 'node:path';
|
import {join} from 'node:path';
|
||||||
import {execFileSync} from 'node:child_process';
|
import {execFileSync} from 'node:child_process';
|
||||||
const cli = 'vendor/archify/bin/archify.mjs';
|
const cli = 'vendor/archify/bin/archify.mjs';
|
||||||
const types = new Set(['architecture','workflow','sequence','dataflow','lifecycle']);
|
const types = new Set(['architecture','workflow','sequence','dataflow','lifecycle']);
|
||||||
|
const inlineStyles = readFileSync(new URL('./inline-viewer.css', import.meta.url), 'utf8');
|
||||||
|
const themeBridge = readFileSync(new URL('./viewer-theme-bridge.js', import.meta.url), 'utf8');
|
||||||
// This directory is generated-only and ignored by Git. Remove stale artifacts.
|
// This directory is generated-only and ignored by Git. Remove stale artifacts.
|
||||||
rmSync('static/diagrams', {recursive: true, force: true});
|
rmSync('static/diagrams', {recursive: true, force: true});
|
||||||
mkdirSync('static/diagrams', {recursive: true});
|
mkdirSync('static/diagrams', {recursive: true});
|
||||||
@@ -23,6 +25,19 @@ for (const file of readdirSync('diagrams').sort()) {
|
|||||||
run(['validate',type,input,'--quality','showcase','--json']);
|
run(['validate',type,input,'--quality','showcase','--json']);
|
||||||
run(['deliver',type,input,output,'--quality','showcase','--json']);
|
run(['deliver',type,input,output,'--quality','showcase','--json']);
|
||||||
run(['check',output,'--json','--require-provenance']);
|
run(['check',output,'--json','--require-provenance']);
|
||||||
|
// Verify the upstream artifact first, then add the scoped portal integration.
|
||||||
|
let viewer = readFileSync(output, 'utf8');
|
||||||
|
// Upstream intentionally disables preset selection in gallery embeds. Enable
|
||||||
|
// only those two guards; fail closed if a future vendor update changes them.
|
||||||
|
const start = viewer.indexOf('Archify.preset = (function () {');
|
||||||
|
const end = viewer.indexOf('Archify.theme = (function () {', start);
|
||||||
|
const preset = viewer.slice(start, end);
|
||||||
|
const guard = "if (html.getAttribute('data-embed') === 'true') return false;";
|
||||||
|
if (start < 0 || end < start || preset.split(guard).length !== 3) throw new Error('Archify preset integration drift');
|
||||||
|
viewer = viewer.slice(0, start) + preset.replaceAll(guard, '') + viewer.slice(end);
|
||||||
|
if (!viewer.includes('</head>') || !viewer.includes('</body>')) throw new Error(`Invalid viewer: ${output}`);
|
||||||
|
writeFileSync(output, viewer.replace('</head>', `<style id="eldorado-inline-controls">${inlineStyles}</style></head>`)
|
||||||
|
.replace('</body>', `<script>${themeBridge}</script></body>`));
|
||||||
renameSync(`static/diagrams/${name}/index.delivery.json`, `.cache/archify/${name}.delivery.json`);
|
renameSync(`static/diagrams/${name}/index.delivery.json`, `.cache/archify/${name}.delivery.json`);
|
||||||
}
|
}
|
||||||
copyFileSync('vendor/archify/LICENSE','static/diagrams/ARCHIFY-LICENSE.txt');
|
copyFileSync('vendor/archify/LICENSE','static/diagrams/ARCHIFY-LICENSE.txt');
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/* Portal integration only; keep the upstream renderer and export code pinned. */
|
||||||
|
html[data-embed="true"] .toolbar {
|
||||||
|
display: flex !important;
|
||||||
|
position: relative;
|
||||||
|
inset: auto;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 52px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
html[data-embed="true"] #btn-present,
|
||||||
|
html[data-embed="true"] #btn-motion { display: none !important; }
|
||||||
|
html[data-embed="true"] .diagram-container > svg {
|
||||||
|
max-height: calc(100vh - 68px);
|
||||||
|
}
|
||||||
|
html[data-embed="true"] .toolbar .preset-menu,
|
||||||
|
html[data-embed="true"] .toolbar .export-menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 52px;
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
width: min(320px, 100vw);
|
||||||
|
max-width: 100vw;
|
||||||
|
max-height: calc(100vh - 52px);
|
||||||
|
overflow-y: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
/* Keep the preset menu in the iframe viewport without moving its capsule. */
|
||||||
|
html[data-embed="true"] .toolbar .export-wrap { position: static; }
|
||||||
|
html[data-embed="true"] .toolbar .export-menu { position: absolute; top: 100%; }
|
||||||
|
html[data-embed="true"] .toolbar .preset-menu button,
|
||||||
|
html[data-embed="true"] .toolbar .export-menu button { min-height: 44px; }
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import {test} from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
import {runInNewContext} from 'node:vm';
|
||||||
|
const read = path => readFileSync(path, 'utf8');
|
||||||
|
|
||||||
|
test('both story layouts permit downloads without weakening origin isolation', () => {
|
||||||
|
const wrapper = read('src/components/ArchifyDiagram/index.tsx');
|
||||||
|
for (const layout of ['desktop', 'mobile']) {
|
||||||
|
const iframe = wrapper.split(`<iframe className="story-${layout}"`)[1].split(' />')[0];
|
||||||
|
assert(iframe.includes('sandbox="allow-scripts allow-downloads"'));
|
||||||
|
assert(iframe.includes('?embed=1&theme=${initialTheme.current}'));
|
||||||
|
}
|
||||||
|
assert(!wrapper.includes('allow-same-origin'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('build adds maintained embed-only controls without changing pinned vendor', () => {
|
||||||
|
const build = read('scripts/build-diagrams.mjs');
|
||||||
|
assert(build.includes("new URL('./inline-viewer.css', import.meta.url)"));
|
||||||
|
assert(build.includes('eldorado-inline-controls'));
|
||||||
|
const css = read('scripts/inline-viewer.css');
|
||||||
|
assert(css.includes('html[data-embed="true"] .toolbar'));
|
||||||
|
assert(css.includes('display: flex !important'));
|
||||||
|
assert(css.includes('position: relative'));
|
||||||
|
assert(css.includes('max-height: calc(100vh - 52px)'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('theme bridge rejects unrelated senders/values and never echoes parent updates', () => {
|
||||||
|
const root = {dataset:{theme:'light'}};
|
||||||
|
let receive, observerCallback, mutations = 0;
|
||||||
|
const messages = [];
|
||||||
|
const parent = {postMessage: message => messages.push(message)};
|
||||||
|
const window = {parent, addEventListener: (type, callback) => {receive = callback;}};
|
||||||
|
const button = {click: () => {root.dataset.theme = root.dataset.theme === 'light' ? 'dark' : 'light'; mutations++;}};
|
||||||
|
class MutationObserver {
|
||||||
|
constructor(callback) {observerCallback = callback;}
|
||||||
|
observe() {}
|
||||||
|
takeRecords() {mutations = 0;}
|
||||||
|
}
|
||||||
|
runInNewContext(read('scripts/viewer-theme-bridge.js'), {window, document:{documentElement:root, getElementById: () => button}, MutationObserver});
|
||||||
|
const send = (source, theme) => receive({source, data:{type:'eldorado:set-theme', theme}});
|
||||||
|
send({}, 'dark'); send(parent, 'invalid');
|
||||||
|
assert.equal(root.dataset.theme, 'light');
|
||||||
|
send(parent, 'dark');
|
||||||
|
assert.equal(root.dataset.theme, 'dark');
|
||||||
|
assert.equal(mutations, 0);
|
||||||
|
assert.equal(messages.length, 0);
|
||||||
|
button.click(); observerCallback();
|
||||||
|
assert.equal(messages.length, 1);
|
||||||
|
assert.equal(messages[0].theme, 'light');
|
||||||
|
});
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import {test} from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
const read = p => readFileSync(p, 'utf8');
|
||||||
|
const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
|
||||||
|
|
||||||
|
test('every strategy page leads with a compact diagram story and closes its references', () => {
|
||||||
|
for (const {id} of model.pages) {
|
||||||
|
const page = read(`docs/strategy/${id}.mdx`);
|
||||||
|
const narrative = page.split('<div className="strategy-content">')[1].replace(/<details>[\s\S]*?<\/details>/g, '');
|
||||||
|
assert.equal((narrative.match(/<ArchifyDiagram /g) || []).length, 1, id);
|
||||||
|
assert(narrative.includes(' story />'), id);
|
||||||
|
assert(page.indexOf(' story />') < page.indexOf('<details>'), id);
|
||||||
|
assert(!/<details\s+open/.test(page), id);
|
||||||
|
assert.equal((page.match(/<details>/g) || []).length, (page.match(/<\/details>/g) || []).length, id);
|
||||||
|
assert.equal((narrative.match(/^## /gm) || []).length, 1, id);
|
||||||
|
assert((narrative.match(/^- /gm) || []).length <= 3, id);
|
||||||
|
assert(narrative.includes('**Next:**'), id);
|
||||||
|
assert(!narrative.includes('| ---'), id);
|
||||||
|
const words = narrative.replace(/<[^>]*>/g, '').trim().split(/\s+/).length;
|
||||||
|
assert(words <= 200, `${id}: ${words} default narrative words`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('mobile story diagrams preserve the same nodes and directed relationships', () => {
|
||||||
|
for (const {id} of model.pages) {
|
||||||
|
const page = read(`docs/strategy/${id}.mdx`);
|
||||||
|
const name = /<ArchifyDiagram name="([^"]+)"[^>]+ story/.exec(page)[1];
|
||||||
|
const desktop = JSON.parse(read(`diagrams/${name}.architecture.json`));
|
||||||
|
const mobile = JSON.parse(read(`diagrams/${name}-mobile.architecture.json`));
|
||||||
|
assert(desktop.components.length >= 5 && desktop.components.length <= 7, name);
|
||||||
|
const semantic = d => ({nodes:d.components.map(({pos,size,...n})=>n),edges:d.connections.map(({fromSide,toSide,...e})=>e)});
|
||||||
|
assert.deepEqual(semantic(desktop), semantic(mobile), name);
|
||||||
|
assert(desktop.connections.every(e => e.label && e.from !== e.to), name);
|
||||||
|
assert.equal(desktop.meta.legend.mode, 'hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('all sixteen exact KPI formulas remain reachable in the closed reference', () => {
|
||||||
|
const page = read('docs/strategy/measurement.mdx');
|
||||||
|
const contracts = page.split('<summary>All 16 KPI contracts')[1].split('</details>')[0];
|
||||||
|
assert.equal((contracts.match(/^### /gm) || []).length, 16);
|
||||||
|
for (const metric of model.kpis) {
|
||||||
|
const section = contracts.split(`### ${metric.name}\n`)[1]?.split('\n### ')[0];
|
||||||
|
assert(section, metric.name);
|
||||||
|
for (const label of ['Numerator','Denominator','Expression','Aggregation','Unit','Eligible population','Exclusions','Events and source','Owner / cadence','Missing evidence','Gaming and limits']) assert(section.includes(`| ${label} |`), `${metric.name}: ${label}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Sandboxed viewers have opaque origins: authenticate the sender by WindowProxy,
|
||||||
|
// not origin. Only exchange a validated theme, never HTML, URLs or commands.
|
||||||
|
(() => {
|
||||||
|
if (window.parent === window) return;
|
||||||
|
let connected = false;
|
||||||
|
window.addEventListener('message', event => {
|
||||||
|
if (event.source !== window.parent || event.data?.type !== 'eldorado:set-theme') return;
|
||||||
|
const theme = event.data.theme;
|
||||||
|
if (theme !== 'light' && theme !== 'dark') return;
|
||||||
|
connected = true;
|
||||||
|
if (document.documentElement.dataset.theme !== theme) {
|
||||||
|
document.getElementById('btn-theme').click();
|
||||||
|
// Parent updates are not new user choices; do not echo stale acknowledgements.
|
||||||
|
observer.takeRecords();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
if (connected) window.parent.postMessage({type: 'eldorado:theme', theme: document.documentElement.dataset.theme}, '*');
|
||||||
|
});
|
||||||
|
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['data-theme']});
|
||||||
|
})();
|
||||||
@@ -1,13 +1,54 @@
|
|||||||
import React, {useEffect, useId, useRef, useState} from 'react';
|
import React, {useEffect, useId, useRef, useState} from 'react';
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
import {useLocation} from '@docusaurus/router';
|
||||||
|
import {useColorMode} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
export default function ArchifyDiagram({name, title, compact = false}: {name: string; title: string; compact?: boolean}): React.ReactElement {
|
export default function ArchifyDiagram({name, title, compact = false, story = false}: {name: string; title: string; compact?: boolean; story?: boolean}): React.ReactElement {
|
||||||
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) throw new Error('Invalid diagram name');
|
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) throw new Error('Invalid diagram name');
|
||||||
const source = useBaseUrl(`/diagrams/${name}/`);
|
const source = useBaseUrl(`/diagrams/${name}/`);
|
||||||
|
const mobileSource = useBaseUrl(`/diagrams/${name}-mobile/`);
|
||||||
const dialog = useRef<HTMLDialogElement>(null);
|
const dialog = useRef<HTMLDialogElement>(null);
|
||||||
const opener = useRef<HTMLButtonElement>(null);
|
const opener = useRef<HTMLButtonElement>(null);
|
||||||
const headingId = useId();
|
const headingId = useId();
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
const {colorMode, setColorMode} = useColorMode();
|
||||||
|
const initialTheme = useRef(colorMode);
|
||||||
|
const desktop = useRef<HTMLIFrameElement>(null);
|
||||||
|
const mobile = useRef<HTMLIFrameElement>(null);
|
||||||
|
const fullscreen = useRef<HTMLIFrameElement>(null);
|
||||||
|
const syncTheme = (frame: HTMLIFrameElement | null) => frame?.contentWindow?.postMessage({type: 'eldorado:set-theme', theme: colorMode}, '*');
|
||||||
|
useEffect(() => {
|
||||||
|
for (const frame of [desktop, mobile, fullscreen]) syncTheme(frame.current);
|
||||||
|
const receiveTheme = (event: MessageEvent) => {
|
||||||
|
if (!event.source || ![desktop, mobile, fullscreen].some(frame => frame.current?.contentWindow === event.source)) return;
|
||||||
|
if (event.data?.type !== 'eldorado:theme' || !['light', 'dark'].includes(event.data.theme)) return;
|
||||||
|
if (event.data.theme !== colorMode) setColorMode(event.data.theme);
|
||||||
|
};
|
||||||
|
window.addEventListener('message', receiveTheme);
|
||||||
|
return () => window.removeEventListener('message', receiveTheme);
|
||||||
|
}, [colorMode, setColorMode, expanded]);
|
||||||
|
const {pathname, hash} = useLocation();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!story || !hash) return;
|
||||||
|
let id: string;
|
||||||
|
try {id = decodeURIComponent(hash.slice(1));} catch {return;}
|
||||||
|
const frame = requestAnimationFrame(() => {
|
||||||
|
const target = document.getElementById(id);
|
||||||
|
if (!target?.closest('.strategy-content')) return;
|
||||||
|
let detail = target.closest('details');
|
||||||
|
if (!detail) return;
|
||||||
|
while (detail) {
|
||||||
|
if (detail.dataset.collapsed === 'true') {
|
||||||
|
detail.querySelector<HTMLElement>(':scope > summary')?.click();
|
||||||
|
} else if (!detail.hasAttribute('data-collapsed')) {
|
||||||
|
detail.open = true;
|
||||||
|
}
|
||||||
|
detail = detail.parentElement?.closest('details') ?? null;
|
||||||
|
}
|
||||||
|
target.scrollIntoView();
|
||||||
|
});
|
||||||
|
return () => cancelAnimationFrame(frame);
|
||||||
|
}, [story, pathname, hash]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!expanded) return;
|
if (!expanded) return;
|
||||||
dialog.current?.showModal();
|
dialog.current?.showModal();
|
||||||
@@ -16,12 +57,15 @@ export default function ArchifyDiagram({name, title, compact = false}: {name: st
|
|||||||
return () => {document.body.style.overflow = previousOverflow;};
|
return () => {document.body.style.overflow = previousOverflow;};
|
||||||
}, [expanded]);
|
}, [expanded]);
|
||||||
const close = () => {dialog.current?.close();};
|
const close = () => {dialog.current?.close();};
|
||||||
return <section className={`archify-panel${compact ? ' archify-panel--compact' : ''}`} aria-label={title}>
|
return <section className={`archify-panel${compact ? ' archify-panel--compact' : ''}${story ? ' archify-panel--story' : ''}`} data-diagram={name} aria-label={title}>
|
||||||
<div className="archify-toolbar"><button ref={opener} type="button" className="archify-expand" aria-label={`Expand ${title}`} title="Expand diagram" onClick={() => setExpanded(true)}><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true"><path d="M8 3H3v5M16 3h5v5M21 16v5h-5M8 21H3v-5" /></svg></button></div>
|
<div className="archify-toolbar"><button ref={opener} type="button" className="archify-expand" aria-label={`Expand ${title}`} title="Expand diagram" onClick={() => setExpanded(true)}><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true"><path d="M8 3H3v5M16 3h5v5M21 16v5h-5M8 21H3v-5" /></svg></button></div>
|
||||||
<iframe src={source} title={title} sandbox="allow-scripts allow-downloads" loading="lazy" referrerPolicy="no-referrer" />
|
{story ? <>
|
||||||
|
<iframe className="story-desktop" ref={desktop} onLoad={() => syncTheme(desktop.current)} src={`${source}?embed=1&theme=${initialTheme.current}`} title={title} sandbox="allow-scripts allow-downloads" loading="lazy" referrerPolicy="no-referrer" />
|
||||||
|
<iframe className="story-mobile" ref={mobile} onLoad={() => syncTheme(mobile.current)} src={`${mobileSource}?embed=1&theme=${initialTheme.current}`} title={`${title} — narrow layout`} sandbox="allow-scripts allow-downloads" loading="lazy" referrerPolicy="no-referrer" />
|
||||||
|
</> : <iframe ref={desktop} onLoad={() => syncTheme(desktop.current)} src={`${source}?theme=${initialTheme.current}`} title={title} sandbox="allow-scripts allow-downloads" loading="lazy" referrerPolicy="no-referrer" />}
|
||||||
<dialog ref={dialog} className="archify-modal" aria-labelledby={headingId} onClose={() => {setExpanded(false); opener.current?.focus();}}>
|
<dialog ref={dialog} className="archify-modal" aria-labelledby={headingId} onClose={() => {setExpanded(false); opener.current?.focus();}}>
|
||||||
<div className="archify-modal-toolbar"><strong id={headingId}>{title}</strong><button type="button" onClick={close} autoFocus aria-label="Close full-screen diagram"><span aria-hidden="true">×</span></button></div>
|
<div className="archify-modal-toolbar"><strong id={headingId}>{title}</strong><button type="button" onClick={close} autoFocus aria-label="Close full-screen diagram"><span aria-hidden="true">×</span></button></div>
|
||||||
{expanded && <iframe src={source} title={`${title} — expanded`} sandbox="allow-scripts allow-downloads" referrerPolicy="no-referrer" />}
|
{expanded && <iframe ref={fullscreen} onLoad={() => syncTheme(fullscreen.current)} src={`${source}?theme=${initialTheme.current}`} title={`${title} — expanded`} sandbox="allow-scripts allow-downloads" referrerPolicy="no-referrer" />}
|
||||||
</dialog>
|
</dialog>
|
||||||
</section>;
|
</section>;
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,25 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
|
|||||||
.archify-toolbar {display: flex; justify-content: flex-end; padding: 4px; background: var(--surface);}
|
.archify-toolbar {display: flex; justify-content: flex-end; padding: 4px; background: var(--surface);}
|
||||||
.archify-panel iframe {width: 100%; height: 720px; border: 0; display: block; background: #f6f6f6;}
|
.archify-panel iframe {width: 100%; height: 720px; border: 0; display: block; background: #f6f6f6;}
|
||||||
.archify-panel--compact > iframe {height: 500px;}
|
.archify-panel--compact > iframe {height: 500px;}
|
||||||
|
.archify-panel--story {max-width: 740px;}
|
||||||
|
.archify-panel--story > iframe {height: auto; aspect-ratio: 480 / 408;}
|
||||||
|
.archify-panel--story > .story-mobile {display: none;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-target"] > iframe {aspect-ratio: 480 / 628;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-adoption"] > iframe {aspect-ratio: 545 / 408;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-maintenance"] > iframe {aspect-ratio: 524 / 408;}
|
||||||
|
.strategy-content > details {margin: .65rem 0; border: 1px solid var(--line); padding: .8rem 1rem; background: var(--surface);}
|
||||||
|
.strategy-content summary {cursor: pointer; font-weight: 700;}
|
||||||
|
.strategy-content summary:focus-visible {outline: 3px solid #b88719; outline-offset: 4px;}
|
||||||
|
.strategy-content > details[open] > summary {margin-bottom: 1rem;}
|
||||||
@media (max-width: 700px) {.archify-panel iframe {height: 650px;}}
|
@media (max-width: 700px) {.archify-panel iframe {height: 650px;}}
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.archify-panel--story > .story-desktop {display: none;}
|
||||||
|
.archify-panel--story > .story-mobile {display: block; height: auto; aspect-ratio: 240 / 748;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-roadmap"] > .story-mobile {aspect-ratio: 240 / 628;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-adoption"] > .story-mobile {aspect-ratio: 305 / 748;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-maintenance"] > .story-mobile {aspect-ratio: 284 / 748;}
|
||||||
|
.archify-panel--story[data-diagram="strategy-target"] > .story-mobile {aspect-ratio: 301 / 868;}
|
||||||
|
}
|
||||||
.archify-expand {display: grid; place-items: center; width: 44px; height: 44px; border: 0; padding: 0; background: transparent; color: var(--ifm-link-color); cursor: pointer;}
|
.archify-expand {display: grid; place-items: center; width: 44px; height: 44px; border: 0; padding: 0; background: transparent; color: var(--ifm-link-color); cursor: pointer;}
|
||||||
.archify-expand:hover {background: var(--ifm-hover-overlay);}
|
.archify-expand:hover {background: var(--ifm-hover-overlay);}
|
||||||
.archify-modal {position: fixed; inset: 0; margin: 0; padding: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; border: 0; background: var(--surface); color: var(--ifm-color-content);}
|
.archify-modal {position: fixed; inset: 0; margin: 0; padding: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; border: 0; background: var(--surface); color: var(--ifm-color-content);}
|
||||||
|
|||||||
Reference in new issue
Block a user