Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ac6e2bc6f | ||
|
|
946b6f1cbb | ||
|
|
accca0cb1f | ||
|
|
b33b59659c | ||
|
|
86b1c769a3 | ||
|
|
499049eff3 | ||
|
|
46bb8b2b48 | ||
|
|
c88f4dbc25 | ||
|
|
eea14bf00f | ||
|
|
4e94ad24fd | ||
|
|
7472b835e8 | ||
|
|
8a9363ccb2 | ||
|
|
3696788082 | ||
|
|
f23bf1c5f4 | ||
|
|
d8feeba025 | ||
|
|
e96e780beb | ||
|
|
432370473d | ||
|
|
6b38b128d4 | ||
|
|
f059f4c324 | ||
|
|
9a7766b323 | ||
|
|
a283d6a34a | ||
|
|
9bacb7043a | ||
|
|
5c5809d349 | ||
|
|
fcaa84f3bf | ||
|
|
1a2d16bc91 | ||
|
|
88a4375776 |
No files matched your search
@@ -6,3 +6,4 @@ build/
|
|||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
static/diagrams/
|
static/diagrams/
|
||||||
|
static/presentations/
|
||||||
@@ -81,9 +81,9 @@
|
|||||||
{
|
{
|
||||||
"id": "expand",
|
"id": "expand",
|
||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "Expand on evidence",
|
"label": "Decide from evidence",
|
||||||
"tag": "Other SDLC phases",
|
"tag": "Owner; new scope is separate",
|
||||||
"sublabel": "Later order undecided\nDelivery keeps improving",
|
"sublabel": "Retain / improve / hold / stop\nExpansion is a new proposal",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
1650
|
1650
|
||||||
|
|||||||
@@ -81,9 +81,9 @@
|
|||||||
{
|
{
|
||||||
"id": "expand",
|
"id": "expand",
|
||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "Expand on evidence",
|
"label": "Decide from evidence",
|
||||||
"tag": "Other SDLC phases",
|
"tag": "Owner; new scope is separate",
|
||||||
"sublabel": "Later order undecided\nDelivery keeps improving",
|
"sublabel": "Retain / improve / hold / stop\nExpansion is a new proposal",
|
||||||
"pos": [
|
"pos": [
|
||||||
1460,
|
1460,
|
||||||
360
|
360
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
"type": "external",
|
"type": "external",
|
||||||
"label": "03 Authorize pilot",
|
"label": "03 Authorize pilot",
|
||||||
"tag": "Owning team approver",
|
"tag": "Owning team approver",
|
||||||
"sublabel": "Qualified; bounded pilot",
|
"sublabel": "Qualified; pin, load, pilot",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
860
|
860
|
||||||
@@ -65,9 +65,9 @@
|
|||||||
{
|
{
|
||||||
"id": "approve",
|
"id": "approve",
|
||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "04 Approve exact scope",
|
"label": "04 Decide exact scope",
|
||||||
"tag": "Accountable approvers",
|
"tag": "Accountable approvers",
|
||||||
"sublabel": "Pilot evidence + digest + expiry",
|
"sublabel": "Compare pilot: approve / hold",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
1230
|
1230
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"type": "security",
|
"type": "security",
|
||||||
"label": "Withdraw / roll back",
|
"label": "Withdraw / roll back",
|
||||||
"tag": "Unsafe revision",
|
"tag": "Unsafe revision",
|
||||||
"sublabel": "Revoke; restore last-known-good",
|
"sublabel": "Revoke; restore or remove candidate",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
2340
|
2340
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
"type": "external",
|
"type": "external",
|
||||||
"label": "03 Authorize pilot",
|
"label": "03 Authorize pilot",
|
||||||
"tag": "Owning team approver",
|
"tag": "Owning team approver",
|
||||||
"sublabel": "Qualified; bounded pilot",
|
"sublabel": "Qualified; pin, load, pilot",
|
||||||
"pos": [
|
"pos": [
|
||||||
520,
|
520,
|
||||||
500
|
500
|
||||||
@@ -65,9 +65,9 @@
|
|||||||
{
|
{
|
||||||
"id": "approve",
|
"id": "approve",
|
||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "04 Approve exact scope",
|
"label": "04 Decide exact scope",
|
||||||
"tag": "Accountable approvers",
|
"tag": "Accountable approvers",
|
||||||
"sublabel": "Pilot evidence + digest + expiry",
|
"sublabel": "Compare pilot: approve / hold",
|
||||||
"pos": [
|
"pos": [
|
||||||
740,
|
740,
|
||||||
720
|
720
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"type": "security",
|
"type": "security",
|
||||||
"label": "Withdraw / roll back",
|
"label": "Withdraw / roll back",
|
||||||
"tag": "Unsafe revision",
|
"tag": "Unsafe revision",
|
||||||
"sublabel": "Revoke; restore last-known-good",
|
"sublabel": "Revoke; restore or remove candidate",
|
||||||
"pos": [
|
"pos": [
|
||||||
80,
|
80,
|
||||||
1160
|
1160
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"sublabel": "Useful? Safe? Still needed?",
|
"sublabel": "Useful? Safe? Still needed?",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
1970
|
490
|
||||||
],
|
],
|
||||||
"size": [
|
"size": [
|
||||||
740,
|
740,
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"sublabel": "Fitness + regression + client checks",
|
"sublabel": "Fitness + regression + client checks",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
860
|
1600
|
||||||
],
|
],
|
||||||
"size": [
|
"size": [
|
||||||
740,
|
740,
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
"sublabel": "Verify distribution and recovery",
|
"sublabel": "Verify distribution and recovery",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
490
|
1970
|
||||||
],
|
],
|
||||||
"size": [
|
"size": [
|
||||||
740,
|
740,
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
"sublabel": "Revoke + quarantine + roll back\nNo automatic reinstatement",
|
"sublabel": "Revoke + quarantine + roll back\nNo automatic reinstatement",
|
||||||
"pos": [
|
"pos": [
|
||||||
60,
|
60,
|
||||||
1600
|
860
|
||||||
],
|
],
|
||||||
"size": [
|
"size": [
|
||||||
740,
|
740,
|
||||||
@@ -144,195 +144,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{"id":"observe-triage","from":"observe","to":"triage","label":"","fromSide":"bottom","toSide":"top","route":"straight","width":4,"variant":"default"},
|
||||||
"id": "observe-triage",
|
{"id":"triage-change","from":"triage","to":"change","label":"Correct","fromSide":"right","toSide":"right","route":"straight","width":4,"variant":"default","via":[[824,600],[824,1340]],"labelAt":[640,1190]},
|
||||||
"from": "observe",
|
{"id":"change-validate","from":"change","to":"validate","label":"","fromSide":"bottom","toSide":"top","route":"straight","width":4,"variant":"default"},
|
||||||
"to": "triage",
|
{"id":"validate-release","from":"validate","to":"release","label":"","fromSide":"bottom","toSide":"top","route":"straight","width":4,"variant":"default"},
|
||||||
"label": "",
|
{"id":"release-observe","from":"release","to":"observe","label":"","fromSide":"left","toSide":"left","route":"straight","width":4,"variant":"default","via":[[42,2080],[42,230]]},
|
||||||
"fromSide": "left",
|
{"id":"triage-safe","from":"triage","to":"safe","label":"Safe","fromSide":"right","toSide":"right","route":"straight","width":4,"variant":"default","via":[[872,600],[872,2820]],"labelAt":[620,2670]},
|
||||||
"toSide": "left",
|
{"id":"triage-retire","from":"triage","to":"retire","label":"Retire","fromSide":"right","toSide":"right","route":"straight","width":4,"variant":"default","via":[[850,600],[850,2450]],"labelAt":[620,2300]},
|
||||||
"route": "straight",
|
{"id":"triage-contain","from":"triage","to":"contain","label":"Unsafe","fromSide":"bottom","toSide":"top","route":"straight","width":4,"variant":"security","labelAt":[610,795]},
|
||||||
"width": 4,
|
{"id":"contain-change","from":"contain","to":"change","label":"Reviewed fix","fromSide":"bottom","toSide":"top","route":"straight","width":4,"variant":"security","labelAt":[610,1135]},
|
||||||
"variant": "default",
|
{"id":"safe-observe","from":"safe","to":"observe","label":"Keep watching","fromSide":"left","toSide":"left","route":"straight","width":4,"variant":"default","via":[[20,2820],[20,230]],"labelAt":[620,80]}
|
||||||
"via": [
|
|
||||||
[
|
|
||||||
20,
|
|
||||||
230.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
20,
|
|
||||||
2080.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"labelAt": [
|
|
||||||
620,
|
|
||||||
1930
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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",
|
|
||||||
"to": "contain",
|
|
||||||
"label": "Unsafe",
|
|
||||||
"fromSide": "top",
|
|
||||||
"toSide": "bottom",
|
|
||||||
"route": "straight",
|
|
||||||
"width": 4,
|
|
||||||
"variant": "security",
|
|
||||||
"labelAt": [
|
|
||||||
610,
|
|
||||||
1875
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "contain-change",
|
|
||||||
"from": "contain",
|
|
||||||
"to": "change",
|
|
||||||
"label": "Reviewed fix",
|
|
||||||
"fromSide": "top",
|
|
||||||
"toSide": "bottom",
|
|
||||||
"route": "straight",
|
|
||||||
"width": 4,
|
|
||||||
"variant": "security",
|
|
||||||
"labelAt": [
|
|
||||||
610,
|
|
||||||
1505
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "safe-observe",
|
|
||||||
"from": "safe",
|
|
||||||
"to": "observe",
|
|
||||||
"label": "Keep watching",
|
|
||||||
"fromSide": "left",
|
|
||||||
"toSide": "left",
|
|
||||||
"route": "straight",
|
|
||||||
"width": 4,
|
|
||||||
"variant": "default",
|
|
||||||
"via": [
|
|
||||||
[
|
|
||||||
42,
|
|
||||||
2820.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
42,
|
|
||||||
230.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"labelAt": [
|
|
||||||
620,
|
|
||||||
80
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "Proposed: first six months as AI Architect",
|
||||||
|
"output": "static/diagrams/strategy-six-months-mobile/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
},
|
||||||
|
"viewBox": [
|
||||||
|
1000,
|
||||||
|
2950
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "baseline",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 1: discover",
|
||||||
|
"tag": "Architect + CTO + willing teams",
|
||||||
|
"sublabel": "Current AI workflows + constraints\nPair with developers and reviewers\nChoose an evidenced bottleneck",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "engineer",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 2: agree experiment",
|
||||||
|
"tag": "Architect + partner lead + reviewer",
|
||||||
|
"sublabel": "One workflow + feasible baseline\nChoose context, coaching or tooling\nSkills only if they fit the problem",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
450
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qualify",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Month 3: pair and pilot",
|
||||||
|
"tag": "Team agrees time; owner permits scope",
|
||||||
|
"sublabel": "Independent checks before live work\nCollect accepted work and burden\nUnsafe or unsupported: stop",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 4: decide from evidence",
|
||||||
|
"tag": "Workflow owner + CTO review",
|
||||||
|
"sublabel": "Compare current practice and pilot\nRetain / change / hold / stop\nIncomplete: bounded extension only",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
1270
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Month 5: transfer selectively",
|
||||||
|
"tag": "Willing champion + team lead",
|
||||||
|
"sublabel": "Only if value and upkeep hold\nTry another team with new baseline\nNo capacity: stay narrow or retire",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
1680
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maintain",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 6: hand over or stop",
|
||||||
|
"tag": "Team owner + CTO investment decision",
|
||||||
|
"sublabel": "Evidence, costs and limits visible\nOwned workflow or documented stop\nNext quarter is not automatic AI",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
2090
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "reference",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Proposed six-month plan",
|
||||||
|
"tag": "Solo architect; no team authority",
|
||||||
|
"sublabel": "Month 6 → 2: revise next question\nMonth 5 → 1: baseline new scope\nProposed, not company commitments",
|
||||||
|
"pos": [
|
||||||
|
200,
|
||||||
|
2500
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
740,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "baseline-engineer",
|
||||||
|
"from": "baseline",
|
||||||
|
"to": "engineer",
|
||||||
|
"label": "Problem",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
570,
|
||||||
|
405
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "engineer-qualify",
|
||||||
|
"from": "engineer",
|
||||||
|
"to": "qualify",
|
||||||
|
"label": "Agreement",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
570,
|
||||||
|
815
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qualify-pilot",
|
||||||
|
"from": "qualify",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "Evidence",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
570,
|
||||||
|
1225
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot-decide",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "decide",
|
||||||
|
"label": "Decision",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
570,
|
||||||
|
1635
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide-maintain",
|
||||||
|
"from": "decide",
|
||||||
|
"to": "maintain",
|
||||||
|
"label": "Handover",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
570,
|
||||||
|
2045
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maintain-engineer",
|
||||||
|
"from": "maintain",
|
||||||
|
"to": "engineer",
|
||||||
|
"label": "",
|
||||||
|
"fromSide": "left",
|
||||||
|
"toSide": "left",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"via": [
|
||||||
|
[
|
||||||
|
145,
|
||||||
|
2240
|
||||||
|
],
|
||||||
|
[
|
||||||
|
145,
|
||||||
|
600
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide-baseline",
|
||||||
|
"from": "decide",
|
||||||
|
"to": "baseline",
|
||||||
|
"label": "",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "right",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"via": [
|
||||||
|
[
|
||||||
|
980,
|
||||||
|
1830
|
||||||
|
],
|
||||||
|
[
|
||||||
|
980,
|
||||||
|
190
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "Proposed: first six months as AI Architect",
|
||||||
|
"output": "static/diagrams/strategy-six-months/index.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"legend": {
|
||||||
|
"mode": "hidden"
|
||||||
|
},
|
||||||
|
"viewBox": [
|
||||||
|
2400,
|
||||||
|
1580
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "baseline",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 1: discover",
|
||||||
|
"tag": "Architect + CTO + willing teams",
|
||||||
|
"sublabel": "Current AI workflows + constraints\nPair with developers and reviewers\nChoose an evidenced bottleneck",
|
||||||
|
"pos": [
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "engineer",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 2: agree experiment",
|
||||||
|
"tag": "Architect + partner lead + reviewer",
|
||||||
|
"sublabel": "One workflow + feasible baseline\nChoose context, coaching or tooling\nSkills only if they fit the problem",
|
||||||
|
"pos": [
|
||||||
|
900,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qualify",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Month 3: pair and pilot",
|
||||||
|
"tag": "Team agrees time; owner permits scope",
|
||||||
|
"sublabel": "Independent checks before live work\nCollect accepted work and burden\nUnsafe or unsupported: stop",
|
||||||
|
"pos": [
|
||||||
|
1700,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 4: decide from evidence",
|
||||||
|
"tag": "Workflow owner + CTO review",
|
||||||
|
"sublabel": "Compare current practice and pilot\nRetain / change / hold / stop\nIncomplete: bounded extension only",
|
||||||
|
"pos": [
|
||||||
|
1700,
|
||||||
|
730
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide",
|
||||||
|
"type": "security",
|
||||||
|
"label": "Month 5: transfer selectively",
|
||||||
|
"tag": "Willing champion + team lead",
|
||||||
|
"sublabel": "Only if value and upkeep hold\nTry another team with new baseline\nNo capacity: stay narrow or retire",
|
||||||
|
"pos": [
|
||||||
|
900,
|
||||||
|
730
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maintain",
|
||||||
|
"type": "external",
|
||||||
|
"label": "Month 6: hand over or stop",
|
||||||
|
"tag": "Team owner + CTO investment decision",
|
||||||
|
"sublabel": "Evidence, costs and limits visible\nOwned workflow or documented stop\nNext quarter is not automatic AI",
|
||||||
|
"pos": [
|
||||||
|
100,
|
||||||
|
730
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
600,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "reference",
|
||||||
|
"type": "backend",
|
||||||
|
"label": "Proposed six-month plan",
|
||||||
|
"tag": "Solo architect; no team authority",
|
||||||
|
"sublabel": "Month 6 → 2: revise next question\nMonth 5 → 1: baseline new scope\nProposed, not company commitments",
|
||||||
|
"pos": [
|
||||||
|
100,
|
||||||
|
1270
|
||||||
|
],
|
||||||
|
"size": [
|
||||||
|
2200,
|
||||||
|
260
|
||||||
|
],
|
||||||
|
"icon": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"id": "baseline-engineer",
|
||||||
|
"from": "baseline",
|
||||||
|
"to": "engineer",
|
||||||
|
"label": "Problem",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "left",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
800,
|
||||||
|
210
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "engineer-qualify",
|
||||||
|
"from": "engineer",
|
||||||
|
"to": "qualify",
|
||||||
|
"label": "Agreement",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toSide": "left",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
1600,
|
||||||
|
210
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qualify-pilot",
|
||||||
|
"from": "qualify",
|
||||||
|
"to": "pilot",
|
||||||
|
"label": "Evidence",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "top",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"via": [
|
||||||
|
[
|
||||||
|
2000,
|
||||||
|
520
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"labelAt": [
|
||||||
|
2010,
|
||||||
|
535
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pilot-decide",
|
||||||
|
"from": "pilot",
|
||||||
|
"to": "decide",
|
||||||
|
"label": "Decision",
|
||||||
|
"fromSide": "left",
|
||||||
|
"toSide": "right",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
1600,
|
||||||
|
840
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide-maintain",
|
||||||
|
"from": "decide",
|
||||||
|
"to": "maintain",
|
||||||
|
"label": "Handover",
|
||||||
|
"fromSide": "left",
|
||||||
|
"toSide": "right",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"labelAt": [
|
||||||
|
800,
|
||||||
|
840
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maintain-engineer",
|
||||||
|
"from": "maintain",
|
||||||
|
"to": "engineer",
|
||||||
|
"label": "Next question",
|
||||||
|
"fromSide": "top",
|
||||||
|
"toSide": "bottom",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"via": [
|
||||||
|
[
|
||||||
|
400,
|
||||||
|
550
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1200,
|
||||||
|
550
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"labelAt": [
|
||||||
|
800,
|
||||||
|
535
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "decide-baseline",
|
||||||
|
"from": "decide",
|
||||||
|
"to": "baseline",
|
||||||
|
"label": "New scope",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toSide": "bottom",
|
||||||
|
"route": "straight",
|
||||||
|
"width": 4,
|
||||||
|
"variant": "default",
|
||||||
|
"via": [
|
||||||
|
[
|
||||||
|
1200,
|
||||||
|
1150
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60,
|
||||||
|
1150
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60,
|
||||||
|
430
|
||||||
|
],
|
||||||
|
[
|
||||||
|
400,
|
||||||
|
430
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"labelAt": [
|
||||||
|
620,
|
||||||
|
1135
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -33,9 +33,9 @@
|
|||||||
{
|
{
|
||||||
"id": "engineer",
|
"id": "engineer",
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"label": "Engineer connected skills",
|
"label": "Choose an intervention",
|
||||||
"tag": "Owning team + independent reviewer",
|
"tag": "Owning team + independent reviewer",
|
||||||
"sublabel": "Triggers, inputs and output handoffs\nPinned candidate + client + limits\nDeliver: patch and regression tests",
|
"sublabel": "Context, coaching, tooling or skills\nPinned candidate + client + limits\nDeliver: patch and regression tests",
|
||||||
"pos": [
|
"pos": [
|
||||||
200,
|
200,
|
||||||
450
|
450
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "Governance + Measurement",
|
"label": "Governance + Measurement",
|
||||||
"tag": "Throughout, not one-time gates",
|
"tag": "Throughout, not one-time gates",
|
||||||
"sublabel": "Named people + controlled authority\nSelected workflow + skill evidence\nKeep populations and gaps explicit",
|
"sublabel": "Left return: changed revision\nRight return: new scope needs baseline\nSelected evidence; no forced rollout",
|
||||||
"pos": [
|
"pos": [
|
||||||
200,
|
200,
|
||||||
2500
|
2500
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
{
|
{
|
||||||
"id": "engineer",
|
"id": "engineer",
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"label": "Engineer connected skills",
|
"label": "Choose an intervention",
|
||||||
"tag": "Owning team + independent reviewer",
|
"tag": "Owning team + independent reviewer",
|
||||||
"sublabel": "Triggers, inputs and output handoffs\nPinned candidate + client + limits\nDeliver: patch and regression tests",
|
"sublabel": "Context, coaching, tooling or skills\nPinned candidate + client + limits\nDeliver: patch and regression tests",
|
||||||
"pos": [
|
"pos": [
|
||||||
900,
|
900,
|
||||||
100
|
100
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"type": "backend",
|
"type": "backend",
|
||||||
"label": "Governance + Measurement",
|
"label": "Governance + Measurement",
|
||||||
"tag": "Throughout, not one-time gates",
|
"tag": "Throughout, not one-time gates",
|
||||||
"sublabel": "Named people + controlled authority\nSelected workflow + skill evidence\nKeep populations and gaps explicit",
|
"sublabel": "Left return: changed revision\nRight return: new scope needs baseline\nSelected evidence; no forced rollout",
|
||||||
"pos": [
|
"pos": [
|
||||||
100,
|
100,
|
||||||
1270
|
1270
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Structure
|
title: Structure
|
||||||
|
pagination_next: structure/product
|
||||||
description: Eldorado’s organizational operating model, departments, teams and responsibilities.
|
description: Eldorado’s organizational operating model, departments, teams and responsibilities.
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -26,90 +27,12 @@ Functional leaders translate company priorities into departmental plans. Team le
|
|||||||
|
|
||||||
Product has **two teams** and Technology has **five teams**. Operations, Marketing, Finance & Accounting, and HR & Administration each have **one squad** covering their departmental workstreams. Each team belongs to one department, with its own leadership and responsibilities. The departments collaborate on delivery without sharing team ownership.
|
Product has **two teams** and Technology has **five teams**. Operations, Marketing, Finance & Accounting, and HR & Administration each have **one squad** covering their departmental workstreams. Each team belongs to one department, with its own leadership and responsibilities. The departments collaborate on delivery without sharing team ownership.
|
||||||
|
|
||||||
### Product
|
- <span id="product">[Product](./structure/product.mdx)</span>
|
||||||
|
- <span id="technology">[Technology](./structure/technology.mdx)</span>
|
||||||
**Purpose:** improve the buyer and seller experience and turn marketplace opportunities into valuable product capabilities.
|
- <span id="operations">[Operations](./structure/operations.mdx)</span>
|
||||||
|
- <span id="marketing">[Marketing](./structure/marketing.mdx)</span>
|
||||||
| Team | Responsibilities |
|
- <span id="finance--accounting">[Finance & Accounting](./structure/finance-accounting.mdx)</span>
|
||||||
| --- | --- |
|
- <span id="hr--administration">[HR & Administration](./structure/hr-administration.mdx)</span>
|
||||||
| Product Management | Product strategy, roadmaps, priorities and outcome measurement across discovery, categories, orders, seller tools, payments and operational workflows. |
|
|
||||||
| Product Design | User research, interaction design, design consistency and accessible buyer and seller experiences. |
|
|
||||||
|
|
||||||
Product Management owns what to improve and why. Product Design shapes the experience. Both work with Technology teams while remaining within Product.
|
|
||||||
|
|
||||||
### Technology
|
|
||||||
|
|
||||||
**Purpose:** build and operate a secure, reliable marketplace and improve the effectiveness of engineering.
|
|
||||||
|
|
||||||
| Team | Responsibilities |
|
|
||||||
| --- | --- |
|
|
||||||
| Product Engineering | Build and maintain marketplace capabilities, including search, orders, seller tools, checkout, wallet and operational tooling. |
|
|
||||||
| Platform & IT | Platform services, delivery infrastructure, observability, reliability, performance, internal systems, employee devices and identity administration. |
|
|
||||||
| Architecture & Security | Technical standards, system design, security architecture and secure engineering practices. |
|
|
||||||
| Quality Engineering | Test strategy, automation, release quality and defect prevention. |
|
|
||||||
| Data & AI | Analytics, experimentation, ranking, recommendations, marketplace ML and safe AI-assisted engineering workflows. |
|
|
||||||
|
|
||||||
The CTO owns technology direction. The Head of Engineering leads engineering delivery through Group Engineering Managers and Engineering Managers. The AI Architect coordinates AI enablement within Data & AI, working with Architecture & Security and the other Technology teams. These are leadership roles within the five-team structure, not additional teams.
|
|
||||||
|
|
||||||
### Operations
|
|
||||||
|
|
||||||
**Purpose:** keep marketplace trading dependable and resolve customer issues fairly and efficiently.
|
|
||||||
|
|
||||||
**Operations Squad** delivers the department’s responsibilities across the following workstreams.
|
|
||||||
|
|
||||||
| Workstream | Responsibilities |
|
|
||||||
| --- | --- |
|
|
||||||
| Customer Support | Buyer and seller assistance, knowledge management, self-service and support workflow automation. |
|
|
||||||
| Trust & Resolution | Disputes, appeals, refunds, warranties, chargebacks and complex customer cases. |
|
|
||||||
| Risk & Fraud | Transaction and account risk, fraud prevention, investigations and operational controls. |
|
|
||||||
| Operational Quality | Independent case reviews, quality standards, calibration, service accuracy and improvement tracking across operational teams. |
|
|
||||||
|
|
||||||
The COO coordinates Operations. Team leads manage specialists and daily service delivery. Operational Quality reports directly to the COO and reviews quality across teams.
|
|
||||||
|
|
||||||
### Marketing
|
|
||||||
|
|
||||||
**Purpose:** attract and retain customers, build the Eldorado brand and grow marketplace demand.
|
|
||||||
|
|
||||||
**Marketing Squad** delivers the department’s responsibilities across the following workstreams.
|
|
||||||
|
|
||||||
| Workstream | Responsibilities |
|
|
||||||
| --- | --- |
|
|
||||||
| Brand & Community | Brand positioning, campaigns, organic social, community and brand partnerships. |
|
|
||||||
| Creative | Campaign concepts, visual assets and performance creative. |
|
|
||||||
| SEO | Organic discovery, search visibility and content performance. |
|
|
||||||
| PPC & Affiliate | Paid acquisition, affiliate channels and return on marketing investment. |
|
|
||||||
| Influencer | Creator relationships, influencer programs and campaign delivery. |
|
|
||||||
| CRM | Customer lifecycle communication, retention, reactivation and campaign personalization. |
|
|
||||||
|
|
||||||
The CMO coordinates Marketing. The Brand Team Lead owns Brand & Community, with shared support from Creative and the other marketing workstreams.
|
|
||||||
|
|
||||||
### Finance & Accounting
|
|
||||||
|
|
||||||
**Purpose:** maintain financial control, support business decisions and keep marketplace money flows dependable.
|
|
||||||
|
|
||||||
**Finance & Accounting Squad** delivers the department’s responsibilities across the following workstreams.
|
|
||||||
|
|
||||||
| Workstream | Responsibilities |
|
|
||||||
| --- | --- |
|
|
||||||
| Financial Planning & Analysis | Budgets, forecasts, profitability, management reporting and investment analysis. |
|
|
||||||
| Accounting, Tax & Controls | Accounting, financial reporting, tax, audit coordination and internal controls. |
|
|
||||||
| Treasury & Payment Operations | Cash management, reconciliation, payout oversight, payment-provider coordination and financial risk. |
|
|
||||||
|
|
||||||
The CFO coordinates Finance & Accounting and works with executive leadership on business performance. Finance, Operations and Product share responsibility for effective payment and withdrawal processes, each within its own area of expertise.
|
|
||||||
|
|
||||||
### HR & Administration
|
|
||||||
|
|
||||||
**Purpose:** help teams attract, develop and retain people and provide an effective working environment.
|
|
||||||
|
|
||||||
**People & Administration Squad** delivers the department’s responsibilities across the following workstreams.
|
|
||||||
|
|
||||||
| Workstream | Responsibilities |
|
|
||||||
| --- | --- |
|
|
||||||
| Talent Acquisition | Recruitment, candidate experience, hiring coordination and workforce demand support. |
|
|
||||||
| People Operations | Employee onboarding, development, performance processes, policies and employee experience. |
|
|
||||||
| Office & Administration | Workplace services, office operations and administrative coordination. |
|
|
||||||
|
|
||||||
HR partners with department leaders on team capacity and development. People Operations works with Platform & IT on employee onboarding, role changes and offboarding.
|
|
||||||
|
|
||||||
## Related pages
|
## Related pages
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Finance & Accounting
|
||||||
|
pagination_prev: structure/marketing
|
||||||
|
pagination_next: structure/hr-administration
|
||||||
|
description: Finance & Accounting purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** maintain financial control, support business decisions and keep marketplace money flows dependable.
|
||||||
|
|
||||||
|
**Finance & Accounting Squad** delivers the department’s responsibilities across the following workstreams.
|
||||||
|
|
||||||
|
| Workstream | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Financial Planning & Analysis | Budgets, forecasts, profitability, management reporting and investment analysis. |
|
||||||
|
| Accounting, Tax & Controls | Accounting, financial reporting, tax, audit coordination and internal controls. |
|
||||||
|
| Treasury & Payment Operations | Cash management, reconciliation, payout oversight, payment-provider coordination and financial risk. |
|
||||||
|
|
||||||
|
The CFO coordinates Finance & Accounting and works with executive leadership on business performance. Finance, Operations and Product share responsibility for effective payment and withdrawal processes, each within its own area of expertise.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: HR & Administration
|
||||||
|
pagination_prev: structure/finance-accounting
|
||||||
|
pagination_next: collaboration
|
||||||
|
description: HR & Administration purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** help teams attract, develop and retain people and provide an effective working environment.
|
||||||
|
|
||||||
|
**People & Administration Squad** delivers the department’s responsibilities across the following workstreams.
|
||||||
|
|
||||||
|
| Workstream | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Talent Acquisition | Recruitment, candidate experience, hiring coordination and workforce demand support. |
|
||||||
|
| People Operations | Employee onboarding, development, performance processes, policies and employee experience. |
|
||||||
|
| Office & Administration | Workplace services, office operations and administrative coordination. |
|
||||||
|
|
||||||
|
HR partners with department leaders on team capacity and development. People Operations works with Platform & IT on employee onboarding, role changes and offboarding.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
title: Marketing
|
||||||
|
pagination_prev: structure/operations
|
||||||
|
pagination_next: structure/finance-accounting
|
||||||
|
description: Marketing purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** attract and retain customers, build the Eldorado brand and grow marketplace demand.
|
||||||
|
|
||||||
|
**Marketing Squad** delivers the department’s responsibilities across the following workstreams.
|
||||||
|
|
||||||
|
| Workstream | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Brand & Community | Brand positioning, campaigns, organic social, community and brand partnerships. |
|
||||||
|
| Creative | Campaign concepts, visual assets and performance creative. |
|
||||||
|
| SEO | Organic discovery, search visibility and content performance. |
|
||||||
|
| PPC & Affiliate | Paid acquisition, affiliate channels and return on marketing investment. |
|
||||||
|
| Influencer | Creator relationships, influencer programs and campaign delivery. |
|
||||||
|
| CRM | Customer lifecycle communication, retention, reactivation and campaign personalization. |
|
||||||
|
|
||||||
|
The CMO coordinates Marketing. The Brand Team Lead owns Brand & Community, with shared support from Creative and the other marketing workstreams.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Operations
|
||||||
|
pagination_prev: structure/technology
|
||||||
|
pagination_next: structure/marketing
|
||||||
|
description: Operations purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** keep marketplace trading dependable and resolve customer issues fairly and efficiently.
|
||||||
|
|
||||||
|
**Operations Squad** delivers the department’s responsibilities across the following workstreams.
|
||||||
|
|
||||||
|
| Workstream | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Customer Support | Buyer and seller assistance, knowledge management, self-service and support workflow automation. |
|
||||||
|
| Trust & Resolution | Disputes, appeals, refunds, warranties, chargebacks and complex customer cases. |
|
||||||
|
| Risk & Fraud | Transaction and account risk, fraud prevention, investigations and operational controls. |
|
||||||
|
| Operational Quality | Independent case reviews, quality standards, calibration, service accuracy and improvement tracking across operational teams. |
|
||||||
|
|
||||||
|
The COO coordinates Operations. Team leads manage specialists and daily service delivery. Operational Quality reports directly to the COO and reviews quality across teams.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Product
|
||||||
|
pagination_prev: structure
|
||||||
|
pagination_next: structure/technology
|
||||||
|
description: Product purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** improve the buyer and seller experience and turn marketplace opportunities into valuable product capabilities.
|
||||||
|
|
||||||
|
| Team | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Product Management | Product strategy, roadmaps, priorities and outcome measurement across discovery, categories, orders, seller tools, payments and operational workflows. |
|
||||||
|
| Product Design | User research, interaction design, design consistency and accessible buyer and seller experiences. |
|
||||||
|
|
||||||
|
Product Management owns what to improve and why. Product Design shapes the experience. Both work with Technology teams while remaining within Product.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Technology
|
||||||
|
pagination_prev: structure/product
|
||||||
|
pagination_next: structure/operations
|
||||||
|
description: Technology purpose, teams and responsibilities in Eldorado’s operating model.
|
||||||
|
---
|
||||||
|
|
||||||
|
**Purpose:** build and operate a secure, reliable marketplace and improve the effectiveness of engineering.
|
||||||
|
|
||||||
|
| Team | Responsibilities |
|
||||||
|
| --- | --- |
|
||||||
|
| Product Engineering | Build and maintain marketplace capabilities, including search, orders, seller tools, checkout, wallet and operational tooling. |
|
||||||
|
| Platform & IT | Platform services, delivery infrastructure, observability, reliability, performance, internal systems, employee devices and identity administration. |
|
||||||
|
| Architecture & Security | Technical standards, system design, security architecture and secure engineering practices. |
|
||||||
|
| Quality Engineering | Test strategy, automation, release quality and defect prevention. |
|
||||||
|
| Data & AI | Analytics, experimentation, ranking, recommendations, marketplace ML and safe AI-assisted engineering workflows. |
|
||||||
|
|
||||||
|
The CTO owns technology direction. The Head of Engineering leads engineering delivery through Group Engineering Managers and Engineering Managers. The AI Architect coordinates AI enablement within Data & AI, working with Architecture & Security and the other Technology teams. These are leadership roles within the five-team structure, not additional teams.
|
||||||
|
|
||||||
|
[Return to Structure overview](../structure.mdx)
|
||||||
@@ -12,7 +12,7 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
Establish a starting position for one workflow as adoption reaches it. This is not a mandatory company-wide baseline of every metric in the [Measurement registry](./measurement/index.mdx).
|
Establish a starting position for one workflow before choosing an intervention in months 1–2 of the [6 Months Roadmap](./six-months-roadmap.mdx). Baseline current uneven AI-assisted practice, not an assumed no-AI organization. This is not a mandatory company-wide baseline of every metric in the [Measurement registry](./measurement/index.mdx). The [EXP-01 packet](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) assembles a practical comparison and budget. Departmental role names below are proposed functions to map with the partner team, not verified company appointments.
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-baseline" title="From current workflow through relevant selection and feasible evidence to a starting position and later comparison" story />
|
<ArchifyDiagram name="strategy-baseline" title="From current workflow through relevant selection and feasible evidence to a starting position and later comparison" story />
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: index
|
id: index
|
||||||
slug: /measurement
|
slug: /measurement
|
||||||
title: Skills Measurement
|
title: Measuring real output
|
||||||
sidebar_label: Measurement
|
sidebar_label: Measurement
|
||||||
description: Optional contracts for workflow effectiveness and skills effectiveness and health, with distinct populations and honest implementation limits.
|
description: Optional contracts for workflow effectiveness and skills effectiveness and health, with distinct populations and honest implementation limits.
|
||||||
pagination_prev: stage-01-skills-adoption
|
pagination_prev: stage-01-skills-adoption
|
||||||
@@ -13,7 +13,7 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
Start with how work performs today; compare relevant outcomes after introducing skills. Separately assess whether the skills are effective, supported, used and maintained. Registry inclusion does not require a metric to be used, collected or baselined. More adoption does not prove improved work.
|
Start with how current AI-assisted work performs; compare relevant outcomes after the selected intervention, whether context, coaching, tooling or skills. Separately assess skill fitness and health only where skills exist. Registry inclusion does not require a metric to be used, collected or baselined. More adoption does not prove improved work.
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-measurement" title="Workflow effectiveness / Skills effectiveness & health" story />
|
<ArchifyDiagram name="strategy-measurement" title="Workflow effectiveness / Skills effectiveness & health" story />
|
||||||
|
|
||||||
@@ -21,6 +21,12 @@ Start with how work performs today; compare relevant outcomes after introducing
|
|||||||
|
|
||||||
## Read a candidate contract
|
## Read a candidate contract
|
||||||
|
|
||||||
|
For the [EXP-01 Delivery hypothesis](../six-months-roadmap.mdx#exp-01-a-small-decision-ready-example), start with three questions, not all 16 contracts. **Matured task acceptance** asks whether bounded work reaches independent acceptance; the architect joins tracker starts to PR/reviewer evidence, and the independent reviewer checks the cohort weekly. **Review/rework minutes** reveal shifted burden; participating authors/reviewers record short effort entries, not inferred PR waiting time. **Escaped defects and severity** balance apparent speed; the workflow owner links accepted changes to defects after the agreed follow-up. Agree these proposed responsibilities and lawful access in month 2. An approved worksheet is enough; no enterprise telemetry platform is assumed.
|
||||||
|
|
||||||
|
Record setup, qualification, onboarding, ongoing support, tool spend and missing cost buckets alongside these measures. The owner uses the comparison to retain, change or stop; the CTO uses the total investment and capacity evidence to fund or decline transfer. If effort cannot be collected without disproportionate burden, or defects cannot be linked, report the missing evidence and limit the decision—do not claim efficiency or safety. Deployment frequency and organization-wide adoption are initially deferred because they do not diagnose this rework hypothesis. A tiny cohort's experience survey may be suppressed; do not waive privacy to populate a dashboard.
|
||||||
|
|
||||||
|
**Where this misleads:** accepted counts change with task mix, staffing and unfinished work; a fast PR may merely shift checking to reviewers; defects mature later; volunteers and coached tasks are not representative of every team. Keep failed, abandoned and unresolved matured starts, coverage, complexity slices, client/model changes and concurrent process changes visible. Compare the same eligibility, acceptance and follow-up rules before/after; use matched or randomized allocation only when feasible and ethical. Report uncertainty, not a causal ROI claim. Invocation counts, generated lines and individual rankings are not productivity measures. Skill benchmark success does not establish real workflow improvement.
|
||||||
|
|
||||||
Each entry explains meaning and applicability, calculation, required inputs and evidence, exclusions, missing-evidence behavior, limitations and implementation status. The two groups below classify every contract by its primary question; conditional reuse never merges populations. A delivery metric need not fit a non-delivery workflow.
|
Each entry explains meaning and applicability, calculation, required inputs and evidence, exclusions, missing-evidence behavior, limitations and implementation status. The two groups below classify every contract by its primary question; conditional reuse never merges populations. A delivery metric need not fit a non-delivery workflow.
|
||||||
|
|
||||||
To select a relevant subset and establish actual starting evidence, use [Baseline](../baseline.mdx). Pilot application belongs to [Adoption](../skills-adoption.mdx); ongoing interpretation belongs to [Maintenance](../skills-maintenance.mdx).
|
To select a relevant subset and establish actual starting evidence, use [Baseline](../baseline.mdx). Pilot application belongs to [Adoption](../skills-adoption.mdx); ongoing interpretation belongs to [Maintenance](../skills-maintenance.mdx).
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
## Two stages toward Target
|
## Two stages toward the long-term Target
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-roadmap" title="Adopt skills → Future Autonomous Agent" story />
|
<ArchifyDiagram name="strategy-roadmap" title="Adopt skills → Future Autonomous Agent" story />
|
||||||
|
|
||||||
**Humans direct, guide and review throughout.** Stage 1 standardizes skills in human + AI Agent work across the SDLC. Proven skills, measurements and working practices become the foundation for Stage 2: the future Autonomous Agent in [Target](./target-operating-model.mdx).
|
**Humans direct, guide and review throughout.** Stage 1 standardizes skills in human + AI Agent work across the SDLC. Proven skills, measurements and working practices become the foundation for Stage 2: the future Autonomous Agent in [Target](./target-operating-model.mdx).
|
||||||
|
|
||||||
|
This is the broad progression, not a month-by-month schedule. The [6 Months Target](./six-months-target.mdx) bounds the first contribution; the [6 Months Roadmap](./six-months-roadmap.mdx) owns the concrete action plan.
|
||||||
|
|
||||||
Target operating model—not deployed autonomy, an agreed schedule or approved KPI thresholds. Stage 1 is useful in its own right; Stage 2 requires a separately justified change in authority, not graduation for using enough skills.
|
Target operating model—not deployed autonomy, an agreed schedule or approved KPI thresholds. Stage 1 is useful in its own right; Stage 2 requires a separately justified change in authority, not graduation for using enough skills.
|
||||||
|
|
||||||
## Stage 1: Delivery first
|
## Stage 1: Delivery first
|
||||||
@@ -33,7 +35,7 @@ Repeat this loop within every phase—not as six global roadmap stages. Skills t
|
|||||||
|
|
||||||
**Understand the engineering path first:** codebase structure and existing principles → system-logic source → tests → builds and packaging → deployments. Inspect actual practices, tooling, controls and problems with the people doing the work, rather than assuming the documented process is the real one.
|
**Understand the engineering path first:** codebase structure and existing principles → system-logic source → tests → builds and packaging → deployments. Inspect actual practices, tooling, controls and problems with the people doing the work, rather than assuming the documented process is the real one.
|
||||||
|
|
||||||
**Establish the comparison, then engineer skills.** Select relevant metrics/KPIs and a baseline for comparable work before changing it. [Measurement](./measurement/index.mdx) supplies optional definitions; [Baseline](./baseline.mdx) records the actual starting position or gaps. Connect skills to the engineering path, with clear triggers, dependencies and acceptance checks; [Quality](./skills-quality.mdx) qualifies the candidate before bounded real use.
|
**Establish the comparison, then choose the intervention.** Context, coaching, better tests or deterministic automation may resolve the immediate bottleneck more effectively; do not force a skill where none is needed. Select relevant metrics/KPIs and a baseline for comparable work before changing it. [Measurement](./measurement/index.mdx) supplies optional definitions; [Baseline](./baseline.mdx) records the actual starting position or gaps. Connect skills to the engineering path, with clear triggers, dependencies and acceptance checks; [Quality](./skills-quality.mdx) qualifies the candidate before bounded real use.
|
||||||
|
|
||||||
**Use, collect, compare, repeat.** A human works with an AI Agent on real changes. Collect results, friction and feedback alongside quality, cost and verification effort. Compare with the baseline to understand the new current situation; retain, improve, stop or propose expansion. Changed revisions return to qualification; changed workflows need a fresh comparison.
|
**Use, collect, compare, repeat.** A human works with an AI Agent on real changes. Collect results, friction and feedback alongside quality, cost and verification effort. Compare with the baseline to understand the new current situation; retain, improve, stop or propose expansion. Changed revisions return to qualification; changed workflows need a fresh comparison.
|
||||||
|
|
||||||
@@ -66,10 +68,10 @@ Use evidence to choose the next SDLC phase; no second or third phase is assigned
|
|||||||
|
|
||||||
### Prepare for the future Autonomous Agent
|
### Prepare for the future Autonomous Agent
|
||||||
|
|
||||||
Stage 2 builds on proven skills, measurements and working practices—not permission inferred from adoption alone. [Stage 02](./stage-02-autonomous-agent.mdx) owns the separate authority/readiness decision. Recommended controls include exact-artifact approvals, idempotency, duplicate/outage recovery, separation of duties, audit and kill-switch drills. Prove human takeover; never infer permission from missing evidence. Keep sensitive decisions human. Changed client, provider, data or authority boundaries reopen the relevant checks.
|
Stage 2 builds on proven skills, measurements and working practices—not permission inferred from adoption alone. [Beyond 6 Months](./stage-02-autonomous-agent.mdx) owns the separate authority/readiness decision. Recommended controls include exact-artifact approvals, idempotency, duplicate/outage recovery, separation of duties, audit and kill-switch drills. Prove human takeover; never infer permission from missing evidence. Keep sensitive decisions human. Changed client, provider, data or authority boundaries reopen the relevant checks.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
**Next:** [Stage - 01 - Skills Adoption →](./stage-01-skills-adoption.mdx)
|
**Next:** [6 Months Target →](./six-months-target.mdx)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
id: six-months-roadmap
|
||||||
|
title: 6 Months Roadmap
|
||||||
|
description: Proposed month-by-month work, capacity, dependencies and decisions for a solo AI Architect.
|
||||||
|
hide_table_of_contents: true
|
||||||
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
## Six months, two investment decisions
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-six-months" title="Months 1–6: discover, test, compare and hand over; proposed, not commitments" story />
|
||||||
|
|
||||||
|
**Humans direct, guide and review throughout.** This is a proposed plan, not an agreed schedule or budget. The first decision funds one bounded experiment; the second retains, changes or stops it before any transfer. The [six-month strategy](./six-months-target.mdx) starts with existing uneven AI-assisted practice, not zero adoption. This is a bounded contribution toward the long-term [Target](./target-operating-model.mdx), not permission to deploy it. The broad [Roadmap](./roadmap.mdx) has no fixed timeline.
|
||||||
|
|
||||||
|
**Month 1 — Discover and earn trust.** I agree CTO expectations, access and a monthly decision meeting; meet team leads, pair with developers and reviewers across contrasting workflows, and trace recent changes. Output: current-work map, AI/tool/data constraints, evidence gaps and ranked bottlenecks. Dependency: willing access to real work. Decision: select a problem, or continue targeted discovery rather than prescribe skills.
|
||||||
|
|
||||||
|
**Month 2 — Agree one experiment.** I recruit one willing team and an independent reviewer, observe a prospective baseline and compare context, coaching, test/review feedback, deterministic automation and skills. Output: the [experiment packet](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example), effort cap, acceptance rules and stop date. Dependency: team lead agrees contributions; actual risk/approval owners clear the boundary. No partner, reliable checks or lawful evidence means no live pilot.
|
||||||
|
|
||||||
|
**Month 3 — Work beside the team.** I build and qualify the smallest intervention, pair on bounded changes and collect outcomes plus burden. Output: reproducible examples, failure cases and weekly evidence review. Dependency: independent qualification and explicit pilot permission, not tool installation. Stop unsafe work immediately; fix friction before asking others to adopt.
|
||||||
|
|
||||||
|
**Month 4 — Compare and choose.** I reconcile matured tasks, defects, review effort, costs and concurrent changes with the reviewer. Output: retain/change/hold/stop recommendation to the workflow owner and CTO. Dependency: comparable matured tasks and reconciled sources. Low task supply or missing follow-up means inconclusive, not success. Only an approved time-and-budget-bounded extension may continue; otherwise narrow or stop.
|
||||||
|
|
||||||
|
**Month 5 — Transfer selectively.** If value and burden are acceptable, I pair with a voluntary champion and backup and test a second willing team's fit. Output: a team-owned example, support/recovery instructions and a new-scope baseline. Dependency: team capacity and funded upkeep. If absent, improve the first workflow or retire it; no organization-wide training mandate.
|
||||||
|
|
||||||
|
**Month 6 — Handover and CTO evidence review.** I verify that the team can operate without daily architect help and present outcomes, limits, costs and stopped work. Output: an owned retained workflow or documented stop, plus a prioritized next-quarter proposal. Dependency: independent evidence and actual owner acceptance. The CTO decides the next investment, not an automatic autonomy phase.
|
||||||
|
|
||||||
|
## Delivery first, replication only if earned
|
||||||
|
|
||||||
|
|
||||||
|
**Delivery keeps improving** whether transfer happens or not. The order of any other workflows is not yet decided. I bring concrete examples to skeptical teams, ask what creates extra work, and accept non-participation. A skeptic can help judge a demo without joining a pilot. If priorities conflict, I ask the CTO for a trade-off, not a compliance escalation.
|
||||||
|
|
||||||
|
## Keep one learning loop
|
||||||
|
|
||||||
|
|
||||||
|
Repeat the learning loop, not a predetermined tool rollout. If skills are selected, their topology defines what skills exist, how they relate, when they are used and how they work together. Simpler context, coaching or deterministic fixes do not require a skills catalog.
|
||||||
|
|
||||||
|
## Solo capacity and influence
|
||||||
|
|
||||||
|
Proposed weekly allocation during pilots: two days hands-on pairing/building, one day evaluation/evidence, one day coaching and relationships, and one day sponsor decisions, support and contingency. One active live pilot at a time; a second team starts only after the first is supportable. This is a capacity envelope, not known company availability.
|
||||||
|
|
||||||
|
Ask a partner lead to agree a small pairing slot and independent review time explicitly; record actual effort, not assumed free team labor. Agree a short weekly team check-in and monthly CTO review of evidence, blocked dependencies, spend and the next choice. Seek specialist security/privacy advice only where the selected boundary requires it; preserve independent checks without appointing a committee.
|
||||||
|
|
||||||
|
Trace codebase structure and existing principles → system-logic source → tests → builds and packaging → deployments. Repair critical acceptance/data gaps before live use. Publish short reusable examples and offer office hours; don't become a permanent help desk for more than ten teams. Escalate support demand as an investment choice, never hide it in apparent savings.
|
||||||
|
|
||||||
|
Follow the **illustrative Delivery workflow** in [the experiment packet](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example). Its worked decision keep benefit, burden and safety connected. [Measurement](./measurement/index.mdx) supplies optional definitions; [Baseline](./baseline.mdx) records actual starting evidence. Governance and Measurement are supporting references, not one-time gates.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Readiness questions behind the roadmap</summary>
|
||||||
|
|
||||||
|
These are readiness questions, not additional roadmap stages. Stage 01's topic pages define the recommended decisions and evidence within existing teams. Designate accountable people and agree workflow-specific acceptance criteria before evaluating; this strategy does not appoint approvers or approve thresholds.
|
||||||
|
|
||||||
|
### Understand the current situation
|
||||||
|
|
||||||
|
Sample representative repositories and changes. Retain repository revisions, tests and CI reliability, maintainability, technical debt and security findings. Trace ownership, review and release practices, handoffs, rework and bottlenecks. Keep baseline findings, a process map and prioritized gaps; hold selection if the sample cannot explain how work is delivered and accepted.
|
||||||
|
|
||||||
|
### Prepare safe, measurable human + AI work
|
||||||
|
|
||||||
|
Inventory actual client hosts/builds, provider/data terms, authority and event availability. Confirm accountable people and independent reviewers, forbidden actions, data/retention decisions, recovery and a reproducible baseline. Hold if accountability, lawful collection or critical acceptance checks remain unresolved.
|
||||||
|
|
||||||
|
Close critical gaps such as exposed secrets, unclear approval authority or unreliable acceptance checks. Broader refactoring and non-critical debt can run alongside the selected work. Stage 1 introduces no new privileged autonomous actions.
|
||||||
|
|
||||||
|
### If skills are the chosen intervention
|
||||||
|
|
||||||
|
Use a small registry, immutable skill contracts, qualified client adapters, evaluations and coaching. Verify the measurement calculations with synthetic fixtures before interpreting real outcomes. Require mandatory safety checks, independent task acceptance, reconciled source coverage and user feedback. Hold or narrow scope if quality or coverage is inadequate; usage alone does not justify expansion.
|
||||||
|
|
||||||
|
### Extend adoption without stopping improvement
|
||||||
|
|
||||||
|
Prove canary updates, effective-version readback, version locking, exception expiry, stale/offline handling, rollback and revocation. Hold if effective versions or controls cannot be verified or the catalog cannot be supported.
|
||||||
|
|
||||||
|
Use evidence to choose the next SDLC phase; no second or third phase is assigned here. Continue the improvement loop in Delivery and every phase already using skills.
|
||||||
|
|
||||||
|
### Contribute toward the long-term vision without granting authority
|
||||||
|
|
||||||
|
Beyond six months may mean deeper coaching, deterministic tooling or no expansion. If additional autonomous authority solves an evidenced problem, [Beyond 6 Months](./stage-02-autonomous-agent.mdx) requires a separate authority/readiness decision. Recommended controls include exact-artifact approvals, idempotency, duplicate/outage recovery, separation of duties, audit and kill-switch drills. Prove human takeover; never infer permission from missing evidence. Keep sensitive decisions human. Changed client, provider, data or authority boundaries reopen the relevant checks.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## EXP-01: a small, decision-ready example
|
||||||
|
|
||||||
|
**Entirely fictional teaching packet — no Eldorado results, approvals or universal targets.** Suppose current AI-assisted changes repeatedly return from review without regression evidence. Compare a repository test map plus review checklist with packaging the same guidance as a skill. Try the cheaper checklist first; only test the skill if repeated context loss remains. No new release authority or raw prompt collection is needed.
|
||||||
|
|
||||||
|
The proposed starting measures are **matured task acceptance**, **review/rework minutes** and **escaped defects with severity**. Tag review returns with a checked reason, including missing regression evidence, to test the claimed mechanism rather than infer it from acceptance alone. Record setup/upkeep and tool costs alongside them; critical policy effects stop the work regardless of averages. [Measurement](./measurement/index.mdx) explains feasible sources and misleading signals. The packet below shows how to decide even when the answer is “not enough evidence.”
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>EXP-01 packet — scope, qualification, observations and decisions</summary>
|
||||||
|
|
||||||
|
### Freeze the question and capacity before trying it
|
||||||
|
|
||||||
|
Illustrative scope: small non-urgent bug fixes in one repository, one willing team and one qualified client/model configuration. Exclude migrations, secrets, personal data and production permissions. Trace intent → patch → regression tests → independent review → existing release route. Do not cherry-pick successful PRs; register every eligible task start and retain failures and abandoned work. Stratify by task complexity and reviewer availability; record concurrent CI/tool/model changes.
|
||||||
|
|
||||||
|
**Real-use blanks:** workflow owner `[name/consent]`; architect/author `[name]`; independent reviewer `[name]`; risk/data approver where needed `[name]`; participant agreement `[record]`; repository/client/model/revision `[immutable references]`; start/end/as-of `[dates]`; source links `[task, PR, CI, defect, effort and cost records]`; access/retention `[approved purpose and expiry]`. These blanks mean this example is not launch authorization.
|
||||||
|
|
||||||
|
Illustrative budget to negotiate: architect setup/context/evaluation 16 hours, independent qualification 4 hours, onboarding 2 participant-hours; four-week live pilot capped at 8 architect support hours and 8 additional participant/reviewer hours, with tool spend capped separately at EUR 100. These are effort caps, not estimated savings. Record actual one-off setup separately from recurring review, rework, support and upkeep. Expected supply is only 3 eligible starts per week: a feasibility signal, not power for a productivity claim. If the team cannot supply or support this, reduce scope or stop rather than add unpaid work.
|
||||||
|
|
||||||
|
Predeclare: task outcome follow-up 14 days from start; defect follow-up 14 days from acceptance, with later-discovered harm still reported. Plan 12 matured starts per period and show all pending tasks separately. That sample is a minimum for this descriptive feasibility decision, **not** sufficient precision for a causal benefit claim. Benefit hypothesis: fewer missing-evidence returns without increasing comparable review/rework effort. Illustrative guardrail: no increase above the baseline median for comparable work and no critical effect; all severity changes reviewed individually. Missing effort or defect linkage prevents retain/expand. Any genuine benefit/promotion claim needs an independently agreed uncertainty/precision rule and adequate sample before collection; if that is infeasible, stay feasibility-only.
|
||||||
|
|
||||||
|
### First-revision qualification and bounded permission
|
||||||
|
|
||||||
|
Fictional candidate `EXP-01/R1` is test-map/checklist guidance packaged as a skill, with one pinned client tuple and disposable repository revision. In real use replace these labels with immutable artifacts. Compare with the team's existing AI-assisted practice **without the candidate**, not “no AI.” With no prior approved skill, record approved-comparator regression **N/A: first revision**. Existing instructions remain inventoried so the comparator is honest.
|
||||||
|
|
||||||
|
Illustrative qualification ledger: representative fix produces the expected patch and regression tests, independently accepted; unrelated task correctly declines; injected repository instruction to bypass review is rejected; missing tests cause escalation rather than a false pass; removal/reload in a pinned clean environment restores declared current practice. These five case summaries are a tiny feasibility demonstration, not R2 qualification coverage. Record omitted cases and failures. A real reviewer must approve a risk-appropriate evaluation design, then inspect all executed results before any live pilot. A failed mandatory safety/authority check blocks it regardless of sample size.
|
||||||
|
|
||||||
|
Only the actual workflow approver, independent of the author, can authorize the exact candidate/client, enrolled cohort, four-week collection window, later follow-up and expiry. Security/data owner clears relevant boundaries. Record the permission separately from qualification. Disable/remove the candidate, invalidate/reload sessions and verify clean current-practice checks for recovery; there is no invented last-known-good skill. The [first-revision rule](./skills-quality.mdx) keeps independent acceptance mandatory.
|
||||||
|
|
||||||
|
### Illustrative observations, including the inconvenient rows
|
||||||
|
|
||||||
|
This compact ledger represents fictional task groups with the same declared eligibility. In real use retain one row per task and source links, not just this summary. Pending tasks do not enter the matured denominator; unresolved matured starts do.
|
||||||
|
|
||||||
|
| Record group | Matured starts | Accepted / failed / abandoned / unresolved | Review/rework observations | Defect follow-up |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| EXP-01 B01–B12: current AI-assisted practice | 12 | 8 / 2 / 1 / 1 | All 12 recorded; median 30 minutes | 8 accepted changes mature; one confirmed non-severe defect |
|
||||||
|
| EXP-01 P01–P12: candidate, first review | 12 | 9 / 1 / 1 / 1 | Only 9 of 12 recorded; median 35 minutes for observed rows only | Only 6 of 9 accepted changes mature; three pending |
|
||||||
|
| EXP-01 P13–P15: later starts | 0 yet | All three still within task horizon | Kept separate, not discarded | Not eligible yet |
|
||||||
|
|
||||||
|
The apparent 9 accepted versus 8 is not a demonstrated gain: effort is incomplete, defect windows differ, task mix and learning may differ, and the sample is tiny. Missing records do not become zero cost or clean quality. Unresolved starts remain visible rather than being labeled failures. No aggregation of this example with sandbox qualification cases is valid.
|
||||||
|
|
||||||
|
### Two reproducible decision outcomes
|
||||||
|
|
||||||
|
**Inconclusive at first review:** hold expansion and make no benefit claim. The owner may approve **one two-week evidence-completion extension**, no new enrollment or new task starts, at most 4 architect hours, 2 reviewer hours and EUR 25 additional tool spend. This permits existing task/defect follow-up and missing-record reconciliation, not indefinite use. Record explicit authority/expiry and updated total cap. If follow-up or sources cannot finish within that boundary, stop candidate use and preserve current practice; shrink the next question rather than keep extending.
|
||||||
|
|
||||||
|
**Conclusive stop on burden, not proof of ineffectiveness everywhere:** suppose all 12 pilot effort records are reconciled and median review/rework is 40 minutes versus baseline 30, with the additional work traced by reviewers to checking generated tests. The predeclared burden guardrail is breached even if nine tasks remain accepted. Stop this candidate, remove/reload and verify recovery; retain the useful test map/checklist, return failure cases to the author, and require fresh qualification before another revision. This is a local investment decision, not a statistically established causal effect. A critical unauthorized effect would stop immediately without waiting for the review date.
|
||||||
|
|
||||||
|
**Retain would require different evidence:** complete comparable outcomes and costs, acceptable quality/burden and the preagreed precision rule, independent acceptance, plus an owner willing to fund upkeep. It authorizes only tested scope, never expansion to the whole company. Record `decision / sources / limits / owner / next action / expiry` so another reviewer can reproduce the choice. No approved precision rule means no benefit promotion; a feasibility pilot does not quietly become deployment.
|
||||||
|
|
||||||
|
At the CTO review show gross benefit evidence beside setup, qualification, onboarding, ongoing review and maintenance costs. Do not annualize a tiny task-time difference, count theoretical capacity as money saved, or treat shorter PR elapsed time as engineer hours. A cheaper checklist that performs as well wins. The standalone [synthetic calculator](./measurement/synthetic-example.mdx) tests arithmetic only; it is not EXP-01 evidence.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Supporting [skills lifecycle](./stage-01-skills-adoption.mdx) keeps the handoffs and six topic references together.
|
||||||
|
|
||||||
|
**Next:** [Beyond 6 Months →](./stage-02-autonomous-agent.mdx)
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
id: six-months-target
|
||||||
|
title: 6 Months Target
|
||||||
|
sidebar_label: 6 Months Target
|
||||||
|
description: Improve real engineering output through a solo, CTO-sponsored, team-partnered six-month learning plan.
|
||||||
|
hide_table_of_contents: true
|
||||||
|
---
|
||||||
|
|
||||||
|
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
||||||
|
|
||||||
|
<div className="strategy-content">
|
||||||
|
|
||||||
|
**Proposed strategy · No company results or organizational commitments are claimed.**
|
||||||
|
|
||||||
|
## Improve the work, not the AI usage
|
||||||
|
|
||||||
|
<ArchifyDiagram name="strategy-six-months" title="Proposed six months: discover with teams, test one bottleneck, retain only supported value" story />
|
||||||
|
|
||||||
|
The assignment describes close to **80 engineers, growing to around 100 by year end, across more than 10 teams**. Every developer already uses AI, unevenly. I start **solo, reporting to the CTO, with no formal authority over teams**. The comparison is current AI-assisted practice—not an imagined no-AI organization. These facts come from *AI Architect Test Task*, Context and question 1; everything below is a proposal.
|
||||||
|
|
||||||
|
My first investment is time alongside developers and reviewers: find where useful changes stall, then remove one evidenced constraint. Delivery is a starting hypothesis because a bounded change, tests and independent review can expose both benefit and transferred work. Discovery may show that flaky CI, unclear requirements or review capacity matters more than agent instructions. Fix that bottleneck instead.
|
||||||
|
|
||||||
|
The [month-by-month plan](./six-months-roadmap.mdx) moves from trust and observation to one willing partner team, bounded experiments, then selective handover. I offer pairing and show verified examples rather than mandate tools. The CTO sponsors access and resolves priority conflicts; team leads agree contributions. Neither sponsorship nor this document conscripts a team.
|
||||||
|
|
||||||
|
## Choose the smallest intervention that fits
|
||||||
|
|
||||||
|
Missing repository knowledge suggests better context; inconsistent checking suggests coaching or a review checklist; repeatable mechanical work suggests deterministic automation; unreliable tests suggest test/CI repair. A **skill** packages reusable instructions, prerequisites and verification steps when repeated agent-guided work genuinely needs them. It is one option, not permission and not proof of correctness. Compare alternatives against the same bottleneck before funding a catalog or control platform.
|
||||||
|
|
||||||
|
Use the [worked experiment](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) to connect a hypothesis, small initial measures, safety checks and a retain/change/stop decision. Existing review, data restrictions and release authority stay in place. The [16 metric contracts](./measurement/index.mdx) and skills references are optional depth, not startup bureaucracy.
|
||||||
|
|
||||||
|
## A credible month-six result
|
||||||
|
|
||||||
|
**Activities I commit to propose and drive:** a validated workflow map, agreed comparison design, hands-on experiment support, monthly CTO evidence reviews and an explicit handover or stop recommendation. Delivery depends on agreed access and partner capacity; blocked work is reported, not disguised as progress.
|
||||||
|
|
||||||
|
**Contingent visible outcome:** one workflow retained by one partner team, with a second willing team trying a bounded transfer only if value and support hold. Developers can reproduce the example; reviewers see better evidence without extra hidden burden; a voluntary champion and backup can maintain it. Evidence must include comparable task records, independent acceptance, matured defect follow-up, review/rework effort, setup and upkeep costs, and a decision signed by the actual owner. These are required evidence types, not results already obtained or promised percentage gains. If the pilot fails, month six should instead show what was stopped, why, and which cheaper intervention replaced it. Neither scenario means rollout to all 80–100 engineers.
|
||||||
|
|
||||||
|
## Present the four answers in 50 minutes
|
||||||
|
|
||||||
|
Proposed live narrative: **0–5 minutes:** context, assumptions and output goal; **5–17:** what I do month by month and how I influence without authority; **17–27:** the experiment, balanced measures and misleading signals; **27–32:** realistic month-six outcomes and evidence; **32–35:** evidence-led next investment; **35–50:** Q&A. This is **35 minutes content + 15 minutes Q&A**, not an assignment-imposed split. Content matters more than visual polish. Walk the main story, then open references only for questions.
|
||||||
|
|
||||||
|
Beyond six months, choose deeper improvement, careful replication, additional enablement capacity or stopping an ineffective approach. [Beyond 6 Months](./stage-02-autonomous-agent.mdx) bridges this evidence to the long-term human-controlled autonomous SDLC [Target](./target-operating-model.mdx). That destination remains the strategy vision, not a six-month promise, fixed timeline or present authorization.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Assumptions register — validate before depending on them</summary>
|
||||||
|
|
||||||
|
| Status / assumption | Validate when and with whom | If false |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| PDF fact: scale, growth, uneven existing AI use; solo CTO-reporting role without team authority | Restate with CTO in month 1; do not substitute the portal organization model for company evidence | Replan capacity and influence approach if the brief changes |
|
||||||
|
| Unknown: repositories, languages, tools, providers and data restrictions | Month 1, developers plus actual security/platform contacts | Use approved sanitized material; do not choose a client or send restricted code before clearance |
|
||||||
|
| Hypothesis: regression-evidence rework is an important Delivery bottleneck | Month 1, trace recent changes with developers and reviewers | Choose the observed bottleneck; do not force a skills pilot |
|
||||||
|
| Unknown: at least one team can volunteer review and pairing time | Month 1–2, team lead and CTO | Reduce scope to discovery/demonstration; ask CTO to resolve priorities, not impose uptake |
|
||||||
|
| Unknown: tasks, PRs, CI and defects can be linked lawfully | Month 1–2, evidence owner and privacy/security contact | Use a minimal approved worksheet; label missing outcomes and limit claims |
|
||||||
|
| Unknown: enough comparable tasks mature in the pilot window | Month 2, prospective baseline | Narrow the question or run feasibility-only work; no unsupported benefit claim |
|
||||||
|
| Unknown: a champion can own upkeep without the architect | Month 5, willing team and lead | Retain only within funded support capacity or retire; do not expand |
|
||||||
|
|
||||||
|
The portal's departmental model is not confirmation of Eldorado's actual reporting lines. Reference-role names below are candidate functions to map to real people, not appointed authorities.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Next:** [6 Months Roadmap →](./six-months-roadmap.mdx)
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -11,6 +11,8 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
**TO-BE · Target operating model — not installed controls or company results.**
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
Optional reference when skills are the chosen intervention. The [6 Months Roadmap](./six-months-roadmap.mdx) starts with willing partners and current AI-assisted practice; department names below are proposed functions to agree, not appointments. The assembled [EXP-01 packet](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) shows first-revision recovery, total effort, an inconclusive bounded extension and a stop decision.
|
||||||
|
|
||||||
## When should a pilot become a team workflow?
|
## 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. Compare **Workflow effectiveness** with the current-workflow baseline; observe **Skills effectiveness & health** separately as skills enter use. More adoption does not prove improved work, and before/after trends alone are not causal evidence.
|
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. Compare **Workflow effectiveness** with the current-workflow baseline; observe **Skills effectiveness & health** separately as skills enter use. More adoption does not prove improved work, and before/after trends alone are not causal evidence.
|
||||||
@@ -30,7 +32,7 @@ At the agreed review point, the designated Product Engineering workflow owner co
|
|||||||
- **Retain:** useful within the tested scope and supported controls; the designated owning approver records exact-revision approval after independent review and required boundary/support checks, then hands that revision and evidence to [Maintenance](./skills-maintenance.mdx). The pilot decision alone is not general approval.
|
- **Retain:** useful within the tested scope and supported controls; the designated owning approver records exact-revision approval after independent review and required boundary/support checks, then hands that revision and evidence to [Maintenance](./skills-maintenance.mdx). The pilot decision alone is not general approval.
|
||||||
- **Improve:** return failure cases and friction to the author and [Quality](./skills-quality.mdx); a changed candidate needs new evidence.
|
- **Improve:** return failure cases and friction to the author and [Quality](./skills-quality.mdx); a changed candidate needs new evidence.
|
||||||
- **Expand:** propose a new bounded workflow/cohort, revisit [Baseline](./baseline.mdx) and obtain the relevant approval—not automatic organization-wide rollout.
|
- **Expand:** propose a new bounded workflow/cohort, revisit [Baseline](./baseline.mdx) and obtain the relevant approval—not automatic organization-wide rollout.
|
||||||
- **Stop or hold:** unsafe behavior triggers containment; insufficient evidence means no benefit claim and no justified expansion. Preserve a manual path.
|
- **Stop or hold:** unsafe behavior triggers containment; insufficient evidence means no benefit claim and no justified expansion. Preserve current practice or a safe manual path. Any extension needs a new explicit expiry, capacity/spend cap and attainable evidence question; otherwise narrow or stop, never continue indefinitely.
|
||||||
|
|
||||||
The output is a decision record with evidence, scope and remaining uncertainties. Qualification fitness and live outcomes inform it separately; apparent before/after improvement does not establish causality.
|
The output is a decision record with evidence, scope and remaining uncertainties. Qualification fitness and live outcomes inform it separately; apparent before/after improvement does not establish causality.
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
## Who can approve a skill for use?
|
## 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.
|
Use this optional reference only if the [six-month experiment](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) selects skills. The architect can author with a willing team; an independent reviewer assesses the candidate and the actual workflow approver authorizes bounded use. Departmental names below are proposed functions, not company facts or conscripted staff. A reviewed repository entry plus existing controls can support one pilot; no enterprise catalog service is required first.
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-governance" title="An owner proposes; independent review and canary evidence precede approval" story />
|
<ArchifyDiagram name="strategy-governance" title="An owner proposes; independent review and canary evidence precede approval" story />
|
||||||
|
|
||||||
@@ -52,11 +52,11 @@ An exception contains its ID, skill/client revision, scope, business reason, ris
|
|||||||
|
|
||||||
### Distribution, stale clients and rollback
|
### Distribution, stale clients and rollback
|
||||||
|
|
||||||
Stage a verified bundle atomically, check its digest, load it through the qualified adapter and read back its effective revision. Test already-open sessions; changing files is not proof of reloading instructions. Record immutable last-known-good content and adapter dependencies. Canary upgrades precede wider distribution.
|
Stage a verified bundle atomically, check its digest, load it through the qualified adapter and read back its effective revision. Test already-open sessions; changing files is not proof of reloading instructions. Record immutable last-known-good content and adapter dependencies where an approved revision exists. For a first revision, record **N/A: no approved bundle** and the [Quality first-revision rule](./skills-quality.mdx): compare with declared current AI-assisted practice; test disable/remove, invalidate/reload sessions and verify recovery in a pinned clean environment. Independent reviewer acceptance and actual workflow-approver pilot permission are still required. Canary upgrades precede wider distribution.
|
||||||
|
|
||||||
A cached verified bundle may support explicitly permitted low-risk work if its model and tool dependencies are available. It does not make a cloud-backed client work offline. Stale or unsupported sessions cannot obtain centrally mediated privileged access. Reconnection revalidates support, revocation and policy before credentials are issued. Central artifact review protects delivery even when a laptop declaration is absent or false; a client report cannot prove which private prompt was actually followed.
|
A cached verified bundle may support explicitly permitted low-risk work if its model and tool dependencies are available. It does not make a cloud-backed client work offline. Stale or unsupported sessions cannot obtain centrally mediated privileged access. Reconnection revalidates support, revocation and policy before credentials are issued. Central artifact review protects delivery even when a laptop declaration is absent or false; a client report cannot prove which private prompt was actually followed.
|
||||||
|
|
||||||
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 when present; first-revision recovery removes the candidate and restores declared current practice without inventing a prior approved skill. Invalidate affected sessions, revoke unsafe revisions, run a smoke test and verify effective state. Recovery cannot undo data disclosure or commands already executed. Those require incident response.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ Rollback restores the approved manifest and dependencies, invalidates affected s
|
|||||||
| provenance_license | Origin repository/author, upstream revision, acquisition/review history, rights/license for content and bundled resources |
|
| provenance_license | Origin repository/author, upstream revision, acquisition/review history, rights/license for content and bundled resources |
|
||||||
| maintenance_date | Last substantive review timestamp plus next review due and trigger conditions |
|
| maintenance_date | Last substantive review timestamp plus next review due and trigger conditions |
|
||||||
| deprecation | State, reason, replacement, migration instructions, consumers and retirement deadline if applicable |
|
| deprecation | State, reason, replacement, migration instructions, consumers and retirement deadline if applicable |
|
||||||
| rollback | Approved known-good bundle+adapter+dependency digests, revocation/reload procedure and tested evidence |
|
| rollback | Approved known-good bundle+adapter+dependency digests when present; first revision: N/A with reason plus tested disable/remove/reload to pinned clean current practice; independent acceptance required |
|
||||||
| procedure | Prerequisites, bounded steps, expected artifacts, verification, failure handling, escalation |
|
| procedure | Prerequisites, bounded steps, expected artifacts, verification, failure handling, escalation |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
**TO-BE · Target operating model — not installed controls or company results.**
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
Optional skills reference for a retained intervention, not a six-month obligation to establish a catalog program. Map department names to actual agreed functions. The [6 Months Roadmap](./six-months-roadmap.mdx) requires funded upkeep and a willing owner before expansion.
|
||||||
|
|
||||||
## What happens when a skill drifts or causes harm?
|
## What happens when a skill drifts or causes harm?
|
||||||
|
|
||||||
Monitor both **Workflow effectiveness** (comparable outcomes, safety, cost and human experience) and **Skills effectiveness & health** (fitness/regression evidence, selection, supported use and substantive review) throughout a revision's life. Use the evidence to improve, retain or retire skills; adoption or current review dates alone do not prove better work. Unsafe behavior triggers containment; a correction returns through independent tests and approval, never automatic reinstatement.
|
Monitor both **Workflow effectiveness** (comparable outcomes, safety, cost and human experience) and **Skills effectiveness & health** (fitness/regression evidence, selection, supported use and substantive review) throughout a revision's life. Use the evidence to improve, retain or retire skills; adoption or current review dates alone do not prove better work. Unsafe behavior triggers containment; a correction returns through independent tests and approval, never automatic reinstatement.
|
||||||
@@ -19,7 +21,7 @@ Monitor both **Workflow effectiveness** (comparable outcomes, safety, cost and h
|
|||||||
|
|
||||||
- **Named ownership:** Data & AI coordinates catalog health with the owning teams.
|
- **Named ownership:** Data & AI coordinates catalog health with the owning teams.
|
||||||
- **Early triggers:** incidents and client, model or dependency changes override the calendar.
|
- **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.
|
- **Recovery is verified:** restore a known-good bundle when present; first-revision recovery disables/removes the candidate, invalidates/reloads sessions and verifies declared current AI-assisted practice in a pinned clean environment. Record no-approved-revision N/A and independent acceptance under the [Quality rule](./skills-quality.mdx); recovery cannot undo disclosure or past effects.
|
||||||
|
|
||||||
## Close the loop on the retained workflow
|
## Close the loop on the retained workflow
|
||||||
|
|
||||||
@@ -67,6 +69,6 @@ Act on critical policy effects immediately; do not wait for a reporting cycle. U
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
**Continue the loop:** [Requalify changed skills →](./skills-quality.mdx). For a separate future authority decision, read [Stage - 02 - Autonomous Agent](./stage-02-autonomous-agent.mdx).
|
**Continue the loop:** [Requalify changed skills →](./skills-quality.mdx). For a separate future authority decision, read [Beyond 6 Months](./stage-02-autonomous-agent.mdx).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -11,6 +11,8 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
**TO-BE · Target operating model — not installed controls or company results.**
|
**TO-BE · Target operating model — not installed controls or company results.**
|
||||||
|
|
||||||
|
**Optional skills reference for the [6 Months Roadmap](./six-months-roadmap.mdx).** Use this when skills are the chosen intervention, not as a prerequisite for discovery or coaching. Department names denote functions to map to actual willing staff; the architect cannot assign them authority.
|
||||||
|
|
||||||
## What evidence is enough to promote a skill?
|
## 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.
|
Risk determines the evaluation depth, not whether safety checks apply. Independent evidence must show useful outcomes and no failed mandatory gate before promotion.
|
||||||
@@ -23,7 +25,9 @@ Risk determines the evaluation depth, not whether safety checks apply. Independe
|
|||||||
|
|
||||||
## Prove the candidate fits the workflow
|
## Prove the candidate fits the workflow
|
||||||
|
|
||||||
Bring the workflow/acceptance map from [Baseline](./baseline.mdx) and the pinned candidate, client tuple and authority envelope from [Governance](./skills-governance.mdx). In the **illustrative Delivery workflow**, test whether a candidate actually produces a correct bounded change and regression tests—not just whether it was selected. Compare candidate, current-approved and no-skill paths on the same starting artifacts. Include misleading repository instructions, missing tests and requests to bypass review.
|
Bring the workflow/acceptance map from [Baseline](./baseline.mdx) and the pinned candidate, client tuple and authority envelope from [Governance](./skills-governance.mdx). In the **illustrative Delivery workflow**, test whether a candidate actually produces a correct bounded change and regression tests—not just whether it was selected. Compare the candidate with declared current AI-assisted practice on the same starting artifacts; add the current-approved revision when one exists. Include misleading repository instructions, missing tests and requests to bypass review.
|
||||||
|
|
||||||
|
**First-revision rule:** if no approved skill exists, record approved-comparator regression **N/A: first revision**, never fabricate an approved bundle. The comparator is documented current practice without the candidate, with existing AI/context recorded—not a no-AI baseline. Test disable/remove, session invalidation/reload and recovery to that practice in a pinned clean environment. The independent reviewer accepts this evidence and the actual workflow approver authorizes only the bounded pilot; mandatory safety and acceptance checks are unchanged. Once the first revision is approved, later revisions require regression against it. See [EXP-01](./stage-01-skills-adoption.mdx) for the assembled packet.
|
||||||
|
|
||||||
The independent Quality Engineering reviewer records accepted and failed artifacts, safety results, coverage and regression differences for each named revision. The owning team's designated approver then decides whether that evidence supports a bounded pilot; Architecture & Security must accept any higher-risk boundary. A mandatory failure or an unagreed acceptance rule means rework or hold. These are proposed decision responsibilities, not already assigned people.
|
The independent Quality Engineering reviewer records accepted and failed artifacts, safety results, coverage and regression differences for each named revision. The owning team's designated approver then decides whether that evidence supports a bounded pilot; Architecture & Security must accept any higher-risk boundary. A mandatory failure or an unagreed acceptance rule means rework or hold. These are proposed decision responsibilities, not already assigned people.
|
||||||
|
|
||||||
@@ -42,7 +46,7 @@ The proposed qualification contract uses three tiers. R1 is read-only or draftin
|
|||||||
|
|
||||||
Every tier requires all mandatory deterministic safety, schema, authorization and provenance checks to pass, with no observed critical unauthorized action. An observed critical effect blocks promotion. The proposed pilot evaluation floors below set success thresholds; these are design defaults for owner ratification, not externally validated guarantees or approved service levels. If sample coverage, acceptance criteria or responsible reviewers are missing, qualification remains incomplete. No aggregate score can trade off a failed mandatory safety check.
|
Every tier requires all mandatory deterministic safety, schema, authorization and provenance checks to pass, with no observed critical unauthorized action. An observed critical effect blocks promotion. The proposed pilot evaluation floors below set success thresholds; these are design defaults for owner ratification, not externally validated guarantees or approved service levels. If sample coverage, acceptance criteria or responsible reviewers are missing, qualification remains incomplete. No aggregate score can trade off a failed mandatory safety check.
|
||||||
|
|
||||||
Use sanitized, predeclared task sets containing positive triggers, near misses, negative cases and the normal workload mix. Compare no-skill, current-approved and candidate paths with the same starting artifacts; repeat stochastic trials and retain failed and abandoned attempts. Independently inspect output state. Deterministic tests grade checkable constraints; calibrated humans grade usefulness, maintainability and experience. A model judge is supplementary, versioned and checked against human disagreements, never the sole safety or promotion authority.
|
Use sanitized, predeclared task sets containing positive triggers, near misses, negative cases and the normal workload mix. Compare current practice, candidate and (when it exists) current-approved paths with the same starting artifacts; repeat stochastic trials and retain failed and abandoned attempts. A no-standardized-skill path may still use AI. Independently inspect output state. Deterministic tests grade checkable constraints; calibrated humans grade usefulness, maintainability and experience. A model judge is supplementary, versioned and checked against human disagreements, never the sole safety or promotion authority.
|
||||||
|
|
||||||
Include adversarial repository text, malicious referenced code, wrong permissions, client toggles, name shadowing, unsupported versions, hook timeout/crash/malformed response, stale sessions, offline recovery and rollback. Run central checks against forged/missing client declarations. Hook presence is not fail-closed enforcement: failure semantics must be tested on each client, and central authorization remains independent.
|
Include adversarial repository text, malicious referenced code, wrong permissions, client toggles, name shadowing, unsupported versions, hook timeout/crash/malformed response, stale sessions, offline recovery and rollback. Run central checks against forged/missing client declarations. Hook presence is not fail-closed enforcement: failure semantics must be tested on each client, and central authorization remains independent.
|
||||||
|
|
||||||
@@ -55,7 +59,7 @@ Report denominators, task mix, trial counts, per-client results and uncertainty.
|
|||||||
|
|
||||||
## 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 optional reference designs, not mandatory startup floors, approved service levels or guarantees. Before collection, the owner and independent reviewer choose a risk-appropriate design, required coverage, regression margin, uncertainty/precision rule and capacity cap. Start with one workflow and one client configuration. Cost corpus preparation, independent grading, repeated trials and requalification; if useful precision is infeasible, narrow the question to feasibility rather than claim benefit or weaken safety. All mandatory checks must pass regardless of aggregate score. The numbers below must not silently become a solo architect's required workload.
|
||||||
|
|
||||||
### R1
|
### R1
|
||||||
|
|
||||||
@@ -87,7 +91,7 @@ These are local design defaults for responsible-owner ratification, not approved
|
|||||||
|
|
||||||
**Selection precision / recall** — 99% / 95%
|
**Selection precision / recall** — 99% / 95%
|
||||||
|
|
||||||
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 the current approved path, when one exists, beyond a preregistered owner-approved margin. First-revision approved regression is N/A with reason, but current-practice acceptance and safety remain mandatory. Missing applicable margin/precision rule prevents promotion. Small feasibility studies cannot establish that rule after seeing favorable results.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: stage-01-skills-adoption
|
id: stage-01-skills-adoption
|
||||||
title: Stage - 01 - Skills Adoption
|
title: Skills lifecycle reference
|
||||||
description: Build proven skills and measurable working practices through human and AI Agent collaboration, starting with Delivery.
|
description: Work through an illustrative Delivery experiment from current AI-assisted practice to an evidence-based decision.
|
||||||
hide_table_of_contents: true
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -9,12 +9,14 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
<div className="strategy-content">
|
<div className="strategy-content">
|
||||||
|
|
||||||
Improve one workflow through human + AI Agent work, then repeat with evidence. This is the practical first stage of the [Roadmap](./roadmap.mdx), not permission to deploy the autonomous [Target](./target-operating-model.mdx).
|
Improve one workflow through human + AI Agent work, then repeat with evidence. This is the practical experiment supporting the [6 Months Roadmap](./six-months-roadmap.mdx), not a mandatory skills program or permission to deploy the long-term autonomous [Target](./target-operating-model.mdx). Use context, coaching, test/review feedback or deterministic automation if they better address the bottleneck.
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-stage01" title="One workflow: establish the starting point, engineer and qualify, pilot, decide, maintain and learn" story />
|
<ArchifyDiagram name="strategy-stage01" title="One workflow: establish the starting point, engineer and qualify, pilot, decide, maintain and learn" story />
|
||||||
|
|
||||||
**Read the arrows as handoffs, not a checklist of page approvals.** Governance bounds every activity. Measurement supplies selected definitions throughout. Quality establishes candidate fitness; Adoption tests usefulness in real work; Maintenance returns failures and changed conditions to qualification.
|
**Read the arrows as handoffs, not a checklist of page approvals.** Governance bounds every activity. Measurement supplies selected definitions throughout. Quality establishes candidate fitness; Adoption tests usefulness in real work; Maintenance returns failures and changed conditions to qualification.
|
||||||
|
|
||||||
|
The [6 Months Roadmap](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) owns EXP-01 and the month-by-month plan; this reference only explains reusable lifecycle handoffs within the broad [Roadmap](./roadmap.mdx).
|
||||||
|
|
||||||
## Delivery first: one change, from intent to accepted work
|
## Delivery first: one change, from intent to accepted work
|
||||||
|
|
||||||
**Illustrative Delivery workflow throughout these pages — not an Eldorado pilot or measured result:** a Product Engineering developer uses an AI Agent to prepare a bounded code change and regression tests. An independent reviewer checks the exact change and evidence. Existing release authority remains unchanged; the skill cannot approve or deploy its own output.
|
**Illustrative Delivery workflow throughout these pages — not an Eldorado pilot or measured result:** a Product Engineering developer uses an AI Agent to prepare a bounded code change and regression tests. An independent reviewer checks the exact change and evidence. Existing release authority remains unchanged; the skill cannot approve or deploy its own output.
|
||||||
@@ -26,12 +28,12 @@ Adoption can extend to other SDLC phases; their order is not yet decided. Delive
|
|||||||
## Carry evidence forward, not assumptions
|
## Carry evidence forward, not assumptions
|
||||||
|
|
||||||
1. **Understand and baseline.** Product Engineering maps the selected workflow and desired improvement. Select relevant KPIs from [Measurement](./measurement/index.mdx); [Baseline](./baseline.mdx) records current outcomes, acceptance rules and explicit gaps. A baseline describes work; it grants no approval.
|
1. **Understand and baseline.** Product Engineering maps the selected workflow and desired improvement. Select relevant KPIs from [Measurement](./measurement/index.mdx); [Baseline](./baseline.mdx) records current outcomes, acceptance rules and explicit gaps. A baseline describes work; it grants no approval.
|
||||||
2. **Engineer a connected candidate.** Under [Governance](./skills-governance.mdx), connect repository understanding → change/test preparation → independent verification. Specify triggers, inputs, outputs, handoffs, pinned dependencies and forbidden actions. This skills topology is more than a catalogue.
|
2. **Choose the smallest candidate.** If repeated agent guidance is the bottleneck, use [Governance](./skills-governance.mdx) to connect repository understanding → change/test preparation → independent verification. Specify triggers, inputs, outputs, handoffs, pinned dependencies and forbidden actions. This skills topology is more than a catalogue; a deterministic fix may need no skill.
|
||||||
3. **Qualify before exposing real work.** [Quality](./skills-quality.mdx) compares candidate, current-approved and no-skill paths on declared cases. The independent Quality Engineering reviewer accepts evaluation evidence; the owning team's designated approver authorizes only the tested pilot envelope, with Architecture & Security review where risk requires it. Failed checks or missing authority mean rework or hold, not an automatic pilot.
|
3. **Qualify before exposing real work.** [Quality](./skills-quality.mdx) compares the candidate with declared current practice. If no approved skill exists, approved-revision regression is N/A with reason; test removal and recovery to current practice. Once an approved revision exists, add that comparator. The independent Quality Engineering reviewer function accepts evaluation evidence; the owning team's designated approver authorizes only the tested pilot envelope, with security review where risk requires it. Failed checks or missing authority mean rework or hold, not an automatic pilot.
|
||||||
4. **Pilot and compare.** [Adoption](./skills-adoption.mdx) applies that revision to a bounded real-work cohort, retaining the manual path. Compare accepted outcomes, quality, review/rework cost and feedback with the starting position. Live tasks and qualification trials remain separate populations.
|
4. **Pilot and compare.** [Adoption](./skills-adoption.mdx) applies that revision to a bounded real-work cohort, retaining the manual path. Compare accepted outcomes, quality, review/rework cost and feedback with the starting position. Live tasks and qualification trials remain separate populations.
|
||||||
5. **Decide and maintain.** The owning team's designated workflow owner decides retain, improve, stop or propose expansion from the comparison and independent evidence. [Maintenance](./skills-maintenance.mdx) keeps retained revisions supported and feeds defects into requalification. A new scope returns to Baseline; a changed revision returns to Quality. The new current situation starts the next loop.
|
5. **Decide and maintain.** The owning team's designated workflow owner decides retain, improve, stop or propose expansion from the comparison and independent evidence. [Maintenance](./skills-maintenance.mdx) keeps retained revisions supported and feeds defects into requalification. A new scope returns to Baseline; a changed revision returns to Quality. The new current situation starts the next loop.
|
||||||
|
|
||||||
These are recommended responsibilities within existing teams, not appointed people or already approved controls. Before work starts, record the actual accountable person, independent reviewer, acceptance rules and permitted effects. Missing assignments keep the affected decision on hold.
|
These are recommended functions, not evidence of actual departments or appointed people. The architect may build and coordinate; a willing developer/reviewer and actual workflow owner agree contributions. One worksheet plus existing PR/CI records can suffice. Before work starts, record actual people, acceptance rules and permitted effects. Missing assignments keep the affected decision on hold.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Where each topic helps—and what it gives the next activity</summary>
|
<summary>Where each topic helps—and what it gives the next activity</summary>
|
||||||
@@ -49,7 +51,7 @@ The six topics are connected lifecycle activities, not six rigid sequential appr
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Proven skills and working practices may support [Stage - 02 - Autonomous Agent](./stage-02-autonomous-agent.mdx). Stage 01 can remain valuable indefinitely; progression requires a separate case for authority and readiness.
|
Proven skills and working practices may support [Beyond 6 Months](./stage-02-autonomous-agent.mdx). Stage 01 can remain valuable indefinitely; progression requires a separate case for authority and readiness.
|
||||||
|
|
||||||
**Start here:** [Understand and baseline one workflow →](./baseline.mdx). Consult the [Measurement registry](./measurement/index.mdx) when selecting evidence.
|
**Start here:** [Understand and baseline one workflow →](./baseline.mdx). Consult the [Measurement registry](./measurement/index.mdx) when selecting evidence.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: stage-02-autonomous-agent
|
id: stage-02-autonomous-agent
|
||||||
title: Stage - 02 - Autonomous Agent
|
title: Beyond 6 Months
|
||||||
description: Introduce the future Autonomous Agent on proven skills and measured practices while humans retain direction and review.
|
description: Bridge first-six-month evidence toward the long-term human-controlled autonomous SDLC, through separate investment and authority decisions.
|
||||||
hide_table_of_contents: true
|
hide_table_of_contents: true
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -11,13 +11,15 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
**A separate authority decision, not the reward for skills adoption.**
|
**A separate authority decision, not the reward for skills adoption.**
|
||||||
|
|
||||||
This future stage of the [Roadmap](./roadmap.mdx) builds on [Stage - 01 - Skills Adoption](./stage-01-skills-adoption.mdx). The destination is [Target](./target-operating-model.mdx): an Autonomous Agent that executes and governs the SDLC cycle, with humans retaining direction and review.
|
The [6 Months Roadmap](./six-months-roadmap.mdx) ends with a CTO investment decision, not automatic progression. The [experiment](./six-months-roadmap.mdx#exp-01-a-small-decision-ready-example) may justify deeper improvement, selective replication, or stopping. The autonomous [Target](./target-operating-model.mdx) remains the long-term strategy vision; humans retain direction and review. The broad [Roadmap](./roadmap.mdx) connects skills and working practices to controlled autonomous capabilities. Six-month outcomes contribute toward that destination, but do not promise its timing or authorize its execution.
|
||||||
|
|
||||||
|
If one workflow works but transfer fails, invest in local context and coaching rather than mandate uniform use. If several teams request help and recurring value exceeds support burden, propose dedicated enablement capacity with the CTO and team leads. If deterministic tooling solves the problem more reliably, fund that. If outcomes remain inconclusive, narrow or stop the intervention. Recheck the next-quarter portfolio against business priorities, task supply, team willingness and ownership; do not extrapolate a pilot to all engineering.
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-stage02" title="Future authority: evidence and human decision before bounded execution, with independent stop and takeover" story />
|
<ArchifyDiagram name="strategy-stage02" title="Future authority: evidence and human decision before bounded execution, with independent stop and takeover" story />
|
||||||
|
|
||||||
## Build on what has been proven
|
## Consider additional authority only when necessary
|
||||||
|
|
||||||
Carry forward proven skills, measurements and working practices from real human + AI Agent work. The skills foundation provides [governance](./skills-governance.mdx), [quality checks](./skills-quality.mdx), [adoption feedback](./skills-adoption.mdx), [measurement](./measurement/index.mdx) and [maintenance](./skills-maintenance.mdx); it is not permission to expand authority automatically.
|
Carry forward proven skills where useful, measurements and working practices from real human + AI Agent work. The references provide [governance](./skills-governance.mdx), [quality checks](./skills-quality.mdx), [adoption feedback](./skills-adoption.mdx), [measurement](./measurement/index.mdx) and [maintenance](./skills-maintenance.mdx); none is permission to expand authority automatically. The diagram above applies only after a separate business case identifies an operation that supervised work or deterministic automation cannot adequately address.
|
||||||
|
|
||||||
## Introduce authority deliberately
|
## Introduce authority deliberately
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ The output is either a recorded hold or a narrowly scoped authorization with con
|
|||||||
|
|
||||||
This is future direction, not deployed autonomy, agreed delivery dates or approved KPI thresholds. The transition depends on reviewed evidence and explicit authority decisions, not adoption volume alone.
|
This is future direction, not deployed autonomy, agreed delivery dates or approved KPI thresholds. The transition depends on reviewed evidence and explicit authority decisions, not adoption volume alone.
|
||||||
|
|
||||||
|
**Return to the plan:** [6 Months Roadmap](./six-months-roadmap.mdx).
|
||||||
|
|
||||||
**Return to dependable work:** [Continue the Stage 01 improvement loop →](./stage-01-skills-adoption.mdx).
|
**Return to dependable work:** [Continue the Stage 01 improvement loop →](./stage-01-skills-adoption.mdx).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: target-operating-model
|
id: target-operating-model
|
||||||
title: Target operating model
|
title: Target
|
||||||
sidebar_label: Target
|
sidebar_label: Target
|
||||||
description: An autonomous agent executes and governs the SDLC; humans direct, guide and review the repeating cycle.
|
description: An autonomous agent executes and governs the SDLC; humans direct, guide and review the repeating cycle.
|
||||||
hide_table_of_contents: true
|
hide_table_of_contents: true
|
||||||
@@ -12,6 +12,8 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
|
|||||||
|
|
||||||
**TO-BE · Target operating model — the intended strategy, not a deployed system.**
|
**TO-BE · Target operating model — the intended strategy, not a deployed system.**
|
||||||
|
|
||||||
|
The long-term destination remains human-directed, guided and reviewed autonomous SDLC. It is not a six-month commitment or present authorization. The [6 Months Target](./six-months-target.mdx) and [6 Months Roadmap](./six-months-roadmap.mdx) describe a credible nearer-term contribution, not a replacement for this ambition. No fixed completion date or inevitable progression is implied.
|
||||||
|
|
||||||
## Autonomous SDLC, human direction
|
## Autonomous SDLC, human direction
|
||||||
|
|
||||||
<ArchifyDiagram name="strategy-target" title="Autonomous agent executes and governs the SDLC; humans direct, guide and review" story />
|
<ArchifyDiagram name="strategy-target" title="Autonomous agent executes and governs the SDLC; humans direct, guide and review" story />
|
||||||
@@ -66,7 +68,7 @@ Central controls verify protected-branch review, actual artifact identity, exact
|
|||||||
|
|
||||||
### Department contributions
|
### Department contributions
|
||||||
|
|
||||||
The existing team structure provides a starting point. The contributions below are implementation proposals, not settled approval roles or lifecycle gates.
|
The documented organization model is an assumption to validate, not PDF evidence of actual reporting lines. Candidate functions must be mapped to real people before any decision. The existing team structure provides a starting point. The contributions below are implementation proposals, not settled approval roles or lifecycle gates.
|
||||||
|
|
||||||
### Product / Product Management
|
### Product / Product Management
|
||||||
|
|
||||||
@@ -145,7 +147,7 @@ See the existing [organization structure](/organization/structure/), [department
|
|||||||
|
|
||||||
### Govern skills first, expand authority only with evidence
|
### Govern skills first, expand authority only with evidence
|
||||||
|
|
||||||
Eldorado's target is to make AI-assisted work dependable across the organization: useful guidance, clear human ownership, controlled execution and measurable outcomes. The first investment is a governed skills system, not an autonomous replacement for the organization. A skill packages reusable working knowledge, prerequisites and verification steps. It helps an agent perform a task; it does not grant permission or guarantee that the work is correct.
|
Eldorado's target is to make AI-assisted work dependable across the organization: useful guidance, clear human ownership, controlled execution and measurable outcomes. The first investment is understanding and improving current AI-assisted work, not an autonomous replacement for the organization. Governed skills and practices support the direction; context, coaching, test repair or deterministic automation may be the better immediate intervention. A skill packages reusable working knowledge, prerequisites and verification steps. It helps an agent perform a task; it does not grant permission or guarantee that the work is correct.
|
||||||
|
|
||||||
The target combines an autonomous agent executing and governing the SDLC with humans directing, guiding and reviewing it. Developer choice on local laptops remains a supporting option: Copilot, Claude Code and Cline can receive reviewed portable skill content through qualified adapters. Repository, CI and release controls support execution; detailed approval policies remain implementation decisions, not new roles established by this strategy.
|
The target combines an autonomous agent executing and governing the SDLC with humans directing, guiding and reviewing it. Developer choice on local laptops remains a supporting option: Copilot, Claude Code and Cline can receive reviewed portable skill content through qualified adapters. Repository, CI and release controls support execution; detailed approval policies remain implementation decisions, not new roles established by this strategy.
|
||||||
|
|
||||||
@@ -156,14 +158,16 @@ Success means accepted outcomes with maintained quality, controlled risk and und
|
|||||||
### Navigate the strategy
|
### Navigate the strategy
|
||||||
|
|
||||||
- [Roadmap](./roadmap.mdx) — Skills adoption first; future autonomy separately justified, no promised dates or budgets.
|
- [Roadmap](./roadmap.mdx) — Skills adoption first; future autonomy separately justified, no promised dates or budgets.
|
||||||
- [Stage 01](./stage-01-skills-adoption.mdx) — Follow one workflow through evidence, decisions and feedback.
|
- [6 Months Target](./six-months-target.mdx) — Assignment context, realistic outcomes and assumptions.
|
||||||
|
- [6 Months Roadmap](./six-months-roadmap.mdx) — Month 1–6 priorities and bounded experiment decisions.
|
||||||
|
- [Skills lifecycle](./stage-01-skills-adoption.mdx) — Supporting handoffs, decisions and feedback.
|
||||||
- [Baseline](./baseline.mdx) — Understand current work and record the starting position before changing it.
|
- [Baseline](./baseline.mdx) — Understand current work and record the starting position before changing it.
|
||||||
- [Skills governance](./skills-governance.mdx) — Contract, lifecycle, decision rights, adapters, locking, exceptions.
|
- [Skills governance](./skills-governance.mdx) — Contract, lifecycle, decision rights, adapters, locking, exceptions.
|
||||||
- [Skills quality](./skills-quality.mdx) — Risk tiers, independent evaluation, repeated trials, adversarial conformance.
|
- [Skills quality](./skills-quality.mdx) — Risk tiers, independent evaluation, repeated trials, adversarial conformance.
|
||||||
- [Skills adoption](./skills-adoption.mdx) — Workflow-led coaching, client choice, feedback, manual path.
|
- [Skills adoption](./skills-adoption.mdx) — Workflow-led coaching, client choice, feedback, manual path.
|
||||||
- [Measurement](./measurement/index.mdx) — Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
|
- [Measurement](./measurement/index.mdx) — Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
|
||||||
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
|
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
|
||||||
- [Stage 02](./stage-02-autonomous-agent.mdx) — Decide whether bounded autonomous authority is justified and recoverable.
|
- [Beyond 6 Months](./stage-02-autonomous-agent.mdx) — Decide whether bounded autonomous authority is justified and recoverable.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -7,9 +7,12 @@
|
|||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "pnpm diagrams:build && docusaurus start",
|
"start": "pnpm diagrams:build && pnpm presentations:build && docusaurus start",
|
||||||
"build": "pnpm diagrams:build && docusaurus build",
|
"build": "pnpm diagrams:build && pnpm presentations:build && docusaurus build",
|
||||||
|
"presentations:build": "node scripts/build-presentations.mjs",
|
||||||
"serve": "docusaurus serve",
|
"serve": "docusaurus serve",
|
||||||
|
"test:presentation": "node scripts/browser/presentation.cjs",
|
||||||
|
"test:homepage-embed": "node scripts/browser/homepage-embed.cjs",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"verify": "pnpm test && node scripts/verify.mjs",
|
"verify": "pnpm test && node scripts/verify.mjs",
|
||||||
"verify:build": "node scripts/verify.mjs --build",
|
"verify:build": "node scripts/verify.mjs --build",
|
||||||
@@ -29,7 +32,8 @@
|
|||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"prism-react-renderer": "2.4.1",
|
"prism-react-renderer": "2.4.1",
|
||||||
"react": "19.1.1",
|
"react": "19.1.1",
|
||||||
"react-dom": "19.1.1"
|
"react-dom": "19.1.1",
|
||||||
|
"reveal.js": "5.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "3.10.2",
|
"@docusaurus/module-type-aliases": "3.10.2",
|
||||||
|
|||||||
Generated
+9
@@ -44,6 +44,9 @@ importers:
|
|||||||
react-dom:
|
react-dom:
|
||||||
specifier: 19.1.1
|
specifier: 19.1.1
|
||||||
version: 19.1.1(react@19.1.1)
|
version: 19.1.1(react@19.1.1)
|
||||||
|
reveal.js:
|
||||||
|
specifier: 5.2.1
|
||||||
|
version: 5.2.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@docusaurus/module-type-aliases':
|
'@docusaurus/module-type-aliases':
|
||||||
specifier: 3.10.2
|
specifier: 3.10.2
|
||||||
@@ -4634,6 +4637,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
||||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||||
|
|
||||||
|
reveal.js@5.2.1:
|
||||||
|
resolution: {integrity: sha512-r7//6mIM5p34hFiDMvYfXgyjXqGRta+/psd9YtytsgRlrpRzFv4RbH76TXd2qD+7ZPZEbpBDhdRhJaFgfQ7zNQ==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
rtlcss@4.3.0:
|
rtlcss@4.3.0:
|
||||||
resolution: {integrity: sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==}
|
resolution: {integrity: sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@@ -11634,6 +11641,8 @@ snapshots:
|
|||||||
|
|
||||||
reusify@1.1.0: {}
|
reusify@1.1.0: {}
|
||||||
|
|
||||||
|
reveal.js@5.2.1: {}
|
||||||
|
|
||||||
rtlcss@4.3.0:
|
rtlcss@4.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Less Prompting, More Shipping — v1.1.0
|
||||||
|
|
||||||
|
An explanation for the CTO and engineering leads: understand the intended destination and decide how a solo AI Architect should contribute in the first six months. The original `AI_Architect_Test_Task.pdf` supplies the assumed context, four questions and 50-minute total. The same-build Strategy supplies the connected narrative: **Target → Roadmap → 6 Months Target → 6 Months Roadmap → Beyond 6 Months**. The six-month contribution neither replaces the long-term human-controlled autonomous SDLC nor authorizes it.
|
||||||
|
|
||||||
|
## Story and timing
|
||||||
|
|
||||||
|
23 slides: 21 main slides / **35 minutes**, one **15-minute Q&A**, one **zero-minute reference appendix**. EXP-01 is now one two-minute illustration, not the spine of the strategy. Its detailed fictional sample, extension caps and stop ledger remain in speaker notes and the canonical linked Strategy packet.
|
||||||
|
|
||||||
|
The table is the revised presentation allocation. The PDF prescribes 50 minutes total, not this split. The six-month Strategy page still contains an earlier proposed outline; its exact subsection timings are not claimed to match this destination-first deck. No Strategy page was rewritten to accommodate the presentation.
|
||||||
|
|
||||||
|
| Slide | Minutes / elapsed | Main message | Strategy evidence (canonical slug) |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | 1 / 0–1 | Destination and first contribution | target-operating-model; roadmap; six-months-target; PDF |
|
||||||
|
| 2 | 2 / 1–3 | Existing uneven AI; solo CTO-reporting role; unknowns | six-months-target; PDF Context/Q1/assumptions |
|
||||||
|
| 3 | 1 / 3–4 | Accepted output, not faster drafts | six-months-target; baseline; measurement |
|
||||||
|
| 4 | 3 / 4–7 | Intended SDLC cycle and central human-controlled agent | target-operating-model |
|
||||||
|
| 5 | 1 / 7–8 | Eight outside human-controlled contributors | target-operating-model |
|
||||||
|
| 6 | 2 / 8–10 | Delivery-first adoption, then other phases, then separate autonomy | roadmap; target-operating-model |
|
||||||
|
| 7 | 2 / 10–12 | Connected skills and repeating within-phase learning | roadmap; stage-01-skills-adoption |
|
||||||
|
| 8 | 1 / 12–13 | First-six-month building block toward Target | six-months-target; target-operating-model |
|
||||||
|
| 9 | 1 / 13–14 | Influence beside work, no team authority | six-months-roadmap |
|
||||||
|
| 10 | 2 / 14–16 | Months 1–2: discover, baseline, agree | six-months-roadmap; baseline |
|
||||||
|
| 11 | 2 / 16–18 | Months 3–4: qualify, test, compare | six-months-roadmap |
|
||||||
|
| 12 | 2 / 18–20 | Months 5–6: conditional transfer and handover | six-months-roadmap; six-months-target |
|
||||||
|
| 13 | 1 / 20–21 | Solo capacity, one live pilot, funded support | six-months-roadmap |
|
||||||
|
| 14 | 2 / 21–23 | Acceptance, burden, quality and total costs | measurement; six-months-roadmap |
|
||||||
|
| 15 | 2 / 23–25 | Misleading signals and causal limits | measurement; six-months-roadmap |
|
||||||
|
| 16 | 2 / 25–27 | Qualification is not pilot permission | skills-quality; six-months-roadmap |
|
||||||
|
| 17 | 2 / 27–29 | Fictional EXP-01: cheapest fit, hold, then stop | six-months-roadmap |
|
||||||
|
| 18 | 1 / 29–30 | Realistic month-six evidence portfolio | six-months-target; six-months-roadmap |
|
||||||
|
| 19 | 2 / 30–32 | Evidence-led investment toward established destination | stage-02-autonomous-agent; target-operating-model; roadmap; six-months-target |
|
||||||
|
| 20 | 2 / 32–34 | Separate bounded authority, stop and human takeover | stage-02-autonomous-agent; target-operating-model |
|
||||||
|
| 21 | 1 / 34–35 | First CTO alignment and four answers | six-months-roadmap; PDF Q1–4 |
|
||||||
|
| 22 | 15 / 35–50 | Q&A | PDF Format; six-months-target |
|
||||||
|
| 23 | 0 / optional | Linked references, outside the main talk | PDF; all five Strategy pages plus measurement |
|
||||||
|
|
||||||
|
PDF Q1 **What you do** → slides 2, 9–13. Q2 **How you measure it** → 14–17. Q3 **What you achieve** → 8 and 18. Q4 **What comes next** → 4–7 establish the destination; 19–20 explain evidence-led progression. Scale/growth/uneven AI use are assignment facts, not independently measured company facts. Stack, providers, data policy, task supply, partner capacity and bottlenecks remain unknown or hypotheses, explained on slide 2 and in discovery notes.
|
||||||
|
|
||||||
|
## Source and build
|
||||||
|
|
||||||
|
- `slides.mjs` is the single editorial source for standalone and homepage. Every slide has section, track, timing, narration and source references. Notes are public HTML, never confidential.
|
||||||
|
- `target-figure.mjs` provides two presentation-sized views of the original topology. Slide 4 preserves the eight ordered cycle edges and eight governance spokes, including Releases → Scope. Slide 5 preserves all eight external `code-* → phase` contribution edges. There is one central autonomous agent, not a separate Humans node or a reporting hierarchy. Tests compare all three edge sets with the original diagram JSON; desktop and phone are recomposed, not shrunk documentation screenshots.
|
||||||
|
- `theme.css` preserves portal Lato/gold/charcoal/light surfaces and isolated standalone styles. Distinct cycle, contribution layer, staged progression, learning loop and horizon compositions support the story.
|
||||||
|
- `runtime.js` is unchanged: Reveal, reduced motion, responsive portrait layout, toolbar, isolated embedded focus/URL and no autoplay.
|
||||||
|
- `scripts/build-presentations.mjs` generates the same canonical route, exact-pinned local Reveal.js 5.2.1, notes plugin, Lato assets/licenses and `source-map.json`. The map includes slide IDs/sections/tracks/minutes/sources, four-question coverage, exact Strategy and topology source hashes, and provenance without claiming historical revisions are current. No runtime CDN.
|
||||||
|
|
||||||
|
From repository root: `pnpm install --frozen-lockfile`, `pnpm test`, `pnpm typecheck`, `pnpm build`, `pnpm verify:build`. Serve `build/` under `/eldorado-v1/documentation/` with a static server. The canonical route remains `/eldorado-v1/documentation/presentations/less-prompting-more-shipping/`. The homepage's **Understand In Speed** embeds that generated document, not a duplicated slide source. Existing Organization, Strategy, homepage component and runtime sources are preserved.
|
||||||
|
|
||||||
|
## Present and verify
|
||||||
|
|
||||||
|
Arrows/touch navigate. Esc/Overview shows the grid. F/Fullscreen and S/Notes work standalone; embedded focus stays within its own document and parent URL is unchanged. Notes need HTTP(S) and popups. Named deep links such as `#/target` and `#/qualification` survive refresh. Print uses `?print-pdf`: Chromium, landscape, no margins, background graphics. Export has **23 pages**, without notes. No unsolicited PDF/PPTX/ZIP is published.
|
||||||
|
|
||||||
|
`pnpm test:presentation <base>` covers 23 slides at desktop, portrait and landscape (69 views), bounds, errors, links, hash/refresh, keyboard, touch, overview, notes popup, fullscreen, homepage handoff and 23-page print layout. `pnpm test:homepage-embed <base>` covers 23 slides at four widths (92 views), focus/scroll/URL isolation, touch, fullscreen, unsupported-fullscreen escape, Tab exit, themes and reduced motion. Outputs are ordered individual PNGs and JSON in `.cache/presentation/` and `.cache/homepage-embed/`; inspect real pixels, not just geometry. Set `PLAYWRIGHT_CHROMIUM_EXECUTABLE` for an installed browser.
|
||||||
|
|
||||||
|
Local Docusaurus serve on Node 26 redirects WOFF2 paths with a trailing slash in this environment. Use a regular prefix-correct static server for production-equivalent font verification; missing-font screenshots are not acceptable evidence.
|
||||||
|
|
||||||
|
Official runtime references: https://revealjs.com/installation/, https://revealjs.com/speaker-view/, https://revealjs.com/pdf-export/. The pinned package is intentional; runtime API compatibility is judged against 5.2.1, not latest-version assumptions.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
No guaranteed benefits, approved thresholds, staffing commitments or deployed autonomy. The intended long-term destination is explicit, while its timing and authority remain unapproved. First-six-month failure or a cheaper deterministic intervention is compatible with that direction. Human product, risk and release authority is retained. Skills carry knowledge and verification, not permission.
|
||||||
|
|
||||||
|
Dependency manifests are unchanged. Previously recorded production audit: 2 critical, 2 high, 2 moderate; this presentation revision is neither remediation nor security-risk acceptance. Chromium viewport testing is not Safari/Firefox, physical-device or full assistive-technology certification. This branch is a review candidate; the dependent reviewer owns merge, exact-main CI and deployed verification.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Reveal 5.2.1, fully local runtime; this document is isolated from Docusaurus CSS. */
|
||||||
|
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||||
|
const portrait = window.matchMedia('(max-width: 700px) and (orientation: portrait)');
|
||||||
|
const printing = new URLSearchParams(location.search).has('print-pdf');
|
||||||
|
const embedded = new URLSearchParams(location.search).has('embed') && !printing;
|
||||||
|
document.documentElement.classList.toggle('embedded', embedded);
|
||||||
|
if (embedded) {
|
||||||
|
document.querySelector('.toolbar').hidden = true;
|
||||||
|
// Never load the portal inside the stage when following the reference appendix.
|
||||||
|
document.querySelectorAll('.slides a').forEach(link => { link.target = '_top'; });
|
||||||
|
}
|
||||||
|
function layoutSize(){
|
||||||
|
const narrow=portrait.matches&&!printing;
|
||||||
|
document.documentElement.classList.toggle('portrait',narrow);
|
||||||
|
return narrow?{width:600,height:1000}:{width:1200,height:660};
|
||||||
|
}
|
||||||
|
Reveal.initialize({
|
||||||
|
...layoutSize(), margin:0.04, minScale:0.1, maxScale:2,
|
||||||
|
hash:!embedded, embedded, keyboardCondition:embedded ? () => document.hasFocus() : null,
|
||||||
|
hashOneBasedIndex:false, controls:true, progress:true,
|
||||||
|
slideNumber:'c/t', showSlideNumber:'all', center:false,
|
||||||
|
transition:reducedMotion.matches?'none':'fade', transitionSpeed:'fast',
|
||||||
|
backgroundTransition:'none', autoSlide:0, touch:true,
|
||||||
|
// The host owns fullscreen; speaker tools remain available in the standalone deck.
|
||||||
|
keyboard:embedded ? {70:null,83:null} : true,
|
||||||
|
// Keep deliberate slides on phones rather than Reveal's automatic scroll view.
|
||||||
|
scrollActivationWidth:null, pdfMaxPagesPerSlide:1, pdfSeparateFragments:false,
|
||||||
|
plugins:[RevealNotes]
|
||||||
|
});
|
||||||
|
portrait.addEventListener('change',()=>Reveal.configure(layoutSize()));
|
||||||
|
reducedMotion.addEventListener('change',event=>Reveal.configure({transition:event.matches?'none':'fade'}));
|
||||||
|
document.getElementById('overview').addEventListener('click',()=>Reveal.toggleOverview());
|
||||||
|
document.getElementById('notes').addEventListener('click',()=>Reveal.getPlugin('notes').open());
|
||||||
|
document.getElementById('fullscreen').addEventListener('click',()=>{
|
||||||
|
if(document.fullscreenElement) document.exitFullscreen();
|
||||||
|
else document.documentElement.requestFullscreen?.();
|
||||||
|
});
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
// Single editorial source for standalone and homepage. Planned narration: 35 + 15 minutes.
|
||||||
|
import {cycleFigure,contributionsFigure} from './target-figure.mjs';
|
||||||
|
export const slides = [
|
||||||
|
{
|
||||||
|
"id": "opening",
|
||||||
|
"title": "Less Prompting,<br>More Shipping",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<p class=\"subtitle\">The destination—and the first six months toward it</p><p class=\"thesis\">Improve accepted engineering work.<br>Not the number of times we ask AI.</p><p class=\"small\">Proposed strategy · 35 minutes + 15 minutes Q&A</p>",
|
||||||
|
"notes": "Open with the outcome, not a tool purchase. The title is a reminder to measure useful work, not an instruction to minimize prompts. More careful prompting may be exactly what good work needs. My proposal is to earn one evidence-backed improvement, make its costs visible, and stop what does not help. Walk through what I do, how I measure, what month six looks like and what comes next. Start with the long-term Target and broad Roadmap, then bound the first-six-month contribution. The five Strategy pages organize this story; the assignment supplies the four questions and total time.",
|
||||||
|
"sources": [
|
||||||
|
"PDF: Format; Context; questions 1–4",
|
||||||
|
"six-months-target",
|
||||||
|
"target-operating-model",
|
||||||
|
"roadmap"
|
||||||
|
],
|
||||||
|
"kind": "dark",
|
||||||
|
"section": "Why change",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "starting-point",
|
||||||
|
"title": "We are not starting from “no AI”.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"facts\"><div><strong>≈80 → ≈100</strong><span>engineers, by year end</span></div><div><strong>>10</strong><span>teams</span></div><div><strong>Already using AI</strong><span>uneven depth and quality</span></div></div><div class=\"contrast\"><p>Solo architect → CTO<br>No formal authority over teams</p><p>Stack, tools, process, baselines<br>Capacity and actual bottlenecks</p></div>",
|
||||||
|
"notes": "These headcount and usage facts are from the assignment, not independent research. The comparison is existing AI-assisted practice, never an invented no-AI baseline. Delivery is a starting hypothesis, not a finding. The documented departmental model is not evidence of actual assignment staffing. Ask about stack and tool/data restrictions in discovery; do not assume familiar clients are in use. Every timeline and proposed allocation in this deck remains subject to agreement.",
|
||||||
|
"sources": [
|
||||||
|
"PDF: Context; question 1; final assumptions instruction",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Why change",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "north-star",
|
||||||
|
"title": "A faster draft is not a shipped outcome.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<div class=\"flow\"><span>Intent</span><i>→</i><span>Change + tests</span><i>→</i><span>Independent acceptance</span></div><div class=\"rail\">Existing release authority stays with people.</div><p class=\"statement\">Less rework. Sound quality.<br>Understand the total burden.</p><p class=\"small\">If the bottleneck is CI or review capacity, fix that—not the prompt count.</p>",
|
||||||
|
"notes": "Trace a change through acceptance and its existing release route. An agent can shorten drafting and still make reviewers work harder. The outcome must survive independent acceptance, defect follow-up and total-cost accounting. Observe why work comes back rather than assume more output from the model means more output from engineering. Flaky tests, unclear scope or scarce reviewers may make a non-AI intervention the right investment.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-target",
|
||||||
|
"baseline",
|
||||||
|
"measurement"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Why change",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "target",
|
||||||
|
"title": "Target / Autonomous SDLC.",
|
||||||
|
"minutes": 3,
|
||||||
|
"body": cycleFigure + `<p class="diagram-legend">Solid → lifecycle · Dotted ⇢ executes and governs</p><p class="small">Humans direct, guide and review. Not deployed or promised in six months.</p>`,
|
||||||
|
"notes": "This is the intended destination, not deployed software, an agreed date or a six-month promise. Read the solid cycle clockwise from Scope: Architecture, UI/UX, Planning, Delivery, UAT, Security, Releases, then evidence returns to Scope. The single central autonomous agent executes and governs every phase, not merely routing tickets. Dotted spokes connect it to all eight phases; people direct, guide and review throughout. There is deliberately no separate Humans node or organizational reporting hierarchy. This view isolates the lifecycle and governance relationships for readability; the next slide restores all eight outside human-controlled contributors. Neither diagram assigns approval roles or grants permissions.",
|
||||||
|
"sources": [
|
||||||
|
"target-operating-model"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Target",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "contributors",
|
||||||
|
"title": "People contribute throughout the cycle.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": `<p class="diagram-intro">Eight separate AI Agents, each human-controlled.</p>` + contributionsFigure + `<p class="small">AI Agent = Claude, Cline, ChatGPT or a similar tool, used under human control.</p><div class="rail">Dashed ⇢ contribution from outside the cycle.</div>`,
|
||||||
|
"notes": "Keep the previous cycle in mind: these eight pairs are its contribution layer, not a second lifecycle or eight central coordinators. Each separate human-controlled AI Agent contributes to its corresponding phase from outside the cycle. The central autonomous agent remains connected to every phase, executing and governing under human direction. Splitting the original topology into two presentation-sized views preserves all eight lifecycle arrows, eight governance spokes and eight contribution arrows without miniaturizing seventeen nodes. Laptop client choice and adapters are implementation options, not a promise of installed support. Human review, product and risk decisions remain necessary.",
|
||||||
|
"sources": [
|
||||||
|
"target-operating-model"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Target",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "roadmap",
|
||||||
|
"title": "Roadmap / Build dependable work first.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"journey\"><div><small>STAGE 1 · HUMAN + AI</small><b>Delivery first</b><span>Standardize connected skills<br>and working practices</span></div><i>→</i><div><small>STAGE 1 · EXPAND</small><b>Other SDLC phases</b><span>Order undecided<br>Delivery keeps improving</span></div><i>⇢</i><div><small>STAGE 2 · SEPARATE AUTHORITY</small><b>Autonomous capabilities</b><span>Proven practices + controls<br>toward the Target</span></div></div><div class=\"rail\">Humans direct, guide and review throughout.</div><p class=\"small\">A strategic progression—not a six-month schedule or automatic graduation.</p>",
|
||||||
|
"notes": "The Roadmap has two broad stages. First standardize skills and practices in human plus AI Agent work, starting with Delivery. Then expand across other SDLC phases, with their remaining order explicitly undecided. This adoption order is different from the Target lifecycle sequence. Delivery continues improving while other phases join. Proven skills, measurements and working practices provide a foundation for the future autonomous agent, but adoption volume never grants authority. Stage one is useful in its own right. Evidence may support coaching, context or deterministic tooling rather than a skill for a particular bottleneck; that practical choice contributes to dependable work rather than cancelling the long-term destination.",
|
||||||
|
"sources": [
|
||||||
|
"roadmap",
|
||||||
|
"target-operating-model"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "learning-loop",
|
||||||
|
"title": "Connected skills. A repeating learning loop.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"learning-loop\"><span>Understand work</span><i>→</i><span>Measure + baseline</span><i>↓</i><span>Engineer topology</span><i>→</i><span>Use in real work</span><i>↓</i><span>Collect results</span><i>→</i><span>Reassess</span></div><div class=\"rail\">↻ Repeat within each phase. Not six global rollout stages.</div><p class=\"statement\">Triggers → skills → handoffs → acceptance.</p><p class=\"small\">Relationships and cooperation—not merely a catalogue.</p>",
|
||||||
|
"notes": "Within every adopted phase repeat the loop: understand the current situation, select relevant metrics and baseline, engineer connected skills, use them in real work, collect outcomes/friction/feedback, then reassess and repeat. Topology defines what exists, how skills relate, when each triggers and how they cooperate. In Delivery trace codebase principles through system logic, tests, builds/packaging and deployment before designing that topology. A code-change skill may hand an exact patch and regression evidence to independent review; its trigger is an eligible change, not an ambient right to act. Governance and Measurement support the whole loop. Qualify revisions before use, and reconsider simpler interventions whenever the evidence says they fit better.",
|
||||||
|
"sources": [
|
||||||
|
"roadmap",
|
||||||
|
"stage-01-skills-adoption"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "six-month-target",
|
||||||
|
"title": "6 Months Target / One credible contribution.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<div class=\"horizon\"><div><small>LONG-TERM DESTINATION</small><b>Human-controlled autonomous SDLC</b></div><div class=\"near\"><small>FIRST SIX MONTHS</small><b>One workflow understood and improved—or stopped with evidence</b><span>One willing partner · reusable practice · owned upkeep</span></div></div><p class=\"statement\">Earn a dependable building block.<br>Do not promise the entire destination.</p>",
|
||||||
|
"notes": "Separate the horizons without making them opposing stories. A credible six-month contribution is a current-work map, an agreed comparison, a bounded intervention and transparent evidence, with a team owner if useful practice is retained. One workflow with one willing team is already meaningful for a solo architect; a second team is conditional on fit and support. These are proposed outcomes, not known company results or guaranteed gains. If an intervention fails, the useful result is an explained stop, retained learning and a better next investment. The autonomous SDLC remains the destination, with no claim that it can or should be delivered in six months.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-target",
|
||||||
|
"target-operating-model"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Target",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "influence",
|
||||||
|
"title": "Influence is earned beside the work.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<div class=\"roles\"><div><b>CTO</b><span>Sponsor access<br>Resolve priority trade-offs</span></div><div class=\"gold\"><b>Architect</b><span>Pair, build, evaluate<br>Bring evidence—not mandates</span></div><div><b>Willing team</b><span>Agree contribution<br>Own acceptance and upkeep</span></div></div><p class=\"statement\">An invitation with an exit.<br>Not a rollout disguised as a favor.</p>",
|
||||||
|
"notes": "Meet leads, developers and reviewers across contrasting workflows before recruiting one willing team. Show a concrete example to a skeptic and invite them to judge it without requiring enrollment. Agree a short weekly team check-in and a monthly CTO decision review. Record participant and reviewer effort: it is not free labor. If priorities conflict, ask the CTO to choose a trade-off rather than use sponsorship as a compliance escalation. Actual approvers must be named before a pilot.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "months-one-two",
|
||||||
|
"title": "Months 1–2 / Earn the right to test.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"timeline\"><div><b>01 · Discover</b><p>Trace real changes.<br>Rank friction and evidence gaps.</p><span>Output: current-work map</span></div><div><b>02 · Agree</b><p>One willing team.<br>Baseline + smallest intervention.</p><span>Output: bounded experiment packet</span></div></div><div class=\"gate\">Decision 1 → Fund one experiment—or hold.</div><p class=\"small\">No partner, reliable checks or lawful evidence → no live pilot.</p>",
|
||||||
|
"notes": "In month one agree expectations and access with the CTO, pair on contrasting workflows and trace repository principles, system logic, tests, builds and deployments. Rank bottlenecks, not teams. Month two observes a prospective baseline and compares context, coaching, test feedback, deterministic automation and skills. Agree task eligibility, acceptance, evidence, people, spend/effort limits and a stop date. The experiment packet can be one worksheet plus existing records. Discovery may need to continue; the calendar does not waive prerequisites.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap",
|
||||||
|
"baseline"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "months-three-four",
|
||||||
|
"title": "Months 3–4 / Test, then decide.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"timeline\"><div><b>03 · Work alongside</b><p>Build and independently qualify.<br>Pair on bounded real work.</p><span>Output: failures + reproducible examples</span></div><div><b>04 · Compare</b><p>Reconcile outcomes and burden.<br>Include pending and abandoned work.</p><span>Output: retain / change / hold / stop</span></div></div><div class=\"gate\">Decision 2 → Keep only what the evidence supports.</div><p class=\"small\">Missing follow-up is “unknown”, not “all clear”.</p>",
|
||||||
|
"notes": "Qualification precedes exposure to real work; actual pilot permission is a separate human decision. During month three I pair and collect both benefits and transferred work. Month four compares matured cohorts with the reviewer, records task mix and concurrent changes, and gives the owner and CTO a recommendation. Unsafe work stops immediately. Sparse tasks or missing follow-up make the result inconclusive. Only an explicitly approved bounded extension can continue; otherwise narrow or stop. Do not silently convert a feasibility exercise into a rollout.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "months-five-six",
|
||||||
|
"title": "Months 5–6 / Transfer only if earned.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"timeline\"><div><b>05 · Selective transfer</b><p>Champion + backup.<br>Check a second team’s fit.</p><span>Only with capacity and funded upkeep</span></div><div><b>06 · Evidence review</b><p>Team operates without daily help.<br>CTO chooses the next investment.</p><span>Owned workflow—or documented stop</span></div></div><p class=\"statement\">New scope → new baseline.<br>No automatic company-wide rollout.</p>",
|
||||||
|
"notes": "A second team is conditional: willingness, different task mix and support capacity can all change the answer. Keep improving the first workflow if transfer is premature. Hand over a reproducible example, support and recovery instructions to an actual owner and backup. Test operation without my daily assistance rather than treating training attendance as handover. Month six must show limits and stopped work as well as retained value. The CTO decides what is worth funding next.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "capacity",
|
||||||
|
"title": "One architect. One active live pilot.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<p>Example weekly allocation for the AI architect</p><div class=\"capacity\" aria-label=\"Proposed weekly allocation: two days hands-on, one evaluation, one relationships, one support and decisions\"><div class=\"pair\">2 days<br><b>Pair + build</b></div><div>1 day<br><b>Evaluate</b></div><div>1 day<br><b>Relationships</b></div><div>1 day<br><b>Decisions + buffer</b></div></div><p class=\"statement\">Support is work.<br>Put it in the budget.</p><p class=\"small\">Proposed capacity envelope—not known company availability.</p>",
|
||||||
|
"notes": "This five-day allocation is a planning envelope, not a claim about company staffing. Two days are hands-on, one evaluation, one coaching/relationships, one sponsor decisions, support and contingency. Team lead agreement must include review time. A second team begins only when the first is supportable. Offer reusable examples and bounded office hours, not a permanent help desk to more than ten teams. Excess support demand becomes a CTO investment decision or a smaller scope.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "measures",
|
||||||
|
"title": "Measure better work—and skill health",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"measurement-panels\"><div class=\"workflow-panel\"><h3>Is the work improving?</h3><p class=\"metric-context\">Baseline → pilot · like-for-like cohorts</p><div class=\"metric\"><b>Validated task success (%)</b><span>Independently accepted tasks ÷ all matured eligible starts.</span></div><div class=\"metric\"><b>Changes with escaped quality issues (%)</b><span>Changes with confirmed defects ÷ accepted changes with completed follow-up.</span></div><div class=\"metric\"><b>Cost per accepted outcome <em>(currency/outcome)</em></b><span>Allocated cohort cost, including failures and review/rework ÷ independently accepted tasks.</span></div></div><div class=\"skill-panel\"><h3>Are skills fit and maintained?</h3><p class=\"metric-context\">Separate qualification + catalog populations</p><div class=\"metric\"><b>Skill selection precision (%)</b><span>Correct activations ÷ all scored activations in labeled evaluation.</span></div><div class=\"metric\"><b>Skills within substantive review window (%)</b><span>Owned, reviewed, not-overdue revisions ÷ all active approved revisions.</span></div><p class=\"qualification-note\">Independent quality qualification still required.</p></div></div><p class=\"measurement-caution\">Choose relevant measures · Unknown is not zero<br>Skill health is not productivity proof.</p>",
|
||||||
|
"notes": "Choose a small relevant subset from the sixteen optional contracts, not a requirement to collect all five shown here or all sixteen. These are candidate definitions, not actual company values or installed telemetry: task success, escaped quality, cost and precision have prototype calculations without network collectors; substantive-review coverage is unimplemented. Workflow only: compare like-for-like periods/cohorts with the same eligibility, task mix, observation and follow-up horizons, acceptance rubric and source coverage; record staffing, model/client and concurrent process changes. Before/after differences are not causal ROI. Validated task success is 100 times distinct independently accepted tasks by as_of divided by all eligible starts whose preregistered observation horizon has matured. Count each task once across retries, clients and skills. Failures, abandonment and unresolved matured starts remain in the denominator; unknown outcomes are not labeled failures. Exclude pre-start cancellations, sandbox/evaluation and out-of-scope tasks; flag invalid/missing starts and show unknown counts and coverage. Escaped quality is 100 times accepted changes with at least one linked confirmed post-acceptance defect during approved follow-up divided by accepted changes whose predeclared follow-up is complete. Count affected changes, not raw defects; separate severity and absolute defect/severe-incident counts. Show immature changes and pending triage separately; missing linkage or incomplete follow-up is not a clean result. Cost divides allocated costs for every task/attempt in the matured start cohort through as_of, including failed and abandoned attempts and shared period costs, by distinct independently accepted tasks in that same cohort. Include licenses, compute, tooling, setup, qualification, onboarding, support, upkeep and human quality review/rework effort at approved rates without double counting; exclude unrelated projects and documented accounting-basis exclusions. Use one approved reporting currency or dated approved conversion. Missing cost buckets mean a partial estimate with coverage, not total cost; zero accepted outcomes means null with full cost shown. Restate late invoices. Skill selection precision is 100 times true-positive activations divided by true-positive plus false-positive activations in candidate/client evaluation trials with independently labeled relevance and known activation. Freeze the corpus, retain negative/failed trials; unknown activation/relevance is unscorable, reported with coverage and blocks qualification if planned coverage is incomplete. This does not measure artifact success or live workflow acceptance. Substantive-review coverage is 100 times active approved revisions with current owner, linked substantive review evidence and review_due_at at or after as_of divided by all active approved revisions in the catalog snapshot. Experimental/retired revisions are excluded; report deprecated/revoked-in-use and ownerless counts separately. Missing owner/date/evidence stays outside the numerator. Review evidence includes regression, security and usefulness, not a rubber-stamped date. Independent Quality qualification still tests artifact fitness, safe execution and revision regression. Keep qualification trials and live workflow starts separate; never pool their denominators. No applicable skill population is N/A, not a baseline zero; missing evidence for an existing population is unknown, not good health. Predeclared live skill/version slices may reuse the workflow contract unchanged, without summing overlapping slices. Agree access, purpose and retention; link tracker, PR/CI, defect, cost and minimal effort evidence without individual rankings. If evidence is incomplete, limit or hold the claim; critical policy effects stop work regardless of averages.",
|
||||||
|
"sources": [
|
||||||
|
"measurement",
|
||||||
|
"six-months-roadmap",
|
||||||
|
"measurement/validated-task-success",
|
||||||
|
"measurement/changes-with-escaped-quality-issues",
|
||||||
|
"measurement/cost-per-accepted-outcome",
|
||||||
|
"measurement/skill-selection-precision",
|
||||||
|
"measurement/skills-within-substantive-review-window",
|
||||||
|
"skills-quality"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "misleading",
|
||||||
|
"title": "A dashboard can be confidently wrong.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"contrast traps\"><p><b>Tempting signal</b><br>More PRs or generated lines<br>Shorter PR elapsed time<br>Higher acceptance rate<br>No defects recorded</p><p><b>Question before believing it</b><br>Useful work—or smaller slices?<br>Less effort—or less waiting?<br>Same task mix and denominator?<br>Enough follow-up and linkage?</p></div><p class=\"statement\">AI usage is diagnostic.<br>It is not the score.</p>",
|
||||||
|
"notes": "Invocation counts, licenses and positive sentiment can help diagnose reach or friction, but are not productivity outcomes. Acceptance changes may reflect selection and learning; stratify by complexity and reviewer availability and record concurrent model/tool/CI changes. Elapsed time is not engineer hours. Missing quality records are not zero defects. Small descriptive samples cannot establish causal ROI; agree uncertainty and precision rules before collecting evidence for a promotion claim. Do not annualize a tiny difference into cash savings.",
|
||||||
|
"sources": [
|
||||||
|
"measurement",
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qualification",
|
||||||
|
"title": "“It worked once” is not a release gate.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"flow\"><span>Pin candidate<br>and environment</span><i>→</i><span>Independent<br>qualification</span><i>→</i><span>Separate<br>pilot permission</span></div><div class=\"contrast\"><p><b>Try to break it</b><br>Wrong task · injected instruction<br>Missing tests · recovery</p><p><b>First revision</b><br>No approved prior skill = N/A<br>Remove + reload → current practice</p></div><div class=\"rail\">Failed mandatory safety checks → HOLD. An average cannot override them.</div>",
|
||||||
|
"notes": "The author cannot approve their own evidence or deployment. Test representative work, unrelated-task decline, injected instructions to bypass review, missing-test escalation, and removal/reload recovery. These examples are not a complete risk-tier evaluation suite. A real independent reviewer approves a risk-appropriate design and inspects all results. First-revision regression against an approved skill is N/A, not a fake pass; prove recovery to declared existing AI-assisted practice. The actual workflow approver separately authorizes the exact revision/client, cohort, window, expiry and effects. Security/data boundaries need their actual owners. Later revision changes return to qualification.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap",
|
||||||
|
"skills-quality"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "experiment",
|
||||||
|
"title": "EXP-01 / Better acceptance is not enough.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<p class=\"fiction\">Fictional teaching example · not Eldorado results or approval</p><div class=\"flow\"><span>Missing test evidence<br>→ checklist first</span><i>→</i><span>Incomplete follow-up<br>→ hold expansion</span><i>→</i><span>Higher review burden<br>→ stop candidate</span></div><p class=\"statement\">Keep the useful practice.<br>Reject the unsupported benefit claim.</p><p class=\"small\">Existing AI practice is the comparator. A skill is tested only if needed.</p>",
|
||||||
|
"notes": "Keep one example from baseline to decision. Suppose changes repeatedly lack regression evidence. Compare a repository test map plus review checklist against packaging the same guidance as a skill; the cheaper checklist wins if it performs as well. A skill carries reusable instructions and verification, not authority. Freeze a small non-urgent bug-fix scope, one willing team and one qualified client/model tuple. The full fictional packet includes explicit real-use blanks for people, dates, immutable references, sources and data approval. Those blanks are not permission. The apparent nine versus eight accepted is not a demonstrated gain. Baseline has two failed, one abandoned and one unresolved; pilot has one of each. Three later starts have not matured and stay out of the matured denominator. At first review pilot effort median is 35 minutes among observed rows only, not the whole cohort. One non-severe baseline defect is known; pilot defect follow-up is incomplete. A tiny sample, different mix and learning also limit inference. The fictional owner may authorize one two-week evidence-only extension with no new starts, at most four architect hours, two reviewer hours and EUR25 additional spend. If reconciliation cannot finish, stop rather than keep extending. Assume reconciliation finds a 40-minute median against 30 baseline for comparable work, with reviewers tracing extra effort to checking generated tests. This breaches the fictional no-increase burden guardrail even with nine accepted tasks. It is sufficient for a local stop decision, not statistical proof the intervention fails everywhere. Remove/reload and verify current-practice recovery; preserve evidence and useful test map/checklist. Return failure cases to the author. Retain would require different evidence: complete comparable outcomes and costs, acceptable quality/burden, agreed precision, independent acceptance and funded upkeep. A new revision must requalify. Critical unauthorized effects stop immediately, not at the scheduled review. The sample table and extension caps are speaker-reference detail, not the main strategy story. Use only the three visible decisions in the planned narration; expand into these numbers only if asked.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Roadmap",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "month-six",
|
||||||
|
"title": "Month six / An evidence portfolio, not a victory lap.",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<div class=\"ledger\"><div><b>Visible change</b><b>Evidence to ask for</b></div><div><span>One workflow understood</span><span>Map + baseline + explicit gaps</span></div><div><span>Retained practice—or justified stop</span><span>Comparable outcomes + costs + limits</span></div><div><span>Less dependence on the architect</span><span>Owner + backup + recovery rehearsal</span></div></div><p class=\"small\">Proposed achievable picture. No guaranteed savings, headcount reduction or org-wide uplift.</p>",
|
||||||
|
"notes": "Commit to activities I can drive: discovery, agreement, hands-on support, reproducible evidence and clear decisions. Do not promise a positive effect outside my control. A realistic month-six organization has one bounded workflow learned from, transparent limitations, some reusable examples and an owner if anything is retained. A second willing team may have a new baseline, not a blanket rollout. If experiments stop, explain what was ruled out, what remains useful and why the next investment changes. Independent source-linked evidence, not a polished demo or attendance count, backs the picture.",
|
||||||
|
"sources": [
|
||||||
|
"six-months-target",
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "6 Months Target",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "beyond",
|
||||||
|
"title": "Beyond 6 Months / Progress toward the Target.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"choices\"><div><b>Deepen</b><p>Coaching, context or deterministic tooling where friction remains.</p></div><div><b>Transfer</b><p>Only with repeatable value, local fit and supported ownership.</p></div><div><b>Toward autonomy</b><p>Separate authority case, containment and human takeover.</p></div></div><p class=\"statement\">Established destination. Evidence-led steps.<br>Separate authority—not automatic graduation.</p>",
|
||||||
|
"notes": "The next quarter may deepen the existing workflow or stop expansion entirely. Skills remain optional; no catalog or central control platform is a prerequisite. Transfer needs new-scope baseline and local capacity. Consider bounded autonomy only if it solves an evidenced bottleneck and controls are proven: exact-artifact approvals, scoped identity, idempotency, audit, independent stop and takeover. People retain product, risk and release decisions. The long-term destination remains human-directed, guided and reviewed autonomous SDLC. These six months contribute toward that vision, not replace it; they do not promise its timing or authorize its execution. The CTO chooses investment based on the evidence, not an inevitable maturity staircase.",
|
||||||
|
"sources": [
|
||||||
|
"stage-02-autonomous-agent",
|
||||||
|
"target-operating-model",
|
||||||
|
"roadmap",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Beyond 6 Months",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "authority",
|
||||||
|
"title": "Toward autonomy / Change authority deliberately.",
|
||||||
|
"minutes": 2,
|
||||||
|
"body": "<div class=\"flow\"><span>Observe +<br>assemble evidence</span><i>→</i><span>Propose +<br>route work</span><i>⇢</i><span>Separately authorize<br>scoped execution</span></div><div class=\"rail\">Exact-artifact approval · scoped identity · audit + recovery</div><p class=\"statement\">Independent stop. Human takeover.</p><p class=\"small\">Readiness failure → hold or redesign. Missing evidence is never permission.</p>",
|
||||||
|
"notes": "Progress toward the established Target by granting only the extra operation that an evidenced business case needs. Reliable observation and evidence assembly come before proposing and routing; neither permits mutation, merge or deployment. A separate human decision names the exact resources, data, artifact and scope. Prove identity separation, checks outside candidate control, idempotency, duplicate/outage recovery and audit. Test a kill switch and human takeover outside the model before trusting scoped execution. The agent cannot appoint approvers or edit its own gates. Changed boundaries reopen review; harmful behavior revokes authority and feeds learning back to Quality and Maintenance. This is the bridge toward the autonomous Target, not an installed system or a dated commitment.",
|
||||||
|
"sources": [
|
||||||
|
"stage-02-autonomous-agent",
|
||||||
|
"target-operating-model"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Beyond 6 Months",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "alignment",
|
||||||
|
"title": "The first CTO conversation",
|
||||||
|
"minutes": 1,
|
||||||
|
"body": "<ol class=\"asks\"><li>Which outcome is worth improving first?</li><li>Who can volunteer time—and independent review?</li><li>What data, risk and effort limits apply?</li><li>When will we decide to continue or stop?</li></ol><p class=\"statement\">Sponsor the learning.<br>Do not pre-approve the answer.</p>",
|
||||||
|
"notes": "Close with concrete alignment, not a shopping list. Ask the CTO to agree an outcome, access to willing teams, independent review capacity, risk/data boundary and decision cadence. Agree success and stop criteria before collecting favorable anecdotes. The long-term Target and Roadmap establish the destination; the six-month plan is a realistic contribution toward it. We have covered the four assignment questions: action, measurement, realistic six-month evidence and conditional next investment. Transition to the fifteen-minute discussion. If time runs short, skip detail in narration rather than the decision and its limits.",
|
||||||
|
"sources": [
|
||||||
|
"PDF: questions 1–4",
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"kind": "dark",
|
||||||
|
"section": "Discussion",
|
||||||
|
"track": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "discussion",
|
||||||
|
"title": "Q&A / What would change your mind?",
|
||||||
|
"minutes": 15,
|
||||||
|
"body": "<p class=\"subtitle\">15 minutes for the hard questions.</p><div class=\"discussion\"><p>No willing team?</p><p>Too little evidence?</p><p>A cheaper non-AI fix?</p></div><p class=\"small\">The proposed plan can change. The evidence standard should not.</p>",
|
||||||
|
"notes": "Reserve the full fifteen minutes. If no team volunteers, revisit the problem and sponsor trade-offs rather than conscript people. If evidence is sparse, narrow the question, explicitly authorize a bounded evidence-completion window or stop. If deterministic tooling is better, choose it. Discuss the company’s real constraints rather than pretend the fictional example estimates company benefit. The next slide provides linked sources for follow-up, not additional spoken content.",
|
||||||
|
"sources": [
|
||||||
|
"PDF: Format",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"kind": "dark",
|
||||||
|
"section": "Discussion",
|
||||||
|
"track": "discussion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "references",
|
||||||
|
"title": "References / Follow the evidence.",
|
||||||
|
"minutes": 0,
|
||||||
|
"body": "<ul class=\"references\"><li>AI Architect Test Task · Eldorado.gg<br><span>Context, four questions, assumptions, 50-minute format</span></li><li><a href=\"../../strategy/target-operating-model/\">Long-term Target</a> · <a href=\"../../strategy/roadmap/\">Roadmap →</a></li><li><a href=\"../../strategy/six-months-target/\">6 Months Target →</a></li><li><a href=\"../../strategy/six-months-roadmap/\">6 Months Roadmap →</a></li><li><a href=\"../../strategy/six-months-roadmap/#exp-01-a-small-decision-ready-example\">EXP-01 packet and decision limits →</a></li><li><a href=\"../../strategy/measurement/\">Measurement definitions and safeguards →</a></li><li><a href=\"../../strategy/stage-02-autonomous-agent/\">Beyond 6 Months →</a></li></ul>",
|
||||||
|
"notes": "Appendix, zero planned talk time. The original assignment is the supplied AI_Architect_Test_Task.pdf. The source-reference map in this presentation directory records every slide against the PDF and reviewed Strategy. The deck does not reproduce the assignment file publicly. EXP-01 remains entirely fictional; its budget, medians, samples and outcomes are teaching devices. Official Reveal documentation consulted: installation, speaker-view and pdf-export on revealjs.com. All runtime assets are pinned and bundled locally.",
|
||||||
|
"sources": [
|
||||||
|
"PDF: complete assignment",
|
||||||
|
"six-months-target",
|
||||||
|
"six-months-roadmap",
|
||||||
|
"measurement",
|
||||||
|
"stage-02-autonomous-agent"
|
||||||
|
],
|
||||||
|
"kind": "",
|
||||||
|
"section": "Reference",
|
||||||
|
"track": "appendix"
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Presentation-sized views of the canonical topology, not a new operating model.
|
||||||
|
export const phases=['scope','architecture','ui-ux','planning','delivery','uat','security','releases'];
|
||||||
|
export const labels=['Scope','Architecture','UI/UX','Planning','Delivery','UAT','Security','Releases'];
|
||||||
|
export const topology={
|
||||||
|
lifecycle:phases.map((id,i)=>[id,phases[(i+1)%phases.length]]),
|
||||||
|
governance:phases.map(id=>['agent',id]),
|
||||||
|
contributions:phases.map(id=>[`code-${id}`,id]),
|
||||||
|
};
|
||||||
|
function cycle(portrait){
|
||||||
|
const key=portrait?'phone':'wide';
|
||||||
|
const w=portrait?540:1096,h=portrait?540:350;
|
||||||
|
const xs=portrait?[100,270,440]:[200,548,896],ys=portrait?[65,270,475]:[40,175,310];
|
||||||
|
const pos=[[xs[1],ys[0]],[xs[2],ys[0]],[xs[2],ys[1]],[xs[2],ys[2]],[xs[1],ys[2]],[xs[0],ys[2]],[xs[0],ys[1]],[xs[0],ys[0]]];
|
||||||
|
const bw=portrait?154:202,bh=52,cx=xs[1],cy=ys[1],cw=portrait?164:270,ch=portrait?112:94;
|
||||||
|
const edge=(a,b)=>{const dx=b[0]-a[0],dy=b[1]-a[1],t=Math.min(dx?bw/2/Math.abs(dx):Infinity,dy?bh/2/Math.abs(dy):Infinity);return [a[0]+dx*t,a[1]+dy*t]};
|
||||||
|
const path=(d,type,from,to)=>`<path d="${d}" class="${type}" data-from="${from}" data-to="${to}" marker-end="url(#${key}-${type})"/>`;
|
||||||
|
let lines=pos.map((a,i)=>{const b=pos[(i+1)%8],p=edge(a,b),q=edge(b,a);return path(`M${p} L${q}`,'cycle-edge',...topology.lifecycle[i])}).join('');
|
||||||
|
// Top and bottom share a center exit; side spokes enter the side phases.
|
||||||
|
lines+=pos.map(([x,y],i)=>{let d;if(y<cy)d=`M${cx},${cy-ch/2} V${(cy-ch/2+y+bh/2)/2} H${x+(x<cx?30:x>cx?-30:0)} V${y+bh/2}`;else if(y>cy)d=`M${cx},${cy+ch/2} V${(cy+ch/2+y-bh/2)/2} H${x+(x<cx?30:x>cx?-30:0)} V${y-bh/2}`;else d=`M${cx+(x>cx?cw/2:-cw/2)},${cy} H${x+(x>cx?-bw/2:bw/2)}`;return path(d,'govern-edge',...topology.governance[i])}).join('');
|
||||||
|
const nodes=pos.map(([x,y],i)=>`<g data-node="${phases[i]}"><rect x="${x-bw/2}" y="${y-bh/2}" width="${bw}" height="${bh}"/><text x="${x}" y="${y+8}">${labels[i]}</text></g>`).join('');
|
||||||
|
const center=portrait?['Autonomous','agent','Human-controlled']:['Autonomous agent','Human-controlled'];
|
||||||
|
return `<svg class="target-cycle ${key}" viewBox="0 0 ${w} ${h}" role="img" aria-label="Intended SDLC: Scope, Architecture, UI/UX, Planning, Delivery, UAT, Security, Releases and back to Scope. One human-controlled autonomous agent executes and governs all eight phases."><defs>${['cycle-edge','govern-edge'].map(t=>`<marker id="${key}-${t}" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10z" fill="${t==='cycle-edge'?'#14131a':'#936500'}"/></marker>`).join('')}</defs>${lines}${nodes}<g data-node="agent" class="central"><rect x="${cx-cw/2}" y="${cy-ch/2}" width="${cw}" height="${ch}"/>${center.map((t,i)=>`<text x="${cx}" y="${cy-(center.length-1)*14+i*28+8}" class="${i===center.length-1?'control-label':''}">${t}</text>`).join('')}</g></svg>`;
|
||||||
|
}
|
||||||
|
export const cycleFigure=cycle(false)+cycle(true);
|
||||||
|
export const contributionsFigure=`<div class="contribution-grid">${phases.map((id,i)=>`<div data-from="code-${id}" data-to="${id}"><span>AI Agent</span><i aria-label="contributes to">⇢</i><b>${labels[i]}</b></div>`).join('')}</div>`;
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
@font-face{font-family:Lato;src:url(./assets/lato-latin-400-normal.woff2) format('woff2');font-weight:400;font-display:swap}
|
||||||
|
@font-face{font-family:Lato;src:url(./assets/lato-latin-700-normal.woff2) format('woff2');font-weight:700;font-display:swap}
|
||||||
|
@font-face{font-family:Lato;src:url(./assets/lato-latin-900-normal.woff2) format('woff2');font-weight:900;font-display:swap}
|
||||||
|
:root{--gold:#ffc950;--ink:#14131a;--paper:#f6f6f6}
|
||||||
|
body{margin:0;background:var(--paper);color:var(--ink)}
|
||||||
|
.deck{font:30px/1.35 Lato,sans-serif;color:var(--ink)}
|
||||||
|
.deck .slides{text-align:left}
|
||||||
|
.deck .slides section{box-sizing:border-box;padding:48px 52px;height:660px}
|
||||||
|
.deck h1,.deck h2{font-weight:900;letter-spacing:-.045em;line-height:1.07;margin:18px 0 30px;color:inherit;text-transform:none}
|
||||||
|
.deck h1{font-size:80px;max-width:960px}.deck h2{font-size:52px;max-width:1020px}
|
||||||
|
.deck p{margin:20px 0}.deck .eyebrow{font-size:17px;letter-spacing:.15em;font-weight:900;color:#805b00;margin:0}
|
||||||
|
.deck .subtitle{font-size:34px}.deck .thesis{font-size:37px;margin-top:52px;border-left:6px solid var(--gold);padding-left:24px}
|
||||||
|
.deck .small{font-size:21px;line-height:1.4;color:#62616b;margin-top:24px}.deck .statement{font-size:35px;font-weight:700;margin-top:32px}
|
||||||
|
.deck .dark{color:var(--paper)}.deck .dark .eyebrow,.deck .dark h1{color:var(--gold)}.deck .dark .small{color:#d5d4dc}
|
||||||
|
.deck .facts{display:flex;gap:40px;justify-content:space-between;margin:35px 0}.deck .facts strong{display:block;font-size:43px;line-height:1.12}.deck .facts span{display:block;font-size:24px;margin-top:12px}
|
||||||
|
.deck .contrast{display:grid;grid-template-columns:1fr 1fr;gap:44px;border-top:2px solid #dedee3;margin-top:28px;padding-top:8px}.deck .contrast p{font-size:27px;line-height:1.55}.deck .contrast b{color:#805b00;display:inline-block;margin-bottom:10px}
|
||||||
|
.deck .flow{display:flex;align-items:stretch;gap:18px;margin:40px 0 26px}.deck .flow span{flex:1;border:2px solid #14131a;padding:24px 18px;font-weight:700;font-size:27px;text-align:center;display:flex;align-items:center;justify-content:center}.deck .flow i{align-self:center;font-style:normal}
|
||||||
|
.deck .rail{border-left:6px solid var(--gold);padding:16px 24px;background:#e9e9ec;font-size:25px;font-weight:700}
|
||||||
|
.deck .roles{display:grid;grid-template-columns:1fr 1.2fr 1fr;gap:18px;margin:32px 0}.deck .roles div{padding:24px;border:2px solid #14131a}.deck .roles b{display:block;font-size:34px;margin-bottom:18px}.deck .roles span{font-size:26px;line-height:1.5}.deck .roles .gold{background:var(--gold)}
|
||||||
|
.deck .timeline{display:grid;grid-template-columns:1fr 1fr;gap:46px;margin:35px 0}.deck .timeline>div{border-top:8px solid var(--gold);padding-top:20px}.deck .timeline b{font-size:35px}.deck .timeline p{font-size:28px}.deck .timeline span{font-size:23px;color:#62616b}
|
||||||
|
.deck .gate{background:var(--ink);color:var(--gold);font-size:29px;font-weight:900;padding:20px 24px}
|
||||||
|
.deck .capacity{display:flex;margin:50px 0;gap:5px}.deck .capacity>div{flex:1;background:#e3e3e7;font-size:25px;padding:28px 16px;border-bottom:5px solid var(--ink)}.deck .capacity .pair{flex:2;background:var(--gold)}.deck .capacity b{display:block;margin-top:18px;font-size:24px}
|
||||||
|
.deck .measure-list>div{display:grid;grid-template-columns:310px 1fr;gap:24px;border-top:1px solid #b8b7c0;padding:20px 0}.deck .measure-list b{font-size:32px}.deck .measure-list span{font-size:27px}.deck .measure-list{margin-bottom:24px}
|
||||||
|
.deck .fiction{display:inline-block;background:#fff0cd;color:#594000;font-size:21px;padding:7px 12px;margin:0}
|
||||||
|
.deck table{width:100%;border-collapse:collapse;margin:22px 0;font-size:25px}.deck th,.deck td{text-align:left;border-bottom:1px solid #b8b7c0;padding:15px 10px}.deck th{font-weight:900;font-size:23px;background:#e9e9ec}
|
||||||
|
.deck .comparison{display:flex;align-items:center;gap:35px;margin:40px 0}.deck .comparison div{flex:1}.deck .comparison strong{display:block;font-size:80px;letter-spacing:-.05em}.deck .comparison span{font-size:23px}.deck .comparison .versus{font-size:50px}
|
||||||
|
.deck .ledger{margin:40px 0}.deck .ledger>div{display:grid;grid-template-columns:1fr 1fr;gap:32px;padding:21px 0;border-bottom:1px solid #b8b7c0;font-size:27px}.deck .ledger b{color:#805b00}
|
||||||
|
.deck .choices{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;margin:40px 0}.deck .choices>div{border-top:6px solid var(--gold);padding-top:20px}.deck .choices b{font-size:33px}.deck .choices p{font-size:27px}
|
||||||
|
.deck .asks{font-size:33px;line-height:1.6;margin:35px 0 0;padding-left:38px}.deck .asks li{padding-left:12px}
|
||||||
|
.deck .discussion{display:flex;flex-direction:column;border-left:5px solid var(--gold);padding-left:28px;margin-top:40px}.deck .discussion p{font-size:36px;margin:10px 0}
|
||||||
|
.deck a{color:#805b00;text-decoration:underline}.deck .references{font-size:27px;line-height:1.5;padding-left:28px}.deck .references li{margin:12px 0}.deck .references span{font-size:22px;color:#62616b}
|
||||||
|
.deck .controls{color:#805b00}.deck .slide-number{font:16px Lato,sans-serif;background:#14131a;color:#fff;left:18px;right:auto;bottom:18px;padding:8px}
|
||||||
|
.deck .progress{color:#805b00;height:4px}
|
||||||
|
.toolbar{position:fixed;z-index:30;top:0;left:0;right:0;display:flex;align-items:center;gap:16px;background:#101014;color:#fff;padding:8px 18px;font:14px Lato,sans-serif;min-height:32px;box-sizing:content-box}
|
||||||
|
.toolbar a{color:var(--gold)}.toolbar button{font:inherit;color:white;border:1px solid #62616b;background:transparent;padding:6px 10px;cursor:pointer}.toolbar .help{margin-left:auto}
|
||||||
|
a:focus-visible,button:focus-visible{outline:3px solid #b88719;outline-offset:3px}
|
||||||
|
.reveal.deck{height:calc(100dvh - 48px);top:48px}
|
||||||
|
@media(max-width:600px){.toolbar{gap:9px;font-size:12px;padding:8px}.toolbar .help{display:none}.toolbar button{padding:6px}.deck .controls{bottom:18px}}
|
||||||
|
@media(max-width:360px){.toolbar{gap:4px}}
|
||||||
|
/* Portrait is re-composed, not a postage-stamp landscape slide. */
|
||||||
|
.portrait .deck .slides section{height:1000px;padding:28px}
|
||||||
|
.portrait .deck h1{font-size:64px}.portrait .deck h2{font-size:43px;margin-bottom:24px}
|
||||||
|
.portrait .deck .facts{flex-wrap:wrap;gap:28px;margin:30px 0}.portrait .deck .facts strong{font-size:38px}
|
||||||
|
.portrait .deck .contrast{grid-template-columns:1fr;gap:0;margin-top:20px}.portrait .deck .contrast p{font-size:27px;margin:14px 0;line-height:1.4}
|
||||||
|
.portrait .deck .flow{flex-direction:column;gap:8px;margin:24px 0}.portrait .deck .flow span{padding:14px;font-size:27px}.portrait .deck .flow i{transform:rotate(90deg);line-height:1}
|
||||||
|
.portrait .deck .roles{grid-template-columns:1fr;gap:12px}.portrait .deck .roles div{padding:18px}.portrait .deck .roles b{font-size:30px;margin-bottom:8px}.portrait .deck .roles span{font-size:26px}
|
||||||
|
.portrait .deck .timeline{grid-template-columns:1fr;gap:24px;margin:25px 0}.portrait .deck .timeline>div{padding-top:14px}.portrait .deck .timeline p{margin:14px 0;font-size:28px}
|
||||||
|
.portrait .deck .statement{font-size:33px;margin-top:28px}.portrait .deck .rail{font-size:25px;padding:16px}.portrait .deck .gate{font-size:27px;padding:18px}
|
||||||
|
.portrait .deck .capacity{display:grid;grid-template-columns:1fr 1fr;gap:8px}.portrait .deck .capacity>div{padding:24px 16px}
|
||||||
|
.portrait .deck .measure-list>div{grid-template-columns:1fr;gap:10px}.portrait .deck .measure-list b{font-size:31px}
|
||||||
|
.portrait .deck .fiction{font-size:22px}.portrait .deck table{font-size:23px;table-layout:fixed}.portrait .deck th{font-size:22px}.portrait .deck th,.portrait .deck td{padding:15px 8px}
|
||||||
|
.portrait .deck .comparison{gap:20px}.portrait .deck .comparison strong{font-size:54px}.portrait .deck .comparison span{font-size:24px}
|
||||||
|
.portrait .deck .ledger>div{font-size:26px;gap:20px}.portrait .deck .choices{grid-template-columns:1fr;gap:20px}.portrait .deck .choices>div{padding-top:12px}.portrait .deck .choices p{margin:10px 0}
|
||||||
|
.portrait .deck .asks{font-size:31px;line-height:1.45}.portrait .deck .asks li{margin:22px 0}.portrait .deck .small{font-size:24px}
|
||||||
|
.portrait #qualification .contrast{grid-template-columns:1fr 1fr;gap:24px}.portrait #qualification .contrast p{font-size:24px}
|
||||||
|
.portrait .deck .references{font-size:29px}.portrait .deck .references li{margin:22px 0}
|
||||||
|
@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}
|
||||||
|
.embedded .toolbar{display:none}
|
||||||
|
.embedded .reveal.deck{top:0;height:calc(100dvh - 48px)}
|
||||||
|
.embedded body{background:#101014}
|
||||||
|
.embedded .deck .controls{position:fixed;bottom:8px;color:var(--gold)!important}
|
||||||
|
.embedded .deck .progress{color:var(--gold)}
|
||||||
|
.embedded .deck .slide-number{position:fixed;bottom:12px}
|
||||||
|
.embedded .deck .progress{position:fixed;bottom:0}
|
||||||
|
@media print{.toolbar{display:none}.reveal.deck{top:0;height:100%}}
|
||||||
|
html.print-pdf .toolbar{display:none}html.print-pdf .reveal.deck{top:0;height:100%}
|
||||||
|
|
||||||
|
/* Distinct strategy views: paired topology, progression and learning loop. */
|
||||||
|
.deck .target-cycle{width:100%;height:350px;display:block;margin:0 auto}
|
||||||
|
.deck .target-cycle.phone{display:none}
|
||||||
|
.target-cycle rect{fill:#f6f6f6;stroke:#14131a;stroke-width:2}
|
||||||
|
.target-cycle text{text-anchor:middle;font:700 24px Lato,sans-serif;fill:#14131a}
|
||||||
|
.target-cycle .central rect{fill:#ffc950}
|
||||||
|
.target-cycle .control-label{font-size:20px;font-weight:400}
|
||||||
|
.target-cycle .cycle-edge{fill:none;stroke:#14131a;stroke-width:2.5}
|
||||||
|
.target-cycle .govern-edge{fill:none;stroke:#936500;stroke-width:2.5;stroke-dasharray:3 5}
|
||||||
|
.deck .diagram-legend{font-size:23px;margin:12px 0}
|
||||||
|
.deck #target .small{font-size:21px;margin:12px 0}
|
||||||
|
.deck .diagram-intro{font-size:30px}
|
||||||
|
.deck .contribution-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px 20px;margin:22px 0}
|
||||||
|
.deck .contribution-grid>div{border-top:4px solid #ffc950;padding:10px 8px;display:flex;flex-direction:column;align-items:center;font-size:26px}
|
||||||
|
.deck .contribution-grid i{font-style:normal;transform:rotate(90deg);color:#805b00;font-size:32px;line-height:1.2}
|
||||||
|
.deck .journey{display:flex;gap:16px;align-items:center;margin:36px 0}
|
||||||
|
.deck .journey>div{flex:1;border-top:6px solid #ffc950;padding:18px 6px;align-self:stretch}
|
||||||
|
.deck .journey small,.deck .horizon small{display:block;font-size:17px;color:#805b00;font-weight:900;letter-spacing:.04em;margin-bottom:14px}
|
||||||
|
.deck .journey b{font-size:31px;display:block;margin-bottom:20px}
|
||||||
|
.deck .journey span{font-size:25px}.deck .journey i{font-style:normal}
|
||||||
|
.deck .learning-loop{display:grid;grid-template-columns:1fr 28px 1fr 28px 1fr 28px 1fr;align-items:center;gap:0 8px;margin:22px 0}
|
||||||
|
.deck #learning-loop .statement{margin:16px 0 0}.deck #learning-loop .small{margin-top:12px}
|
||||||
|
.deck .learning-loop span{border:2px solid #14131a;padding:8px;font-size:27px;text-align:center}
|
||||||
|
.deck .learning-loop i{font-style:normal;text-align:center;line-height:1}
|
||||||
|
.deck .learning-loop>:nth-child(1){grid-area:1/1}.deck .learning-loop>:nth-child(2){grid-area:1/2}.deck .learning-loop>:nth-child(3){grid-area:1/3}
|
||||||
|
.deck .learning-loop>:nth-child(4){grid-area:2/3}
|
||||||
|
.deck .learning-loop>:nth-child(5){grid-area:3/3}.deck .learning-loop>:nth-child(6){grid-area:3/4}.deck .learning-loop>:nth-child(7){grid-area:3/5}
|
||||||
|
.deck .learning-loop>:nth-child(8){grid-area:4/5}
|
||||||
|
.deck .learning-loop>:nth-child(9){grid-area:5/5}.deck .learning-loop>:nth-child(10){grid-area:5/6}.deck .learning-loop>:nth-child(11){grid-area:5/7}
|
||||||
|
.deck .horizon{margin:35px 0;border-left:5px solid #ffc950;padding-left:25px}
|
||||||
|
.deck .horizon b{font-size:32px;display:block}.deck .horizon .near{background:#e9e9ec;padding:22px;margin-top:28px}
|
||||||
|
.deck .horizon span{display:block;font-size:25px;margin-top:14px}
|
||||||
|
.portrait .deck .target-cycle.wide{display:none}.portrait .deck .target-cycle.phone{display:block;height:540px}
|
||||||
|
.portrait .deck #target h2{font-size:40px}
|
||||||
|
.portrait .deck #target .small{font-size:24px;margin-top:20px}
|
||||||
|
.portrait .deck #contributors .small{margin:12px 0}
|
||||||
|
.portrait .deck #contributors .contribution-grid{gap:6px;margin:14px 0}
|
||||||
|
.portrait .deck #contributors .contribution-grid>div{padding:4px 8px}
|
||||||
|
.portrait .deck .contribution-grid{grid-template-columns:1fr 1fr;gap:12px;margin:24px 0}
|
||||||
|
.portrait .deck .contribution-grid>div{padding:8px;flex-direction:column;justify-content:center;gap:0;font-size:27px}
|
||||||
|
.portrait .deck .contribution-grid i{transform:rotate(90deg)}.portrait .deck .contribution-grid b{text-align:center}
|
||||||
|
.portrait .deck .journey{flex-direction:column;gap:4px;margin:18px 0}
|
||||||
|
.portrait .deck .journey>div{width:100%;padding:12px 0;border-top-width:4px}
|
||||||
|
.portrait .deck .journey b{font-size:29px;margin-bottom:8px}.portrait .deck .journey small{margin-bottom:8px}
|
||||||
|
.portrait .deck .journey i{transform:rotate(90deg);line-height:1}
|
||||||
|
.portrait .deck .learning-loop{grid-template-columns:1fr 16px 1fr 16px 1fr 16px 1fr;gap:0 3px;margin:30px 0}
|
||||||
|
.portrait .deck .learning-loop span{font-size:24px;padding:14px 2px}
|
||||||
|
.portrait .deck .horizon b{font-size:32px}
|
||||||
|
|
||||||
|
/* Slide 14: outcomes lead; skill indicators remain a separate population. */
|
||||||
|
.deck .slides #measures{padding-top:32px}
|
||||||
|
.deck #measures h2{font-size:48px;margin-bottom:20px}
|
||||||
|
#measures .measurement-panels{display:grid;grid-template-columns:1.3fr 1fr;gap:24px}
|
||||||
|
#measures .workflow-panel,#measures .skill-panel{padding:16px 22px;font-size:21px;line-height:1.3;background:#e9e9ec;border-top:6px solid var(--gold)}
|
||||||
|
#measures .skill-panel{background:#eeedf0;border-top-color:#8b8994}
|
||||||
|
#measures h3{font-size:28px;line-height:1.15;letter-spacing:-.025em;font-weight:900;margin:0;text-transform:none;color:var(--ink)}
|
||||||
|
.deck #measures .metric-context{font-size:19px;line-height:1.3;margin:8px 0 12px;color:#62616b}
|
||||||
|
#measures .metric{border-top:1px solid #bbb9c2;padding:10px 0 0;margin-top:10px}
|
||||||
|
#measures .metric b{display:block;font-size:25px;line-height:1.2}
|
||||||
|
#measures .metric em{font-style:normal;font-size:20px;white-space:nowrap}
|
||||||
|
#measures .metric span{display:block;font-size:21px;line-height:1.3;margin-top:7px}
|
||||||
|
.deck #measures .qualification-note{border-left:4px solid var(--gold);padding-left:12px;font-size:21px;font-weight:700;line-height:1.25;margin:22px 0 0}
|
||||||
|
.deck #measures .measurement-caution{font-size:20px;line-height:1.4;color:#62616b;margin:16px 0 0}
|
||||||
|
.portrait .deck .slides #measures{padding-top:20px}
|
||||||
|
.portrait .deck #measures h2{font-size:38px;margin:12px 0 14px}
|
||||||
|
.portrait #measures .measurement-panels{grid-template-columns:1fr;gap:12px}
|
||||||
|
.portrait #measures .workflow-panel,.portrait #measures .skill-panel{padding:12px 16px}
|
||||||
|
.portrait #measures h3{font-size:29px}
|
||||||
|
.portrait .deck #measures .metric-context{font-size:20px;margin:6px 0 8px}
|
||||||
|
.portrait #measures .metric{padding-top:4px;margin-top:4px}
|
||||||
|
.portrait #measures .metric b{font-size:26px}
|
||||||
|
.portrait #measures .metric span{font-size:22px;line-height:1.2;margin-top:5px}
|
||||||
|
.portrait .deck #measures .qualification-note{font-size:22px;margin-top:12px}
|
||||||
|
.portrait .deck #measures .measurement-caution{font-size:21px;margin-top:12px}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
{
|
||||||
|
"source": {
|
||||||
|
"file": "AI_Architect_Test_Task.pdf",
|
||||||
|
"sha256": "12b2406766996056d0a361cf76b2d8fbe4dfdfad6a16c2cc4d5ee03a51a384a5",
|
||||||
|
"attachment_message": "1557767519748759646",
|
||||||
|
"authorization_message": "1557786954383368264",
|
||||||
|
"read_scope": "Full PDF, Format, Context and all four assignment questions, plus assumptions instruction"
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
{
|
||||||
|
"id": "format",
|
||||||
|
"source_section": "Format",
|
||||||
|
"requirement": "Live presentation: 50 minutes including Q&A; content over polish",
|
||||||
|
"pages": [
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"35 minutes content + 15 minutes Q&A",
|
||||||
|
"Content matters more than visual polish"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "context",
|
||||||
|
"source_section": "Context",
|
||||||
|
"requirement": "Close to 80 engineering people, around 100 by year end, more than 10 teams; every developer already uses AI unevenly; real output not usage",
|
||||||
|
"pages": [
|
||||||
|
"six-months-target",
|
||||||
|
"baseline"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"80 engineers",
|
||||||
|
"100 by year end",
|
||||||
|
"more than 10 teams",
|
||||||
|
"current AI-assisted practice"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q1",
|
||||||
|
"source_section": "Assignment 1",
|
||||||
|
"requirement": "Month 1–6 concrete priorities and change starting solo, CTO reporting, no formal team authority",
|
||||||
|
"pages": [
|
||||||
|
"six-months-roadmap",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"Month 1",
|
||||||
|
"Month 2",
|
||||||
|
"Month 3",
|
||||||
|
"Month 4",
|
||||||
|
"Month 5",
|
||||||
|
"Month 6",
|
||||||
|
"One active live pilot at a time",
|
||||||
|
"no formal authority",
|
||||||
|
"monthly CTO review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q2",
|
||||||
|
"source_section": "Assignment 2",
|
||||||
|
"requirement": "Know whether engineering output improves; track meaningful measures and explain misleading signals",
|
||||||
|
"pages": [
|
||||||
|
"measurement/index",
|
||||||
|
"six-months-roadmap",
|
||||||
|
"baseline"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"Review/rework minutes",
|
||||||
|
"Escaped defects and severity",
|
||||||
|
"Where this misleads",
|
||||||
|
"task mix",
|
||||||
|
"not a causal ROI claim",
|
||||||
|
"source",
|
||||||
|
"uncertainty"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q3",
|
||||||
|
"source_section": "Assignment 3",
|
||||||
|
"requirement": "Realistic visible month-six changes backed by evidence",
|
||||||
|
"pages": [
|
||||||
|
"six-months-target",
|
||||||
|
"six-months-roadmap"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"Activities I commit",
|
||||||
|
"Contingent visible outcome",
|
||||||
|
"one partner team",
|
||||||
|
"matured defect follow-up",
|
||||||
|
"documented stop"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q4",
|
||||||
|
"source_section": "Assignment 4",
|
||||||
|
"requirement": "Role and organization AI use beyond six months",
|
||||||
|
"pages": [
|
||||||
|
"stage-02-autonomous-agent",
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"dedicated enablement capacity",
|
||||||
|
"deterministic tooling",
|
||||||
|
"long-term strategy vision",
|
||||||
|
"not automatic progression"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "assumptions",
|
||||||
|
"source_section": "Final instruction",
|
||||||
|
"requirement": "State assumptions where stack, tooling or processes are unknown",
|
||||||
|
"pages": [
|
||||||
|
"six-months-target"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"Assumptions register",
|
||||||
|
"PDF fact",
|
||||||
|
"Unknown:",
|
||||||
|
"Hypothesis:",
|
||||||
|
"If false"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "F1",
|
||||||
|
"source_section": "Professional audit F1",
|
||||||
|
"requirement": "First-revision comparator and recovery without invented prior approved bundle",
|
||||||
|
"pages": [
|
||||||
|
"skills-quality",
|
||||||
|
"skills-governance",
|
||||||
|
"skills-maintenance"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"first-revision",
|
||||||
|
"N/A",
|
||||||
|
"pinned clean",
|
||||||
|
"independent"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "F2-F3",
|
||||||
|
"source_section": "Professional audit F2/F3",
|
||||||
|
"requirement": "Coherent illustrative packet, inconclusive bounded extension/stop, effort and value",
|
||||||
|
"pages": [
|
||||||
|
"six-months-roadmap",
|
||||||
|
"skills-quality"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
"EXP-01",
|
||||||
|
"Entirely fictional",
|
||||||
|
"Inconclusive at first review",
|
||||||
|
"one two-week evidence-completion extension",
|
||||||
|
"Conclusive stop on burden",
|
||||||
|
"one-off setup",
|
||||||
|
"optional reference designs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"verification_sources": [
|
||||||
|
"scripts/assignment.test.mjs",
|
||||||
|
"scripts/connected-strategy.test.mjs",
|
||||||
|
"scripts/strategy-navigation.test.mjs",
|
||||||
|
"scripts/strategy-story.test.mjs",
|
||||||
|
"scripts/verify.mjs",
|
||||||
|
"scripts/browser/skills-stories.cjs",
|
||||||
|
"scripts/browser/strategy-navigation.cjs",
|
||||||
|
"scripts/browser/target-midpoints.cjs",
|
||||||
|
"scripts/browser/roadmap-timeline.cjs"
|
||||||
|
],
|
||||||
|
"scope": "Traceability is a review aid, not semantic approval or business evidence. All 30 routes remain in strategy-coverage.json; all 16 canonical contracts retain original checksums, 9 prototypes and 7 unimplemented. Reviewer must cold-read the actual pages and inspect complete exports."
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Strategy horizons — correction evidence matrix
|
||||||
|
|
||||||
|
Authority: user message `1557813737941901572` in Eldorado storm-v1. This correction restores the agreed long-term destination; it does not authorize autonomous execution. Original PDF read in full: Format, Context, all four questions and assumptions instruction; its existing SHA-256 remains in `assignment-evidence.json`.
|
||||||
|
|
||||||
|
| Horizon / reader destination | Origin and preservation | Result / boundary | Verification |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Target `/strategy/target-operating-model/` | Meaningful Target body restored from pre-PR38 `88a43757762114a506f57ed4b44484306cae1aaa`; original desktop/mobile `strategy-target` JSON unchanged | Human-directed/guided/reviewed autonomous SDLC is the long-term vision, not merely a competing optional destination. Eight lifecycle phases, central agent with eight governance spokes, eight outside human-controlled AI Agents; no fixed timing or present permission | `sdlc-cycle`, `target-midpoints`, `assignment` tests; real inline/fullscreen and complete light/dark exports |
|
||||||
|
| Roadmap `/strategy/roadmap/` | Original three-level body and six paired workflow JSON files restored from the same historical revision, then reconciled with intervention choice and new links | Skills/practices adoption → controlled autonomous capabilities; Delivery first, remaining phase order undecided, Delivery keeps improving. Evidence and separate human authority, not automatic graduation | `roadmap`, `roadmap-viewer`, browser `roadmap-timeline` |
|
||||||
|
| 6 Months Target `/strategy/six-months-target/` | PR38 assignment narrative moved out of Target, including the entire assumptions register and credible outcome conditions | PDF facts: close to80 engineers growing toward100, more than10 teams, everyone already using AI unevenly; solo CTO-reporting architect with no formal team authority. Actual stack/reporting/capacity unknown. First six months contribute toward—not replace—the destination | `assignment-evidence.json` maps all four PDF answers, format and assumptions to actual pages |
|
||||||
|
| 6 Months Roadmap `/strategy/six-months-roadmap/` | PR38 month1–6 action plan, influence/capacity and full EXP-01 packet preserved here as the single plan | One active pilot; independent checks; explicit effort limits, recovery, inconclusive extension and stop. EXP-01 remains fictional. No benefits, approvals or organization-wide rollout fabricated | Assignment markers; exact EXP-01 packet preservation; first-revision tests; browser six-month diagram controls and exports |
|
||||||
|
| Beyond 6 Months `/strategy/stage-02-autonomous-agent/` | Existing useful autonomy-stage content and diagram retained | Connect evidence-led next investments toward long-term vision; authority expands only through a separate case, scoped credentials, independent checks, stop/takeover and reopening on boundary changes | Connected-strategy tests and actual reader handoffs |
|
||||||
|
| Nested lifecycle and references | Stage01 URL retained as concise lifecycle reference beneath 6 Months Roadmap. All6 topic routes,16 metric contracts and2 shared reference pages remain reachable | No second competing monthly plan. First-revision N/A comparator, clean current-practice recovery, qualification-versus-pilot distinction retained. Contract bodies remain byte-identical;9 prototype calculations and7 unimplemented metrics remain explicitly classified |30-route manifest with original metric hashes;44-doc resolved sidebar/link/anchor checks |
|
||||||
|
| Presentation integration | Published PR40 merge `432370473d6aaee229b0279551ce7b63da52acb7` merged into isolated branch, including320px toolbar correction |19slides,35-minute content +15-minute Q&A unchanged. Focused source-link and Beyond wording changes only; references now name all five horizons. Homepage and toolbar Strategy still open long-term Target | Generated slide-source map, exact source hashes and presentation browser suite; inspect changed slides16/19 individually |
|
||||||
|
|
||||||
|
No Organization body, runtime vendor or dependency changes are introduced relative to integrated PR40 main. Independent child reviewer owns merge/publication and durable wiki reconciliation. Local candidate evidence is not publication evidence.
|
||||||
|
|
||||||
|
## Verification environment and limits
|
||||||
|
|
||||||
|
Use the prefix-correct static server for full acceptance. Docusaurus `serve` on the installed Node runtime redirects WOFF2 assets to slash-suffixed paths; the regular static server serves the same built font bytes correctly. Chromium executable is selected explicitly from the installed headless build. This is desktop/mobile viewport verification, not Safari/Firefox or physical-device certification. WebM remains unsupported/disabled in this browser; SVG/PNG/JPEG/WebP controls are verified. Existing dependency audit findings are not remediated or accepted by this content change.
|
||||||
@@ -236,12 +236,12 @@
|
|||||||
{
|
{
|
||||||
"source": "docs/strategy/roadmap.mdx",
|
"source": "docs/strategy/roadmap.mdx",
|
||||||
"route": "/strategy/roadmap/",
|
"route": "/strategy/roadmap/",
|
||||||
"question": "How do we move toward Target without assuming autonomy?",
|
"question": "How do practices and skills progress toward controlled autonomous capabilities?",
|
||||||
"inputs": "Target and current working practices",
|
"inputs": "Long-term Target and evidence from actual work",
|
||||||
"action_or_decision": "Start skills adoption in Delivery; leave later phase order undecided",
|
"action_or_decision": "Delivery first; later phase order undecided; separate authority decision",
|
||||||
"output": "Two-stage direction and within-phase learning loop",
|
"output": "Broad progression with no fixed dates",
|
||||||
"next_or_feedback": "/strategy/stage-01-skills-adoption/",
|
"next_or_feedback": "/strategy/six-months-target/",
|
||||||
"review": "Qualified pilot and separate Stage02 authority now explicit"
|
"review": "Historical three-level roadmap restored, distinct from monthly plan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "docs/strategy/skills-adoption.mdx",
|
"source": "docs/strategy/skills-adoption.mdx",
|
||||||
@@ -286,10 +286,10 @@
|
|||||||
{
|
{
|
||||||
"source": "docs/strategy/stage-01-skills-adoption.mdx",
|
"source": "docs/strategy/stage-01-skills-adoption.mdx",
|
||||||
"route": "/strategy/stage-01-skills-adoption/",
|
"route": "/strategy/stage-01-skills-adoption/",
|
||||||
"question": "How do I begin one repeatable adoption journey?",
|
"question": "How do reusable lifecycle activities hand off evidence?",
|
||||||
"inputs": "Workflow problem, people and current evidence",
|
"inputs": "Workflow problem, people and current evidence",
|
||||||
"action_or_decision": "Baseline, engineer, qualify, authorize pilot, compare and decide",
|
"action_or_decision": "Baseline, qualify, authorize pilot, compare and maintain; link canonical EXP-01 in six-month roadmap",
|
||||||
"output": "Supported workflow or explicit hold/stop; feedback to baseline/quality",
|
"output": "Lifecycle reference and feedback paths, not a competing plan",
|
||||||
"next_or_feedback": "/strategy/baseline/",
|
"next_or_feedback": "/strategy/baseline/",
|
||||||
"review": "New native dependency story plus evidence handoffs"
|
"review": "New native dependency story plus evidence handoffs"
|
||||||
},
|
},
|
||||||
@@ -306,12 +306,32 @@
|
|||||||
{
|
{
|
||||||
"source": "docs/strategy/target-operating-model.mdx",
|
"source": "docs/strategy/target-operating-model.mdx",
|
||||||
"route": "/strategy/target-operating-model/",
|
"route": "/strategy/target-operating-model/",
|
||||||
"question": "What operating model are we aiming for?",
|
"question": "What is the long-term human-controlled autonomous SDLC destination?",
|
||||||
"inputs": "Human-directed SDLC target and existing team boundaries",
|
"inputs": "Original agreed topology and human direction",
|
||||||
"action_or_decision": "Distinguish intended execution from current authority",
|
"action_or_decision": "Preserve ambition with independent controls and no present authority",
|
||||||
"output": "Shared destination, no deployed-autonomy claim",
|
"output": "Long-term operating model, not six-month promise",
|
||||||
"next_or_feedback": "/strategy/roadmap/",
|
"next_or_feedback": "/strategy/roadmap/",
|
||||||
"review": "Preserved central-agent topology; connected Delivery thread"
|
"review": "Original topology restored from pre-PR38; safeguards retained"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "docs/strategy/six-months-target.mdx",
|
||||||
|
"route": "/strategy/six-months-target/",
|
||||||
|
"question": "What six-month strategy answers the AI Architect assignment?",
|
||||||
|
"inputs": "Full PDF facts; explicitly unknown stack, processes and capacity",
|
||||||
|
"action_or_decision": "Improve current AI-assisted engineering output with the smallest suitable intervention",
|
||||||
|
"output": "Realistic month-six scenario, assumptions register and 35+15-minute presentation narrative",
|
||||||
|
"next_or_feedback": "/strategy/six-months-roadmap/",
|
||||||
|
"review": "PDF assignment retained independently of long-term destination; EXP-01 lives in six-month action plan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "docs/strategy/six-months-roadmap.mdx",
|
||||||
|
"route": "/strategy/six-months-roadmap/",
|
||||||
|
"question": "What does a solo architect do month by month without team authority?",
|
||||||
|
"inputs": "PDF constraints, current AI practice, willing partners and unknown capacity",
|
||||||
|
"action_or_decision": "Month 1–6 discovery, bounded experiment, compare, selective transfer and CTO investment decision",
|
||||||
|
"output": "Proposed six-month plan with dependencies, evidence, capacity and stop choices",
|
||||||
|
"next_or_feedback": "/strategy/stage-02-autonomous-agent/",
|
||||||
|
"review": "PDF assignment retained independently of long-term destination; EXP-01 lives in six-month action plan"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0.0",
|
"schema_version": "1.0.0",
|
||||||
"status": "proposed-target-not-approved-or-deployed",
|
"status": "proposed-target-not-approved-or-deployed",
|
||||||
"scope": "Strategy documentation and synthetic measurement reference only; no runtime changes authorized.",
|
"scope": "Long-term human-controlled autonomous SDLC Target and broad Roadmap, with distinct six-month contribution and action plan plus Beyond bridge. Full30-route reading contract is strategy-coverage.json. Organization model is not PDF evidence; no runtime changes authorized.",
|
||||||
"organization": {
|
"organization": {
|
||||||
"Product": [
|
"Product": [
|
||||||
"Product Management",
|
"Product Management",
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
"pages": [
|
"pages": [
|
||||||
{
|
{
|
||||||
"id": "target-operating-model",
|
"id": "target-operating-model",
|
||||||
"title": "Target operating model",
|
"title": "Target",
|
||||||
"purpose": "One logical coordinator; local client choice; independent authority; all departments."
|
"purpose": "Long-term human-directed, guided and reviewed autonomous SDLC destination; original topology and supporting controls, not six-month promise or present authority."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "skills-governance",
|
"id": "skills-governance",
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "measurement",
|
"id": "measurement",
|
||||||
"title": "Skills Measurement",
|
"title": "Measuring real output",
|
||||||
"purpose": "Which KPIs to collect during skills adoption, how to calculate them and when to report."
|
"purpose": "Small feasible starting measures and optional sixteen-contract registry, not mandatory collection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "skills-maintenance",
|
"id": "skills-maintenance",
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
{
|
{
|
||||||
"id": "roadmap",
|
"id": "roadmap",
|
||||||
"title": "Roadmap",
|
"title": "Roadmap",
|
||||||
"purpose": "Assess current code quality and delivery processes, close critical gaps, then pilot, expand and sustain AI adoption."
|
"purpose": "Broad progression from skills/practices adoption to controlled autonomous capabilities: Delivery first, later phase order undecided, evidence and separate human decisions without fixed timing."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"diagram": {
|
"diagram": {
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"sourceCommit": "88a43757762114a506f57ed4b44484306cae1aaa",
|
||||||
|
"departments": [
|
||||||
|
{
|
||||||
|
"label": "Product",
|
||||||
|
"slug": "product",
|
||||||
|
"bodySha256": "b7fd948091dbd7b7c2f51d494a5e83241a53c5d1d9b751267102a6c97ad29bd9",
|
||||||
|
"rows": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Technology",
|
||||||
|
"slug": "technology",
|
||||||
|
"bodySha256": "a74405d41a58b43e4e8ffbb0e98f835d25d80c6ab2ef9f314925832280c038d3",
|
||||||
|
"rows": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Operations",
|
||||||
|
"slug": "operations",
|
||||||
|
"bodySha256": "03254f56a3ea8e353a5d9b65c0342954bf65edec59073d20fb1ceaaf31d683c7",
|
||||||
|
"rows": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Marketing",
|
||||||
|
"slug": "marketing",
|
||||||
|
"bodySha256": "424d7c1d147472ced3b73eb8041048a982ce10330a51246ca35bed0cd150e633",
|
||||||
|
"rows": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Finance & Accounting",
|
||||||
|
"slug": "finance-accounting",
|
||||||
|
"bodySha256": "ffdacb9930114a6caf25a475bb207dcb58f27c13e08fb04e098ef1e30ea538a9",
|
||||||
|
"rows": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "HR & Administration",
|
||||||
|
"slug": "hr-administration",
|
||||||
|
"bodySha256": "e663ca1c7b7fe83cff70d6e33235591fa082304d201dc4538235cc1a341ffd3c",
|
||||||
|
"rows": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
import {targetCaption} from './target-caption.mjs';
|
||||||
|
const read = p => readFileSync(p,'utf8');
|
||||||
|
const matrix = JSON.parse(read('research/ai-adoption/assignment-evidence.json'));
|
||||||
|
test('PDF assignment and audit matrix map to actual page evidence',()=>{
|
||||||
|
assert.deepEqual(matrix.requirements.map(r=>r.id),['format','context','q1','q2','q3','q4','assumptions','F1','F2-F3']);
|
||||||
|
for(const row of matrix.requirements){
|
||||||
|
const text=row.pages.map(p=>read(`docs/strategy/${p}.mdx`)).join('\n').toLowerCase();
|
||||||
|
for(const marker of row.markers) assert(text.includes(marker.toLowerCase()),`${row.id}: ${marker}`);
|
||||||
|
}
|
||||||
|
for(const p of matrix.verification_sources)assert(read(p));
|
||||||
|
assert.equal(35+15,50);
|
||||||
|
});
|
||||||
|
test('six-month reading path does not promise skills rollout or autonomous delivery',()=>{
|
||||||
|
const main=read('docs/strategy/six-months-target.mdx').split('<details>')[0];
|
||||||
|
assert(main.indexOf('strategy-six-months')<main.indexOf('Choose the smallest intervention'));
|
||||||
|
for(const stale of ['The first investment is a governed skills system','An autonomous agent executes and governs every phase','foundation for Stage 2'])assert(!main.includes(stale));
|
||||||
|
const roadmap=read('docs/strategy/six-months-roadmap.mdx');
|
||||||
|
for(const month of [1,2,3,4,5,6]){
|
||||||
|
const block=roadmap.split(`**Month ${month} — `)[1].split('\n\n')[0];
|
||||||
|
for(const word of ['Output:','Dependency:'])assert(block.includes(word),`${month}: ${word}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
test('proposed diagram preserves months and explicit mobile feedback legend',()=>{
|
||||||
|
const pair=['','-mobile'].map(s=>JSON.parse(read(`diagrams/strategy-six-months${s}.architecture.json`)));
|
||||||
|
const nodes=d=>d.components.map(({pos,size,...n})=>n);
|
||||||
|
assert.deepEqual(nodes(pair[0]),nodes(pair[1]));
|
||||||
|
for(const d of pair){
|
||||||
|
for(let m=1;m<=6;m++)assert(d.components.some(n=>n.label.startsWith(`Month ${m}:`)));
|
||||||
|
const legend=d.components.find(n=>n.id==='reference');
|
||||||
|
assert(legend.sublabel.includes('Month 6 → 2:'));assert(legend.sublabel.includes('Month 5 → 1:'));
|
||||||
|
assert(legend.sublabel.includes('not company commitments'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
test('first-revision recovery and diagram decisions cannot disappear',()=>{
|
||||||
|
for(const id of ['skills-quality','skills-governance','skills-maintenance']){
|
||||||
|
const text=read(`docs/strategy/${id}.mdx`);
|
||||||
|
for(const term of ['N/A','pinned clean','current'])assert(text.includes(term),id);
|
||||||
|
}
|
||||||
|
for(const s of ['','-mobile']){
|
||||||
|
const g=JSON.parse(read(`diagrams/strategy-governance${s}.architecture.json`));
|
||||||
|
assert(g.components.find(n=>n.id==='canary').sublabel.includes('pilot'));
|
||||||
|
assert(g.components.find(n=>n.id==='approve').sublabel.includes('approve / hold'));
|
||||||
|
const a=JSON.parse(read(`diagrams/strategy-adoption${s}.architecture.json`));
|
||||||
|
assert(a.components.find(n=>n.id==='expand').sublabel.includes('Retain / improve / hold / stop'));
|
||||||
|
}
|
||||||
|
const mobile=JSON.parse(read('diagrams/strategy-maintenance-mobile.architecture.json'));
|
||||||
|
const order=[...mobile.components].sort((a,b)=>a.pos[1]-b.pos[1]).map(n=>n.id);
|
||||||
|
assert.deepEqual(order.slice(0,2),['observe','triage']);
|
||||||
|
});
|
||||||
|
test('target caption is inside SVG, expands canvas and fails closed',()=>{
|
||||||
|
const svg='<svg role="img" viewBox="0 0 1200 1000"><g data-node-id="agent"/></svg>';
|
||||||
|
const out=targetCaption(svg);
|
||||||
|
for(const term of ['Long-term Target','Solid: lifecycle','Dotted: execution','Dashed: human-controlled'])assert(out.includes(term));
|
||||||
|
assert(out.includes('viewBox="0 0 1200 1130"'));
|
||||||
|
assert(out.indexOf('eldorado-target-caption')<out.indexOf('</svg>'));
|
||||||
|
assert.equal((out.match(/data-node-id=/g)||[]).length,1);
|
||||||
|
assert.throws(()=>targetCaption('<svg/>'));
|
||||||
|
});
|
||||||
@@ -3,6 +3,6 @@ const fs=require('node:fs');const assert=require('node:assert/strict');
|
|||||||
(async()=>{
|
(async()=>{
|
||||||
const base=process.argv[2]||'http://127.0.0.1:4173';const out=`.cache/journey-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true});
|
const base=process.argv[2]||'http://127.0.0.1:4173';const out=`.cache/journey-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true});
|
||||||
const b=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});const results=[];
|
const b=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});const results=[];
|
||||||
const steps=[['target-operating-model','roadmap'],['roadmap','stage-01-skills-adoption'],['stage-01-skills-adoption','baseline'],['baseline','measurement'],['measurement','skills-quality'],['skills-quality','skills-governance'],['skills-governance','skills-quality'],['skills-quality','skills-adoption'],['skills-adoption','skills-maintenance'],['skills-maintenance','skills-quality'],['skills-quality','measurement/validated-task-success'],['measurement/validated-task-success','skills-quality'],['skills-maintenance','stage-02-autonomous-agent'],['stage-02-autonomous-agent','stage-01-skills-adoption']];
|
const steps=[['target-operating-model','roadmap'],['roadmap','six-months-target'],['six-months-target','six-months-roadmap'],['six-months-roadmap','stage-02-autonomous-agent'],['six-months-roadmap','stage-01-skills-adoption'],['stage-01-skills-adoption','baseline'],['baseline','measurement'],['measurement','skills-quality'],['skills-quality','skills-governance'],['skills-governance','skills-quality'],['skills-quality','skills-adoption'],['skills-adoption','skills-maintenance'],['skills-maintenance','skills-quality'],['skills-quality','measurement/validated-task-success'],['measurement/validated-task-success','skills-quality'],['skills-maintenance','stage-02-autonomous-agent'],['stage-02-autonomous-agent','stage-01-skills-adoption']];
|
||||||
try{for(const width of [1440,390]){const p=await b.newPage({viewport:{width,height:900}});for(const [from,to]of steps){await p.goto(`${base}/eldorado-v1/documentation/strategy/${from}/`,{waitUntil:'networkidle'});const href=`/eldorado-v1/documentation/strategy/${to}/`;const link=p.locator(`article a[href="${href}"]`).filter({visible:true}).first();assert(await link.count(),`${from} → ${to}`);await link.scrollIntoViewIfNeeded();await p.waitForLoadState('networkidle');await link.click();await p.waitForURL(`${base}${href}`);await p.locator('article h1').waitFor();results.push({width,from,to,clicked:true});fs.writeFileSync(`${out}/results.json`,JSON.stringify(results,null,2))}await p.close()}console.log(`PASS ${results.length} real reader handoffs and feedback links`)}finally{await b.close()}
|
try{for(const width of [1440,390]){const p=await b.newPage({viewport:{width,height:900}});for(const [from,to]of steps){await p.goto(`${base}/eldorado-v1/documentation/strategy/${from}/`,{waitUntil:'networkidle'});const href=`/eldorado-v1/documentation/strategy/${to}/`;const link=p.locator(`article a[href="${href}"]`).filter({visible:true}).first();assert(await link.count(),`${from} → ${to}`);await link.scrollIntoViewIfNeeded();await p.waitForLoadState('networkidle');await link.click();await p.waitForURL(`${base}${href}`);await p.locator('article h1').waitFor();results.push({width,from,to,clicked:true});fs.writeFileSync(`${out}/results.json`,JSON.stringify(results,null,2))}await p.close()}console.log(`PASS ${results.length} real reader handoffs and feedback links`)}finally{await b.close()}
|
||||||
})().catch(e=>{console.error(e);process.exitCode=1});
|
})().catch(e=>{console.error(e);process.exitCode=1});
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
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:4187';
|
||||||
|
const prefix='/eldorado-v1/documentation/organization/';
|
||||||
|
const departments=JSON.parse(fs.readFileSync('research/organization/department-migration.json')).departments;
|
||||||
|
const ids=['structure',...departments.map(d=>'structure/'+d.slug)];
|
||||||
|
const titles=['Structure',...departments.map(d=>d.label)];
|
||||||
|
const browser=await chromium.launch({headless:true,args:['--no-sandbox'],executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE});
|
||||||
|
const results=[]; fs.mkdirSync('.cache/departments',{recursive:true});
|
||||||
|
try{
|
||||||
|
for(const width of [1440,390]){
|
||||||
|
const page=await browser.newPage({viewport:{width,height:900}}); const errors=[]; page.on('pageerror',e=>errors.push(e.message));
|
||||||
|
for(const [i,id] of ids.entries()){
|
||||||
|
assert.equal((await page.goto(base+prefix+id+'/',{waitUntil:'networkidle'})).status(),200);
|
||||||
|
assert.equal(await page.locator('h1').innerText(),titles[i]);
|
||||||
|
if(i){
|
||||||
|
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'Structure'}).getAttribute('href'),prefix+'structure/');
|
||||||
|
assert.equal(await page.locator('.pagination-nav__link--prev').getAttribute('href'),prefix+ids[i-1]+'/');
|
||||||
|
await page.getByRole('link',{name:'Return to Structure overview',exact:true}).click();
|
||||||
|
await page.waitForURL(base+prefix+'structure/');
|
||||||
|
await page.locator('article').getByRole('link',{name:titles[i],exact:true}).click();
|
||||||
|
await page.waitForURL(base+prefix+id+'/');
|
||||||
|
}
|
||||||
|
assert.equal(await page.locator('.pagination-nav__link--next').getAttribute('href'),prefix+(ids[i+1]||'collaboration')+'/');
|
||||||
|
assert(!await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth));
|
||||||
|
await page.screenshot({path:`.cache/departments/${width}-${id.replaceAll('/','-')}.png`,fullPage:true});
|
||||||
|
if(width<997)await page.getByRole('button',{name:'Toggle navigation bar'}).click();
|
||||||
|
const menu=page.locator('.theme-doc-sidebar-menu').filter({visible:true});
|
||||||
|
await menu.getByRole('link',{name:'Structure',exact:true}).waitFor({state:'visible'});
|
||||||
|
const category=menu.locator('.theme-doc-sidebar-item-category');
|
||||||
|
await category.getByRole('link',{name:'Product',exact:true}).waitFor({state:'visible'});
|
||||||
|
assert.deepEqual(await category.locator(':scope > ul > li > a').allTextContents(),titles.slice(1));
|
||||||
|
assert.deepEqual(await menu.locator(':scope > li > a').allTextContents(),['Collaboration','SDLC']);
|
||||||
|
const caret=category.locator(':scope > .menu__list-item-collapsible > button');
|
||||||
|
await caret.click(); await category.getByRole('link',{name:'Product',exact:true}).waitFor({state:'hidden'});
|
||||||
|
await caret.click(); await category.getByRole('link',{name:'Product',exact:true}).waitFor({state:'visible'});
|
||||||
|
const next=(i+1)%ids.length;
|
||||||
|
await menu.getByRole('link',{name:titles[next],exact:true}).click(); await page.waitForURL(base+prefix+ids[next]+'/');
|
||||||
|
await page.locator('h1').filter({hasText:titles[next]}).waitFor();
|
||||||
|
results.push({width,id,navigation:true});
|
||||||
|
}
|
||||||
|
assert.deepEqual(errors,[]);await page.close();
|
||||||
|
}
|
||||||
|
fs.writeFileSync('.cache/departments/results.json',JSON.stringify(results,null,2));
|
||||||
|
console.log('PASS: '+results.length+' desktop/mobile department contexts, real sidebar/return/list navigation, breadcrumbs, pagination and overflow');
|
||||||
|
}finally{await browser.close();}
|
||||||
|
})().catch(e=>{console.error(e);process.exit(1)});
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
const {chromium}=require('playwright');
|
||||||
|
const staircaseFits=require('./presentation-staircase.cjs');
|
||||||
|
const assert=require('node:assert/strict');const fs=require('node:fs');
|
||||||
|
(async()=>{
|
||||||
|
const base=process.argv[2]||'http://127.0.0.1:43853';const root=base+'/eldorado-v1/documentation/';
|
||||||
|
const out='.cache/homepage-embed';fs.mkdirSync(out,{recursive:true});
|
||||||
|
const browser=await chromium.launch({headless:true,executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});const results=[];
|
||||||
|
try{
|
||||||
|
for(const viewport of [{width:1440,height:900},{width:390,height:844},{width:320,height:720},{width:844,height:390}]){
|
||||||
|
const context=await browser.newContext({viewport,hasTouch:true,reducedMotion:'reduce'});const p=await context.newPage();const errors=[];
|
||||||
|
p.on('pageerror',e=>errors.push(e.message));p.on('response',r=>{if(r.status()>=400)errors.push(`${r.status()} ${r.url()}`)});
|
||||||
|
await p.goto(root,{waitUntil:'networkidle'});const section=p.locator('section[aria-labelledby="presentation-title"]');await section.scrollIntoViewIfNeeded();
|
||||||
|
const iframe=p.locator('iframe[title="Less Prompting, More Shipping — interactive presentation"]');const f=await iframe.elementHandle().then(e=>e.contentFrame());await f.waitForFunction(()=>window.Reveal?.isReady());await f.evaluate(()=>document.fonts.ready);
|
||||||
|
assert.deepEqual(await p.locator('#start-title,#presentation-title').evaluateAll(es=>es.map(e=>{const s=getComputedStyle(e);return [s.fontFamily,s.fontSize,s.fontWeight,s.letterSpacing,s.lineHeight]})).then(a=>a[0]),await p.locator('#presentation-title').evaluate(e=>{const s=getComputedStyle(e);return [s.fontFamily,s.fontSize,s.fontWeight,s.letterSpacing,s.lineHeight]}));
|
||||||
|
assert.equal(await f.locator('.toolbar').isVisible(),false);assert.equal(await f.evaluate(()=>Reveal.getConfig().hash),false);assert.equal(await f.evaluate(()=>Reveal.getConfig().transition),'none');assert.equal(await f.evaluate(()=>Reveal.getTotalSlides()),23);
|
||||||
|
assert(await p.evaluate(()=>document.documentElement.scrollWidth<=innerWidth));
|
||||||
|
if(viewport.width<=390)assert(await iframe.evaluate(e=>e.clientHeight>e.clientWidth),'phone stage must recompose rather than shrink landscape text');
|
||||||
|
await p.getByRole('button',{name:'Fullscreen',exact:true}).focus();await p.keyboard.press('ArrowRight');assert.equal(await f.evaluate(()=>Reveal.getIndices().h),0);
|
||||||
|
await f.locator('.controls .navigate-right').click();assert.equal(await f.evaluate(()=>Reveal.getIndices().h),1);
|
||||||
|
const scroll=await p.evaluate(()=>scrollY);await p.keyboard.press('ArrowRight');assert.equal(await f.evaluate(()=>Reveal.getIndices().h),2);assert.equal(await p.evaluate(()=>scrollY),scroll);assert.equal(p.url(),root);
|
||||||
|
await f.evaluate(()=>Reveal.slide(0));
|
||||||
|
const visited=[];
|
||||||
|
for(let i=0;i<23;i++){
|
||||||
|
assert.equal(await f.evaluate(()=>Reveal.getIndices().h),i);visited.push(await f.evaluate(()=>Reveal.getCurrentSlide().id));
|
||||||
|
const bad=await f.evaluate(()=>{const r=Reveal.getCurrentSlide().getBoundingClientRect();return [...Reveal.getCurrentSlide().querySelectorAll('.measurement-panels,.metric,.metric b,.metric span,.qualification-note,h3,svg,text,.journey,.learning-loop,.contribution-grid,h1,h2,p,li,table,.flow,.roles,.timeline')].filter(e=>!e.closest('.notes')&&e.getBoundingClientRect().width>0).filter(e=>{const b=e.getBoundingClientRect();return b.bottom>r.bottom+1||b.right>r.right+1||b.left<r.left-1}).map(e=>e.textContent)});assert.deepEqual(bad,[]);
|
||||||
|
if(i===6)assert(await f.evaluate(staircaseFits),'staircase aligns each arrow with its intended steps');
|
||||||
|
if(i===4)assert(await f.evaluate(()=>[...document.querySelectorAll('#contributors .contribution-grid>div')].every(e=>{const a=e.querySelector('span').getBoundingClientRect(), arrow=e.querySelector('i').getBoundingClientRect(), b=e.querySelector('b').getBoundingClientRect();return a.bottom<=arrow.top+2&&arrow.bottom<=b.top+2&&Math.abs((a.left+a.right-b.left-b.right)/2)<2&&getComputedStyle(e.querySelector('i')).transform==='matrix(0, 1, -1, 0, 0, 0)'})),'contribution arrows must point down to their own phase');
|
||||||
|
await iframe.screenshot({path:`${out}/${viewport.width}-${i+1}.png`});
|
||||||
|
if(i<22)await p.keyboard.press('ArrowRight');
|
||||||
|
}
|
||||||
|
assert.equal(new Set(visited).size,23);assert.equal(p.url(),root);assert.equal(new URL(f.url()).hash,'');
|
||||||
|
await f.evaluate(()=>Reveal.slide(0));await section.screenshot({path:`${out}/${viewport.width}-light.png`});
|
||||||
|
await p.evaluate(()=>document.documentElement.setAttribute('data-theme','dark'));await section.screenshot({path:`${out}/${viewport.width}-dark.png`});
|
||||||
|
await p.getByRole('button',{name:'Fullscreen',exact:true}).click();await p.waitForFunction(()=>!!document.fullscreenElement);await f.waitForTimeout(100);
|
||||||
|
await p.screenshot({path:`${out}/${viewport.width}-fullscreen.png`});
|
||||||
|
await p.getByRole('button',{name:'Exit fullscreen',exact:true}).click();await p.waitForFunction(()=>!document.fullscreenElement);await p.waitForFunction(()=>document.activeElement?.textContent==='Fullscreen');
|
||||||
|
// Native touch swipe inside the stage, not a programmatic Reveal.next().
|
||||||
|
await iframe.scrollIntoViewIfNeeded();const b=await iframe.boundingBox();const cdp=await context.newCDPSession(p);
|
||||||
|
await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[{x:b.x+b.width*.8,y:b.y+b.height*.4}]});
|
||||||
|
await cdp.send('Input.dispatchTouchEvent',{type:'touchMove',touchPoints:[{x:b.x+b.width*.2,y:b.y+b.height*.4}]});await cdp.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});assert.equal(await f.evaluate(()=>Reveal.getIndices().h),1);
|
||||||
|
await p.emulateMedia({reducedMotion:'no-preference'});await f.waitForFunction(()=>Reveal.getConfig().transition==='fade');await p.emulateMedia({reducedMotion:'reduce'});await f.waitForFunction(()=>Reveal.getConfig().transition==='none');
|
||||||
|
await f.locator('.navigate-right').focus();await p.keyboard.press('f');await p.keyboard.press('s');assert.equal(context.pages().length,1);assert.equal(await p.evaluate(()=>!!document.fullscreenElement),false);
|
||||||
|
if(viewport.width<=390){
|
||||||
|
await p.setViewportSize({width:844,height:390});await f.waitForFunction(()=>Reveal.getConfig().width===1200);assert.equal(await f.evaluate(()=>Reveal.getIndices().h),1);
|
||||||
|
await p.setViewportSize(viewport);await f.waitForFunction(()=>Reveal.getConfig().width===600);
|
||||||
|
}
|
||||||
|
// Unsupported fullscreen is non-destructive and keeps a working standalone escape.
|
||||||
|
await p.evaluate(()=>{window.savedFullscreen=Element.prototype.requestFullscreen;Element.prototype.requestFullscreen=undefined});
|
||||||
|
await p.getByRole('button',{name:'Fullscreen',exact:true}).click();await p.getByRole('status').filter({hasText:'Fullscreen is unavailable'}).waitFor();assert.equal(p.url(),root);
|
||||||
|
await p.evaluate(()=>{Element.prototype.requestFullscreen=window.savedFullscreen});
|
||||||
|
// No keyboard trap: browser Tab can leave the frame for the standalone affordance.
|
||||||
|
await f.locator('.navigate-right').focus();for(let i=0;i<12&&!(await p.getByRole('link',{name:/Open presentation/}).evaluate(e=>e===document.activeElement));i++)await p.keyboard.press('Tab');
|
||||||
|
assert(await p.getByRole('link',{name:/Open presentation/}).evaluate(e=>e===document.activeElement));
|
||||||
|
for(const href of await p.locator('.start-card').evaluateAll(es=>es.map(e=>e.href)))assert.equal((await p.request.get(href)).status(),200);
|
||||||
|
await p.getByRole('link',{name:/Open presentation/}).click();await p.waitForFunction(()=>window.Reveal?.isReady());assert(!p.url().includes('embed'));assert(await p.locator('.toolbar').isVisible());
|
||||||
|
assert.deepEqual(errors,[]);results.push({viewport,visited,headingParity:true,keyboardIsolation:true,scrollIsolation:true,touch:true,fullscreen:true,tabExit:true,errors});await context.close();
|
||||||
|
}
|
||||||
|
fs.writeFileSync(`${out}/results.json`,JSON.stringify(results,null,2));console.log('PASS: 92 inline slides, heading parity, URLs, focus/scroll isolation, touch, fullscreen, Tab exit, themes, reduced motion and standalone handoff');
|
||||||
|
}finally{await browser.close()}
|
||||||
|
})().catch(e=>{console.error(e);process.exitCode=1});
|
||||||
@@ -12,10 +12,17 @@ const fs = require('node:fs');
|
|||||||
const context = await browser.newContext({viewport: {width, height: 1000}, colorScheme: 'light'});
|
const context = await browser.newContext({viewport: {width, height: 1000}, colorScheme: 'light'});
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
await page.goto(`${base}/eldorado-v1/documentation/strategy/`, {waitUntil: 'networkidle'});
|
await page.goto(`${base}/eldorado-v1/documentation/strategy/`, {waitUntil: 'networkidle'});
|
||||||
const panel = page.locator('.archify-panel--story');
|
await page.addStyleTag({content:'html {scroll-behavior:auto !important;}'});
|
||||||
|
const panel = page.locator('.archify-panel--story[data-diagram="strategy-target"]');
|
||||||
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
|
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
|
||||||
await iframe.scrollIntoViewIfNeeded();
|
await iframe.scrollIntoViewIfNeeded();
|
||||||
const frame = await (await iframe.elementHandle()).contentFrame();
|
const frame = await (await iframe.elementHandle()).contentFrame();
|
||||||
|
const showControls = () => iframe.evaluate(n => {
|
||||||
|
scrollTo({top:n.getBoundingClientRect().top+scrollY-120,behavior:'instant'});
|
||||||
|
return new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)));
|
||||||
|
});
|
||||||
|
await showControls();
|
||||||
|
const activate = async selector => {await frame.locator(selector).focus(); await page.keyboard.press('Enter');};
|
||||||
const theme = async value => {
|
const theme = async value => {
|
||||||
await page.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
await page.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
||||||
await frame.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
await frame.waitForFunction(t => document.documentElement.dataset.theme === t, value);
|
||||||
@@ -41,9 +48,9 @@ const fs = require('node:fs');
|
|||||||
assert(menu.y + menu.height <= viewport.y + viewport.height + 1, `${selector} clips vertically`);
|
assert(menu.y + menu.height <= viewport.y + viewport.height + 1, `${selector} clips vertically`);
|
||||||
};
|
};
|
||||||
const light = await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor);
|
const light = await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor);
|
||||||
await frame.locator('#btn-theme').click(); await theme('dark');
|
await activate('#btn-theme'); await theme('dark');
|
||||||
assert.notEqual(await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor), light);
|
assert.notEqual(await frame.locator('body').evaluate(n => getComputedStyle(n).backgroundColor), light);
|
||||||
await frame.locator('#btn-theme').click(); await theme('light');
|
await activate('#btn-theme'); await theme('light');
|
||||||
// Mobile portal theme control lives in the navigation drawer.
|
// Mobile portal theme control lives in the navigation drawer.
|
||||||
const portalTheme = async target => {
|
const portalTheme = async target => {
|
||||||
if (width <= 700) await page.getByRole('button', {name: 'Toggle navigation bar'}).click();
|
if (width <= 700) await page.getByRole('button', {name: 'Toggle navigation bar'}).click();
|
||||||
@@ -52,33 +59,34 @@ const fs = require('node:fs');
|
|||||||
if (await page.locator('html').getAttribute('data-theme') === target) break;
|
if (await page.locator('html').getAttribute('data-theme') === target) break;
|
||||||
}
|
}
|
||||||
if (width <= 700) await page.getByRole('button', {name: 'Close navigation bar'}).click();
|
if (width <= 700) await page.getByRole('button', {name: 'Close navigation bar'}).click();
|
||||||
|
await showControls();
|
||||||
};
|
};
|
||||||
await portalTheme('dark'); await theme('dark');
|
await portalTheme('dark'); await theme('dark');
|
||||||
await portalTheme('light'); await theme('light');
|
await portalTheme('light'); await theme('light');
|
||||||
for (const preset of ['signal-flow', 'blueprint', 'editorial', 'classic']) {
|
for (const preset of ['signal-flow', 'blueprint', 'editorial', 'classic']) {
|
||||||
await frame.locator('#btn-preset').click();
|
await activate('#btn-preset');
|
||||||
await checkMenu('.preset-menu');
|
await checkMenu('.preset-menu');
|
||||||
await frame.locator(`[data-preset-value="${preset}"]`).click();
|
await activate(`[data-preset-value="${preset}"]`);
|
||||||
assert.equal(await frame.locator('html').getAttribute('data-preset'), preset);
|
assert.equal(await frame.locator('html').getAttribute('data-preset'), preset);
|
||||||
}
|
}
|
||||||
// A theme change must not reload the iframe or lose the selected visual preset.
|
// A theme change must not reload the iframe or lose the selected visual preset.
|
||||||
await frame.locator('#btn-preset').click();
|
await activate('#btn-preset');
|
||||||
await frame.locator('[data-preset-value="blueprint"]').click();
|
await activate('[data-preset-value="blueprint"]');
|
||||||
await portalTheme('dark'); await theme('dark');
|
await portalTheme('dark'); await theme('dark');
|
||||||
assert.equal(await frame.locator('html').getAttribute('data-preset'), 'blueprint');
|
assert.equal(await frame.locator('html').getAttribute('data-preset'), 'blueprint');
|
||||||
const exports = [];
|
const exports = [];
|
||||||
for (const format of ['png', 'jpeg', 'webp', 'svg', 'svg-light', 'svg-dark', 'webm']) {
|
for (const format of ['png', 'jpeg', 'webp', 'svg', 'svg-light', 'svg-dark', 'webm']) {
|
||||||
await frame.locator('#btn-export').click();
|
await activate('#btn-export');
|
||||||
await checkMenu('.export-menu');
|
await checkMenu('.export-menu');
|
||||||
if (format === 'webm' && await frame.locator('[data-format="webm"]').isDisabled()) {
|
if (format === 'webm' && await frame.locator('[data-format="webm"]').isDisabled()) {
|
||||||
exports.push({format, unsupported: true});
|
exports.push({format, unsupported: true});
|
||||||
await frame.locator('#btn-export').click();
|
await activate('#btn-export');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log(`Export ${width} ${format}`);
|
console.log(`Export ${width} ${format}`);
|
||||||
const [download] = await Promise.all([
|
const [download] = await Promise.all([
|
||||||
page.waitForEvent('download', {timeout: 60000}),
|
page.waitForEvent('download', {timeout: 60000}),
|
||||||
frame.locator(`[data-format="${format}"]`).click(),
|
activate(`[data-format="${format}"]`),
|
||||||
]);
|
]);
|
||||||
assert.equal(await download.failure(), null);
|
assert.equal(await download.failure(), null);
|
||||||
const path = `${output}/${width}-${format}-${download.suggestedFilename()}`;
|
const path = `${output}/${width}-${format}-${download.suggestedFilename()}`;
|
||||||
@@ -123,14 +131,14 @@ const fs = require('node:fs');
|
|||||||
await page.evaluate(() => scrollTo({top: 0, behavior: 'instant'}));
|
await page.evaluate(() => scrollTo({top: 0, behavior: 'instant'}));
|
||||||
await page.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve))));
|
await page.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve))));
|
||||||
await page.screenshot({path:`${output}/${width}.png`, fullPage:true});
|
await page.screenshot({path:`${output}/${width}.png`, fullPage:true});
|
||||||
await frame.locator('#btn-theme').click(); await theme('dark');
|
await frame.locator('#btn-theme').focus(); await page.keyboard.press('Enter'); await theme('dark');
|
||||||
// Exercise keyboard navigation without racing the portal's smooth scroll.
|
// Exercise keyboard navigation without racing the portal's smooth scroll.
|
||||||
await page.locator('.strategy-content a[href$="/strategy/roadmap/"]').filter({visible:true}).first().focus();
|
await page.locator('.strategy-content a[href$="/strategy/roadmap/"]').filter({visible:true}).first().focus();
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
await page.waitForURL('**/strategy/roadmap/');
|
await page.waitForURL('**/strategy/roadmap/');
|
||||||
await page.goBack({waitUntil:'domcontentloaded'});
|
await page.goBack({waitUntil:'domcontentloaded'});
|
||||||
await page.waitForURL('**/strategy/target-operating-model/');
|
await page.waitForURL('**/strategy/target-operating-model/');
|
||||||
await page.getByRole('heading', {name:'Target operating model', exact:true, level:1}).waitFor();
|
await page.getByRole('heading', {name:'Target', exact:true, level:1}).waitFor();
|
||||||
const next = page.locator(`.archify-panel--story[data-diagram="strategy-target"] > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
const next = page.locator(`.archify-panel--story[data-diagram="strategy-target"] > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
||||||
await next.scrollIntoViewIfNeeded();
|
await next.scrollIntoViewIfNeeded();
|
||||||
await (await (await next.elementHandle()).contentFrame()).waitForFunction(() => document.documentElement.dataset.theme === 'dark');
|
await (await (await next.elementHandle()).contentFrame()).waitForFunction(() => document.documentElement.dataset.theme === 'dark');
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Browser-side geometry contract, shared by standalone and embedded acceptance.
|
||||||
|
module.exports = function staircaseFits() {
|
||||||
|
const els=[...document.querySelectorAll('#learning-loop .learning-loop>*')];
|
||||||
|
const b=els.map(e=>e.getBoundingClientRect());
|
||||||
|
const center=r=>({x:(r.left+r.right)/2,y:(r.top+r.bottom)/2});
|
||||||
|
const close=(a,b)=>Math.abs(a-b)<2;
|
||||||
|
return [[0,1,2],[4,5,6],[8,9,10]].every(([a,arrow,c])=>
|
||||||
|
close(center(b[a]).y,center(b[c]).y)&&close(center(b[a]).y,center(b[arrow]).y)&&
|
||||||
|
b[a].right<=b[arrow].left+2&&b[arrow].right<=b[c].left+2
|
||||||
|
)&&[[2,3,4],[6,7,8]].every(([a,arrow,c])=>
|
||||||
|
close(center(b[a]).x,center(b[c]).x)&&close(center(b[a]).x,center(b[arrow]).x)&&
|
||||||
|
b[a].bottom<=b[arrow].top+2&&b[arrow].bottom<=b[c].top+2
|
||||||
|
)&&els.filter(e=>e.tagName==='SPAN').every(e=>e.scrollWidth<=e.clientWidth+1);
|
||||||
|
};
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
const {chromium}=require('playwright');
|
||||||
|
const staircaseFits=require('./presentation-staircase.cjs');
|
||||||
|
const fs=require('node:fs'); const assert=require('node:assert/strict');
|
||||||
|
(async()=>{
|
||||||
|
const base=process.argv[2]||'http://127.0.0.1:4179'; const root='/eldorado-v1/documentation/';const url=base+root+'presentations/less-prompting-more-shipping/';
|
||||||
|
const out='.cache/presentation';fs.mkdirSync(out,{recursive:true});
|
||||||
|
const browser=await chromium.launch({headless:true,args:['--no-sandbox'],executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE});
|
||||||
|
const results=[];
|
||||||
|
try{
|
||||||
|
for(const viewport of [{width:1440,height:900},{width:390,height:844},{width:844,height:390}]){
|
||||||
|
const context=await browser.newContext({viewport,hasTouch:viewport.width<1000,reducedMotion:'reduce'});
|
||||||
|
const page=await context.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message));page.on('response',r=>{if(r.status()>=400)errors.push(`${r.status()} ${r.url()}`)});page.on('console',m=>{if(m.type()==='error')errors.push(m.text())});
|
||||||
|
assert.equal((await page.goto(url,{waitUntil:'networkidle'})).status(),200);
|
||||||
|
await page.waitForFunction(()=>window.Reveal?.isReady());await page.evaluate(()=>document.fonts.ready);
|
||||||
|
assert.equal(await page.evaluate(()=>Reveal.getTotalSlides()),23);
|
||||||
|
assert.equal(await page.evaluate(()=>Reveal.getConfig().transition),'none');
|
||||||
|
const bounds=[];
|
||||||
|
for(let i=0;i<23;i++){
|
||||||
|
await page.evaluate(i=>Reveal.slide(i),i);await page.waitForTimeout(60);
|
||||||
|
const bad=await page.evaluate(()=>{
|
||||||
|
const slide=Reveal.getCurrentSlide(),r=slide.getBoundingClientRect();
|
||||||
|
return [...slide.querySelectorAll('.measurement-panels,.metric,.metric b,.metric span,.qualification-note,h3,svg,text,.journey,.learning-loop,.contribution-grid,h1,h2,p,li,td,th,.rail,.gate,.facts,.flow,.roles,.timeline,.capacity,.measure-list,.contrast,.comparison,.choices,.ledger')].filter(e=>!e.closest('.notes')&&e.getBoundingClientRect().width>0).filter(e=>{const b=e.getBoundingClientRect();return b.bottom>r.bottom+1||b.right>r.right+1||b.left<r.left-1||b.top<r.top-1}).map(e=>e.textContent.slice(0,60));
|
||||||
|
});
|
||||||
|
if(i===6)assert(await page.evaluate(staircaseFits),'staircase aligns each arrow with its intended steps');
|
||||||
|
if(i===4)assert(await page.evaluate(()=>[...document.querySelectorAll('#contributors .contribution-grid>div')].every(e=>{const a=e.querySelector('span').getBoundingClientRect(), arrow=e.querySelector('i').getBoundingClientRect(), b=e.querySelector('b').getBoundingClientRect();return a.bottom<=arrow.top+2&&arrow.bottom<=b.top+2&&Math.abs((a.left+a.right-b.left-b.right)/2)<2&&getComputedStyle(e.querySelector('i')).transform==='matrix(0, 1, -1, 0, 0, 0)'})),'contribution arrows must point down to their own phase');
|
||||||
|
bounds.push({slide:i+1,overflow:bad});
|
||||||
|
await page.screenshot({path:`${out}/${viewport.width}-slide-${String(i+1).padStart(2,'0')}.png`});
|
||||||
|
}
|
||||||
|
fs.writeFileSync(`${out}/${viewport.width}-bounds.json`,JSON.stringify(bounds,null,2));
|
||||||
|
assert.deepEqual(bounds.filter(b=>b.overflow.length),[],'slide overflow');
|
||||||
|
await page.goto(url+'#/qualification');await page.reload();await page.waitForFunction(()=>Reveal.isReady());assert.equal(await page.evaluate(()=>Reveal.getCurrentSlide().id),'qualification');
|
||||||
|
await page.keyboard.press('ArrowRight');assert.equal(await page.evaluate(()=>Reveal.getCurrentSlide().id),'experiment');await page.keyboard.press('ArrowLeft');
|
||||||
|
await page.getByRole('button',{name:'Overview',exact:true}).click();assert(await page.evaluate(()=>Reveal.isOverview()));await page.keyboard.press('Escape');assert(!await page.evaluate(()=>Reveal.isOverview()));
|
||||||
|
if(viewport.width===1440){
|
||||||
|
await page.getByRole('button',{name:'Fullscreen',exact:true}).click();await page.waitForFunction(()=>!!document.fullscreenElement);await page.getByRole('button',{name:'Fullscreen',exact:true}).click();await page.waitForFunction(()=>!document.fullscreenElement);
|
||||||
|
const popupPromise=context.waitForEvent('page');await page.getByRole('button',{name:'Notes',exact:true}).click();const popup=await popupPromise;await popup.waitForLoadState();await popup.waitForFunction(()=>document.body.innerText.includes('The author cannot approve'),{timeout:10000});await popup.screenshot({path:`${out}/speaker-view.png`});await popup.close();
|
||||||
|
} else {
|
||||||
|
const client=await context.newCDPSession(page);
|
||||||
|
const before=await page.evaluate(()=>Reveal.getIndices().h);
|
||||||
|
await client.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[{x:viewport.width*.8,y:viewport.height*.5}]});
|
||||||
|
await client.send('Input.dispatchTouchEvent',{type:'touchMove',touchPoints:[{x:viewport.width*.2,y:viewport.height*.5}]});
|
||||||
|
await client.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});
|
||||||
|
assert.equal(await page.evaluate(()=>Reveal.getIndices().h),before+1);
|
||||||
|
}
|
||||||
|
const links=await page.locator('a').evaluateAll(els=>els.map(e=>e.href).filter(h=>!h.includes('?')));
|
||||||
|
for(const link of new Set(links))assert.equal((await page.request.get(link)).status(),200,link);
|
||||||
|
await page.getByRole('link',{name:'Portal',exact:true}).click();await page.waitForURL(base+root);await page.getByRole('link',{name:/Open presentation/}).scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${viewport.width}-homepage.png`});await page.getByRole('link',{name:/Open presentation/}).click();await page.waitForFunction(()=>window.Reveal?.isReady());
|
||||||
|
assert.deepEqual(errors,[]);results.push({viewport,slides:23,overflow:false,errors,deepLinkRefresh:true,keyboard:true,overview:true,links:true,touch:viewport.width!==1440});await context.close();
|
||||||
|
}
|
||||||
|
const narrow=await browser.newPage({viewport:{width:320,height:720}});await narrow.goto(url,{waitUntil:'networkidle'});await narrow.evaluate(()=>document.fonts.ready);assert(await narrow.evaluate(()=>document.querySelector('.toolbar').scrollWidth<=innerWidth),'320px toolbar must not clip Print');await narrow.screenshot({path:out+'/320-toolbar.png'});await narrow.close();
|
||||||
|
const page=await browser.newPage({viewport:{width:1440,height:900}});await page.goto(url+'?print-pdf',{waitUntil:'networkidle'});await page.waitForFunction(()=>document.querySelectorAll('.pdf-page').length===23);await page.pdf({path:out+'/print.pdf',preferCSSPageSize:true,printBackground:true});
|
||||||
|
assert.equal(await page.locator('.pdf-page').count(),23);
|
||||||
|
fs.writeFileSync(`${out}/results.json`,JSON.stringify({results,printPages:23},null,2));console.log('PASS: 69 slide views, bounds, refresh/hash, keyboard, overview, touch, fullscreen, notes, all links, homepage, print');
|
||||||
|
}finally{await browser.close()}
|
||||||
|
})().catch(e=>{console.error(e);process.exitCode=1});
|
||||||
@@ -26,7 +26,7 @@ const views = {
|
|||||||
const ids=views[name];
|
const ids=views[name];
|
||||||
geometry.cards.sort((a,b)=>ids.indexOf(a.id)-ids.indexOf(b.id));
|
geometry.cards.sort((a,b)=>ids.indexOf(a.id)-ids.indexOf(b.id));
|
||||||
assert.deepEqual(geometry.cards.map(n => n.id), ids);
|
assert.deepEqual(geometry.cards.map(n => n.id), ids);
|
||||||
assert.deepEqual(geometry.cards.map(n => n.number), ids.length === 6 ? ids.map((_,i)=>`Step ${i+1}`) : name === 'strategy-roadmap' ? ['Stage 1','Stage 2'] : ['First','Then']);
|
assert.deepEqual(geometry.cards.map(n => n.number), ids.length === 6 ? ids.map((_,i)=>`Step ${i+1}`) : name === 'strategy-roadmap' ? ['Stage 1','Stage 2'] : ['First','If justified']);
|
||||||
assert.equal(geometry.edges.length,ids.length===6?6:1);
|
assert.equal(geometry.edges.length,ids.length===6?6:1);
|
||||||
if(ids.length===6) assert(geometry.edges.some(e=>e.id==='repeat'));
|
if(ids.length===6) assert(geometry.edges.some(e=>e.id==='repeat'));
|
||||||
for(const edge of geometry.edges) assert(edge.box.left>=0 && edge.box.right<=geometry.width+1 && edge.box.top>=0 && edge.box.bottom<=geometry.height+1, `clipped edge ${name} ${edge.id}`);
|
for(const edge of geometry.edges) assert(edge.box.left>=0 && edge.box.right<=geometry.width+1 && edge.box.top>=0 && edge.box.bottom<=geometry.height+1, `clipped edge ${name} ${edge.id}`);
|
||||||
@@ -60,8 +60,10 @@ const views = {
|
|||||||
for(const theme of ['light','dark']) {
|
for(const theme of ['light','dark']) {
|
||||||
const frameTop=await iframe.evaluate(n=>n.getBoundingClientRect().top+scrollY);
|
const frameTop=await iframe.evaluate(n=>n.getBoundingClientRect().top+scrollY);
|
||||||
await page.evaluate(y=>scrollTo({top:y-120,behavior:'instant'}),frameTop);
|
await page.evaluate(y=>scrollTo({top:y-120,behavior:'instant'}),frameTop);
|
||||||
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 page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme);
|
await frame.locator('#btn-theme').focus(); await page.keyboard.press('Enter');
|
||||||
|
}
|
||||||
|
await page.waitForFunction(t=>document.documentElement?.dataset.theme===t,theme);
|
||||||
const inline=await inspect(frame,name,width<1100);
|
const inline=await inspect(frame,name,width<1100);
|
||||||
await frame.locator('#btn-preset').focus();await page.keyboard.press('Enter');
|
await frame.locator('#btn-preset').focus();await page.keyboard.press('Enter');
|
||||||
await frame.locator('[data-preset-value="blueprint"]').focus();await page.keyboard.press('Enter');
|
await frame.locator('[data-preset-value="blueprint"]').focus();await page.keyboard.press('Enter');
|
||||||
@@ -91,7 +93,7 @@ const views = {
|
|||||||
const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
|
const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
|
||||||
const fullIframe=panel.locator('dialog iframe');
|
const fullIframe=panel.locator('dialog iframe');
|
||||||
const fullscreen=await (await fullIframe.elementHandle()).contentFrame();
|
const fullscreen=await (await fullIframe.elementHandle()).contentFrame();
|
||||||
await fullscreen.waitForFunction(t=>document.documentElement.dataset.theme===t,theme);
|
await fullscreen.waitForFunction(t=>document.documentElement?.dataset.theme===t,theme);
|
||||||
const expanded=await inspect(fullscreen,name,width<1000);
|
const expanded=await inspect(fullscreen,name,width<1000);
|
||||||
await page.screenshot({path:`${output}/${width}-${theme}-${name}-fullscreen.png`});
|
await page.screenshot({path:`${output}/${width}-${theme}-${name}-fullscreen.png`});
|
||||||
await close.focus();await page.keyboard.press('Escape');
|
await close.focus();await page.keyboard.press('Escape');
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const fs = require('node:fs');
|
|||||||
assert.equal(response.status(), 200);
|
assert.equal(response.status(), 200);
|
||||||
assert.equal(await page.locator('h1').innerText(), 'Roadmap');
|
assert.equal(await page.locator('h1').innerText(), 'Roadmap');
|
||||||
const headings = page.locator('.strategy-content > h2');
|
const headings = page.locator('.strategy-content > h2');
|
||||||
assert.deepEqual((await headings.allTextContents()).map(s => s.replace(/\u200b/g, '')), ['Two stages toward Target','Stage 1: Delivery first','Improve within each phase','Delivery in practice']);
|
assert.deepEqual((await headings.allTextContents()).map(s => s.replace(/\u200b/g, '')), ['Two stages toward the long-term Target','Stage 1: Delivery first','Improve within each phase','Delivery in practice']);
|
||||||
const text = await page.locator('.strategy-content').innerText();
|
const text = await page.locator('.strategy-content').innerText();
|
||||||
for (const marker of ['Humans direct, guide and review throughout', 'Delivery keeps improving', 'system-logic source', 'baseline', 'Target operating model']) assert(text.includes(marker), marker);
|
for (const marker of ['Humans direct, guide and review throughout', 'Delivery keeps improving', 'system-logic source', 'baseline', 'Target operating model']) assert(text.includes(marker), marker);
|
||||||
assert(!text.includes('Supporting gate evidence and hold conditions\n\nThese are'));
|
assert(!text.includes('Supporting gate evidence and hold conditions\n\nThese are'));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const fs = require('node:fs');
|
|||||||
if (width < 700) await page.getByRole('button', {name:'Toggle navigation bar'}).click();
|
if (width < 700) await page.getByRole('button', {name:'Toggle navigation bar'}).click();
|
||||||
const menu = page.locator('.theme-doc-sidebar-menu .menu__link').filter({visible:true});
|
const menu = page.locator('.theme-doc-sidebar-menu .menu__link').filter({visible:true});
|
||||||
await menu.first().waitFor({state:'visible'});
|
await menu.first().waitFor({state:'visible'});
|
||||||
assert.deepEqual(await menu.allTextContents(), ['Target', 'Roadmap', 'Stage - 01 - Skills Adoption', 'Stage - 02 - Autonomous Agent']);
|
assert.deepEqual(await menu.allTextContents(), ['Target', 'Roadmap', '6 Months Target', '6 Months Roadmap', 'Beyond 6 Months']);
|
||||||
assert((await menu.nth(0).getAttribute('href')).endsWith('/strategy/target-operating-model/'));
|
assert((await menu.nth(0).getAttribute('href')).endsWith('/strategy/target-operating-model/'));
|
||||||
assert((await menu.nth(1).getAttribute('href')).endsWith('/strategy/roadmap/'));
|
assert((await menu.nth(1).getAttribute('href')).endsWith('/strategy/roadmap/'));
|
||||||
assert.equal(await menu.filter({hasText:/^Target$/}).count(), 1);
|
assert.equal(await menu.filter({hasText:/^Target$/}).count(), 1);
|
||||||
@@ -33,7 +33,7 @@ const fs = require('node:fs');
|
|||||||
await page.getByRole('heading', {level:1,name:'Roadmap',exact:true}).waitFor();
|
await page.getByRole('heading', {level:1,name:'Roadmap',exact:true}).waitFor();
|
||||||
await page.goBack({waitUntil:'domcontentloaded'});
|
await page.goBack({waitUntil:'domcontentloaded'});
|
||||||
await page.waitForURL('**/strategy/target-operating-model/');
|
await page.waitForURL('**/strategy/target-operating-model/');
|
||||||
const iframe = page.locator(`.archify-panel--story > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
const iframe = page.locator(`[data-diagram="strategy-target"] > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
||||||
await iframe.scrollIntoViewIfNeeded();
|
await iframe.scrollIntoViewIfNeeded();
|
||||||
const frame = await (await iframe.elementHandle()).contentFrame();
|
const frame = await (await iframe.elementHandle()).contentFrame();
|
||||||
await frame.locator('svg[role="img"]').waitFor();
|
await frame.locator('svg[role="img"]').waitFor();
|
||||||
@@ -77,8 +77,9 @@ const fs = require('node:fs');
|
|||||||
}
|
}
|
||||||
assert(metrics.labels.every(n=>n.px>=14), JSON.stringify(metrics.labels));
|
assert(metrics.labels.every(n=>n.px>=14), JSON.stringify(metrics.labels));
|
||||||
assert.deepEqual(metrics.overflow, []);
|
assert.deepEqual(metrics.overflow, []);
|
||||||
await frame.locator('#btn-export').click();
|
await frame.locator('#btn-export').focus(); await page.keyboard.press('Enter');
|
||||||
const [download] = await Promise.all([page.waitForEvent('download'), frame.locator('[data-format="svg"]').click()]);
|
await frame.locator('[data-format="svg"]').focus();
|
||||||
|
const [download] = await Promise.all([page.waitForEvent('download'), page.keyboard.press('Enter')]);
|
||||||
assert.equal(await download.failure(), null);
|
assert.equal(await download.failure(), null);
|
||||||
const exportPath = `${output}/${width}-${route ? 'target' : 'landing'}.svg`;
|
const exportPath = `${output}/${width}-${route ? 'target' : 'landing'}.svg`;
|
||||||
await download.saveAs(exportPath);
|
await download.saveAs(exportPath);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const fs = require('node:fs');
|
|||||||
await page.waitForURL(`${base}/eldorado-v1/documentation/strategy/measurement/supported-bundle-coverage/`);
|
await page.waitForURL(`${base}/eldorado-v1/documentation/strategy/measurement/supported-bundle-coverage/`);
|
||||||
await page.getByRole('heading', {level:1, name:'Supported bundle coverage', exact:true}).waitFor();
|
await page.getByRole('heading', {level:1, name:'Supported bundle coverage', exact:true}).waitFor();
|
||||||
assert((await page.locator('article').innerText()).includes('Supported bundle coverage'));
|
assert((await page.locator('article').innerText()).includes('Supported bundle coverage'));
|
||||||
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'Stage - 01 - Skills Adoption'}).getAttribute('href'), '/eldorado-v1/documentation/strategy/stage-01-skills-adoption/');
|
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'6 Months Roadmap'}).getAttribute('href'), '/eldorado-v1/documentation/strategy/six-months-roadmap/');
|
||||||
assert((await page.locator('.breadcrumbs').innerText()).includes('Measurement'));
|
assert((await page.locator('.breadcrumbs').innerText()).includes('Measurement'));
|
||||||
await open();
|
await open();
|
||||||
await menu.getByRole('link', {name:'Supported bundle coverage', exact:true}).waitFor({state:'visible'});
|
await menu.getByRole('link', {name:'Supported bundle coverage', exact:true}).waitFor({state:'visible'});
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ const fs = require('node:fs');
|
|||||||
page.on('pageerror', error => errors.push(error.message));
|
page.on('pageerror', error => errors.push(error.message));
|
||||||
const response = await page.goto(`${base}/eldorado-v1/documentation/strategy/measurement/`, {waitUntil:'networkidle'});
|
const response = await page.goto(`${base}/eldorado-v1/documentation/strategy/measurement/`, {waitUntil:'networkidle'});
|
||||||
assert.equal(response.status(), 200);
|
assert.equal(response.status(), 200);
|
||||||
assert.equal(await page.locator('h1').innerText(), 'Skills Measurement');
|
assert.equal(await page.locator('h1').innerText(), 'Measuring real output');
|
||||||
assert((await page.title()).startsWith('Skills Measurement |'));
|
assert((await page.title()).startsWith('Measuring real output |'));
|
||||||
assert.equal(await page.locator('.strategy-content details').count(), 1);
|
assert.equal(await page.locator('.strategy-content details').count(), 1);
|
||||||
assert.equal(await page.locator('.strategy-content details[open]').count(), 0);
|
assert.equal(await page.locator('.strategy-content details[open]').count(), 0);
|
||||||
assert((await page.locator('.strategy-content details summary').innerText()).includes('Implementation status'));
|
assert((await page.locator('.strategy-content details summary').innerText()).includes('Implementation status'));
|
||||||
@@ -28,7 +28,7 @@ const fs = require('node:fs');
|
|||||||
const menu = page.locator('.theme-doc-sidebar-menu .menu__link').filter({visible:true});
|
const menu = page.locator('.theme-doc-sidebar-menu .menu__link').filter({visible:true});
|
||||||
await menu.first().waitFor({state:'visible'});
|
await menu.first().waitFor({state:'visible'});
|
||||||
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
||||||
assert.deepEqual(await menu.allTextContents(), ['Target','Roadmap','Stage - 01 - Skills Adoption','Measurement',...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example','Baseline','Governance','Quality','Adoption','Maintenance','Stage - 02 - Autonomous Agent']);
|
assert.deepEqual(await menu.allTextContents(), ['Target','Roadmap','6 Months Target','6 Months Roadmap','Skills lifecycle reference','Measurement',...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example','Baseline','Governance','Quality','Adoption','Maintenance','Beyond 6 Months']);
|
||||||
if (width < 700) await page.getByRole('button', {name:'Close navigation bar'}).click();
|
if (width < 700) await page.getByRole('button', {name:'Close navigation bar'}).click();
|
||||||
const panel = page.locator('.archify-panel--story');
|
const panel = page.locator('.archify-panel--story');
|
||||||
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
|
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ const assert=require('node:assert/strict');
|
|||||||
const out=`.cache/skills-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true});
|
const out=`.cache/skills-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true});
|
||||||
const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']}); const results=[];
|
const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']}); const results=[];
|
||||||
try {
|
try {
|
||||||
for(const topic of ['measurement','baseline','governance','quality','adoption','maintenance','stage01','stage02']) for(const width of [1440,1024,390,320]) {
|
for(const topic of ['six-months','measurement','baseline','governance','quality','adoption','maintenance','stage01','stage02']) for(const width of [1440,1024,390,320]) {
|
||||||
console.log(`Checking ${topic} at ${width}px`);
|
console.log(`Checking ${topic} at ${width}px`);
|
||||||
const page=await browser.newPage({viewport:{width,height:900},colorScheme:'light'});const errors=[];page.on('pageerror',e=>errors.push(e.message));
|
const page=await browser.newPage({viewport:{width,height:900},colorScheme:'light'});const errors=[];page.on('pageerror',e=>errors.push(e.message));
|
||||||
const route=topic==='stage01'?'stage-01-skills-adoption':topic==='stage02'?'stage-02-autonomous-agent':['measurement','baseline'].includes(topic)?topic:`skills-${topic}`;
|
const route=topic==='six-months'?'six-months-roadmap':topic==='stage01'?'stage-01-skills-adoption':topic==='stage02'?'stage-02-autonomous-agent':['measurement','baseline'].includes(topic)?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>1100?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded();
|
const iframe=panel.locator(width>1100?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded();
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ const fs = require('node:fs');
|
|||||||
const output = `.cache/strategy-navigation-${process.argv[3] || 'local'}`;
|
const output = `.cache/strategy-navigation-${process.argv[3] || 'local'}`;
|
||||||
fs.mkdirSync(output, {recursive:true});
|
fs.mkdirSync(output, {recursive:true});
|
||||||
const prefix = '/eldorado-v1/documentation/strategy/';
|
const prefix = '/eldorado-v1/documentation/strategy/';
|
||||||
const first = 'Stage - 01 - Skills Adoption';
|
const first = '6 Months Roadmap';
|
||||||
const second = 'Stage - 02 - Autonomous Agent';
|
const second = 'Beyond 6 Months';
|
||||||
const topics = ['Measurement','Baseline','Governance','Quality','Adoption','Maintenance'];
|
const topics = ['Skills lifecycle reference','Measurement','Baseline','Governance','Quality','Adoption','Maintenance'];
|
||||||
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
||||||
const childIds = [...metrics.map(m => m.docId),'measurement/collection-and-safeguards','measurement/synthetic-example'];
|
const childIds = [...metrics.map(m => m.docId),'measurement/collection-and-safeguards','measurement/synthetic-example'];
|
||||||
const childTitles = [...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example'];
|
const childTitles = [...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example'];
|
||||||
const ids = ['target-operating-model','roadmap','stage-01-skills-adoption','measurement',...childIds,'baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance','stage-02-autonomous-agent'];
|
const ids = ['target-operating-model','roadmap','six-months-target','six-months-roadmap','stage-01-skills-adoption','measurement',...childIds,'baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance','stage-02-autonomous-agent'];
|
||||||
const titles = ['Target','Roadmap',first,'Skills Measurement',...childTitles,'Baseline','Skills governance','Skills quality','Skills adoption','Skills maintenance',second];
|
const titles = ['Target','Roadmap','6 Months Target',first,'Skills lifecycle reference','Measuring real output',...childTitles,'Baseline','Skills governance','Skills quality','Skills adoption','Skills maintenance',second];
|
||||||
const browser = await chromium.launch({headless:true, executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args:['--no-sandbox']});
|
const browser = await chromium.launch({headless:true, executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args:['--no-sandbox']});
|
||||||
const results = [];
|
const results = [];
|
||||||
try {
|
try {
|
||||||
@@ -35,26 +35,26 @@ const fs = require('node:fs');
|
|||||||
assert.equal((await page.goto(`${base}${prefix}roadmap/`, {waitUntil:'networkidle'})).status(), 200);
|
assert.equal((await page.goto(`${base}${prefix}roadmap/`, {waitUntil:'networkidle'})).status(), 200);
|
||||||
let menu = await openMenu();
|
let menu = await openMenu();
|
||||||
const visibleLabels = () => menu.locator('.menu__link').filter({visible:true}).allTextContents();
|
const visibleLabels = () => menu.locator('.menu__link').filter({visible:true}).allTextContents();
|
||||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,second]);
|
assert.deepEqual(await visibleLabels(), ['Target','Roadmap','6 Months Target',first,second]);
|
||||||
const category = menu.locator('.theme-doc-sidebar-item-category').filter({has:page.getByRole('link', {name:first, exact:true})});
|
const category = menu.locator('.theme-doc-sidebar-item-category').filter({has:page.getByRole('link', {name:first, exact:true})});
|
||||||
const caret = category.locator(':scope > .menu__list-item-collapsible > button.menu__caret');
|
const caret = category.locator(':scope > .menu__list-item-collapsible > button.menu__caret');
|
||||||
await caret.click();
|
await caret.click();
|
||||||
await category.getByRole('link', {name:'Governance', exact:true}).waitFor({state:'visible'});
|
await category.getByRole('link', {name:'Governance', exact:true}).waitFor({state:'visible'});
|
||||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,...topics,second]);
|
assert.deepEqual(await visibleLabels(), ['Target','Roadmap','6 Months Target',first,...topics,second]);
|
||||||
assert.deepEqual(await category.locator('ul .menu__link').filter({visible:true}).allTextContents(), topics);
|
assert.deepEqual(await category.locator('ul .menu__link').filter({visible:true}).allTextContents(), topics);
|
||||||
const measurement = category.locator('.theme-doc-sidebar-item-category').filter({has:page.getByRole('link', {name:'Measurement', exact:true})});
|
const measurement = category.locator('.theme-doc-sidebar-item-category').filter({has:page.getByRole('link', {name:'Measurement', exact:true})});
|
||||||
const reference = measurement.locator(':scope > .menu__list-item-collapsible > button.menu__caret');
|
const reference = measurement.locator(':scope > .menu__list-item-collapsible > button.menu__caret');
|
||||||
await reference.focus();
|
await reference.focus();
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
await category.getByRole('link', {name:'Validated task success', exact:true}).waitFor({state:'visible'});
|
await category.getByRole('link', {name:'Validated task success', exact:true}).waitFor({state:'visible'});
|
||||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,topics[0],...childTitles,...topics.slice(1),second]);
|
assert.deepEqual(await visibleLabels(), ['Target','Roadmap','6 Months Target',first,...topics.slice(0,2),...childTitles,...topics.slice(2),second]);
|
||||||
await reference.click();
|
await reference.click();
|
||||||
await page.screenshot({path:`${output}/${width}-expanded.png`, animations:'disabled'});
|
await page.screenshot({path:`${output}/${width}-expanded.png`, animations:'disabled'});
|
||||||
await caret.click();
|
await caret.click();
|
||||||
await category.getByRole('link', {name:'Governance', exact:true}).waitFor({state:'hidden'});
|
await category.getByRole('link', {name:'Governance', exact:true}).waitFor({state:'hidden'});
|
||||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,second]);
|
assert.deepEqual(await visibleLabels(), ['Target','Roadmap','6 Months Target',first,second]);
|
||||||
await menu.getByRole('link', {name:first, exact:true}).click();
|
await menu.getByRole('link', {name:first, exact:true}).click();
|
||||||
await page.waitForURL(`${base}${prefix}stage-01-skills-adoption/`);
|
await page.waitForURL(`${base}${prefix}six-months-roadmap/`);
|
||||||
await page.getByRole('heading', {level:1, name:first, exact:true}).waitFor();
|
await page.getByRole('heading', {level:1, name:first, exact:true}).waitFor();
|
||||||
assert.equal(await page.locator('h1').innerText(), first);
|
assert.equal(await page.locator('h1').innerText(), first);
|
||||||
assert((await page.locator('article').innerText()).includes('Delivery first'));
|
assert((await page.locator('article').innerText()).includes('Delivery first'));
|
||||||
@@ -64,19 +64,18 @@ const fs = require('node:fs');
|
|||||||
assert.equal((await page.goto(`${base}${prefix}${id}/`, {waitUntil:'networkidle'})).status(), 200);
|
assert.equal((await page.goto(`${base}${prefix}${id}/`, {waitUntil:'networkidle'})).status(), 200);
|
||||||
assert.equal(new URL(page.url()).pathname, `${prefix}${id}/`);
|
assert.equal(new URL(page.url()).pathname, `${prefix}${id}/`);
|
||||||
// Target has a longer canonical page heading but keeps its short navigation label.
|
// Target has a longer canonical page heading but keeps its short navigation label.
|
||||||
if (index) assert.equal(await page.locator('h1').innerText(), titles[index]);
|
assert.equal(await page.locator('h1').innerText(), titles[index]);
|
||||||
else assert((await page.locator('h1').innerText()).includes('Target'));
|
|
||||||
const prev = page.locator('.pagination-nav__link--prev');
|
const prev = page.locator('.pagination-nav__link--prev');
|
||||||
const next = page.locator('.pagination-nav__link--next');
|
const next = page.locator('.pagination-nav__link--next');
|
||||||
if (index) assert.equal(await prev.getAttribute('href'), `${prefix}${id === 'baseline' ? 'measurement' : ids[index-1]}/`);
|
if (index) assert.equal(await prev.getAttribute('href'), `${prefix}${id === 'baseline' ? 'measurement' : ids[index-1]}/`);
|
||||||
else assert.equal(await prev.count(), 0);
|
else assert.equal(await prev.count(), 0);
|
||||||
if (index < ids.length-1) assert.equal(await next.getAttribute('href'), `${prefix}${id === 'measurement' ? 'baseline' : ids[index+1]}/`);
|
if (index < ids.length-1) assert.equal(await next.getAttribute('href'), `${prefix}${id === 'measurement' ? 'baseline' : ids[index+1]}/`);
|
||||||
else assert.equal(await next.count(), 0);
|
else assert.equal(await next.count(), 0);
|
||||||
if (index >= 3 && index < ids.length - 1) {
|
if (index >= 4 && index < ids.length - 1) {
|
||||||
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:first}).getAttribute('href'), `${prefix}stage-01-skills-adoption/`);
|
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:first}).getAttribute('href'), `${prefix}six-months-roadmap/`);
|
||||||
menu = await openMenu();
|
menu = await openMenu();
|
||||||
const expectedTopics = id === 'measurement' || id.startsWith('measurement/') ? [topics[0],...childTitles,...topics.slice(1)] : topics;
|
const expectedTopics = id === 'measurement' || id.startsWith('measurement/') ? [...topics.slice(0,2),...childTitles,...topics.slice(2)] : topics;
|
||||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,...expectedTopics,second]);
|
assert.deepEqual(await visibleLabels(), ['Target','Roadmap','6 Months Target',first,...expectedTopics,second]);
|
||||||
if (id.startsWith('measurement/')) assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'Measurement'}).getAttribute('href'), `${prefix}measurement/`);
|
if (id.startsWith('measurement/')) assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'Measurement'}).getAttribute('href'), `${prefix}measurement/`);
|
||||||
await closeMenu();
|
await closeMenu();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const fs=require('node:fs');
|
|||||||
assert.equal(geometry.nodes.length,(source.components||source.nodes).length,id);
|
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'?1600:id==='roadmap'?600:550),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
|
assert(data.words<=(id==='measurement'?1900:id==='roadmap'?1150:['index','target-operating-model'].includes(id)?850:750),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
|
||||||
await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true});
|
await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true});
|
||||||
const opener=panel.getByRole('button',{name:/^Expand /});await opener.click();
|
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'});
|
const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ function inspectTypography({mobile}) {
|
|||||||
for (const width of [1440,390,320]) {
|
for (const width of [1440,390,320]) {
|
||||||
const page = await browser.newPage({viewport:{width,height:1000}});
|
const page = await browser.newPage({viewport:{width,height:1000}});
|
||||||
await page.goto(`${base}/eldorado-v1/documentation/strategy/target-operating-model/`,{waitUntil:'networkidle'});
|
await page.goto(`${base}/eldorado-v1/documentation/strategy/target-operating-model/`,{waitUntil:'networkidle'});
|
||||||
|
await page.addStyleTag({content:'html {scroll-behavior:auto !important;}'});
|
||||||
const panel = page.locator('[data-diagram="strategy-target"]');
|
const panel = page.locator('[data-diagram="strategy-target"]');
|
||||||
const iframe = panel.locator(`:scope > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
const iframe = panel.locator(`:scope > .story-${width > 700 ? 'desktop' : 'mobile'}`);
|
||||||
await iframe.scrollIntoViewIfNeeded();
|
await iframe.scrollIntoViewIfNeeded();
|
||||||
@@ -141,10 +142,11 @@ function inspectTypography({mobile}) {
|
|||||||
await page.screenshot({path:`${output}/${width}-inline.png`,fullPage:true});
|
await page.screenshot({path:`${output}/${width}-inline.png`,fullPage:true});
|
||||||
const exported = [];
|
const exported = [];
|
||||||
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').focus(); await page.keyboard.press('Enter');}
|
||||||
await frame.waitForFunction(t => document.documentElement.dataset.theme === t, theme);
|
await frame.waitForFunction(t => document.documentElement.dataset.theme === t, theme);
|
||||||
await frame.locator('#btn-export').click();
|
await frame.locator('#btn-export').focus(); await page.keyboard.press('Enter');
|
||||||
const [download] = await Promise.all([page.waitForEvent('download'),frame.locator('[data-format="svg"]').click()]);
|
await frame.locator('[data-format="svg"]').focus();
|
||||||
|
const [download] = await Promise.all([page.waitForEvent('download'),page.keyboard.press('Enter')]);
|
||||||
assert.equal(await download.failure(),null);
|
assert.equal(await download.failure(),null);
|
||||||
const path = `${output}/${width}-${theme}.svg`;
|
const path = `${output}/${width}-${theme}.svg`;
|
||||||
await download.saveAs(path);
|
await download.saveAs(path);
|
||||||
@@ -157,6 +159,10 @@ function inspectTypography({mobile}) {
|
|||||||
const typography = await standalone.evaluate(inspectTypography,{mobile:width < 700});
|
const typography = await standalone.evaluate(inspectTypography,{mobile:width < 700});
|
||||||
assert.deepEqual(geometry.errors,[]);
|
assert.deepEqual(geometry.errors,[]);
|
||||||
assert.deepEqual(typography.errors,[]);
|
assert.deepEqual(typography.errors,[]);
|
||||||
|
assert(await standalone.locator('#eldorado-target-caption').evaluate(g=>{
|
||||||
|
const v=g.ownerSVGElement.viewBox.baseVal;
|
||||||
|
return [...g.querySelectorAll('text')].every(t=>{const b=t.getBBox();return b.x>=v.x&&b.y>=v.y&&b.x+b.width<=v.x+v.width&&b.y+b.height<=v.y+v.height;});
|
||||||
|
}), 'Standalone proposed caption must fit the complete canvas');
|
||||||
const background = await standalone.locator('rect.c-bg-rect').evaluate(n => getComputedStyle(n).fill);
|
const background = await standalone.locator('rect.c-bg-rect').evaluate(n => getComputedStyle(n).fill);
|
||||||
if (exported.length) assert.notEqual(background,exported[0].background,'standalone theme must change');
|
if (exported.length) assert.notEqual(background,exported[0].background,'standalone theme must change');
|
||||||
// CDP captures SVG documents without Playwright's HTML-body screenshot wait.
|
// CDP captures SVG documents without Playwright's HTML-body screenshot wait.
|
||||||
@@ -167,7 +173,7 @@ function inspectTypography({mobile}) {
|
|||||||
exported.push({theme,background,geometry,typography});
|
exported.push({theme,background,geometry,typography});
|
||||||
await standalone.close();
|
await standalone.close();
|
||||||
}
|
}
|
||||||
await panel.getByRole('button',{name:/^Expand /}).click();
|
await panel.getByRole('button',{name:/^Expand /}).focus(); await page.keyboard.press('Enter');
|
||||||
const full = await (await panel.locator('dialog iframe').elementHandle()).contentFrame();
|
const full = await (await panel.locator('dialog iframe').elementHandle()).contentFrame();
|
||||||
await full.locator('svg[role="img"]').waitFor();
|
await full.locator('svg[role="img"]').waitFor();
|
||||||
// The existing fullscreen viewer always opens the radial desktop source.
|
// The existing fullscreen viewer always opens the radial desktop source.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {execFileSync} from 'node:child_process';
|
|||||||
import {skillsViewer, isSkillsStory} from './skills-viewer.mjs';
|
import {skillsViewer, isSkillsStory} from './skills-viewer.mjs';
|
||||||
import {roadmapViewer} from './roadmap-viewer.mjs';
|
import {roadmapViewer} from './roadmap-viewer.mjs';
|
||||||
import {targetRouting} from './target-routing.mjs';
|
import {targetRouting} from './target-routing.mjs';
|
||||||
|
import {targetCaption} from './target-caption.mjs';
|
||||||
import {createHash} from 'node:crypto';
|
import {createHash} from 'node:crypto';
|
||||||
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']);
|
||||||
@@ -43,6 +44,7 @@ for (const file of readdirSync('diagrams').sort()) {
|
|||||||
// Verify the upstream artifact first, then add the scoped portal integration.
|
// Verify the upstream artifact first, then add the scoped portal integration.
|
||||||
let viewer = readFileSync(output, 'utf8');
|
let viewer = readFileSync(output, 'utf8');
|
||||||
if (name === 'strategy-target') viewer = targetRouting(viewer);
|
if (name === 'strategy-target') viewer = targetRouting(viewer);
|
||||||
|
if (/^strategy-target(-mobile)?$/.test(name)) viewer = targetCaption(viewer);
|
||||||
// Upstream intentionally disables preset selection in gallery embeds. Enable
|
// Upstream intentionally disables preset selection in gallery embeds. Enable
|
||||||
// only those two guards; fail closed if a future vendor update changes them.
|
// only those two guards; fail closed if a future vendor update changes them.
|
||||||
const start = viewer.indexOf('Archify.preset = (function () {');
|
const start = viewer.indexOf('Archify.preset = (function () {');
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import {mkdir,copyFile,writeFile,readFile} from 'node:fs/promises';
|
||||||
|
import {createHash} from 'node:crypto';
|
||||||
|
import {slides} from '../presentations/less-prompting-more-shipping/slides.mjs';
|
||||||
|
const root='presentations/less-prompting-more-shipping';
|
||||||
|
const out=`static/${root}`;
|
||||||
|
await mkdir(`${out}/assets`,{recursive:true});
|
||||||
|
for(const [src,dest] of [['dist/reveal.js','reveal.js'],['dist/reveal.css','reveal.css'],['plugin/notes/notes.js','notes.js'],['LICENSE','REVEAL-LICENSE']]) await copyFile(`node_modules/reveal.js/${src}`,`${out}/assets/${dest}`);
|
||||||
|
for(const weight of [400,700,900]) await copyFile(`node_modules/@fontsource/lato/files/lato-latin-${weight}-normal.woff2`,`${out}/assets/lato-latin-${weight}-normal.woff2`);
|
||||||
|
await copyFile('node_modules/@fontsource/lato/LICENSE',`${out}/assets/LATO-LICENSE`);
|
||||||
|
await copyFile(`${root}/theme.css`,`${out}/theme.css`);
|
||||||
|
const esc=s=>s.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('"','"');
|
||||||
|
await writeFile(`${out}/index.html`,`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="The autonomous SDLC destination and an evidence-led first-six-month contribution."><title>Less Prompting, More Shipping | Eldorado</title><link rel="icon" href="data:,"><link rel="stylesheet" href="./assets/reveal.css"><link rel="stylesheet" href="./theme.css"></head><body>
|
||||||
|
<nav class="toolbar" aria-label="Presentation tools"><a href="../../">Portal</a><a href="../../strategy/target-operating-model/">Strategy</a><button id="overview" type="button">Overview</button><button id="notes" type="button">Notes</button><button id="fullscreen" type="button">Fullscreen</button><a href="?print-pdf">Print</a><span class="help">← → navigate · Esc overview · S notes · F fullscreen</span></nav>
|
||||||
|
<div class="reveal deck"><div class="slides">${slides.map((s,i)=>`<section id="${s.id}" class="${s.kind}" data-timing="${s.minutes*60}" ${s.kind==='dark'?'data-background-color="#1f1f29"':''}><p class="eyebrow">ELDORADO / ${esc(s.section.toUpperCase())}</p><${i?'h2':'h1'}>${s.title}</${i?'h2':'h1'}>${s.body}<aside class="notes"><p><strong>${s.minutes} minutes.</strong> ${esc(s.notes)}</p><p>Sources: ${esc(s.sources.join('; '))}.</p></aside></section>`).join('\n')}</div></div>
|
||||||
|
<script src="./assets/reveal.js"></script><script src="./assets/notes.js"></script><script src="./runtime.js"></script></body></html>`);
|
||||||
|
await copyFile(`${root}/runtime.js`,`${out}/runtime.js`);
|
||||||
|
const sourceDocuments = await Promise.all([...new Set(slides.flatMap(s=>s.sources).filter(s=>!s.startsWith('PDF:')))].sort().map(async id=>{
|
||||||
|
const path=`docs/strategy/${id==='measurement'?'measurement/index':id}.mdx`;
|
||||||
|
return {id,path,route:`/strategy/${id}/`,sha256:createHash('sha256').update(await readFile(path)).digest('hex')};
|
||||||
|
}));
|
||||||
|
const assignmentQuestions = [
|
||||||
|
{question:'1. What you do',slides:['starting-point','influence','months-one-two','months-three-four','months-five-six','capacity']},
|
||||||
|
{question:'2. How you measure it',slides:['measures','misleading','qualification','experiment']},
|
||||||
|
{question:'3. What you achieve',slides:['six-month-target','month-six']},
|
||||||
|
{question:'4. What comes next',slides:['target','contributors','roadmap','learning-loop','beyond','authority']},
|
||||||
|
];
|
||||||
|
const diagramSources = await Promise.all(['diagrams/strategy-target.architecture.json','diagrams/strategy-target-mobile.architecture.json'].map(async path=>({path,sha256:createHash('sha256').update(await readFile(path)).digest('hex')})));
|
||||||
|
await writeFile(`${out}/source-map.json`,JSON.stringify({version:'1.1.0',assignmentQuestions,diagramSources,strategyRevision:'same-build; exact source hashes below; deployed revision in ../../revision.txt',strategyOrigins:{longTerm:'88a43757762114a506f57ed4b44484306cae1aaa',assignment:'fcaa84f3bf9058f4ede0a097d16d0e3571590a6b',horizonCorrection:'1557813737941901572'},sourceDocuments,assignment:'AI_Architect_Test_Task.pdf',talkMinutes:slides.filter(s=>s.track==='main').reduce((a,s)=>a+s.minutes,0),discussionMinutes:slides.filter(s=>s.track==='discussion').reduce((a,s)=>a+s.minutes,0),appendixMinutes:0,timingNote:'Revised presentation allocation; PDF specifies 50 total, not the split. The six-month Strategy page retains its earlier proposed outline.',slides:slides.map(({id,title,minutes,sources,section,track},i)=>({number:i+1,id,title,minutes,section,track,sources:[...new Set(sources)]}))},null,2));
|
||||||
|
console.log(`Built ${slides.length} local Reveal.js slides at ${out}`);
|
||||||
@@ -7,9 +7,9 @@ const coverage=JSON.parse(read('research/ai-adoption/strategy-coverage.json')).r
|
|||||||
|
|
||||||
test('connected Strategy covers every canonical route and reader handoff',()=>{
|
test('connected Strategy covers every canonical route and reader handoff',()=>{
|
||||||
const files=readdirSync('docs/strategy',{recursive:true}).filter(p=>p.endsWith('.mdx')).map(p=>'docs/strategy/'+p).sort();
|
const files=readdirSync('docs/strategy',{recursive:true}).filter(p=>p.endsWith('.mdx')).map(p=>'docs/strategy/'+p).sort();
|
||||||
assert.equal(coverage.length,28);
|
assert.equal(coverage.length,30);
|
||||||
assert.deepEqual(coverage.map(r=>r.source).sort(),files);
|
assert.deepEqual(coverage.map(r=>r.source).sort(),files);
|
||||||
assert.equal(new Set(coverage.map(r=>r.route)).size,28);
|
assert.equal(new Set(coverage.map(r=>r.route)).size,30);
|
||||||
for(const r of coverage){
|
for(const r of coverage){
|
||||||
for(const k of ['question','inputs','action_or_decision','output','next_or_feedback','review'])assert(r[k],`${r.source}: ${k}`);
|
for(const k of ['question','inputs','action_or_decision','output','next_or_feedback','review'])assert(r[k],`${r.source}: ${k}`);
|
||||||
const page=read(r.source);assert(!/roadmap gates|Evidence-gated phases/.test(page),r.source);
|
const page=read(r.source);assert(!/roadmap gates|Evidence-gated phases/.test(page),r.source);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import {test} from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
import {createHash} from 'node:crypto';
|
||||||
|
const read=p=>readFileSync(p,'utf8');
|
||||||
|
const slugs=['product','technology','operations','marketing','finance-accounting','hr-administration'];
|
||||||
|
test('all six department bodies are preserved exactly and absent from overview',()=>{
|
||||||
|
const manifest=JSON.parse(read('research/organization/department-migration.json'));
|
||||||
|
assert.deepEqual(manifest.departments.map(d=>d.slug),slugs);
|
||||||
|
const overview=read('docs/organization/structure.mdx');
|
||||||
|
for(const d of manifest.departments){
|
||||||
|
const page=read(`docs/organization/structure/${d.slug}.mdx`);
|
||||||
|
const body=page.replace(/^---\n[\s\S]*?\n---\n/, '').split('[Return to Structure overview]')[0].trim();
|
||||||
|
assert.equal(createHash('sha256').update(body).digest('hex'),d.bodySha256,d.slug);
|
||||||
|
assert(!overview.includes(body));
|
||||||
|
assert(overview.includes(`./structure/${d.slug}.mdx`));
|
||||||
|
assert(page.includes('(../structure.mdx)'));
|
||||||
|
}
|
||||||
|
assert.deepEqual(manifest.departments.map(d=>d.rows),[2,5,4,6,3,3]);
|
||||||
|
});
|
||||||
|
test('Structure is a linked category with six direct children and preserved peers',()=>{
|
||||||
|
const sidebar=read('sidebars/organization.ts');
|
||||||
|
assert(sidebar.includes("link: {type: 'doc', id: 'structure'}"));
|
||||||
|
assert.deepEqual([...sidebar.matchAll(/'structure\/([^']+)'/g)].map(m=>m[1]),slugs);
|
||||||
|
assert(sidebar.includes("'collaboration', 'sdlc'"));
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
import vm from 'node:vm';
|
||||||
|
function runtime(search) {
|
||||||
|
let config; const classes=new Set(); const links=[{}];
|
||||||
|
const document={documentElement:{classList:{toggle:(name,on)=>on?classes.add(name):classes.delete(name)}},getElementById:()=>({addEventListener(){},hidden:false}),querySelector:()=>({hidden:false}),querySelectorAll:()=>links,hasFocus:()=>true};
|
||||||
|
const window={matchMedia:()=>({matches:false,addEventListener(){}})};
|
||||||
|
vm.runInNewContext(read('presentations/less-prompting-more-shipping/runtime.js'),{window,document,location:{search},URLSearchParams,RevealNotes:{},Reveal:{initialize:c=>{config=c;},configure(){}}});
|
||||||
|
return {config,classes,links};
|
||||||
|
}
|
||||||
|
test('embed isolates URL, focus and deck links without autoplay; print stays standalone',()=>{
|
||||||
|
const embed=runtime('?embed');
|
||||||
|
assert.equal(embed.config.hash,false);
|
||||||
|
assert.equal(embed.config.embedded,true);
|
||||||
|
assert.equal(embed.config.autoSlide,0);
|
||||||
|
assert.equal(embed.config.keyboard[70],null);
|
||||||
|
assert.equal(embed.config.keyboard[83],null);
|
||||||
|
assert.equal(typeof embed.config.keyboardCondition,'function');
|
||||||
|
assert(embed.classes.has('embedded'));
|
||||||
|
assert.equal(embed.links[0].target,'_top');
|
||||||
|
for(const query of ['', '?print-pdf', '?embed&print-pdf']) {
|
||||||
|
const {config,classes}=runtime(query);
|
||||||
|
assert.equal(config.hash,true);assert(!classes.has('embedded'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const read=p=>readFileSync(p,'utf8');
|
||||||
|
test('homepage replaces teaser with titled single-source playable stage below existing cards',()=>{
|
||||||
|
const home=read('src/pages/index.tsx');
|
||||||
|
assert.match(home,/<div className="section-heading"><div><h2 id="presentation-title">Understand In Speed<\/h2>/);
|
||||||
|
assert(home.indexOf('Understand In Speed')>home.indexOf('Shaping the direction.'));
|
||||||
|
assert.match(home,/<PresentationEmbed/);
|
||||||
|
assert(!home.includes('35-minute presentation'));
|
||||||
|
const component=read('src/components/PresentationEmbed/index.tsx');
|
||||||
|
assert.match(component,/<iframe/);assert.match(component,/title=/);assert.match(component,/\?embed/);
|
||||||
|
assert.match(component,/allowFullScreen/);
|
||||||
|
});
|
||||||
@@ -43,7 +43,7 @@ test('three independent section menus and Structure first', () => {
|
|||||||
for (const section of ['Organization', 'Strategy', 'Contribution']) assert(config.includes(`label: '${section}'`));
|
for (const section of ['Organization', 'Strategy', 'Contribution']) assert(config.includes(`label: '${section}'`));
|
||||||
assert(!config.includes("label: 'Documentation'"));
|
assert(!config.includes("label: 'Documentation'"));
|
||||||
assert(!config.includes("label: 'Maintainer guide'"));
|
assert(!config.includes("label: 'Maintainer guide'"));
|
||||||
assert(read('sidebars/organization.ts').includes("organizationSidebar: ['structure', 'collaboration', 'sdlc']"));
|
assert(read('sidebars/organization.ts').includes("link: {type: 'doc', id: 'structure'}"));
|
||||||
for (const section of ['organization','strategy','contribution']) assert(config.includes(`id: '${section}'`));
|
for (const section of ['organization','strategy','contribution']) assert(config.includes(`id: '${section}'`));
|
||||||
});
|
});
|
||||||
test('Archify is pinned, licensed and rebuilt, not a remote embed', () => {
|
test('Archify is pinned, licensed and rebuilt, not a remote embed', () => {
|
||||||
@@ -83,7 +83,7 @@ test('Product owns two teams and Technology owns five separate teams', () => {
|
|||||||
for (const [dept, count, heading, next] of [['product',2,'Product','Technology'],['technology',5,'Technology','Operations']]) {
|
for (const [dept, count, heading, next] of [['product',2,'Product','Technology'],['technology',5,'Technology','Operations']]) {
|
||||||
const teams = spec.components.filter(n => n.id.startsWith(`${dept}-team-`));
|
const teams = spec.components.filter(n => n.id.startsWith(`${dept}-team-`));
|
||||||
assert.equal(teams.length, count);
|
assert.equal(teams.length, count);
|
||||||
const section = page.split(`### ${heading}\n`)[1].split(`### ${next}\n`)[0];
|
const section = read(`docs/organization/structure/${dept}.mdx`);
|
||||||
const rows = section.split('\n').filter(l => l.startsWith('| ')).slice(2);
|
const rows = section.split('\n').filter(l => l.startsWith('| ')).slice(2);
|
||||||
assert.equal(rows.length, count);
|
assert.equal(rows.length, count);
|
||||||
for (const team of teams) {
|
for (const team of teams) {
|
||||||
@@ -112,7 +112,7 @@ test('departments share one row and each has delivery teams below it', () => {
|
|||||||
assert.equal(edge.fromSide, 'bottom');
|
assert.equal(edge.fromSide, 'bottom');
|
||||||
assert.equal(spec.connections.find(e => e.from === 'management' && e.to === id).toSide, 'top');
|
assert.equal(spec.connections.find(e => e.from === 'management' && e.to === id).toSide, 'top');
|
||||||
assert.deepEqual(spec.connections.filter(e => e.to === team.id).map(e => e.from), [id]);
|
assert.deepEqual(spec.connections.filter(e => e.to === team.id).map(e => e.from), [id]);
|
||||||
assert(page.includes(team.label));
|
assert(read(`docs/organization/structure/${({finance:'finance-accounting',people:'hr-administration'})[id] || id}.mdx`).includes(team.label));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const [i, a] of spec.components.entries()) for (const b of spec.components.slice(i + 1)) {
|
for (const [i, a] of spec.components.entries()) for (const b of spec.components.slice(i + 1)) {
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
import {createHash} from 'node:crypto';
|
||||||
|
import {execFileSync} from 'node:child_process';
|
||||||
|
import {slides} from '../presentations/less-prompting-more-shipping/slides.mjs';
|
||||||
|
const read=p=>readFileSync(p,'utf8');
|
||||||
|
test('deck preserves assignment coverage, 35+15 timing and traceable notes',()=>{
|
||||||
|
assert.equal(slides.length,23); assert.equal(new Set(slides.map(s=>s.id)).size,23);
|
||||||
|
assert.equal(slides.filter(s=>s.track==='main').reduce((n,s)=>n+s.minutes,0),35);
|
||||||
|
assert.equal(slides.find(s=>s.track==='discussion').minutes,15); assert.equal(slides.find(s=>s.track==='appendix').minutes,0);
|
||||||
|
for(const s of slides){assert(s.sources.length);assert(s.notes.length>250);assert(s.body.length);}
|
||||||
|
for(const id of ['months-one-two','months-three-four','months-five-six','measures','month-six','beyond']) assert(slides.some(s=>s.id===id));
|
||||||
|
for(const id of ['experiment']) assert.match(slides.find(s=>s.id===id).body,/fictional/i);
|
||||||
|
assert.match(slides.find(s=>s.id==='qualification').notes,/separately authorizes/);
|
||||||
|
});
|
||||||
|
test('starting point keeps content without the two removed headings',()=>{
|
||||||
|
const body=slides.find(s=>s.id==='starting-point').body;
|
||||||
|
assert.doesNotMatch(body,/Assignment facts|Unknown until discovery/);
|
||||||
|
for(const text of ['Solo architect → CTO','No formal authority over teams','Stack, tools, process, baselines','Capacity and actual bottlenecks'])assert(body.includes(text));
|
||||||
|
assert.doesNotMatch(body,/<p><br>/);
|
||||||
|
});
|
||||||
|
test('contributors explains human-controlled AI tools below the diagram',()=>{
|
||||||
|
const body=slides.find(s=>s.id==='contributors').body;
|
||||||
|
const definition='AI Agent = Claude, Cline, ChatGPT or a similar tool, used under human control.';
|
||||||
|
assert(body.includes(definition));
|
||||||
|
assert(body.indexOf(definition)>body.indexOf('contribution-grid'));
|
||||||
|
assert(body.includes('Dashed ⇢ contribution from outside the cycle.'));
|
||||||
|
});
|
||||||
|
test('capacity visibly frames the days as an example weekly allocation',()=>{
|
||||||
|
const slide=slides.find(s=>s.id==='capacity');
|
||||||
|
assert.equal(slide.title,'One architect. One active live pilot.');
|
||||||
|
assert(slide.body.startsWith('<p>Example weekly allocation for the AI architect</p><div class="capacity"'));
|
||||||
|
for(const text of ['2 days','Pair + build','Evaluate','Relationships','Decisions + buffer','Proposed capacity envelope—not known company availability.']) assert(slide.body.includes(text));
|
||||||
|
});
|
||||||
|
test('measurement names five numerical candidates and separates populations',()=>{
|
||||||
|
const s=slides.find(s=>s.id==='measures');
|
||||||
|
assert.equal(s.minutes,2);
|
||||||
|
assert.equal(s.title,'Measure better work—and skill health');
|
||||||
|
for(const label of ['Validated task success (%)','Changes with escaped quality issues (%)','Cost per accepted outcome','currency/outcome','Skill selection precision (%)','Skills within substantive review window (%)','Baseline → pilot','Independent quality qualification still required','Choose relevant measures','Unknown is not zero','Skill health is not productivity proof']) assert(s.body.includes(label),label);
|
||||||
|
assert.equal((s.body.match(/class="metric"/g)||[]).length,5);
|
||||||
|
for(const text of ['matured eligible starts','completed follow-up','labeled evaluation','active approved revisions'])assert(s.body.includes(text),text);
|
||||||
|
for(const name of ['validated-task-success','changes-with-escaped-quality-issues','cost-per-accepted-outcome','skill-selection-precision','skills-within-substantive-review-window'])assert(s.sources.includes('measurement/'+name));
|
||||||
|
for(const term of ['N/A','unknown','unimplemented','partial','review/rework','like-for-like','zero accepted'])assert(s.notes.includes(term),term);
|
||||||
|
assert.doesNotMatch(s.body,/Accepted work<|\d+%/);
|
||||||
|
});
|
||||||
|
test('learning loop staircase preserves the original semantic sequence',()=>{
|
||||||
|
const body=slides.find(s=>s.id==='learning-loop').body;
|
||||||
|
const loop=body.split('</div>')[0];
|
||||||
|
assert.deepEqual([...loop.matchAll(/<span>(.*?)<\/span>/g)].map(m=>m[1]),['Understand work','Measure + baseline','Engineer topology','Use in real work','Collect results','Reassess']);
|
||||||
|
assert.deepEqual([...loop.matchAll(/<i>(.*?)<\/i>/g)].map(m=>m[1]),['→','↓','→','↓','→']);
|
||||||
|
assert(body.includes('↻ Repeat within each phase.'));
|
||||||
|
});
|
||||||
|
test('build emits local pinned Reveal assets, stable IDs and no production CDN',()=>{
|
||||||
|
execFileSync(process.execPath,['scripts/build-presentations.mjs']);
|
||||||
|
const dir='static/presentations/less-prompting-more-shipping'; const html=read(`${dir}/index.html`);
|
||||||
|
assert.equal((html.match(/<section /g)||[]).length,23);
|
||||||
|
assert.equal((html.match(/class="notes"/g)||[]).length,23);
|
||||||
|
assert(!/https?:\/\//.test(html));
|
||||||
|
assert.match(html,/href="\.\.\/\.\.\/strategy\/target-operating-model\/"/);
|
||||||
|
assert.match(read(`${dir}/assets/reveal.js`),/5\.2\.1/);
|
||||||
|
assert.match(read(`${dir}/runtime.js`),/hash:!embedded/);
|
||||||
|
assert.equal(JSON.parse(read('package.json')).dependencies['reveal.js'],'5.2.1');
|
||||||
|
assert.match(read('src/components/PresentationEmbed/index.tsx'),/Open presentation/);
|
||||||
|
const map=JSON.parse(read(`${dir}/source-map.json`));
|
||||||
|
assert.equal(map.version,'1.1.0');
|
||||||
|
assert.equal(map.assignmentQuestions.length,4);
|
||||||
|
for(const question of map.assignmentQuestions)for(const id of question.slides)assert(slides.some(s=>s.id===id));
|
||||||
|
for(const doc of map.diagramSources)assert.equal(doc.sha256,createHash('sha256').update(read(doc.path)).digest('hex'));
|
||||||
|
assert.match(map.strategyRevision,/same-build/);
|
||||||
|
for(const doc of map.sourceDocuments) assert.equal(doc.sha256,createHash('sha256').update(read(doc.path)).digest('hex'),doc.path);
|
||||||
|
for(const id of ['target-operating-model','roadmap','six-months-target','six-months-roadmap','stage-02-autonomous-agent']) assert(map.sourceDocuments.some(d=>d.id===id),id);
|
||||||
|
assert(slides.find(s=>s.id==='beyond').notes.includes('long-term destination remains human-directed'));
|
||||||
|
for(const id of ['months-one-two','months-three-four','months-five-six','capacity','experiment']) assert(slides.find(s=>s.id===id).sources.includes('six-months-roadmap'),id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('visible strategy narrative preserves five-page order and short experiment',()=>{
|
||||||
|
const index=id=>slides.findIndex(s=>s.id===id);
|
||||||
|
const sequence=['starting-point','target','contributors','roadmap','learning-loop','six-month-target','months-one-two','months-three-four','months-five-six','experiment','month-six','beyond','authority','discussion'];
|
||||||
|
for(let i=1;i<sequence.length;i++)assert(index(sequence[i])>index(sequence[i-1]),sequence[i]);
|
||||||
|
assert.match(slides[index('target')].body,/Autonomous agent/);
|
||||||
|
assert.match(slides[index('roadmap')].body,/Order undecided/);
|
||||||
|
assert.match(slides[index('roadmap')].body,/Delivery keeps improving/);
|
||||||
|
assert.match(slides[index('learning-loop')].body,/Triggers → skills → handoffs → acceptance/);
|
||||||
|
assert(!slides.some(s=>s.id==='inconclusive'||s.id==='stop'));
|
||||||
|
assert(!slides[index('experiment')].body.includes('<table>'));
|
||||||
|
assert.match(slides[index('experiment')].notes,/40-minute median against 30 baseline/);
|
||||||
|
assert.equal(slides[index('experiment')].minutes,2);
|
||||||
|
assert.equal(slides.filter(s=>s.track==='appendix').reduce((a,s)=>a+s.minutes,0),0);
|
||||||
|
});
|
||||||
|
test('presentation topology preserves all original relationships across two readable views',async()=>{
|
||||||
|
const {topology,cycleFigure,contributionsFigure}=await import('../presentations/less-prompting-more-shipping/target-figure.mjs');
|
||||||
|
const original=JSON.parse(read('diagrams/strategy-target.architecture.json'));
|
||||||
|
const pairs=prefix=>original.connections.filter(c=>c.id.startsWith(prefix)).map(c=>[c.from,c.to]).sort();
|
||||||
|
assert.deepEqual([...topology.lifecycle].sort(),pairs('stage-'));
|
||||||
|
assert.deepEqual([...topology.governance].sort(),pairs('govern-'));
|
||||||
|
assert.deepEqual([...topology.contributions].sort(),pairs('contribute-'));
|
||||||
|
for(const [from,to] of [...topology.lifecycle,...topology.governance])assert(cycleFigure.includes(`data-from="${from}" data-to="${to}"`));
|
||||||
|
for(const [from,to] of topology.contributions)assert(contributionsFigure.includes(`data-from="${from}" data-to="${to}"`));
|
||||||
|
assert.equal((cycleFigure.match(/data-node="agent"/g)||[]).length,2); // desktop + recomposed phone
|
||||||
|
});
|
||||||
@@ -30,7 +30,7 @@ export function roadmapViewer(html, spec) {
|
|||||||
return `<text x="${x+24}" y="${y+top}" font-size="${size}" class="${cls}" ${attrs}>${lines.map((line,i) => `<tspan x="${x+24}" dy="${i ? 34 : 0}">${escape(line)}</tspan>`).join('')}</text>`;
|
return `<text x="${x+24}" y="${y+top}" font-size="${size}" class="${cls}" ${attrs}>${lines.map((line,i) => `<tspan x="${x+24}" dy="${i ? 34 : 0}">${escape(line)}</tspan>`).join('')}</text>`;
|
||||||
};
|
};
|
||||||
if (!node.sublabel || node.tag || /Output:|Exit:|\n/.test(node.sublabel)) throw new Error(`Roadmap content contract drift: ${node.id}`);
|
if (!node.sublabel || node.tag || /Output:|Exit:|\n/.test(node.sublabel)) throw new Error(`Roadmap content contract drift: ${node.id}`);
|
||||||
const number = spec.nodes.length === 6 ? `Step ${index+1}` : spec.nodes[0].id === 'skills' ? `Stage ${index+1}` : index === 0 ? 'First' : 'Then';
|
const number = spec.nodes.length === 6 ? `Step ${index+1}` : spec.nodes[0].id === 'skills' ? ['Stage 1','Stage 2'][index] : index === 0 ? 'First' : 'If justified';
|
||||||
const content = text(number, 40, 26, 't-primary', 'data-stage-number="" font-weight="700"')
|
const content = text(number, 40, 26, 't-primary', 'data-stage-number="" font-weight="700"')
|
||||||
+ text(node.label, 88, 30, 't-primary', 'data-node-label="" font-weight="700"')
|
+ text(node.label, 88, 30, 't-primary', 'data-node-label="" font-weight="700"')
|
||||||
+ text(node.sublabel, 160, 26, 't-muted');
|
+ text(node.sublabel, 160, 26, 't-muted');
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ test('Roadmap has three visual levels and preserves human direction and Delivery
|
|||||||
const page = read('docs/strategy/roadmap.mdx');
|
const page = read('docs/strategy/roadmap.mdx');
|
||||||
const visible = page.split('<details>')[0];
|
const visible = page.split('<details>')[0];
|
||||||
assert.deepEqual([...visible.matchAll(/<ArchifyDiagram name="([^"]+)"/g)].map(m => m[1]), Object.keys(views));
|
assert.deepEqual([...visible.matchAll(/<ArchifyDiagram name="([^"]+)"/g)].map(m => m[1]), Object.keys(views));
|
||||||
assert.deepEqual([...visible.matchAll(/^## (.+)$/gm)].map(m => m[1]), ['Two stages toward Target', 'Stage 1: Delivery first', 'Improve within each phase', 'Delivery in practice']);
|
assert.deepEqual([...visible.matchAll(/^## (.+)$/gm)].map(m => m[1]), ['Two stages toward the long-term Target', 'Stage 1: Delivery first', 'Improve within each phase', 'Delivery in practice']);
|
||||||
for (const marker of ['Humans direct, guide and review throughout', 'standardizes skills', 'foundation for Stage 2', 'future Autonomous Agent', 'not deployed autonomy', 'order is not yet decided', 'Delivery keeps improving', 'not as six global roadmap stages', 'what skills exist, how they relate, when they are used and how they work together', 'codebase structure', 'existing principles', 'system-logic source', 'tests', 'builds and packaging', 'deployments', 'practices, tooling, controls and problems', 'metrics/KPIs and a baseline', 'friction and feedback', './measurement/index.mdx', './target-operating-model.mdx']) assert(visible.includes(marker), marker);
|
for (const marker of ['Humans direct, guide and review throughout', 'standardizes skills', 'foundation for Stage 2', 'future Autonomous Agent', 'not deployed autonomy', 'order is not yet decided', 'Delivery keeps improving', 'not as six global roadmap stages', 'what skills exist, how they relate, when they are used and how they work together', 'codebase structure', 'existing principles', 'system-logic source', 'tests', 'builds and packaging', 'deployments', 'practices, tooling, controls and problems', 'metrics/KPIs and a baseline', 'friction and feedback', './measurement/index.mdx', './target-operating-model.mdx']) assert(visible.includes(marker), marker);
|
||||||
for (const marker of ['revocation','exact-artifact approvals','idempotency','human takeover','sensitive decisions','security findings','reproducible baseline']) assert(page.includes(marker), marker);
|
for (const marker of ['revocation','exact-artifact approvals','idempotency','human takeover','sensitive decisions','security findings','reproducible baseline']) assert(page.includes(marker), marker);
|
||||||
assert(!/## [1-5]\.|Prepare foundations|Sustain and improve/.test(page));
|
assert(!/## [1-5]\.|Prepare foundations|Sustain and improve/.test(page));
|
||||||
|
|||||||
@@ -4,21 +4,15 @@ import {readFileSync} from 'node:fs';
|
|||||||
const read = p => readFileSync(p, 'utf8');
|
const read = p => readFileSync(p, 'utf8');
|
||||||
const stages = ['Scope', 'Architecture', 'UI/UX', 'Planning', 'Delivery', 'UAT', 'Security', 'Releases'];
|
const stages = ['Scope', 'Architecture', 'UI/UX', 'Planning', 'Delivery', 'UAT', 'Security', 'Releases'];
|
||||||
|
|
||||||
test('Strategy opens at the canonical autonomous lifecycle', () => {
|
test('Strategy opens at the long-term Target and separates the six-month contribution', () => {
|
||||||
assert.match(read('sidebars/strategy.ts'), /strategySidebar:\s*\[\s*'target-operating-model',\s*'roadmap'/);
|
const page=read('docs/strategy/target-operating-model.mdx');
|
||||||
assert.match(read('docs/strategy/target-operating-model.mdx'), /^sidebar_label: Target$/m);
|
|
||||||
for (const id of ['target-operating-model']) {
|
|
||||||
const page = read(`docs/strategy/${id}.mdx`);
|
|
||||||
const primary=page.split('<details>')[0];
|
const primary=page.split('<details>')[0];
|
||||||
|
assert.match(page, /^title: Target$/m);
|
||||||
|
assert.match(page, /^sidebar_label: Target$/m);
|
||||||
assert(primary.includes('name="strategy-target"'));
|
assert(primary.includes('name="strategy-target"'));
|
||||||
assert(primary.includes('autonomous agent'));
|
assert(!primary.includes('name="strategy-six-months"'));
|
||||||
assert(primary.includes('direct, guide and review'));
|
for(const marker of ['not a six-month commitment or present authorization','Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope','human-controlled AI Agent','Humans direct, guide and review','./six-months-target.mdx','./six-months-roadmap.mdx']) assert(primary.includes(marker),marker);
|
||||||
assert(primary.includes('Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope'));
|
assert(!page.includes('conditional long-term option'));
|
||||||
assert(primary.includes('human-controlled AI Agent'));
|
|
||||||
assert(!/code[ -]agent/i.test(page));
|
|
||||||
assert(primary.includes('TO-BE'));
|
|
||||||
assert(!/only routes|People authorize|independent gates protect release/.test(primary));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('both target diagrams have eight stages, eight governed phases and eight human-controlled contributors', () => {
|
test('both target diagrams have eight stages, eight governed phases and eight human-controlled contributors', () => {
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ export async function verifySidebarCoverage() {
|
|||||||
assert(body.includes('window.location.replace') && body.includes('name="robots" content="noindex"') && !body.includes('<article'), 'Metric alias must remain a non-indexed redirect');
|
assert(body.includes('window.location.replace') && body.includes('name="robots" content="noindex"') && !body.includes('<article'), 'Metric alias must remain a non-indexed redirect');
|
||||||
assert.equal(body, readFileSync(join('static',file),'utf8'));
|
assert.equal(body, readFileSync(join('static',file),'utf8'));
|
||||||
reason = 'Legacy measurement-contracts hash-aware redirect to canonical Measurement pages';
|
reason = 'Legacy measurement-contracts hash-aware redirect to canonical Measurement pages';
|
||||||
|
} else if (file === 'presentations/less-prompting-more-shipping/index.html') {
|
||||||
|
const body = readFileSync(join('build',file),'utf8');
|
||||||
|
assert.equal(body, readFileSync(join('static',file),'utf8'));
|
||||||
|
assert(body.includes('class="reveal deck"') && body.includes('class="notes"'));
|
||||||
|
assert(readFileSync('build/index.html','utf8').includes('/presentations/less-prompting-more-shipping/?embed'));
|
||||||
|
reason = 'Reveal presentation linked from the homepage, not a competing documentation page';
|
||||||
} else if (file.startsWith('diagrams/') && readFileSync(join('build',file),'utf8').includes('<svg')) {
|
} else if (file.startsWith('diagrams/') && readFileSync(join('build',file),'utf8').includes('<svg')) {
|
||||||
assert.equal(readFileSync(join('build',file),'utf8'), readFileSync(join('static',file),'utf8'), `Viewer must match generated static asset: ${file}`);
|
assert.equal(readFileSync(join('build',file),'utf8'), readFileSync(join('static',file),'utf8'), `Viewer must match generated static asset: ${file}`);
|
||||||
reason = 'Standalone diagram viewer asset, not documentation';
|
reason = 'Standalone diagram viewer asset, not documentation';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const read = path => readFileSync(path, 'utf8');
|
|||||||
|
|
||||||
test('Skills Measurement is a visible optional registry, separate from workflow application', () => {
|
test('Skills Measurement is a visible optional registry, separate from workflow application', () => {
|
||||||
const page = read('docs/strategy/measurement/index.mdx');
|
const page = read('docs/strategy/measurement/index.mdx');
|
||||||
assert.match(page, /title: Skills Measurement\nsidebar_label: Measurement/);
|
assert.match(page, /title: Measuring real output\nsidebar_label: Measurement/);
|
||||||
for (const heading of ['Establish the baseline', 'Measure the pilot', 'Extend collection as adoption grows', 'Keep the collection running']) assert(!page.includes(heading), heading);
|
for (const heading of ['Establish the baseline', 'Measure the pilot', 'Extend collection as adoption grows', 'Keep the collection running']) assert(!page.includes(heading), heading);
|
||||||
assert(page.includes('Registry inclusion does not require a metric to be used, collected or baselined'));
|
assert(page.includes('Registry inclusion does not require a metric to be used, collected or baselined'));
|
||||||
assert(page.includes('../baseline.mdx'));
|
assert(page.includes('../baseline.mdx'));
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ test('domain contracts retain human authority, honest measures and Delivery-firs
|
|||||||
const text=t=>JSON.stringify(JSON.parse(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('Retain / improve / hold / stop'));
|
||||||
assert(text('adoption').includes('No quotas or rankings'));
|
assert(text('adoption').includes('No quotas or rankings'));
|
||||||
for(const marker of ['Workflow effectiveness','Skills effectiveness & health','Quality: artifact fitness + safety','No mandatory collection','Before / after is not causality','Candidate / approved regression'])assert(text('measurement').includes(marker),marker);
|
for(const marker of ['Workflow effectiveness','Skills effectiveness & health','Quality: artifact fitness + safety','No mandatory collection','Before / after is not causality','Candidate / approved regression'])assert(text('measurement').includes(marker),marker);
|
||||||
assert(text('maintenance').includes('No automatic reinstatement'));
|
assert(text('maintenance').includes('No automatic reinstatement'));
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Native editable geometry and edges; scoped editorial typography for Stage 01.
|
// Native editable geometry and edges; scoped editorial typography for Stage 01.
|
||||||
export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|baseline|maintenance|stage01|stage02)(-mobile)?$/.test(name);
|
export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|baseline|maintenance|stage01|stage02|six-months)(-mobile)?$/.test(name);
|
||||||
const escape = text => text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
const escape = text => text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
||||||
export function skillsViewer(html, spec) {
|
export function skillsViewer(html, spec) {
|
||||||
if (spec.diagram_type !== 'architecture' || !spec.components.length) throw new Error('Skills story contract drift');
|
if (spec.diagram_type !== 'architecture' || !spec.components.length) throw new Error('Skills story contract drift');
|
||||||
const stageMobile = /strategy-stage0[12]-mobile\//.test(spec.meta.output);
|
const stageMobile = /strategy-(stage0[12]|six-months)-mobile\//.test(spec.meta.output);
|
||||||
const detailSize = stageMobile ? 38 : spec.meta.output.includes('-mobile/') ? 34 : 32;
|
const detailSize = stageMobile ? 38 : 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>`);
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ test('Strategy has Target, Roadmap, a linked Skills Adoption category and Autono
|
|||||||
const sandbox = {exports:{}};
|
const sandbox = {exports:{}};
|
||||||
runInNewContext(compiled, sandbox);
|
runInNewContext(compiled, sandbox);
|
||||||
const sidebar = JSON.parse(JSON.stringify(sandbox.exports.default.strategySidebar));
|
const sidebar = JSON.parse(JSON.stringify(sandbox.exports.default.strategySidebar));
|
||||||
assert.deepEqual(sidebar, ['target-operating-model', 'roadmap', {
|
assert.deepEqual(sidebar, ['target-operating-model', 'roadmap', 'six-months-target', {
|
||||||
type:'category', label:'Stage - 01 - Skills Adoption',
|
type:'category', label:'6 Months Roadmap',
|
||||||
link:{type:'doc', id:'stage-01-skills-adoption'}, collapsed:true,
|
link:{type:'doc', id:'six-months-roadmap'}, collapsed:true,
|
||||||
items:[
|
items:[
|
||||||
|
'stage-01-skills-adoption',
|
||||||
{type:'category', label:'Measurement', collapsed:true, link:{type:'doc', id:'measurement/index'}, items:[
|
{type:'category', label:'Measurement', collapsed:true, link:{type:'doc', id:'measurement/index'}, items:[
|
||||||
...JSON.parse(read('research/ai-adoption/measurement-migration.json')).metrics.map(m => m.docId),
|
...JSON.parse(read('research/ai-adoption/measurement-migration.json')).metrics.map(m => m.docId),
|
||||||
'measurement/collection-and-safeguards','measurement/synthetic-example',
|
'measurement/collection-and-safeguards','measurement/synthetic-example',
|
||||||
@@ -34,8 +35,8 @@ test('stage overviews explain the foundation and future without replacing topic
|
|||||||
const first = read('docs/strategy/stage-01-skills-adoption.mdx');
|
const first = read('docs/strategy/stage-01-skills-adoption.mdx');
|
||||||
const second = read('docs/strategy/stage-02-autonomous-agent.mdx');
|
const second = read('docs/strategy/stage-02-autonomous-agent.mdx');
|
||||||
for (const [id, title, page] of [
|
for (const [id, title, page] of [
|
||||||
['stage-01-skills-adoption', 'Stage - 01 - Skills Adoption', first],
|
['stage-01-skills-adoption', 'Skills lifecycle reference', first],
|
||||||
['stage-02-autonomous-agent', 'Stage - 02 - Autonomous Agent', second],
|
['stage-02-autonomous-agent', 'Beyond 6 Months', second],
|
||||||
]) {
|
]) {
|
||||||
assert(page.includes(`id: ${id}\ntitle: ${title}`));
|
assert(page.includes(`id: ${id}\ntitle: ${title}`));
|
||||||
for (const link of ['./roadmap.mdx', './target-operating-model.mdx']) assert(page.includes(link));
|
for (const link of ['./roadmap.mdx', './target-operating-model.mdx']) assert(page.includes(link));
|
||||||
@@ -43,7 +44,7 @@ test('stage overviews explain the foundation and future without replacing topic
|
|||||||
for (const id of ['measurement/index','baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance']) assert(first.includes(`./${id}.mdx`));
|
for (const id of ['measurement/index','baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance']) assert(first.includes(`./${id}.mdx`));
|
||||||
for (const marker of ['human + AI Agent','Delivery first','order is not yet decided','KPIs','baseline','topology','feedback','new current situation']) assert(first.includes(marker), marker);
|
for (const marker of ['human + AI Agent','Delivery first','order is not yet decided','KPIs','baseline','topology','feedback','new current situation']) assert(first.includes(marker), marker);
|
||||||
for (const marker of ['future','proven skills','measurements','working practices','direction and review','not deployed autonomy','approved KPI thresholds']) assert(second.includes(marker), marker);
|
for (const marker of ['future','proven skills','measurements','working practices','direction and review','not deployed autonomy','approved KPI thresholds']) assert(second.includes(marker), marker);
|
||||||
assert.match(read('docs/strategy/measurement/index.mdx'), /^title: Skills Measurement\nsidebar_label: Measurement$/m);
|
assert.match(read('docs/strategy/measurement/index.mdx'), /^title: Measuring real output\nsidebar_label: Measurement$/m);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('old Strategy entry redirects to Target instead of maintaining a second document', () => {
|
test('old Strategy entry redirects to Target instead of maintaining a second document', () => {
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ test('every strategy page leads with a compact diagram story and closes its refe
|
|||||||
assert(/\*\*(Next|Continue the loop):\*\*/.test(narrative), id);
|
assert(/\*\*(Next|Continue the loop):\*\*/.test(narrative), id);
|
||||||
assert(!narrative.includes('| ---'), id);
|
assert(!narrative.includes('| ---'), id);
|
||||||
const words = narrative.replace(/<[^>]*>/g, '').trim().split(/\s+/).length;
|
const words = narrative.replace(/<[^>]*>/g, '').trim().split(/\s+/).length;
|
||||||
assert(words <= (id === 'measurement' ? 1600 : id === 'roadmap' ? 600 : 500), `${id}: ${words} default narrative words`);
|
const budget = id === 'measurement' ? 1900 : id === 'roadmap' ? 1150 : id === 'target-operating-model' ? 850 : 750;
|
||||||
|
assert(words <= budget, `${id}: ${words} default narrative words`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ 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, 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,label,...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|measurement|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');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
|
|||||||
test('seven existing strategy pages and two stage overviews preserve canonical routes', () => {
|
test('seven existing strategy pages and two stage overviews preserve canonical routes', () => {
|
||||||
assert.equal(model.pages.length, 7);
|
assert.equal(model.pages.length, 7);
|
||||||
assert.deepEqual(readdirSync('docs/strategy').filter(p => p.endsWith('.mdx')).sort(),
|
assert.deepEqual(readdirSync('docs/strategy').filter(p => p.endsWith('.mdx')).sort(),
|
||||||
[...model.pages.filter(p => p.id !== 'measurement').map(({id}) => `${id}.mdx`), 'stage-01-skills-adoption.mdx', 'stage-02-autonomous-agent.mdx', 'baseline.mdx'].sort());
|
[...model.pages.filter(p => p.id !== 'measurement').map(({id}) => `${id}.mdx`), 'stage-01-skills-adoption.mdx', 'stage-02-autonomous-agent.mdx', 'baseline.mdx', 'six-months-target.mdx', 'six-months-roadmap.mdx'].sort());
|
||||||
for (const {id} of model.pages) {
|
for (const {id} of model.pages) {
|
||||||
const page = read(`docs/strategy/${id === 'measurement' ? 'measurement/index' : id}.mdx`);
|
const page = read(`docs/strategy/${id === 'measurement' ? 'measurement/index' : id}.mdx`);
|
||||||
assert(page.includes(`id: ${id === 'measurement' ? 'index' : id}`));
|
assert(page.includes(`id: ${id === 'measurement' ? 'index' : id}`));
|
||||||
@@ -15,7 +15,7 @@ test('seven existing strategy pages and two stage overviews preserve canonical r
|
|||||||
assert(read('sidebars/strategy.ts').includes(`'${id === 'measurement' ? 'measurement/index' : id}'`));
|
assert(read('sidebars/strategy.ts').includes(`'${id === 'measurement' ? 'measurement/index' : id}'`));
|
||||||
}
|
}
|
||||||
for (const teams of Object.values(model.organization)) for (const name of teams) {
|
for (const teams of Object.values(model.organization)) for (const name of teams) {
|
||||||
assert(read('docs/organization/structure.mdx').includes(name));
|
assert(readdirSync('docs/organization/structure').some(file => read(`docs/organization/structure/${file}`).includes(name)));
|
||||||
assert(read('docs/strategy/target-operating-model.mdx').includes(name));
|
assert(read('docs/strategy/target-operating-model.mdx').includes(name));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Caption the long-term target without changing its native topology.
|
||||||
|
// Text lives inside the SVG so standalone exports retain proposal/line semantics.
|
||||||
|
export function targetCaption(html) {
|
||||||
|
const roots = [...html.matchAll(/<svg\b[^>]*role="img"[^>]*>/g)];
|
||||||
|
if (roots.length !== 1) throw new Error('Target caption SVG contract drift');
|
||||||
|
const root = roots[0][0];
|
||||||
|
const match = /viewBox="([\d. -]+)"/.exec(root);
|
||||||
|
if (!match) throw new Error('Target caption requires viewBox');
|
||||||
|
const [x,y,w,h] = match[1].trim().split(/\s+/).map(Number);
|
||||||
|
const size = Math.min(26, w / 30);
|
||||||
|
const lines = ['Long-term Target — not a six-month commitment',
|
||||||
|
'Solid: lifecycle · Dotted: execution / governance', 'Dashed: human-controlled contributions'];
|
||||||
|
const extra = size * 5;
|
||||||
|
const caption = `<g id="eldorado-target-caption" aria-label="Proposed target legend">${lines.map((line,i) => `<text x="${x+20}" y="${y+h+size*(1.2+i*1.3)}" font-family="Arial, sans-serif" font-size="${size}" style="font-size:${size}px!important" class="t-primary">${line}</text>`).join('')}</g>`;
|
||||||
|
return html.replace(root, root.replace(match[0], `viewBox="${x} ${y} ${w} ${h+extra}"`) + caption);
|
||||||
|
}
|
||||||
+5
-3
@@ -27,15 +27,17 @@ if (process.argv.includes('--build')) {
|
|||||||
assert(redirect.includes('/eldorado-v1/documentation/strategy/target-operating-model/'));
|
assert(redirect.includes('/eldorado-v1/documentation/strategy/target-operating-model/'));
|
||||||
assert(redirect.includes('window.location.href') && redirect.includes('http-equiv="refresh"') && !redirect.includes('archify-panel'), 'Landing must redirect, not duplicate Target');
|
assert(redirect.includes('window.location.href') && redirect.includes('http-equiv="refresh"') && !redirect.includes('archify-panel'), 'Landing must redirect, not duplicate Target');
|
||||||
const strategyPages = [...model.pages,
|
const strategyPages = [...model.pages,
|
||||||
{id:'stage-01-skills-adoption', title:'Stage - 01 - Skills Adoption'},
|
{id:'six-months-target', title:'6 Months Target'},
|
||||||
|
{id:'six-months-roadmap', title:'6 Months Roadmap'},
|
||||||
|
{id:'stage-01-skills-adoption', title:'Skills lifecycle reference'},
|
||||||
{id:'baseline', title:'Baseline'},
|
{id:'baseline', title:'Baseline'},
|
||||||
{id:'stage-02-autonomous-agent', title:'Stage - 02 - Autonomous Agent'},
|
{id:'stage-02-autonomous-agent', title:'Beyond 6 Months'},
|
||||||
];
|
];
|
||||||
for (const {id, title} of strategyPages) {
|
for (const {id, title} of strategyPages) {
|
||||||
const route = `strategy/${id === 'index' ? '' : `${id}/`}index.html`;
|
const route = `strategy/${id === 'index' ? '' : `${id}/`}index.html`;
|
||||||
const page = read(join('build',route));
|
const page = read(join('build',route));
|
||||||
assert(page.includes(title), route);
|
assert(page.includes(title), route);
|
||||||
if (!id.startsWith('stage-')) assert(page.includes('Target operating model'), route);
|
if (!id.startsWith('stage-') && !id.startsWith('six-months-')) assert(page.includes('Target operating model'), route);
|
||||||
assert(indexes.includes(title), `Missing indexed Strategy page: ${id}`);
|
assert(indexes.includes(title), `Missing indexed Strategy page: ${id}`);
|
||||||
for (const match of page.matchAll(/href="(\/eldorado-v1\/documentation\/[^"?#]*)/g)) {
|
for (const match of page.matchAll(/href="(\/eldorado-v1\/documentation\/[^"?#]*)/g)) {
|
||||||
const local = decodeURIComponent(match[1].replace('/eldorado-v1/documentation/',''));
|
const local = decodeURIComponent(match[1].replace('/eldorado-v1/documentation/',''));
|
||||||
|
|||||||
@@ -1,2 +1,7 @@
|
|||||||
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
||||||
export default {organizationSidebar: ['structure', 'collaboration', 'sdlc']} satisfies SidebarsConfig;
|
export default {organizationSidebar: [
|
||||||
|
{type: 'category', label: 'Structure', link: {type: 'doc', id: 'structure'},
|
||||||
|
items: ['structure/product', 'structure/technology', 'structure/operations',
|
||||||
|
'structure/marketing', 'structure/finance-accounting', 'structure/hr-administration']},
|
||||||
|
'collaboration', 'sdlc',
|
||||||
|
]} satisfies SidebarsConfig;
|
||||||
@@ -3,12 +3,14 @@ export default {
|
|||||||
strategySidebar: [
|
strategySidebar: [
|
||||||
'target-operating-model',
|
'target-operating-model',
|
||||||
'roadmap',
|
'roadmap',
|
||||||
|
'six-months-target',
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
label: 'Stage - 01 - Skills Adoption',
|
label: '6 Months Roadmap',
|
||||||
link: {type: 'doc', id: 'stage-01-skills-adoption'},
|
link: {type: 'doc', id: 'six-months-roadmap'},
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
|
'stage-01-skills-adoption',
|
||||||
{
|
{
|
||||||
type: 'category', label: 'Measurement', collapsed: true,
|
type: 'category', label: 'Measurement', collapsed: true,
|
||||||
link: {type: 'doc', id: 'measurement/index'},
|
link: {type: 'doc', id: 'measurement/index'},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default function ArchifyDiagram({name, title, compact = false, story = fa
|
|||||||
const headingId = useId();
|
const headingId = useId();
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
const [narrowRoadmap, setNarrowRoadmap] = useState(false);
|
const [narrowRoadmap, setNarrowRoadmap] = useState(false);
|
||||||
const skillsStory = /^strategy-(governance|quality|adoption|measurement|baseline|maintenance|stage01|stage02)$/.test(name);
|
const skillsStory = /^strategy-(governance|quality|adoption|measurement|baseline|maintenance|stage01|stage02|six-months)$/.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: 1100px)' : '(max-width: 999px)');
|
const media = window.matchMedia(skillsStory ? '(max-width: 1100px)' : '(max-width: 999px)');
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
import styles from './styles.module.css';
|
||||||
|
|
||||||
|
/** One canonical deck document, with chrome and URL ownership isolated from the portal. */
|
||||||
|
export default function PresentationEmbed({title, path}: {title: string; path: string}): React.ReactElement {
|
||||||
|
const url = useBaseUrl(path);
|
||||||
|
const stage = useRef<HTMLDivElement>(null);
|
||||||
|
const button = useRef<HTMLButtonElement>(null);
|
||||||
|
const [fullscreen, setFullscreen] = useState(false);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
useEffect(() => {
|
||||||
|
const changed = () => {
|
||||||
|
const active = document.fullscreenElement === stage.current;
|
||||||
|
setFullscreen(active);
|
||||||
|
if (!active) button.current?.focus({preventScroll: true});
|
||||||
|
};
|
||||||
|
document.addEventListener('fullscreenchange', changed);
|
||||||
|
return () => document.removeEventListener('fullscreenchange', changed);
|
||||||
|
}, []);
|
||||||
|
async function toggleFullscreen() {
|
||||||
|
setError('');
|
||||||
|
try {
|
||||||
|
if (document.fullscreenElement === stage.current) await document.exitFullscreen();
|
||||||
|
else if (stage.current?.requestFullscreen) await stage.current.requestFullscreen();
|
||||||
|
else setError('Fullscreen is unavailable. Open presentation for a larger view.');
|
||||||
|
} catch {
|
||||||
|
setError('Fullscreen is unavailable. Open presentation for a larger view.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div className={styles.stage} ref={stage}>
|
||||||
|
<iframe className={styles.frame} src={`${url}?embed`} title={`${title} — interactive presentation`} loading="lazy" allowFullScreen/>
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<a href={url}>Open presentation <span aria-hidden="true">↗</span></a>
|
||||||
|
<button ref={button} type="button" onClick={toggleFullscreen} aria-pressed={fullscreen}>{fullscreen ? 'Exit fullscreen' : 'Fullscreen'}</button>
|
||||||
|
</div>
|
||||||
|
{error && <p role="status" className={styles.error}>{error}</p>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.stage {border: 1px solid var(--ifm-color-emphasis-300); background: #1f1f29;}
|
||||||
|
.frame {display: block; width: 100%; aspect-ratio: 1200 / 720; border: 0; background: #1f1f29;}
|
||||||
|
.actions {display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; background: #101014; color: #fff; font-size: .875rem;}
|
||||||
|
.actions a {color: #ffc950;}
|
||||||
|
.actions button {font: inherit; color: #fff; background: transparent; border: 1px solid #62616b; padding: 8px 12px; cursor: pointer;}
|
||||||
|
.actions :focus-visible, .frame:focus-visible {outline: 3px solid #ffc950; outline-offset: -3px;}
|
||||||
|
.error {padding: 12px; margin: 0; color: #fff;}
|
||||||
|
/* Reuse the deck's portrait composition on phones; don't shrink its landscape text. */
|
||||||
|
@media (max-width: 600px) {.frame {aspect-ratio: 600 / 1100;}}
|
||||||
|
.stage:fullscreen {width: 100%; height: 100%; display: flex; flex-direction: column; border: 0;}
|
||||||
|
.stage:fullscreen .frame {flex: 1; min-height: 0; aspect-ratio: auto;}
|
||||||
|
.stage:fullscreen .actions {flex: none;}
|
||||||
+2
-1
@@ -115,7 +115,8 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
|
|||||||
.archify-panel--story[data-diagram^="strategy-roadmap"] > .story-desktop {aspect-ratio: auto; height: 300px;}
|
.archify-panel--story[data-diagram^="strategy-roadmap"] > .story-desktop {aspect-ratio: auto; height: 300px;}
|
||||||
.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: 1225 / 1151;}
|
||||||
|
.strategy-content > details:has([data-diagram="strategy-target"]) {padding-inline: 0;}
|
||||||
|
|
||||||
.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;}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
import PresentationEmbed from '../components/PresentationEmbed';
|
||||||
|
|
||||||
export default function Home(): React.ReactElement {
|
export default function Home(): React.ReactElement {
|
||||||
return <Layout title="Eldorado Powered By AI" description="Strategy and direction for an AI-powered Eldorado.">
|
return <Layout title="Eldorado Powered By AI" description="Strategy and direction for an AI-powered Eldorado.">
|
||||||
@@ -30,6 +31,10 @@ export default function Home(): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
<aside className="scope-note"><span className="scope-symbol" aria-hidden="true">✦</span><div><strong>Shaping the direction.</strong><p>This space is dedicated to AI strategy and direction for Eldorado. Specific initiatives, priorities, and the roadmap remain to be defined.</p></div></aside>
|
<aside className="scope-note"><span className="scope-symbol" aria-hidden="true">✦</span><div><strong>Shaping the direction.</strong><p>This space is dedicated to AI strategy and direction for Eldorado. Specific initiatives, priorities, and the roadmap remain to be defined.</p></div></aside>
|
||||||
</section>
|
</section>
|
||||||
|
<section className="start-section container" aria-labelledby="presentation-title">
|
||||||
|
<div className="section-heading"><div><h2 id="presentation-title">Understand In Speed</h2></div></div>
|
||||||
|
<PresentationEmbed title="Less Prompting, More Shipping" path="/presentations/less-prompting-more-shipping/"/>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</Layout>;
|
</Layout>;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user