Compare commits

..
Author SHA1 Message Date
jarvis-at-skic a35cade49c feat: [verified] compose Skills Adoption diagrams around their stories
Build and publish Eldorado documentation / build (pull_request) Successful in 40s
2026-10-06 22:35:48 +00:00
jarvis-at-skic ef169cec58 Merge pull request 'fix: expose every documentation page in navigation' (#32) from fix/all-docs-sidebar into main
Build and publish Eldorado documentation / build (push) Successful in 41s
2026-10-06 13:15:15 -07:00
19 changed files with 2377 additions and 834 deletions

No files matched your search

@@ -7,140 +7,239 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
880,
2040
]
}, },
"components": [ "components": [
{ {
"id": "delivery", "id": "delivery",
"type": "backend", "type": "external",
"label": "Delivery first", "label": "Delivery first",
"tag": "Understand real work", "tag": "Start with a real workflow",
"sublabel": "Codebase + principles\nSystem logic and tests\nBuilds and packaging\nDeployments + baseline", "sublabel": "Baseline + bounded canary",
"pos": [ "pos": [
40, 60,
40 120
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "workflow", "id": "human",
"type": "security", "type": "backend",
"label": "Choose bounded work", "label": "Human",
"tag": "Team + Product owner", "tag": "Direct + guide + review",
"sublabel": "Define accepted outcome\nData & AI shapes the skill\nQuality sets acceptance\nSecurity clears data", "sublabel": "Define outcome; inspect artifacts",
"pos": [ "pos": [
40, 60,
610 1280
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "coach", "id": "agent",
"type": "frontend", "type": "external",
"label": "Practice together", "label": "AI Agent",
"tag": "Human + AI Agent", "tag": "Supported client + approved skills",
"sublabel": "Platform qualifies client\nPeople supports learning\nSelect skill; inspect work\nKeep a manual path", "sublabel": "Produce work within the boundary",
"pos": [ "pos": [
40, 60,
1180 910
], ],
"size": [ "size": [
560, 740,
440 220
]
},
{
"id": "verify",
"type": "security",
"label": "Accept actual work",
"tag": "Independent reviewer",
"sublabel": "Check artifacts, not calls\nRecognize unsafe inputs\nUse incident routes\nExplain limits + recovery",
"pos": [
40,
1750
], ],
"size": [ "icon": "none"
560,
440
]
}, },
{ {
"id": "learn", "id": "learn",
"type": "database", "type": "external",
"label": "Review the feedback", "label": "Learn from real work",
"tag": "Owning team", "tag": "Ongoing, reviewed improvement",
"sublabel": "Collect metrics + friction\nNon-use is useful feedback\nRevise through review\nNo quotas or rankings", "sublabel": "Feedback + friction + measures\nRetain a manual path\nNo quotas or rankings",
"pos": [ "pos": [
40, 60,
2320 490
], ],
"size": [ "size": [
560, 740,
440 270
] ],
"icon": "none"
}, },
{ {
"id": "expand", "id": "expand",
"type": "cloud", "type": "backend",
"label": "Expand with evidence", "label": "Expand on evidence",
"tag": "Other SDLC phases", "tag": "Other SDLC phases",
"sublabel": "Later order undecided\nRepeat baseline + topology\nDelivery keeps improving\nNot autonomous authority", "sublabel": "Later order undecided\nDelivery keeps improving",
"pos": [ "pos": [
40, 60,
2890 1650
], ],
"size": [ "size": [
560, 740,
440 240
] ],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "delivery-agent",
"from": "delivery", "from": "delivery",
"to": "workflow", "to": "agent",
"fromSide": "bottom", "label": "Practice",
"toSide": "top", "fromSide": "right",
"route": "straight" "toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
230.0
],
[
850,
1020.0
]
],
"labelAt": [
780,
870
]
}, },
{ {
"id": "flow-1", "id": "human-agent",
"from": "workflow", "from": "human",
"to": "coach", "to": "agent",
"fromSide": "bottom", "label": "Direction",
"toSide": "top", "fromSide": "right",
"route": "straight" "toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
824,
1390.0
],
[
824,
1020.0
]
],
"labelAt": [
770,
1240
]
}, },
{ {
"id": "flow-2", "id": "agent-human",
"from": "coach", "from": "agent",
"to": "verify", "to": "human",
"label": "Work to inspect",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1185
]
}, },
{ {
"id": "flow-3", "id": "agent-learn",
"from": "verify", "from": "agent",
"to": "learn", "to": "learn",
"fromSide": "bottom", "label": "Observe",
"toSide": "top", "fromSide": "top",
"route": "straight" "toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
815
]
}, },
{ {
"id": "flow-4", "id": "learn-delivery",
"from": "learn",
"to": "delivery",
"label": "Improve",
"fromSide": "left",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
42,
625.0
],
[
42,
230.0
]
],
"labelAt": [
620,
80
]
},
{
"id": "human-expand",
"from": "human",
"to": "expand",
"label": "Accepted work",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1555
]
},
{
"id": "learn-expand",
"from": "learn", "from": "learn",
"to": "expand", "to": "expand",
"fromSide": "bottom", "label": "Feedback",
"toSide": "top", "fromSide": "left",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
20,
625.0
],
[
20,
1770.0
]
],
"labelAt": [
620,
1610
]
} }
] ]
} }
+180 -83
View File
@@ -7,140 +7,237 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
2040,
1160
]
}, },
"components": [ "components": [
{ {
"id": "delivery", "id": "delivery",
"type": "backend", "type": "external",
"label": "Delivery first", "label": "Delivery first",
"tag": "Understand real work", "tag": "Start with a real workflow",
"sublabel": "Codebase + principles\nSystem logic and tests\nBuilds and packaging\nDeployments + baseline", "sublabel": "Baseline + bounded canary",
"pos": [ "pos": [
40, 60,
40 350
], ],
"size": [ "size": [
560, 470,
440 210
] ],
"icon": "none"
}, },
{ {
"id": "workflow", "id": "human",
"type": "security", "type": "backend",
"label": "Choose bounded work", "label": "Human",
"tag": "Team + Product owner", "tag": "Direct + guide + review",
"sublabel": "Define accepted outcome\nData & AI shapes the skill\nQuality sets acceptance\nSecurity clears data", "sublabel": "Define outcome; inspect artifacts",
"pos": [ "pos": [
700, 700,
40 90
], ],
"size": [ "size": [
560, 570,
440 190
] ],
"icon": "none"
}, },
{ {
"id": "coach", "id": "agent",
"type": "frontend", "type": "external",
"label": "Practice together", "label": "AI Agent",
"tag": "Human + AI Agent", "tag": "Supported client + approved skills",
"sublabel": "Platform qualifies client\nPeople supports learning\nSelect skill; inspect work\nKeep a manual path", "sublabel": "Produce work within the boundary",
"pos": [ "pos": [
1360, 700,
40 440
], ],
"size": [ "size": [
560, 570,
440 190
]
},
{
"id": "verify",
"type": "security",
"label": "Accept actual work",
"tag": "Independent reviewer",
"sublabel": "Check artifacts, not calls\nRecognize unsafe inputs\nUse incident routes\nExplain limits + recovery",
"pos": [
1360,
610
], ],
"size": [ "icon": "none"
560,
440
]
}, },
{ {
"id": "learn", "id": "learn",
"type": "database", "type": "external",
"label": "Review the feedback", "label": "Learn from real work",
"tag": "Owning team", "tag": "Ongoing, reviewed improvement",
"sublabel": "Collect metrics + friction\nNon-use is useful feedback\nRevise through review\nNo quotas or rankings", "sublabel": "Feedback + friction + measures\nRetain a manual path\nNo quotas or rankings",
"pos": [ "pos": [
700, 700,
610 800
], ],
"size": [ "size": [
560, 570,
440 270
] ],
"icon": "none"
}, },
{ {
"id": "expand", "id": "expand",
"type": "cloud", "type": "backend",
"label": "Expand with evidence", "label": "Expand on evidence",
"tag": "Other SDLC phases", "tag": "Other SDLC phases",
"sublabel": "Later order undecided\nRepeat baseline + topology\nDelivery keeps improving\nNot autonomous authority", "sublabel": "Later order undecided\nDelivery keeps improving",
"pos": [ "pos": [
40, 1460,
610 360
], ],
"size": [ "size": [
560, 520,
440 240
] ],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "delivery-agent",
"from": "delivery", "from": "delivery",
"to": "workflow", "to": "agent",
"label": "Practice",
"fromSide": "right", "fromSide": "right",
"toSide": "left", "toSide": "left",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
585,
455
],
[
585,
535
]
],
"labelAt": [
570,
600
]
}, },
{ {
"id": "flow-1", "id": "human-agent",
"from": "workflow", "from": "human",
"to": "coach", "to": "agent",
"fromSide": "right", "label": "Direction",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-2",
"from": "coach",
"to": "verify",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
1100,
360
]
}, },
{ {
"id": "flow-3", "id": "agent-human",
"from": "verify", "from": "agent",
"to": "learn", "to": "human",
"label": "Work to inspect",
"fromSide": "left", "fromSide": "left",
"toSide": "right", "toSide": "left",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
630,
535
],
[
630,
185
]
],
"labelAt": [
470,
240
]
}, },
{ {
"id": "flow-4", "id": "agent-learn",
"from": "agent",
"to": "learn",
"label": "Observe",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
1100,
720
]
},
{
"id": "learn-delivery",
"from": "learn",
"to": "delivery",
"label": "Improve",
"fromSide": "left",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
295,
935
]
],
"labelAt": [
450,
900
]
},
{
"id": "human-expand",
"from": "human",
"to": "expand",
"label": "Accepted work",
"fromSide": "right",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1720,
185
]
],
"labelAt": [
1550,
140
]
},
{
"id": "learn-expand",
"from": "learn", "from": "learn",
"to": "expand", "to": "expand",
"fromSide": "left", "label": "Feedback",
"toSide": "right", "fromSide": "right",
"route": "straight" "toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1720,
935
]
],
"labelAt": [
1480,
895
]
} }
] ]
} }
@@ -7,140 +7,241 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
880,
2710
]
}, },
"components": [ "components": [
{ {
"id": "owner", "id": "owner",
"type": "backend", "type": "external",
"label": "Propose a skill", "label": "01 Propose",
"tag": "Owning team", "tag": "Owning team",
"sublabel": "Problem + intended users\nData and authority scope\nSKILL.md + dependencies\nTestable outcome", "sublabel": "Scope + testable outcome",
"pos": [ "pos": [
40, 60,
40 120
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "review", "id": "review",
"type": "security", "type": "external",
"label": "Independent review", "label": "02 Review independently",
"tag": "Quality + Security", "tag": "Quality + Security",
"sublabel": "Evaluate useful outcomes\nCheck risk boundaries\nAuthor is not sole approver\nRecord revision evidence", "sublabel": "Author is not sole approver",
"pos": [ "pos": [
40, 60,
610 490
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "canary", "id": "canary",
"type": "frontend", "type": "external",
"label": "Qualify real use", "label": "03 Qualify real use",
"tag": "Human + AI Agent", "tag": "Human + AI Agent",
"sublabel": "Test exact client build\nRun a bounded canary\nInspect work independently\nNo failed mandatory gate", "sublabel": "Exact client + bounded canary",
"pos": [ "pos": [
40, 60,
1180 860
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "approve", "id": "approve",
"type": "security", "type": "backend",
"label": "Approve exact scope", "label": "04 Approve exact scope",
"tag": "Accountable approvers", "tag": "Accountable approvers",
"sublabel": "Bind approval to digest\nPermitted uses + expiry\nExceptions cannot bypass\nprotected controls", "sublabel": "Digest + permitted uses + expiry",
"pos": [ "pos": [
40, 60,
1750 1230
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "publish", "id": "publish",
"type": "database", "type": "backend",
"label": "Version the bundle", "label": "05 Publish the bundle",
"tag": "Data & AI catalog", "tag": "Data & AI catalog",
"sublabel": "Pin skill + adapter\nand dependency revisions\nRecord approval evidence\nKeep last-known-good", "sublabel": "Pin skill, adapter + dependencies",
"pos": [ "pos": [
40, 60,
2320 1600
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "distribute", "id": "distribute",
"type": "cloud", "type": "backend",
"label": "Verify loaded state", "label": "06 Verify loaded state",
"tag": "Platform & IT", "tag": "Platform & IT",
"sublabel": "Stage and check digest\nRead effective revision\nTest open-session reload\nRevoke unsafe revisions", "sublabel": "Read revision; verify reload",
"pos": [ "pos": [
40, 60,
2890 1970
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "withdraw",
"type": "security",
"label": "Withdraw / roll back",
"tag": "Unsafe revision",
"sublabel": "Revoke; restore last-known-good",
"pos": [
60,
2340
],
"size": [
740,
220
],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "owner-review",
"from": "owner", "from": "owner",
"to": "review", "to": "review",
"label": "",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
395
]
}, },
{ {
"id": "flow-1", "id": "review-canary",
"from": "review", "from": "review",
"to": "canary", "to": "canary",
"label": "",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
765
]
}, },
{ {
"id": "flow-2", "id": "canary-approve",
"from": "canary", "from": "canary",
"to": "approve", "to": "approve",
"label": "",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1135
]
}, },
{ {
"id": "flow-3", "id": "approve-publish",
"from": "approve", "from": "approve",
"to": "publish", "to": "publish",
"label": "",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1505
]
}, },
{ {
"id": "flow-4", "id": "publish-distribute",
"from": "publish", "from": "publish",
"to": "distribute", "to": "distribute",
"label": "",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1875
]
},
{
"id": "approve-owner",
"from": "approve",
"to": "owner",
"label": "Rework",
"fromSide": "left",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
20,
1340.0
],
[
20,
230.0
]
],
"labelAt": [
620,
80
]
},
{
"id": "distribute-withdraw",
"from": "distribute",
"to": "withdraw",
"label": "Unsafe",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "security",
"labelAt": [
610,
2245
]
} }
] ]
} }
+205 -74
View File
@@ -7,140 +7,271 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
1760,
1420
]
}, },
"components": [ "components": [
{ {
"id": "owner", "id": "owner",
"type": "backend", "type": "external",
"label": "Propose a skill", "label": "01 Propose",
"tag": "Owning team", "tag": "Owning team",
"sublabel": "Problem + intended users\nData and authority scope\nSKILL.md + dependencies\nTestable outcome", "sublabel": "Scope + testable outcome",
"pos": [ "pos": [
40, 80,
40 60
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "review", "id": "review",
"type": "security", "type": "external",
"label": "Independent review", "label": "02 Review independently",
"tag": "Quality + Security", "tag": "Quality + Security",
"sublabel": "Evaluate useful outcomes\nCheck risk boundaries\nAuthor is not sole approver\nRecord revision evidence", "sublabel": "Author is not sole approver",
"pos": [ "pos": [
700, 300,
40 280
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "canary", "id": "canary",
"type": "frontend", "type": "external",
"label": "Qualify real use", "label": "03 Qualify real use",
"tag": "Human + AI Agent", "tag": "Human + AI Agent",
"sublabel": "Test exact client build\nRun a bounded canary\nInspect work independently\nNo failed mandatory gate", "sublabel": "Exact client + bounded canary",
"pos": [ "pos": [
1360, 520,
40 500
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "approve", "id": "approve",
"type": "security", "type": "backend",
"label": "Approve exact scope", "label": "04 Approve exact scope",
"tag": "Accountable approvers", "tag": "Accountable approvers",
"sublabel": "Bind approval to digest\nPermitted uses + expiry\nExceptions cannot bypass\nprotected controls", "sublabel": "Digest + permitted uses + expiry",
"pos": [ "pos": [
1360, 740,
610 720
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "publish", "id": "publish",
"type": "database", "type": "backend",
"label": "Version the bundle", "label": "05 Publish the bundle",
"tag": "Data & AI catalog", "tag": "Data & AI catalog",
"sublabel": "Pin skill + adapter\nand dependency revisions\nRecord approval evidence\nKeep last-known-good", "sublabel": "Pin skill, adapter + dependencies",
"pos": [ "pos": [
700, 960,
610 940
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "distribute", "id": "distribute",
"type": "cloud", "type": "backend",
"label": "Verify loaded state", "label": "06 Verify loaded state",
"tag": "Platform & IT", "tag": "Platform & IT",
"sublabel": "Stage and check digest\nRead effective revision\nTest open-session reload\nRevoke unsafe revisions", "sublabel": "Read revision; verify reload",
"pos": [ "pos": [
40, 1180,
610 1160
], ],
"size": [ "size": [
560, 500,
440 170
] ],
"icon": "none"
},
{
"id": "withdraw",
"type": "security",
"label": "Withdraw / roll back",
"tag": "Unsafe revision",
"sublabel": "Revoke; restore last-known-good",
"pos": [
80,
1160
],
"size": [
660,
170
],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "owner-review",
"from": "owner", "from": "owner",
"to": "review", "to": "review",
"fromSide": "right", "label": "",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-1",
"from": "review",
"to": "canary",
"fromSide": "right",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-2",
"from": "canary",
"to": "approve",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
330,
255
],
[
550,
255
]
]
}, },
{ {
"id": "flow-3", "id": "review-canary",
"from": "review",
"to": "canary",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
550,
475
],
[
770,
475
]
]
},
{
"id": "canary-approve",
"from": "canary",
"to": "approve",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
770,
695
],
[
990,
695
]
]
},
{
"id": "approve-publish",
"from": "approve", "from": "approve",
"to": "publish", "to": "publish",
"fromSide": "left", "label": "",
"toSide": "right", "fromSide": "bottom",
"route": "straight" "toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
990,
915
],
[
1210,
915
]
]
}, },
{ {
"id": "flow-4", "id": "publish-distribute",
"from": "publish", "from": "publish",
"to": "distribute", "to": "distribute",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1210,
1135
],
[
1430,
1135
]
]
},
{
"id": "approve-owner",
"from": "approve",
"to": "owner",
"label": "Rework",
"fromSide": "left",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
40,
805
],
[
40,
145
]
],
"labelAt": [
180,
680
]
},
{
"id": "distribute-withdraw",
"from": "distribute",
"to": "withdraw",
"label": "Unsafe",
"fromSide": "left", "fromSide": "left",
"toSide": "right", "toSide": "right",
"route": "straight" "route": "straight",
"width": 4,
"variant": "security",
"labelAt": [
950,
1220
]
} }
] ]
} }
@@ -7,140 +7,332 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
880,
3080
]
}, },
"components": [ "components": [
{ {
"id": "monitor", "id": "observe",
"type": "database", "type": "external",
"label": "Watch for change", "label": "Observe use",
"tag": "Data & AI + owners", "tag": "Owner + Data & AI",
"sublabel": "Review usefulness + safety\nDue dates and feedback\nModel / client / tool drift\nFailures trigger early review", "sublabel": "Feedback, drift + review due",
"pos": [ "pos": [
40, 60,
40 120
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "triage", "id": "triage",
"type": "backend", "type": "external",
"label": "Triage the evidence", "label": "Triage the signal",
"tag": "Owner + Quality", "tag": "Owning team",
"sublabel": "Reproduce the failure\nKeep artifact / client IDs\nAdd sanitized regressions\nAssess business effects", "sublabel": "Useful? Safe? Still needed?",
"pos": [ "pos": [
40, 60,
610 1970
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "change",
"type": "external",
"label": "Change the skill",
"tag": "Reviewed correction",
"sublabel": "New immutable revision",
"pos": [
60,
1230
],
"size": [
740,
220
],
"icon": "none"
},
{
"id": "validate",
"type": "external",
"label": "Revalidate",
"tag": "Independent reviewers",
"sublabel": "Regression + client evidence",
"pos": [
60,
860
],
"size": [
740,
220
],
"icon": "none"
},
{
"id": "release",
"type": "backend",
"label": "Approve + version",
"tag": "Accountable human authority",
"sublabel": "Verify distribution and recovery",
"pos": [
60,
490
],
"size": [
740,
220
],
"icon": "none"
},
{
"id": "safe",
"type": "backend",
"label": "Continue safe use",
"tag": "Substantive review passes",
"sublabel": "Keep owner + next review date",
"pos": [
60,
2710
],
"size": [
740,
220
],
"icon": "none"
},
{
"id": "retire",
"type": "external",
"label": "Retire deliberately",
"tag": "No longer useful",
"sublabel": "Reconcile consumers; no new use",
"pos": [
60,
2340
],
"size": [
740,
220
],
"icon": "none"
}, },
{ {
"id": "contain", "id": "contain",
"type": "security", "type": "security",
"label": "If unsafe: contain", "label": "Contain unsafe use",
"tag": "Security + Platform", "tag": "Security + Platform & IT",
"sublabel": "Revoke authority\nQuarantine revision\nRestore known-good bundle\nVerify effective state", "sublabel": "Revoke + quarantine + roll back\nNo automatic reinstatement",
"pos": [ "pos": [
40, 60,
1180 1600
], ],
"size": [ "size": [
560, 740,
440 220
]
},
{
"id": "correct",
"type": "backend",
"label": "Create a new revision",
"tag": "Owning team",
"sublabel": "Correct skill + dependencies\nIndependent tests / review\nRequalify client + model\nNo automatic reinstatement",
"pos": [
40,
1750
], ],
"size": [ "icon": "none"
560,
440
]
},
{
"id": "approve",
"type": "security",
"label": "Authorize restart",
"tag": "Accountable human",
"sublabel": "Require regression evidence\nVerify rollback / revocation\nApprove exact new revision\nCanary before wider use",
"pos": [
40,
2320
],
"size": [
560,
440
]
},
{
"id": "retire",
"type": "cloud",
"label": "Retire when obsolete",
"tag": "Data & AI + Platform",
"sublabel": "Deprecate with migration\nRetire: no new invocation\nTrack revoked versions\nHistory stays in metrics",
"pos": [
40,
2890
],
"size": [
560,
440
]
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "observe-triage",
"from": "monitor", "from": "observe",
"to": "triage", "to": "triage",
"fromSide": "bottom", "label": "",
"toSide": "top", "fromSide": "left",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
20,
230.0
],
[
20,
2080.0
]
],
"labelAt": [
620,
1930
]
}, },
{ {
"id": "flow-1", "id": "triage-change",
"from": "triage",
"to": "change",
"label": "Correct",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
2080.0
],
[
850,
1340.0
]
],
"labelAt": [
780,
1560
]
},
{
"id": "change-validate",
"from": "change",
"to": "validate",
"label": "",
"fromSide": "top",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1135
]
},
{
"id": "validate-release",
"from": "validate",
"to": "release",
"label": "",
"fromSide": "top",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
765
]
},
{
"id": "release-observe",
"from": "release",
"to": "observe",
"label": "",
"fromSide": "top",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
395
]
},
{
"id": "triage-safe",
"from": "triage",
"to": "safe",
"label": "Safe",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
824,
2080.0
],
[
824,
2820.0
]
],
"labelAt": [
620,
2670
]
},
{
"id": "triage-retire",
"from": "triage",
"to": "retire",
"label": "Retire",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
2245
]
},
{
"id": "triage-contain",
"from": "triage", "from": "triage",
"to": "contain", "to": "contain",
"fromSide": "bottom", "label": "Unsafe",
"toSide": "top", "fromSide": "top",
"route": "straight" "toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "security",
"labelAt": [
610,
1875
]
}, },
{ {
"id": "flow-2", "id": "contain-change",
"from": "contain", "from": "contain",
"to": "correct", "to": "change",
"fromSide": "bottom", "label": "Reviewed fix",
"toSide": "top", "fromSide": "top",
"route": "straight" "toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "security",
"labelAt": [
610,
1505
]
}, },
{ {
"id": "flow-3", "id": "safe-observe",
"from": "correct", "from": "safe",
"to": "approve", "to": "observe",
"fromSide": "bottom", "label": "Keep watching",
"toSide": "top", "fromSide": "left",
"route": "straight" "toSide": "left",
}, "route": "straight",
{ "width": 4,
"id": "flow-4", "variant": "default",
"from": "approve", "via": [
"to": "retire", [
"fromSide": "bottom", 42,
"toSide": "top", 2820.0
"route": "straight" ],
[
42,
230.0
]
],
"labelAt": [
620,
80
]
} }
] ]
} }
+320 -96
View File
@@ -7,140 +7,364 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
2630,
1300
]
}, },
"components": [ "components": [
{ {
"id": "monitor", "id": "observe",
"type": "database", "type": "external",
"label": "Watch for change", "label": "Observe use",
"tag": "Data & AI + owners", "tag": "Owner + Data & AI",
"sublabel": "Review usefulness + safety\nDue dates and feedback\nModel / client / tool drift\nFailures trigger early review", "sublabel": "Feedback, drift + review due",
"pos": [ "pos": [
40, 670,
40 60
], ],
"size": [ "size": [
560, 560,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "triage", "id": "triage",
"type": "backend", "type": "external",
"label": "Triage the evidence", "label": "Triage the signal",
"tag": "Owner + Quality", "tag": "Owning team",
"sublabel": "Reproduce the failure\nKeep artifact / client IDs\nAdd sanitized regressions\nAssess business effects", "sublabel": "Useful? Safe? Still needed?",
"pos": [ "pos": [
700, 1340,
40 330
],
"size": [
500,
190
],
"icon": "none"
},
{
"id": "change",
"type": "external",
"label": "Change the skill",
"tag": "Reviewed correction",
"sublabel": "New immutable revision",
"pos": [
1240,
750
],
"size": [
520,
180
],
"icon": "none"
},
{
"id": "validate",
"type": "external",
"label": "Revalidate",
"tag": "Independent reviewers",
"sublabel": "Regression + client evidence",
"pos": [
560,
970
], ],
"size": [ "size": [
560, 560,
440 180
] ],
"icon": "none"
},
{
"id": "release",
"type": "backend",
"label": "Approve + version",
"tag": "Accountable human authority",
"sublabel": "Verify distribution and recovery",
"pos": [
70,
570
],
"size": [
540,
180
],
"icon": "none"
},
{
"id": "safe",
"type": "backend",
"label": "Continue safe use",
"tag": "Substantive review passes",
"sublabel": "Keep owner + next review date",
"pos": [
2010,
80
],
"size": [
550,
180
],
"icon": "none"
},
{
"id": "retire",
"type": "external",
"label": "Retire deliberately",
"tag": "No longer useful",
"sublabel": "Reconcile consumers; no new use",
"pos": [
2010,
430
],
"size": [
550,
180
],
"icon": "none"
}, },
{ {
"id": "contain", "id": "contain",
"type": "security", "type": "security",
"label": "If unsafe: contain", "label": "Contain unsafe use",
"tag": "Security + Platform", "tag": "Security + Platform & IT",
"sublabel": "Revoke authority\nQuarantine revision\nRestore known-good bundle\nVerify effective state", "sublabel": "Revoke + quarantine + roll back\nNo automatic reinstatement",
"pos": [ "pos": [
1360, 2010,
40 800
], ],
"size": [ "size": [
560, 550,
440 220
]
},
{
"id": "correct",
"type": "backend",
"label": "Create a new revision",
"tag": "Owning team",
"sublabel": "Correct skill + dependencies\nIndependent tests / review\nRequalify client + model\nNo automatic reinstatement",
"pos": [
1360,
610
], ],
"size": [ "icon": "none"
560,
440
]
},
{
"id": "approve",
"type": "security",
"label": "Authorize restart",
"tag": "Accountable human",
"sublabel": "Require regression evidence\nVerify rollback / revocation\nApprove exact new revision\nCanary before wider use",
"pos": [
700,
610
],
"size": [
560,
440
]
},
{
"id": "retire",
"type": "cloud",
"label": "Retire when obsolete",
"tag": "Data & AI + Platform",
"sublabel": "Deprecate with migration\nRetire: no new invocation\nTrack revoked versions\nHistory stays in metrics",
"pos": [
40,
610
],
"size": [
560,
440
]
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "observe-triage",
"from": "monitor", "from": "observe",
"to": "triage", "to": "triage",
"label": "",
"fromSide": "right", "fromSide": "right",
"toSide": "left", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1590,
145
]
]
}, },
{ {
"id": "flow-1", "id": "triage-change",
"from": "triage", "from": "triage",
"to": "contain", "to": "change",
"fromSide": "right", "label": "Correct",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-2",
"from": "contain",
"to": "correct",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1590,
620
],
[
1500,
620
]
],
"labelAt": [
1450,
680
]
}, },
{ {
"id": "flow-3", "id": "change-validate",
"from": "correct", "from": "change",
"to": "approve", "to": "validate",
"fromSide": "left", "label": "",
"fromSide": "bottom",
"toSide": "right", "toSide": "right",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1500,
1060
]
]
}, },
{ {
"id": "flow-4", "id": "validate-release",
"from": "approve", "from": "validate",
"to": "release",
"label": "",
"fromSide": "left",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
340,
1060
]
]
},
{
"id": "release-observe",
"from": "release",
"to": "observe",
"label": "",
"fromSide": "top",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
340,
145
]
]
},
{
"id": "triage-safe",
"from": "triage",
"to": "safe",
"label": "Safe",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1920,
425
],
[
1920,
170
]
],
"labelAt": [
1930,
210
]
},
{
"id": "triage-retire",
"from": "triage",
"to": "retire", "to": "retire",
"fromSide": "left", "label": "Retire",
"toSide": "right", "fromSide": "right",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1950,
425
],
[
1950,
520
]
],
"labelAt": [
1900,
490
]
},
{
"id": "triage-contain",
"from": "triage",
"to": "contain",
"label": "Unsafe",
"fromSide": "bottom",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
1590,
580
],
[
1850,
580
],
[
1850,
910
]
],
"labelAt": [
1900,
720
]
},
{
"id": "contain-change",
"from": "contain",
"to": "change",
"label": "Reviewed fix",
"fromSide": "bottom",
"toSide": "bottom",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
2285,
1230
],
[
1500,
1230
]
],
"labelAt": [
1900,
1190
]
},
{
"id": "safe-observe",
"from": "safe",
"to": "observe",
"label": "Keep watching",
"fromSide": "top",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
2285,
20
],
[
950,
20
]
],
"labelAt": [
1640,
45
]
} }
] ]
} }
@@ -2,104 +2,313 @@
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {
"title": "Recommended collection plan: Measurement", "title": "TO-BE: Measurement",
"output": "static/diagrams/strategy-measurement-mobile/index.html", "output": "static/diagrams/strategy-measurement-mobile/index.html",
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
880,
3630
]
}, },
"components": [ "components": [
{ {
"id": "baseline", "id": "success-source",
"type": "backend", "type": "external",
"label": "Establish baseline", "label": "Tracker + acceptance",
"tag": "Comparable workflow", "tag": "Matured task starts",
"sublabel": "Join task / PR / CI IDs\nAgree acceptance + window\nRecord revision and client\nKeep unknowns visible", "sublabel": "Join evidence to the workflow",
"pos": [ "pos": [
40, 60,
40 120
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "success", "id": "success",
"type": "frontend", "type": "frontend",
"label": "Accepted outcomes", "label": "Accepted / eligible starts \u00d7 100",
"tag": "Quality · weekly", "tag": "Task success (%)",
"sublabel": "Tracker: starts + acceptance\nAccepted / eligible starts\nwith ended window × 100\nKeep failed, stopped, unknown\nShow outcome coverage", "sublabel": "Failures + unresolved retained",
"pos": [ "pos": [
40, 60,
610 490
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "quality-source",
"type": "external",
"label": "Changes + defects",
"tag": "Completed follow-up",
"sublabel": "Join evidence to the workflow",
"pos": [
60,
860
],
"size": [
740,
220
],
"icon": "none"
}, },
{ {
"id": "quality", "id": "quality",
"type": "security", "type": "frontend",
"label": "Escaped quality", "label": "Affected / accepted changes \u00d7 100",
"tag": "Quality · monthly", "tag": "Escaped quality (%)",
"sublabel": "PRs + linked defect records\nAffected / followed-up\naccepted changes × 100\nCount each change once\nMissing links ≠ clean", "sublabel": "Count each affected change once",
"pos": [ "pos": [
40, 60,
1180 1230
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "cost-source",
"type": "external",
"label": "Invoices + review minutes",
"tag": "Include failed attempts",
"sublabel": "Join evidence to the workflow",
"pos": [
60,
1600
],
"size": [
740,
220
],
"icon": "none"
}, },
{ {
"id": "cost", "id": "cost",
"type": "cloud", "type": "frontend",
"label": "Cost per outcome", "label": "Allocated cost / accepted tasks",
"tag": "Finance · monthly", "tag": "Cost per accepted outcome",
"sublabel": "Invoices + review minutes\nAll costs / accepted tasks\nSame matured start cohort\nFailed work + licenses too\nMissing buckets = partial", "sublabel": "Missing buckets = partial",
"pos": [ "pos": [
40, 60,
1750 1970
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "confidence-source",
"type": "external",
"label": "Anonymous 1\u20135 survey",
"tag": "Protect small groups",
"sublabel": "Join evidence to the workflow",
"pos": [
60,
2340
],
"size": [
740,
220
],
"icon": "none"
}, },
{ {
"id": "confidence", "id": "confidence",
"type": "frontend", "type": "frontend",
"label": "Verification confidence", "label": "Confidence sum / valid responses",
"tag": "People · each cycle", "tag": "Verification confidence (1\u20135)",
"sublabel": "Anonymous 1–5 survey\nSum of valid scores / replies\nShow spread; response rate:\nreplies / invitations × 100\nProtect small cohorts", "sublabel": "Show distribution + response rate",
"pos": [ "pos": [
40, 60,
2320 2710
], ],
"size": [ "size": [
560, 740,
440 220
],
"icon": "none"
},
{
"id": "interpret",
"type": "backend",
"label": "Compare with baseline",
"tag": "Interpret, then act",
"sublabel": "Like workflows + source coverage\nZero denominator = N/A\nTrends are not causal ROI\nFix gaps; improve the workflow",
"pos": [
60,
3080
],
"size": [
740,
400
],
"icon": "none"
}
],
"connections": [
{
"id": "success-source-success",
"from": "success-source",
"to": "success",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
395
] ]
}, },
{ {
"id": "monitor", "id": "quality-source-quality",
"type": "database", "from": "quality-source",
"label": "Ongoing monitoring", "to": "quality",
"tag": "Catalog + cohort report", "label": "",
"sublabel": "Catalog + cohort records\nTrack support, use, reviews\nCompare with baseline\nShow counts + coverage\nZero denominator = N/A", "fromSide": "bottom",
"pos": [ "toSide": "top",
40, "route": "straight",
2890 "width": 4,
"variant": "default",
"labelAt": [
610,
1135
]
},
{
"id": "cost-source-cost",
"from": "cost-source",
"to": "cost",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1875
]
},
{
"id": "confidence-source-confidence",
"from": "confidence-source",
"to": "confidence",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
2615
]
},
{
"id": "success-interpret",
"from": "success",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
600.0
],
[
850,
3280.0
]
], ],
"size": [ "labelAt": [
560, 620,
440 3040
]
},
{
"id": "quality-interpret",
"from": "quality",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
1340.0
],
[
850,
3280.0
]
],
"labelAt": [
620,
3040
]
},
{
"id": "cost-interpret",
"from": "cost",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
2080.0
],
[
850,
3280.0
]
],
"labelAt": [
620,
3040
]
},
{
"id": "confidence-interpret",
"from": "confidence",
"to": "interpret",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
2985
] ]
} }
], ]
"connections": [] }
}
+247 -60
View File
@@ -2,104 +2,291 @@
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {
"title": "Recommended collection plan: Measurement", "title": "TO-BE: Measurement",
"output": "static/diagrams/strategy-measurement/index.html", "output": "static/diagrams/strategy-measurement/index.html",
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
2400,
1120
]
}, },
"components": [ "components": [
{ {
"id": "baseline", "id": "success-source",
"type": "backend", "type": "external",
"label": "Establish baseline", "label": "Tracker + acceptance",
"tag": "Comparable workflow", "tag": "Matured task starts",
"sublabel": "Join task / PR / CI IDs\nAgree acceptance + window\nRecord revision and client\nKeep unknowns visible", "sublabel": "Join evidence to the workflow",
"pos": [ "pos": [
40, 50,
40 70
], ],
"size": [ "size": [
560, 580,
440 180
] ],
"icon": "none"
}, },
{ {
"id": "success", "id": "success",
"type": "frontend", "type": "frontend",
"label": "Accepted outcomes", "label": "Accepted / eligible starts \u00d7 100",
"tag": "Quality · weekly", "tag": "Task success (%)",
"sublabel": "Tracker: starts + acceptance\nAccepted / eligible starts\nwith ended window × 100\nKeep failed, stopped, unknown\nShow outcome coverage", "sublabel": "Failures + unresolved retained",
"pos": [ "pos": [
700, 770,
40 70
], ],
"size": [ "size": [
560, 700,
440 180
] ],
"icon": "none"
},
{
"id": "quality-source",
"type": "external",
"label": "Changes + defects",
"tag": "Completed follow-up",
"sublabel": "Join evidence to the workflow",
"pos": [
50,
320
],
"size": [
580,
180
],
"icon": "none"
}, },
{ {
"id": "quality", "id": "quality",
"type": "security", "type": "frontend",
"label": "Escaped quality", "label": "Affected / accepted changes \u00d7 100",
"tag": "Quality · monthly", "tag": "Escaped quality (%)",
"sublabel": "PRs + linked defect records\nAffected / followed-up\naccepted changes × 100\nCount each change once\nMissing links ≠ clean", "sublabel": "Count each affected change once",
"pos": [ "pos": [
1360, 770,
40 320
], ],
"size": [ "size": [
560, 700,
440 180
] ],
"icon": "none"
},
{
"id": "cost-source",
"type": "external",
"label": "Invoices + review minutes",
"tag": "Include failed attempts",
"sublabel": "Join evidence to the workflow",
"pos": [
50,
570
],
"size": [
580,
180
],
"icon": "none"
}, },
{ {
"id": "cost", "id": "cost",
"type": "cloud", "type": "frontend",
"label": "Cost per outcome", "label": "Allocated cost / accepted tasks",
"tag": "Finance · monthly", "tag": "Cost per accepted outcome",
"sublabel": "Invoices + review minutes\nAll costs / accepted tasks\nSame matured start cohort\nFailed work + licenses too\nMissing buckets = partial", "sublabel": "Missing buckets = partial",
"pos": [ "pos": [
1360, 770,
610 570
], ],
"size": [ "size": [
560, 700,
440 180
] ],
"icon": "none"
},
{
"id": "confidence-source",
"type": "external",
"label": "Anonymous 1\u20135 survey",
"tag": "Protect small groups",
"sublabel": "Join evidence to the workflow",
"pos": [
50,
820
],
"size": [
580,
180
],
"icon": "none"
}, },
{ {
"id": "confidence", "id": "confidence",
"type": "frontend", "type": "frontend",
"label": "Verification confidence", "label": "Confidence sum / valid responses",
"tag": "People · each cycle", "tag": "Verification confidence (1\u20135)",
"sublabel": "Anonymous 1–5 survey\nSum of valid scores / replies\nShow spread; response rate:\nreplies / invitations × 100\nProtect small cohorts", "sublabel": "Show distribution + response rate",
"pos": [ "pos": [
700, 770,
610 820
], ],
"size": [ "size": [
560, 700,
440 180
],
"icon": "none"
},
{
"id": "interpret",
"type": "backend",
"label": "Compare with baseline",
"tag": "Interpret, then act",
"sublabel": "Like workflows + source coverage\nZero denominator = N/A\nTrends are not causal ROI\nFix gaps; improve the workflow",
"pos": [
1650,
325
],
"size": [
680,
400
],
"icon": "none"
}
],
"connections": [
{
"id": "success-source-success",
"from": "success-source",
"to": "success",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default"
},
{
"id": "quality-source-quality",
"from": "quality-source",
"to": "quality",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default"
},
{
"id": "cost-source-cost",
"from": "cost-source",
"to": "cost",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default"
},
{
"id": "confidence-source-confidence",
"from": "confidence-source",
"to": "confidence",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default"
},
{
"id": "success-interpret",
"from": "success",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1550,
160
],
[
1550,
525
]
] ]
}, },
{ {
"id": "monitor", "id": "quality-interpret",
"type": "database", "from": "quality",
"label": "Ongoing monitoring", "to": "interpret",
"tag": "Catalog + cohort report", "label": "",
"sublabel": "Catalog + cohort records\nTrack support, use, reviews\nCompare with baseline\nShow counts + coverage\nZero denominator = N/A", "fromSide": "right",
"pos": [ "toSide": "left",
40, "route": "straight",
610 "width": 4,
], "variant": "default",
"size": [ "via": [
560, [
440 1550,
410
],
[
1550,
525
]
]
},
{
"id": "cost-interpret",
"from": "cost",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1550,
660
],
[
1550,
525
]
]
},
{
"id": "confidence-interpret",
"from": "confidence",
"to": "interpret",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1550,
910
],
[
1550,
525
]
] ]
} }
], ]
"connections": [] }
}
@@ -7,140 +7,256 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
880,
2800
]
}, },
"components": [ "components": [
{ {
"id": "risk", "id": "selection",
"type": "security", "type": "external",
"label": "Define the envelope", "label": "Right skill?",
"tag": "Owner + reviewers", "tag": "Selection evidence",
"sublabel": "R1: nonsensitive drafting\nR2: code / customer work\nR3: human-authorized\nAgree acceptance rules", "sublabel": "Triggers, near misses, negatives",
"pos": [ "pos": [
40, 60,
40 120
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "compare", "id": "safety",
"type": "backend", "type": "external",
"label": "Compare three paths", "label": "Safe execution?",
"tag": "Same starting artifacts", "tag": "Safety evidence",
"sublabel": "No skill / approved / new\nPositive + negative cases\nRepeat trials per client\nKeep failed attempts", "sublabel": "Permissions + adversarial trials",
"pos": [ "pos": [
40, 60,
610 490
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "inspect", "id": "artifact",
"type": "frontend", "type": "external",
"label": "Inspect the outcome", "label": "Valid artifact?",
"tag": "Independent evidence", "tag": "Independent inspection",
"sublabel": "Right skill selected?\nProcedure safe?\nArtifact checks pass?\nUseful workflow result?", "sublabel": "Tests + human assessment",
"pos": [ "pos": [
40, 60,
1180 860
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
},
{
"id": "outcome",
"type": "external",
"label": "Useful outcome?",
"tag": "Workflow evidence",
"sublabel": "Baseline + repeated trials",
"pos": [
60,
1230
],
"size": [
740,
220
],
"icon": "none"
}, },
{ {
"id": "gate", "id": "gate",
"type": "security", "type": "security",
"label": "Every gate must pass", "label": "Every gate must pass",
"tag": "Quality Engineering", "tag": "Risk sets evaluation depth",
"sublabel": "Safety + authorization\nSchema + provenance\nCritical effect blocks\nMissing coverage blocks", "sublabel": "No averaging away harm\nCritical effect blocks promotion\nMissing coverage = incomplete",
"pos": [ "pos": [
40, 60,
1750 1600
], ],
"size": [ "size": [
560, 740,
440 310
] ],
"icon": "none"
}, },
{ {
"id": "canary", "id": "accept",
"type": "cloud", "type": "backend",
"label": "Test bounded work", "label": "Accept evidence",
"tag": "Human + AI Agent", "tag": "All mandatory gates passed",
"sublabel": "Qualified client + model\nHuman judges usefulness\nShow counts / uncertainty\nEvidence before promotion", "sublabel": "Proceed to scoped approval",
"pos": [ "pos": [
40, 60,
2320 2060
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
}, },
{ {
"id": "improve", "id": "rework",
"type": "database", "type": "security",
"label": "Feed the next revision", "label": "Rework / retest",
"tag": "Owning team", "tag": "Any failure or missing evidence",
"sublabel": "Failures to regression set\nReview corrections\nMaterial client/model drift\ntriggers requalification", "sublabel": "Keep failures in the record",
"pos": [ "pos": [
40, 60,
2890 2430
], ],
"size": [ "size": [
560, 740,
440 220
] ],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "selection-gate",
"from": "risk", "from": "selection",
"to": "compare",
"fromSide": "bottom",
"toSide": "top",
"route": "straight"
},
{
"id": "flow-1",
"from": "compare",
"to": "inspect",
"fromSide": "bottom",
"toSide": "top",
"route": "straight"
},
{
"id": "flow-2",
"from": "inspect",
"to": "gate", "to": "gate",
"fromSide": "bottom", "label": "",
"toSide": "top", "fromSide": "right",
"route": "straight" "toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
230.0
],
[
850,
1755.0
]
],
"labelAt": [
620,
1560
]
}, },
{ {
"id": "flow-3", "id": "safety-gate",
"from": "safety",
"to": "gate",
"label": "",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
600.0
],
[
850,
1755.0
]
],
"labelAt": [
620,
1560
]
},
{
"id": "artifact-gate",
"from": "artifact",
"to": "gate",
"label": "",
"fromSide": "right",
"toSide": "right",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
850,
970.0
],
[
850,
1755.0
]
],
"labelAt": [
620,
1560
]
},
{
"id": "outcome-gate",
"from": "outcome",
"to": "gate",
"label": "",
"fromSide": "bottom",
"toSide": "top",
"route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1505
]
},
{
"id": "gate-accept",
"from": "gate", "from": "gate",
"to": "canary", "to": "accept",
"label": "Pass",
"fromSide": "bottom", "fromSide": "bottom",
"toSide": "top", "toSide": "top",
"route": "straight" "route": "straight",
"width": 4,
"variant": "default",
"labelAt": [
610,
1965
]
}, },
{ {
"id": "flow-4", "id": "gate-rework",
"from": "canary", "from": "gate",
"to": "improve", "to": "rework",
"fromSide": "bottom", "label": "Fail",
"toSide": "top", "fromSide": "right",
"route": "straight" "toSide": "right",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
824,
1755.0
],
[
824,
2540.0
]
],
"labelAt": [
620,
2390
]
} }
] ]
} }
+211 -91
View File
@@ -7,140 +7,260 @@
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
"mode": "hidden" "mode": "hidden"
} },
"viewBox": [
2000,
1050
]
}, },
"components": [ "components": [
{ {
"id": "risk", "id": "selection",
"type": "security", "type": "external",
"label": "Define the envelope", "label": "Right skill?",
"tag": "Owner + reviewers", "tag": "Selection evidence",
"sublabel": "R1: nonsensitive drafting\nR2: code / customer work\nR3: human-authorized\nAgree acceptance rules", "sublabel": "Triggers, near misses, negatives",
"pos": [ "pos": [
40, 60,
40 70
], ],
"size": [ "size": [
560, 510,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "compare", "id": "safety",
"type": "backend", "type": "external",
"label": "Compare three paths", "label": "Safe execution?",
"tag": "Same starting artifacts", "tag": "Safety evidence",
"sublabel": "No skill / approved / new\nPositive + negative cases\nRepeat trials per client\nKeep failed attempts", "sublabel": "Permissions + adversarial trials",
"pos": [ "pos": [
700, 60,
40 310
], ],
"size": [ "size": [
560, 510,
440 170
] ],
"icon": "none"
}, },
{ {
"id": "inspect", "id": "artifact",
"type": "frontend", "type": "external",
"label": "Inspect the outcome", "label": "Valid artifact?",
"tag": "Independent evidence", "tag": "Independent inspection",
"sublabel": "Right skill selected?\nProcedure safe?\nArtifact checks pass?\nUseful workflow result?", "sublabel": "Tests + human assessment",
"pos": [ "pos": [
1360, 60,
40 550
], ],
"size": [ "size": [
560, 510,
440 170
] ],
"icon": "none"
},
{
"id": "outcome",
"type": "external",
"label": "Useful outcome?",
"tag": "Workflow evidence",
"sublabel": "Baseline + repeated trials",
"pos": [
60,
790
],
"size": [
510,
170
],
"icon": "none"
}, },
{ {
"id": "gate", "id": "gate",
"type": "security", "type": "security",
"label": "Every gate must pass", "label": "Every gate must pass",
"tag": "Quality Engineering", "tag": "Risk sets evaluation depth",
"sublabel": "Safety + authorization\nSchema + provenance\nCritical effect blocks\nMissing coverage blocks", "sublabel": "No averaging away harm\nCritical effect blocks promotion\nMissing coverage = incomplete",
"pos": [ "pos": [
1360, 740,
610 350
], ],
"size": [ "size": [
560, 520,
440 310
] ],
"icon": "none"
}, },
{ {
"id": "canary", "id": "accept",
"type": "cloud", "type": "backend",
"label": "Test bounded work", "label": "Accept evidence",
"tag": "Human + AI Agent", "tag": "All mandatory gates passed",
"sublabel": "Qualified client + model\nHuman judges usefulness\nShow counts / uncertainty\nEvidence before promotion", "sublabel": "Proceed to scoped approval",
"pos": [ "pos": [
700, 1430,
610 160
], ],
"size": [ "size": [
560, 510,
440 190
] ],
"icon": "none"
}, },
{ {
"id": "improve", "id": "rework",
"type": "database", "type": "security",
"label": "Feed the next revision", "label": "Rework / retest",
"tag": "Owning team", "tag": "Any failure or missing evidence",
"sublabel": "Failures to regression set\nReview corrections\nMaterial client/model drift\ntriggers requalification", "sublabel": "Keep failures in the record",
"pos": [ "pos": [
40, 1430,
610 760
], ],
"size": [ "size": [
560, 510,
440 190
] ],
"icon": "none"
} }
], ],
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "selection-gate",
"from": "risk", "from": "selection",
"to": "compare",
"fromSide": "right",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-1",
"from": "compare",
"to": "inspect",
"fromSide": "right",
"toSide": "left",
"route": "straight"
},
{
"id": "flow-2",
"from": "inspect",
"to": "gate", "to": "gate",
"fromSide": "bottom", "label": "",
"toSide": "top", "fromSide": "right",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
650,
155
],
[
650,
505
]
]
}, },
{ {
"id": "flow-3", "id": "safety-gate",
"from": "safety",
"to": "gate",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
650,
395
],
[
650,
505
]
]
},
{
"id": "artifact-gate",
"from": "artifact",
"to": "gate",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
650,
635
],
[
650,
505
]
]
},
{
"id": "outcome-gate",
"from": "outcome",
"to": "gate",
"label": "",
"fromSide": "right",
"toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
650,
875
],
[
650,
505
]
]
},
{
"id": "gate-accept",
"from": "gate", "from": "gate",
"to": "canary", "to": "accept",
"fromSide": "left", "label": "Pass",
"toSide": "right", "fromSide": "right",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "default",
"via": [
[
1340,
505
],
[
1340,
255
]
],
"labelAt": [
1330,
210
]
}, },
{ {
"id": "flow-4", "id": "gate-rework",
"from": "canary", "from": "gate",
"to": "improve", "to": "rework",
"fromSide": "left", "label": "Fail",
"toSide": "right", "fromSide": "right",
"route": "straight" "toSide": "left",
"route": "straight",
"width": 4,
"variant": "security",
"via": [
[
1340,
505
],
[
1340,
855
]
],
"labelAt": [
1325,
900
]
} }
] ]
} }
+42
View File
@@ -0,0 +1,42 @@
const {chromium}=require('playwright');
const fs=require('node:fs');
const path=require('node:path');
const assert=require('node:assert/strict');
(async()=>{
const dir=process.argv[2]||'.cache/skills-candidate';
const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});
const results=[];
try {
for(const topic of ['governance','quality','adoption','measurement','maintenance']) for(const width of [1440,1024,390,320]){
const spec=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}${width<=1100?'-mobile':''}.architecture.json`));
const page=await browser.newPage({viewport:{width:1200,height:1000}});
await page.goto('file://'+path.resolve(`${dir}/${topic}-${width}.svg`));
const measured=await page.locator('svg').evaluate(svg=>{
const v=svg.viewBox.baseVal;const issues=[];
for(const el of svg.querySelectorAll('[data-node-id],path[data-edge-id],g[data-edge-id]')){
const b=el.getBBox();if(b.x<v.x-1||b.y<v.y-1||b.x+b.width>v.x+v.width+1||b.y+b.height>v.y+v.height+1)issues.push(el.getAttribute('data-node-id')||el.getAttribute('data-edge-id'));
}
// Measure the whole rendered label group, including its opaque mask:
// text presence alone cannot detect one label hiding another.
const labels=[...svg.querySelectorAll('g[data-edge-id]')].filter(el=>el.querySelector('text')).map(el=>({id:el.dataset.edgeId,box:el.getBoundingClientRect()}));
const labelOverlaps=[];
for(let i=0;i<labels.length;i++)for(let j=i+1;j<labels.length;j++){
const a=labels[i],b=labels[j];
if(Math.min(a.box.right,b.box.right)>Math.max(a.box.left,b.box.left)&&Math.min(a.box.bottom,b.box.bottom)>Math.max(a.box.top,b.box.top))labelOverlaps.push([a.id,b.id]);
}
return {labelOverlaps,viewBox:[v.width,v.height],nodes:[...svg.querySelectorAll('[data-node-id]')].map(n=>n.dataset.nodeId),edges:[...svg.querySelectorAll('path[data-edge-id]')].map(n=>n.dataset.edgeId),text:svg.textContent,issues};
});
assert.deepEqual(measured.viewBox,spec.meta.viewBox);
assert.deepEqual(measured.nodes.sort(),spec.components.map(n=>n.id).sort());
assert.deepEqual(measured.edges.sort(),spec.connections.map(e=>e.id).sort());
assert.deepEqual(measured.issues,[]);
assert.deepEqual(measured.labelOverlaps,[],`${topic}-${width}: rendered edge labels overlap`);
for(const n of spec.components){assert(measured.text.includes(n.label));assert(measured.text.includes(n.tag));for(const line of n.sublabel.split('\n'))assert(measured.text.includes(line));}
for(const e of spec.connections)if(e.label)assert(measured.text.includes(e.label));
if(width===1440)await page.screenshot({path:`${dir}/${topic}-standalone-export.png`});
results.push({topic,width,nodes:measured.nodes.length,edges:measured.edges.length,complete:true});await page.close();
}
fs.writeFileSync(`${dir}/export-results.json`,JSON.stringify(results,null,2));
console.log(`PASS ${results.length} standalone SVGs: exact graph, text, full-canvas containment and non-overlapping edge labels`);
}finally{await browser.close();}
})().catch(e=>{console.error(e);process.exitCode=1});
+2 -2
View File
@@ -33,7 +33,7 @@ const fs = require('node:fs');
const nodes = [...svg.querySelectorAll('[data-node-id]')].map(n => n.getBoundingClientRect().toJSON()); const nodes = [...svg.querySelectorAll('[data-node-id]')].map(n => n.getBoundingClientRect().toJSON());
return {nodes, width:innerWidth, height:innerHeight, minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n => parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))}; return {nodes, width:innerWidth, height:innerHeight, minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n => parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))};
}); });
assert.equal(geometry.nodes.length, 6); assert.equal(geometry.nodes.length, JSON.parse(fs.readFileSync('diagrams/strategy-measurement.architecture.json')).components.length);
for (const n of geometry.nodes) assert(n.x >= 0 && n.y >= 0 && n.right <= geometry.width + 1 && n.bottom <= geometry.height + 1); for (const n of geometry.nodes) assert(n.x >= 0 && n.y >= 0 && n.right <= geometry.width + 1 && n.bottom <= geometry.height + 1);
assert(geometry.minLabel >= 10, `readable node labels: ${geometry.minLabel}`); assert(geometry.minLabel >= 10, `readable node labels: ${geometry.minLabel}`);
await frame.locator('#btn-theme').click(); await frame.locator('#btn-theme').click();
@@ -50,7 +50,7 @@ const fs = require('node:fs');
assert.equal(await download.failure(), null); assert.equal(await download.failure(), null);
const path = `${output}/${width}.svg`; await download.saveAs(path); const path = `${output}/${width}.svg`; await download.saveAs(path);
const svg = fs.readFileSync(path, 'utf8'); const svg = fs.readFileSync(path, 'utf8');
assert(svg.includes('Establish baseline') && svg.includes('Ongoing monitoring')); assert(svg.includes('Compare with baseline') && svg.includes('Zero denominator = N/A'));
const opener = panel.getByRole('button', {name:/^Expand /}); const opener = panel.getByRole('button', {name:/^Expand /});
await opener.click(); await opener.click();
const close = panel.getByRole('button', {name:'Close full-screen diagram', exact:true}); const close = panel.getByRole('button', {name:'Close full-screen diagram', exact:true});
+4 -3
View File
@@ -11,7 +11,7 @@ const assert=require('node:assert/strict');
const route=topic==='measurement'?topic:`skills-${topic}`; const route=topic==='measurement'?topic:`skills-${topic}`;
assert.equal((await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}/`,{waitUntil:'networkidle'})).status(),200); assert.equal((await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}/`,{waitUntil:'networkidle'})).status(),200);
const panel=page.locator('.archify-panel--skills');assert.equal(await panel.count(),1); const panel=page.locator('.archify-panel--skills');assert.equal(await panel.count(),1);
const iframe=panel.locator(width>700?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded(); const iframe=panel.locator(width>1100?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded();
const frame=await(await iframe.elementHandle()).contentFrame();await frame.locator('svg[role="img"]').waitFor(); 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 geometry=await frame.locator('svg[role="img"]').evaluate(svg=>{
const nodes=[...svg.querySelectorAll('g[data-node-id]')];const issues=[];let min=Infinity; const nodes=[...svg.querySelectorAll('g[data-node-id]')];const issues=[];let min=Infinity;
@@ -21,14 +21,15 @@ const assert=require('node:assert/strict');
}} }}
return {nodes:nodes.length,min,issues,width:innerWidth,svgWidth:svg.getBoundingClientRect().width}; return {nodes:nodes.length,min,issues,width:innerWidth,svgWidth:svg.getBoundingClientRect().width};
}); });
assert.equal(geometry.nodes,6);assert.deepEqual(geometry.issues,[]);assert(geometry.min>=10,JSON.stringify(geometry)); const source=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}.architecture.json`));
assert.equal(geometry.nodes,source.components.length);assert.deepEqual(geometry.issues,[]);assert(geometry.min>=10,JSON.stringify(geometry));
for(const theme of ['light','dark']){ for(const theme of ['light','dark']){
if(await frame.locator('html').getAttribute('data-theme')!==theme)await frame.locator('#btn-theme').click(); if(await frame.locator('html').getAttribute('data-theme')!==theme)await frame.locator('#btn-theme').click();
await page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme); await page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme);
await panel.scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${topic}-${width}-${theme}-inline.png`}); await panel.scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${topic}-${width}-${theme}-inline.png`});
const open=panel.getByRole('button',{name:/^Expand /});await open.click();const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'}); const open=panel.getByRole('button',{name:/^Expand /});await open.click();const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
const expanded=await(await panel.locator('dialog iframe').elementHandle()).contentFrame();await expanded.locator('svg[role="img"]').waitFor(); const expanded=await(await panel.locator('dialog iframe').elementHandle()).contentFrame();await expanded.locator('svg[role="img"]').waitFor();
assert((await expanded.url()).includes(width<=700?`${topic}-mobile/`:`${topic}/`)); assert((await expanded.url()).includes(width<=1100?`${topic}-mobile/`:`${topic}/`));
await page.screenshot({path:`${out}/${topic}-${width}-${theme}-fullscreen.png`}); await page.screenshot({path:`${out}/${topic}-${width}-${theme}-fullscreen.png`});
if(width<=700){await page.setViewportSize({width,height:480});assert(await panel.locator('dialog').evaluate(n=>n.scrollHeight>n.clientHeight));await panel.locator('dialog').evaluate(n=>n.scrollTop=n.scrollHeight);await page.screenshot({path:`${out}/${topic}-${width}-${theme}-short-bottom.png`});await page.setViewportSize({width,height:900});} if(width<=700){await page.setViewportSize({width,height:480});assert(await panel.locator('dialog').evaluate(n=>n.scrollHeight>n.clientHeight));await panel.locator('dialog').evaluate(n=>n.scrollTop=n.scrollHeight);await page.screenshot({path:`${out}/${topic}-${width}-${theme}-short-bottom.png`});await page.setViewportSize({width,height:900});}
await close.focus();await page.keyboard.press('Escape');assert(await open.evaluate(n=>n===document.activeElement)); await close.focus();await page.keyboard.press('Escape');assert(await open.evaluate(n=>n===document.activeElement));
+3 -1
View File
@@ -19,7 +19,9 @@ const fs=require('node:fs');
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};}); 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))}; 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>=(id==='roadmap'?2:5) && geometry.nodes.length<=(['index','target-operating-model'].includes(id)?18:7),id); const name=await panel.getAttribute('data-diagram');
const source=JSON.parse(fs.readFileSync(`diagrams/${name}.${name==='strategy-roadmap'?'workflow':'architecture'}.json`));
assert.equal(geometry.nodes.length,(source.components||source.nodes).length,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}`); 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})); 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<=(id==='measurement'?1100:id==='roadmap'?600:200),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id); assert(data.words<=(id==='measurement'?1100:id==='roadmap'?600:200),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
+19 -7
View File
@@ -21,28 +21,40 @@ for(const topic of topics) test(`${topic}: rich native source, wide desktop, mob
const mobile=JSON.parse(read(`diagrams/${name}-mobile.architecture.json`)); const mobile=JSON.parse(read(`diagrams/${name}-mobile.architecture.json`));
const semantic = d=>d.components.map(({pos,size,...n})=>n); const semantic = d=>d.components.map(({pos,size,...n})=>n);
assert.deepEqual(semantic(desktop),semantic(mobile)); assert.deepEqual(semantic(desktop),semantic(mobile));
assert.equal(new Set(desktop.components.map(n=>n.pos[0])).size,3); assert(new Set(desktop.components.map(n=>n.pos[0])).size>1);
assert.equal(new Set(mobile.components.map(n=>n.pos[0])).size,1); assert.equal(new Set(mobile.components.map(n=>n.pos[0])).size,1);
for(const n of desktop.components){assert(n.tag);assert(n.sublabel.split('\n').length>=4);} for(const n of desktop.components){assert(n.tag);assert(n.sublabel);assert(n.sublabel.split('\n').length<=4);}
const dir=mkdtempSync(join(tmpdir(),'skills-viewer-')); const dir=mkdtempSync(join(tmpdir(),'skills-viewer-'));
try{ try{
const path=join(dir,'native.html'); const path=join(dir,'native.html');
execFileSync(process.execPath,['vendor/archify/renderers/architecture/render-architecture.mjs',`diagrams/${name}.architecture.json`,path]); execFileSync(process.execPath,['vendor/archify/renderers/architecture/render-architecture.mjs',`diagrams/${name}.architecture.json`,path]);
const native=read(path);const html=skillsViewer(native,desktop); const native=read(path);const html=skillsViewer(native,desktop);
assert.equal((html.match(/<g\b[^>]*data-node-id=/g)||[]).length,6); assert.equal((html.match(/<g\b[^>]*data-node-id=/g)||[]).length,desktop.components.length);
assert.equal((html.match(/<text data-node-label=/g)||[]).length,0); // Adapter uses explicit position before semantic attributes. assert.equal((html.match(/<text data-node-label=/g)||[]).length,0); // Adapter uses explicit position before semantic attributes.
assert.equal((html.match(/data-node-label=""/g)||[]).length,6); assert.equal((html.match(/data-node-label=""/g)||[]).length,desktop.components.length);
assert(html.includes('eldorado-skills-typography')); assert(html.includes('eldorado-skills-typography'));
assert.throws(()=>skillsViewer(native.replace('data-node-id="'+desktop.components[0].id+'"','data-node-id="missing"'),desktop)); assert.throws(()=>skillsViewer(native.replace('data-node-id="'+desktop.components[0].id+'"','data-node-id="missing"'),desktop));
const bad=structuredClone(desktop);bad.components[0].sublabel='not a full story';assert.throws(()=>skillsViewer(native,bad)); const bad=structuredClone(desktop);bad.components[0].sublabel='';assert.throws(()=>skillsViewer(native,bad));
}finally{rmSync(dir,{recursive:true,force:true});} }finally{rmSync(dir,{recursive:true,force:true});}
}); });
test('domain contracts retain human authority, honest measures and Delivery-first rollout',()=>{ test('domain contracts retain human authority, honest measures and Delivery-first rollout',()=>{
const text=t=>read(`diagrams/strategy-${t}.architecture.json`); const text=t=>JSON.stringify(JSON.parse(read(`diagrams/strategy-${t}.architecture.json`)));
assert(text('governance').includes('Author is not sole approver')); assert(text('governance').includes('Author is not sole approver'));
assert(text('quality').includes('Critical effect blocks')); assert(text('quality').includes('Critical effect blocks'));
assert(text('adoption').includes('Delivery first')&&text('adoption').includes('Later order undecided')); assert(text('adoption').includes('Delivery first')&&text('adoption').includes('Later order undecided'));
assert(text('adoption').includes('No quotas or rankings')); assert(text('adoption').includes('No quotas or rankings'));
for(const marker of ['Tracker:','Invoices + review minutes','linked defect records','Anonymous 1–5 survey','Missing buckets = partial','Zero denominator = N/A'])assert(text('measurement').includes(marker),marker); for(const marker of ['Tracker + acceptance','Invoices + review minutes','Changes + defects','Anonymous 1–5 survey','Missing buckets = partial','Zero denominator = N/A'])assert(text('measurement').includes(marker),marker);
assert(text('maintenance').includes('No automatic reinstatement')); assert(text('maintenance').includes('No automatic reinstatement'));
}); });
test('topic compositions explain distinct relationships rather than a fixed card count',()=>{
const spec=t=>JSON.parse(read(`diagrams/strategy-${t}.architecture.json`));
const has=(d,a,b)=>assert(d.connections.some(e=>e.from===a&&e.to===b),`${a} → ${b}`);
const g=spec('governance');const steps=g.components.filter(n=>/^0[1-6]/.test(n.label));
assert.equal(steps.length,6);
for(let i=1;i<steps.length;i++){assert(steps[i].pos[0]>steps[i-1].pos[0]);assert(steps[i].pos[1]>steps[i-1].pos[1]);has(g,steps[i-1].id,steps[i].id);}
has(g,'approve','owner');has(g,'distribute','withdraw');
const q=spec('quality');for(const id of ['selection','safety','artifact','outcome'])has(q,id,'gate');has(q,'gate','accept');has(q,'gate','rework');
const a=spec('adoption');for(const [x,y] of [['human','agent'],['agent','human'],['agent','learn'],['learn','delivery'],['learn','expand'],['human','expand']])has(a,x,y);
const m=spec('measurement');for(const id of ['success','quality','cost','confidence']){has(m,id+'-source',id);has(m,id,'interpret');}
const c=spec('maintenance');for(const [x,y] of [['observe','triage'],['triage','change'],['change','validate'],['validate','release'],['release','observe'],['triage','safe'],['safe','observe'],['triage','retire'],['triage','contain'],['contain','change']])has(c,x,y);
});
+18 -9
View File
@@ -1,8 +1,9 @@
// Keep native geometry, metadata, routing and exports; enrich only typography. // Native editable geometry and edges; scoped editorial typography for Stage 01.
export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|maintenance)(-mobile)?$/.test(name); export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|maintenance)(-mobile)?$/.test(name);
const escape = text => text.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;'); const escape = text => text.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;');
export function skillsViewer(html, spec) { export function skillsViewer(html, spec) {
if (spec.diagram_type !== 'architecture' || spec.components.length !== 6) throw new Error('Skills story contract drift'); if (spec.diagram_type !== 'architecture' || !spec.components.length) throw new Error('Skills story contract drift');
const detailSize = spec.meta.output.includes('-mobile/') ? 34 : 32;
for (const node of spec.components) { for (const node of spec.components) {
const pattern = new RegExp(`<g\\b[^>]*data-node-id="${node.id}"[^>]*>[\\s\\S]*?<text data-node-label=[\\s\\S]*?</g>`); const pattern = new RegExp(`<g\\b[^>]*data-node-id="${node.id}"[^>]*>[\\s\\S]*?<text data-node-label=[\\s\\S]*?</g>`);
const match = html.match(pattern); const match = html.match(pattern);
@@ -12,24 +13,32 @@ export function skillsViewer(html, spec) {
if (rectangles.length !== 2) throw new Error('Skills shape contract drift'); if (rectangles.length !== 2) throw new Error('Skills shape contract drift');
const [x,y] = node.pos; const [x,y] = node.pos;
const lines = node.sublabel.split('\n'); const lines = node.sublabel.split('\n');
if ((lines.length < 4 || lines.length > 5) || lines.some(line => line.length > 29) || node.label.length > 25) throw new Error(`Skills copy exceeds capacity: ${node.id}`); if (!node.tag || !node.sublabel || lines.length > 4) throw new Error(`Skills copy exceeds capacity: ${node.id}`);
const text = (value, top, size, attrs) => `<text x="${x+28}" y="${y+top}" font-size="${size}" ${attrs}>${escape(value)}</text>`; const text = (value, top, size, attrs) => `<text x="${x+28}" y="${y+top}" font-size="${size}" ${attrs}>${escape(value)}</text>`;
const content = text(node.tag, 52, 36, 'class="t-muted" data-detail="context"') const content = text(node.tag, 40, detailSize, 'class="t-muted" data-detail="context"')
+ text(node.label, 118, 42, 'class="t-primary" data-node-label="" font-weight="700"') + text(node.label, 89, 36, 'class="t-primary" data-node-label="" font-weight="700"')
+ lines.map((line,i) => text(line, 190+i*46, 36, 'class="t-primary" data-detail="context"')).join(''); + lines.map((line,i) => text(line, 138+i*42, detailSize, 'class="t-primary" data-detail="context"')).join('');
const prefix = original.slice(0,rectangles[1].index+rectangles[1][0].length).replaceAll('rx="6"','rx="0"'); const prefix = original.slice(0,rectangles[1].index+rectangles[1][0].length).replaceAll('rx="6"','rx="0"');
html = html.replace(original,prefix+content+'</g>'); html = html.replace(original,prefix+content+'</g>');
} }
const roots = [...html.matchAll(/<svg\b[^>]*role="img"[^>]*>/g)]; const roots = [...html.matchAll(/<svg\b[^>]*role="img"[^>]*>/g)];
if (roots.length !== 1) throw new Error('Skills SVG contract drift'); if (roots.length !== 1) throw new Error('Skills SVG contract drift');
const width = Math.max(...spec.components.map(n=>n.pos[0]+n.size[0]))+40; const [width,height] = spec.meta.viewBox;
const height = Math.max(...spec.components.map(n=>n.pos[1]+n.size[1]))+40;
const root = roots[0][0].replace(/viewBox="[^"]*"/,`viewBox="0 0 ${width} ${height}"`); const root = roots[0][0].replace(/viewBox="[^"]*"/,`viewBox="0 0 ${width} ${height}"`);
// Embedded in SVG so downloaded files retain typography without the viewer. // Embedded in SVG so downloaded files retain typography without the viewer.
html = html.replace(roots[0][0],root+`<style id="eldorado-skills-typography"> html = html.replace(roots[0][0],root+`<style id="eldorado-skills-typography">
[data-node-id] text {font-family:Arial,sans-serif;} [data-node-id] text {font-family:Arial,sans-serif;}
.c-grid {opacity:0;} rect[fill="url(#grid)"] {opacity:0;}
[data-node-id] > rect:not(.c-mask) {stroke-width:3;} [data-node-id] > rect:not(.c-mask) {stroke-width:3;}
[data-edge-id] {opacity:1;}
</style>`); </style>`);
// Native labels use tiny technical annotations. Enlarge both text and mask,
// retaining the native edge identity, routing and explicit label position.
html = html.replace(/(<g data-detail="context"[^>]*data-edge-id[^>]*>)([\s\S]*?)(<\/g>)/g, (all,open,body,close) => {
const text = body.match(/<text x="([^"]+)" y="([^"]+)"([^>]*)>([\s\S]*?)<\/text>/);
if (!text) throw new Error('Skills edge label contract drift');
const x=Number(text[1]), y=Number(text[2]), width=text[4].replace(/&[^;]+;/g,'x').length*17+24;
return open+`<rect x="${x-width/2}" y="${y-34}" width="${width}" height="44" class="c-mask"/>`+text[0].replace('font-size="8"',`font-size="${detailSize}"`)+close;
});
return html; return html;
} }
+2 -2
View File
@@ -35,10 +35,10 @@ test('mobile story diagrams preserve the same nodes and directed relationships',
} }
const desktop = JSON.parse(read(`diagrams/${name}.architecture.json`)); const desktop = JSON.parse(read(`diagrams/${name}.architecture.json`));
const mobile = JSON.parse(read(`diagrams/${name}-mobile.architecture.json`)); const mobile = JSON.parse(read(`diagrams/${name}-mobile.architecture.json`));
assert(desktop.components.length >= 5 && desktop.components.length <= (name === 'strategy-target' ? 18 : 7), name); assert(desktop.components.length >= 5, name);
const semantic = d => ({nodes:d.components.map(({pos,size,...n})=>n),edges:d.connections.map(({fromSide,toSide,route,via,labelAt,...e})=>e)}); const semantic = d => ({nodes:d.components.map(({pos,size,...n})=>n),edges:d.connections.map(({fromSide,toSide,route,via,labelAt,...e})=>e)});
assert.deepEqual(semantic(desktop), semantic(mobile), name); assert.deepEqual(semantic(desktop), semantic(mobile), name);
assert(desktop.connections.every(e => (e.label || e.id.startsWith('govern-') || /^strategy-(governance|quality|adoption|maintenance)$/.test(name)) && e.from !== e.to), name); assert(desktop.connections.every(e => (e.label || e.id.startsWith('govern-') || /^strategy-(governance|quality|adoption|measurement|maintenance)$/.test(name)) && e.from !== e.to), name);
assert.equal(desktop.meta.legend.mode, 'hidden'); assert.equal(desktop.meta.legend.mode, 'hidden');
} }
}); });
+1 -1
View File
@@ -15,7 +15,7 @@ export default function ArchifyDiagram({name, title, compact = false, story = fa
const skillsStory = /^strategy-(governance|quality|adoption|measurement|maintenance)$/.test(name); const skillsStory = /^strategy-(governance|quality|adoption|measurement|maintenance)$/.test(name);
useEffect(() => { useEffect(() => {
if (!name.startsWith('strategy-roadmap') && !skillsStory) return; if (!name.startsWith('strategy-roadmap') && !skillsStory) return;
const media = window.matchMedia(skillsStory ? '(max-width: 700px)' : '(max-width: 999px)'); const media = window.matchMedia(skillsStory ? '(max-width: 1100px)' : '(max-width: 999px)');
const update = () => setNarrowRoadmap(media.matches); const update = () => setNarrowRoadmap(media.matches);
update(); update();
media.addEventListener('change', update); media.addEventListener('change', update);
+12 -11
View File
@@ -116,8 +116,7 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
.archify-panel--story[data-diagram="strategy-roadmap-loop"] {--roadmap-height: 1840px;} .archify-panel--story[data-diagram="strategy-roadmap-loop"] {--roadmap-height: 1840px;}
.archify-panel--story[data-diagram="strategy-roadmap-loop"] > .story-desktop {height: 460px;} .archify-panel--story[data-diagram="strategy-roadmap-loop"] > .story-desktop {height: 460px;}
.archify-panel--story[data-diagram="strategy-target"] > iframe {aspect-ratio: 1620 / 1430;} .archify-panel--story[data-diagram="strategy-target"] > iframe {aspect-ratio: 1620 / 1430;}
.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 > 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 {cursor: pointer; font-weight: 700;}
.strategy-content summary:focus-visible {outline: 3px solid #b88719; outline-offset: 4px;} .strategy-content summary:focus-visible {outline: 3px solid #b88719; outline-offset: 4px;}
@@ -127,8 +126,7 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
.archify-panel--story > .story-desktop {display: none;} .archify-panel--story > .story-desktop {display: none;}
.archify-panel--story > .story-mobile {display: block; height: auto; aspect-ratio: 240 / 748;} .archify-panel--story > .story-mobile {display: block; height: auto; aspect-ratio: 240 / 748;}
.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: 680 / 2340;} .archify-panel--story[data-diagram="strategy-target"] > .story-mobile {aspect-ratio: 680 / 2340;}
} }
/* Keep the three-card loop readable beside the documentation sidebar. */ /* Keep the three-card loop readable beside the documentation sidebar. */
@@ -156,13 +154,16 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
/* Skills Adoption alone uses the full reading column, not a narrow preview. */ /* Skills Adoption alone uses the full reading column, not a narrow preview. */
.theme-doc-markdown:has(.archify-panel--skills) {max-width: none;} .theme-doc-markdown:has(.archify-panel--skills) {max-width: none;}
.archify-panel--story.archify-panel--skills {max-width: none;} .archify-panel--story.archify-panel--skills {max-width: none;}
.archify-panel--story.archify-panel--skills > .story-desktop {aspect-ratio: auto; min-height: 460px; height: calc((100vw - 364px) * .56 + 72px); max-height: 720px;} .archify-panel--skills {--skills-wide: 2000 / 1200; --skills-narrow: 880 / 2900;}
@media (max-width: 996px) and (min-width: 701px) { .archify-panel--skills[data-diagram="strategy-governance"] {--skills-wide: 1760 / 1550;}
.archify-panel--story.archify-panel--skills > .story-desktop {height: calc(100vw * .56 + 72px);} .archify-panel--skills[data-diagram="strategy-adoption"] {--skills-wide: 2040 / 1300; --skills-narrow: 880 / 2200;}
} .archify-panel--skills[data-diagram="strategy-measurement"] {--skills-wide: 2400 / 1280; --skills-narrow: 880 / 3900;}
@media (max-width: 700px) { .archify-panel--skills[data-diagram="strategy-maintenance"] {--skills-wide: 2630 / 1480; --skills-narrow: 880 / 3250;}
.archify-panel--story.archify-panel--skills > .story-mobile {aspect-ratio: auto; height: 1680px; max-width: 400px; margin-inline: auto;} .archify-panel--story.archify-panel--skills > .story-desktop {aspect-ratio: var(--skills-wide); height: auto;}
@media (max-width: 1100px) {
.archify-panel--story.archify-panel--skills > .story-desktop {display: none;}
.archify-panel--story.archify-panel--skills > .story-mobile {display: block; aspect-ratio: var(--skills-narrow); height: auto; max-width: 440px; margin-inline: auto;}
.archify-panel--skills .archify-modal {overflow-y: auto; overscroll-behavior: contain;} .archify-panel--skills .archify-modal {overflow-y: auto; overscroll-behavior: contain;}
.archify-panel--skills .archify-modal-toolbar {position: sticky; top: 0; z-index: 1; flex-shrink: 0; background: var(--surface);} .archify-panel--skills .archify-modal-toolbar {position: sticky; top: 0; z-index: 1; flex-shrink: 0; background: var(--surface);}
.archify-panel--skills .archify-modal iframe {flex: none; height: 1900px; min-height: 1900px;} .archify-panel--skills .archify-modal iframe {flex: none; height: auto; min-height: 0; aspect-ratio: var(--skills-narrow); max-width: 600px; margin-inline: auto;}
} }