Compare commits

...
Author SHA1 Message Date
jarvis-at-skic baf79e125b fix: make Target canonical and place Roadmap second
Build and publish Eldorado documentation / build (pull_request) Successful in 40s
2026-10-05 18:16:57 +00:00
jarvis-at-skic 9651417ba7 Merge pull request 'docs: label central autonomous agent Human Controlled' (#20) from docs/target-human-controlled into main
Build and publish Eldorado documentation / build (push) Successful in 40s
2026-10-05 11:02:33 -07:00
jarvis-at-skic 4cc2bb4dfd docs: label central autonomous agent Human Controlled
Build and publish Eldorado documentation / build (pull_request) Successful in 1m22s
2026-10-05 17:59:59 +00:00
jarvis-at-skic afb6a97e97 Merge pull request 'docs: center Target lifecycle on autonomous agent' (#19) from docs/target-central-agent into main
Build and publish Eldorado documentation / build (push) Successful in 40s
2026-10-05 10:25:47 -07:00
jarvis-at-skic 1057433c2a docs: center Target lifecycle on autonomous agent
Build and publish Eldorado documentation / build (pull_request) Successful in 41s
2026-10-05 17:23:56 +00:00
jarvis-at-skic 504d9f8845 Merge pull request 'docs: lead Strategy with autonomous SDLC cycle' (#18) from docs/autonomous-sdlc-cycle into main
Build and publish Eldorado documentation / build (push) Successful in 42s
2026-10-05 09:34:42 -07:00
22 changed files with 313 additions and 136 deletions

No files matched your search

@@ -3,25 +3,49 @@
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target-mobile/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}}, "meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target-mobile/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}},
"components": [ "components": [
{"id": "humans", "type": "backend", "label": "Humans", "sublabel": "Direct, guide and review", "pos": [20, 20], "size": [240, 80]}, {"id":"agent","type":"security","label":"Autonomous agent","sublabel":"Human Controlled","pos":[140,200],"size":[360,120]},
{"id": "agent", "type": "security", "label": "Autonomous agent", "sublabel": "Executes and governs SDLC", "pos": [20, 180], "size": [240, 80]}, {"id":"scope","type":"backend","label":"Scope","sublabel":"01","pos":[100,440],"size":[240,100]},
{"id": "scope", "type": "backend", "label": "Scope", "sublabel": "01", "pos": [20, 340], "size": [240, 80]}, {"id":"architecture","type":"backend","label":"Architecture","sublabel":"02","pos":[100,660],"size":[240,100]},
{"id": "architecture", "type": "backend", "label": "Architecture", "sublabel": "02", "pos": [20, 500], "size": [240, 80]}, {"id":"ui-ux","type":"backend","label":"UI/UX","sublabel":"03","pos":[100,880],"size":[240,100]},
{"id": "ui-ux", "type": "backend", "label": "UI/UX", "sublabel": "03", "pos": [20, 660], "size": [240, 80]}, {"id":"planning","type":"backend","label":"Planning","sublabel":"04","pos":[100,1100],"size":[240,100]},
{"id": "planning", "type": "backend", "label": "Planning", "sublabel": "04", "pos": [20, 820], "size": [240, 80]}, {"id":"delivery","type":"backend","label":"Delivery","sublabel":"05","pos":[100,1320],"size":[240,100]},
{"id": "delivery", "type": "backend", "label": "Delivery", "sublabel": "05", "pos": [20, 980], "size": [240, 80]}, {"id":"uat","type":"backend","label":"UAT","sublabel":"06","pos":[100,1540],"size":[240,100]},
{"id": "uat", "type": "backend", "label": "UAT", "sublabel": "06", "pos": [20, 1140], "size": [240, 80]}, {"id":"security","type":"backend","label":"Security","sublabel":"07","pos":[100,1760],"size":[240,100]},
{"id": "releases", "type": "backend", "label": "Releases", "sublabel": "07", "pos": [20, 1300], "size": [240, 80]} {"id":"releases","type":"backend","label":"Releases","sublabel":"08","pos":[100,1980],"size":[240,100]},
{"id":"code-scope","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,440],"size":[240,100]},
{"id":"code-architecture","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,660],"size":[240,100]},
{"id":"code-ui-ux","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,880],"size":[240,100]},
{"id":"code-planning","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1100],"size":[240,100]},
{"id":"code-delivery","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1320],"size":[240,100]},
{"id":"code-uat","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1540],"size":[240,100]},
{"id":"code-security","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1760],"size":[240,100]},
{"id":"code-releases","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1980],"size":[240,100]}
], ],
"connections": [ "connections": [
{"id": "human-direction", "from": "humans", "to": "agent", "label": "Guide", "fromSide": "bottom", "toSide": "top"},
{"id": "agent-lifecycle", "from": "agent", "to": "scope", "label": "Entire cycle", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-scope","from":"agent","to":"scope","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,490]]},
{"id": "stage-1", "from": "scope", "to": "architecture", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-architecture","from":"agent","to":"architecture","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,710]]},
{"id": "stage-2", "from": "architecture", "to": "ui-ux", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-ui-ux","from":"agent","to":"ui-ux","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,930]]},
{"id": "stage-3", "from": "ui-ux", "to": "planning", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-planning","from":"agent","to":"planning","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1150]]},
{"id": "stage-4", "from": "planning", "to": "delivery", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-delivery","from":"agent","to":"delivery","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1370]]},
{"id": "stage-5", "from": "delivery", "to": "uat", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-uat","from":"agent","to":"uat","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1590]]},
{"id": "stage-6", "from": "uat", "to": "releases", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-security","from":"agent","to":"security","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1810]]},
{"id": "stage-7", "from": "releases", "to": "scope", "label": "Repeat indefinitely", "fromSide": "right", "toSide": "right", "via": [[300, 1340], [300, 380]], "labelAt": [180, 1430]} {"id":"govern-releases","from":"agent","to":"releases","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,2030]]},
{"id":"stage-1","from":"scope","to":"architecture","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-2","from":"architecture","to":"ui-ux","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-3","from":"ui-ux","to":"planning","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-4","from":"planning","to":"delivery","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-5","from":"delivery","to":"uat","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-6","from":"uat","to":"security","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-7","from":"security","to":"releases","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-8","from":"releases","to":"scope","label":"Repeat indefinitely","variant":"emphasis","fromSide":"bottom","toSide":"top","via":[[220,2140],[680,2140],[680,380],[220,380]],"labelAt":[440,2180]},
{"id":"contribute-scope","from":"code-scope","to":"scope","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-architecture","from":"code-architecture","to":"architecture","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-ui-ux","from":"code-ui-ux","to":"ui-ux","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-planning","from":"code-planning","to":"planning","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-delivery","from":"code-delivery","to":"delivery","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-uat","from":"code-uat","to":"uat","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-security","from":"code-security","to":"security","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
{"id":"contribute-releases","from":"code-releases","to":"releases","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"}
] ]
} }
+42 -18
View File
@@ -3,25 +3,49 @@
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}}, "meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}},
"components": [ "components": [
{"id": "humans", "type": "backend", "label": "Humans", "sublabel": "Direct, guide and review", "pos": [40, 20], "size": [240, 80]}, {"id":"agent","type":"security","label":"Autonomous agent","sublabel":"Human Controlled","pos":[465,450],"size":[270,90]},
{"id": "agent", "type": "security", "label": "Autonomous agent", "sublabel": "Executes and governs SDLC", "pos": [360, 20], "size": [240, 80]}, {"id":"scope","type":"backend","label":"Scope","sublabel":"01","pos":[510,187.5],"size":[180,75]},
{"id": "scope", "type": "backend", "label": "Scope", "sublabel": "01", "pos": [40, 220], "size": [240, 80]}, {"id":"architecture","type":"backend","label":"Architecture","sublabel":"02","pos":[780,187.5],"size":[180,75]},
{"id": "architecture", "type": "backend", "label": "Architecture", "sublabel": "02", "pos": [360, 220], "size": [240, 80]}, {"id":"ui-ux","type":"backend","label":"UI/UX","sublabel":"03","pos":[780,457.5],"size":[180,75]},
{"id": "ui-ux", "type": "backend", "label": "UI/UX", "sublabel": "03", "pos": [680, 220], "size": [240, 80]}, {"id":"planning","type":"backend","label":"Planning","sublabel":"04","pos":[780,727.5],"size":[180,75]},
{"id": "planning", "type": "backend", "label": "Planning", "sublabel": "04", "pos": [680, 380], "size": [240, 80]}, {"id":"delivery","type":"backend","label":"Delivery","sublabel":"05","pos":[510,727.5],"size":[180,75]},
{"id": "delivery", "type": "backend", "label": "Delivery", "sublabel": "05", "pos": [680, 540], "size": [240, 80]}, {"id":"uat","type":"backend","label":"UAT","sublabel":"06","pos":[240,727.5],"size":[180,75]},
{"id": "uat", "type": "backend", "label": "UAT", "sublabel": "06", "pos": [360, 540], "size": [240, 80]}, {"id":"security","type":"backend","label":"Security","sublabel":"07","pos":[240,457.5],"size":[180,75]},
{"id": "releases", "type": "backend", "label": "Releases", "sublabel": "07", "pos": [40, 540], "size": [240, 80]} {"id":"releases","type":"backend","label":"Releases","sublabel":"08","pos":[240,187.5],"size":[180,75]},
{"id":"code-scope","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[510,37.5],"size":[180,75]},
{"id":"code-architecture","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[780,37.5],"size":[180,75]},
{"id":"code-ui-ux","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[1005,457.5],"size":[180,75]},
{"id":"code-planning","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[780,877.5],"size":[180,75]},
{"id":"code-delivery","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[510,877.5],"size":[180,75]},
{"id":"code-uat","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[240,877.5],"size":[180,75]},
{"id":"code-security","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[15,457.5],"size":[180,75]},
{"id":"code-releases","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[240,37.5],"size":[180,75]}
], ],
"connections": [ "connections": [
{"id": "human-direction", "from": "humans", "to": "agent", "label": "Guide", "fromSide": "right", "toSide": "left"},
{"id": "agent-lifecycle", "from": "agent", "to": "scope", "label": "Entire cycle", "fromSide": "bottom", "toSide": "top", "via": [[480, 160], [160, 160]], "labelAt": [320, 145]}, {"id":"govern-scope","from":"agent","to":"scope","label":"","variant":"security","fromSide":"right","toSide":"bottom","via":[[750,495],[750,292.5],[600,292.5]]},
{"id": "stage-1", "from": "scope", "to": "architecture", "label": "Then", "fromSide": "right", "toSide": "left"}, {"id":"govern-architecture","from":"agent","to":"architecture","label":"","variant":"security","fromSide":"right","toSide":"bottom","via":[[765,495],[765,345],[870,345]]},
{"id": "stage-2", "from": "architecture", "to": "ui-ux", "label": "Then", "fromSide": "right", "toSide": "left"}, {"id":"govern-ui-ux","from":"agent","to":"ui-ux","label":"","variant":"security","fromSide":"right","toSide":"left"},
{"id": "stage-3", "from": "ui-ux", "to": "planning", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-planning","from":"agent","to":"planning","label":"","variant":"security","fromSide":"right","toSide":"top","via":[[765,495],[765,690],[870,690]]},
{"id": "stage-4", "from": "planning", "to": "delivery", "label": "Then", "fromSide": "bottom", "toSide": "top"}, {"id":"govern-delivery","from":"agent","to":"delivery","label":"","variant":"security","fromSide":"bottom","toSide":"top"},
{"id": "stage-5", "from": "delivery", "to": "uat", "label": "Then", "fromSide": "left", "toSide": "right"}, {"id":"govern-uat","from":"agent","to":"uat","label":"","variant":"security","fromSide":"left","toSide":"top","via":[[435,495],[435,690],[330,690]]},
{"id": "stage-6", "from": "uat", "to": "releases", "label": "Then", "fromSide": "left", "toSide": "right"}, {"id":"govern-security","from":"agent","to":"security","label":"","variant":"security","fromSide":"left","toSide":"right"},
{"id": "stage-7", "from": "releases", "to": "scope", "label": "Repeat indefinitely", "fromSide": "top", "toSide": "bottom", "via": [[160, 460], [160, 380]], "labelAt": [260, 420]} {"id":"govern-releases","from":"agent","to":"releases","label":"","variant":"security","fromSide":"left","toSide":"bottom","via":[[435,495],[435,345],[330,345]]},
{"id":"stage-1","from":"scope","to":"architecture","label":"Then","variant":"emphasis","fromSide":"right","toSide":"left"},
{"id":"stage-2","from":"architecture","to":"ui-ux","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-3","from":"ui-ux","to":"planning","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
{"id":"stage-4","from":"planning","to":"delivery","label":"Then","variant":"emphasis","fromSide":"left","toSide":"right"},
{"id":"stage-5","from":"delivery","to":"uat","label":"Then","variant":"emphasis","fromSide":"left","toSide":"right"},
{"id":"stage-6","from":"uat","to":"security","label":"Then","variant":"emphasis","fromSide":"top","toSide":"bottom"},
{"id":"stage-7","from":"security","to":"releases","label":"Then","variant":"emphasis","fromSide":"top","toSide":"bottom"},
{"id":"stage-8","from":"releases","to":"scope","label":"Repeat indefinitely","variant":"emphasis","fromSide":"right","toSide":"left","labelAt":[465,170]},
{"id":"contribute-scope","from":"code-scope","to":"scope","label":"Contribute","variant":"dashed","fromSide":"bottom","toSide":"top"},
{"id":"contribute-architecture","from":"code-architecture","to":"architecture","label":"Contribute","variant":"dashed","fromSide":"bottom","toSide":"top"},
{"id":"contribute-ui-ux","from":"code-ui-ux","to":"ui-ux","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right","labelAt":[990,570]},
{"id":"contribute-planning","from":"code-planning","to":"planning","label":"Contribute","variant":"dashed","fromSide":"top","toSide":"bottom"},
{"id":"contribute-delivery","from":"code-delivery","to":"delivery","label":"Contribute","variant":"dashed","fromSide":"top","toSide":"bottom"},
{"id":"contribute-uat","from":"code-uat","to":"uat","label":"Contribute","variant":"dashed","fromSide":"top","toSide":"bottom"},
{"id":"contribute-security","from":"code-security","to":"security","label":"Contribute","variant":"dashed","fromSide":"right","toSide":"left","labelAt":[220,570]},
{"id":"contribute-releases","from":"code-releases","to":"releases","label":"Contribute","variant":"dashed","fromSide":"bottom","toSide":"top"}
] ]
} }
-54
View File
@@ -1,54 +0,0 @@
---
id: index
title: AI adoption strategy
description: An autonomous SDLC cycle directed, guided and reviewed by humans, supported by governed skills.
slug: /
hide_table_of_contents: true
---
import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
<div className="strategy-content">
**TO-BE · Target operating model — not installed controls or company results.**
## Autonomous SDLC, human direction
<ArchifyDiagram name="strategy-target" title="Autonomous agent executes and governs the SDLC; humans direct, guide and review" story />
An autonomous agent executes and governs the SDLC. Humans direct, guide and review the work throughout the cycle.
**Scope → Architecture → UI/UX → Planning → Delivery → UAT → Releases → Scope**
Releases returns to Scope and the cycle repeats indefinitely. Governed skills and measured outcomes support the path toward this target; they are not a substitute for it.
<details>
<summary>Strategy rationale and reading map</summary>
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
### 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.
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 strategy describes the intended operating model and the evidence required to introduce it. It does not establish that these controls are installed, that every client is supported, or that AI has improved Eldorado's performance. The current reference is the documented six-department organization. Rollout begins by validating actual clients, responsibilities, data boundaries and available evidence.
Success means accepted outcomes with maintained quality, controlled risk and understood total cost. Faster activity without reliable outcomes is not success. More skill invocations, generated lines or tool subscriptions are not productivity targets. People remain accountable for product, customer, financial and personnel decisions.
## Navigate the strategy
- [Target operating model](./target-operating-model.mdx) — The autonomous SDLC cycle, with human direction, guidance and review.
- [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 adoption](./skills-adoption.mdx) — Workflow-led coaching, client choice, feedback, manual path.
- [Measurement](./measurement.mdx) — Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
- [Roadmap](./roadmap.mdx) — Evidence-gated phases, no promised dates or budgets.
</details>
**Next:** [Explore the autonomous SDLC cycle →](./target-operating-model.mdx)
</div>
+1 -1
View File
@@ -70,6 +70,6 @@ There are no invented launch dates, budgets, staffing commitments or guaranteed
</details> </details>
**Next:** [Return to the strategy destination →](./index.mdx) **Next:** [Return to the strategy destination →](./target-operating-model.mdx)
</div> </div>
+30 -3
View File
@@ -1,6 +1,7 @@
--- ---
id: target-operating-model id: target-operating-model
title: Target operating model title: Target operating model
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
--- ---
@@ -15,9 +16,11 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
<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 />
An autonomous agent executes and governs the SDLC. Humans direct, guide and review the work throughout the cycle. An autonomous agent executes and governs every phase. Humans direct, guide and review it; a separate human-controlled code agent contributes to each phase from outside the cycle.
**Scope → Architecture → UI/UX → Planning → Delivery → UAT → Releases → Scope** **Solid arrows:** lifecycle · **Dotted spokes:** execution and governance · **Dashed arrows:** contributions.
**Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope**
Each stage follows the previous one. Releases returns to Scope; the cycle repeats indefinitely, with human direction informing the next iteration. Each stage follows the previous one. Releases returns to Scope; the cycle repeats indefinitely, with human direction informing the next iteration.
@@ -44,7 +47,7 @@ The autonomous agent is more than a task router: it executes and governs the rep
One logical coordinator does not mean one fragile process. A durable task ledger, explicit state transitions, leases and idempotency keys allow recovery or multiple replicas without duplicate delivery. Inference outages stop new agent decisions, not the organization's ability to take over. People can resume work through the normal deterministic workflow. Evidence and authorization services fail closed for privileged actions; missing evidence never becomes permission. One logical coordinator does not mean one fragile process. A durable task ledger, explicit state transitions, leases and idempotency keys allow recovery or multiple replicas without duplicate delivery. Inference outages stop new agent decisions, not the organization's ability to take over. People can resume work through the normal deterministic workflow. Evidence and authorization services fail closed for privileged actions; missing evidence never becomes permission.
These controls support the sequence Scope → Architecture → UI/UX → Planning → Delivery → UAT → Releases → Scope; they do not replace it with a separate lifecycle. Product, engineering, design, quality, security and platform expertise inform human direction and review. Specific approval assignments and release permissions are implementation decisions still to be defined. These controls support the sequence Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope; they do not replace it with a separate lifecycle. Product, engineering, design, quality, security and platform expertise inform human direction and review. Specific approval assignments and release permissions are implementation decisions still to be defined.
### Trust and authority boundaries ### Trust and authority boundaries
@@ -135,6 +138,30 @@ See the existing [organization structure](/organization/structure/), [department
</details> </details>
<details>
<summary>Strategy rationale and reading map</summary>
### 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.
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 strategy describes the intended operating model and the evidence required to introduce it. It does not establish that these controls are installed, that every client is supported, or that AI has improved Eldorado's performance. The current reference is the documented six-department organization. Rollout begins by validating actual clients, responsibilities, data boundaries and available evidence.
Success means accepted outcomes with maintained quality, controlled risk and understood total cost. Faster activity without reliable outcomes is not success. More skill invocations, generated lines or tool subscriptions are not productivity targets. People remain accountable for product, customer, financial and personnel decisions.
### Navigate the strategy
- [Roadmap](./roadmap.mdx) — Evidence-gated phases, no promised dates or budgets.
- [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 adoption](./skills-adoption.mdx) — Workflow-led coaching, client choice, feedback, manual path.
- [Measurement](./measurement.mdx) — Full KPI contracts, minimal events, illustrative calculations, privacy and limits.
- [Skills maintenance](./skills-maintenance.mdx) — Review, drift, deprecation, rollback and incident handling.
</details>
**Next:** [Decide who owns and approves each skill →](./skills-governance.mdx) **Next:** [Decide who owns and approves each skill →](./skills-governance.mdx)
</div> </div>
+1
View File
@@ -18,6 +18,7 @@ const config: Config = {
theme: {customCss: './src/css/custom.css'}, theme: {customCss: './src/css/custom.css'},
} satisfies Preset.Options]], } satisfies Preset.Options]],
plugins: [ plugins: [
['@docusaurus/plugin-client-redirects', {redirects: [{from: '/strategy/', to: '/strategy/target-operating-model/'}]}],
['@docusaurus/plugin-content-docs', {id: 'organization', path: 'docs/organization', routeBasePath: 'organization', sidebarPath: './sidebars/organization.ts'}], ['@docusaurus/plugin-content-docs', {id: 'organization', path: 'docs/organization', routeBasePath: 'organization', sidebarPath: './sidebars/organization.ts'}],
['@docusaurus/plugin-content-docs', {id: 'strategy', path: 'docs/strategy', routeBasePath: 'strategy', sidebarPath: './sidebars/strategy.ts'}], ['@docusaurus/plugin-content-docs', {id: 'strategy', path: 'docs/strategy', routeBasePath: 'strategy', sidebarPath: './sidebars/strategy.ts'}],
['@docusaurus/plugin-content-docs', {id: 'contribution', path: 'docs/contribution', routeBasePath: 'contribution', sidebarPath: './sidebars/contribution.ts'}], ['@docusaurus/plugin-content-docs', {id: 'contribution', path: 'docs/contribution', routeBasePath: 'contribution', sidebarPath: './sidebars/contribution.ts'}],
+1
View File
@@ -20,6 +20,7 @@
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.10.2", "@docusaurus/core": "3.10.2",
"@docusaurus/plugin-client-redirects": "3.10.2",
"@docusaurus/preset-classic": "3.10.2", "@docusaurus/preset-classic": "3.10.2",
"@docusaurus/theme-common": "3.10.2", "@docusaurus/theme-common": "3.10.2",
"@easyops-cn/docusaurus-search-local": "0.55.3", "@easyops-cn/docusaurus-search-local": "0.55.3",
+51
View File
@@ -14,6 +14,9 @@ importers:
'@docusaurus/core': '@docusaurus/core':
specifier: 3.10.2 specifier: 3.10.2
version: 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(debug@4.4.3)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3) version: 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(debug@4.4.3)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
'@docusaurus/plugin-client-redirects':
specifier: 3.10.2
version: 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
'@docusaurus/preset-classic': '@docusaurus/preset-classic':
specifier: 3.10.2 specifier: 3.10.2
version: 3.10.2(@algolia/client-search@5.59.0)(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(search-insights@2.17.3)(typescript@5.9.3) version: 3.10.2(@algolia/client-search@5.59.0)(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(search-insights@2.17.3)(typescript@5.9.3)
@@ -1115,6 +1118,13 @@ packages:
react: '*' react: '*'
react-dom: '*' react-dom: '*'
'@docusaurus/plugin-client-redirects@3.10.2':
resolution: {integrity: sha512-z5I5ttCXw+8y2gHVZvqAMmUw4Rb0ZzKA5eCPk87SfM/jCKOTvE24yDpPAwwipvug96ij7mOwEHXWw8G4LlWdGA==}
engines: {node: '>=20.0'}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
'@docusaurus/plugin-content-blog@3.10.2': '@docusaurus/plugin-content-blog@3.10.2':
resolution: {integrity: sha512-0cbEnNKf0InmLkhj/+nVRmqEnWEoOE8Mh+2x1qOXI0qYpCnphq4RXknVJ8BvybKRXqYVvbmdMfiJSup+k4tm5w==} resolution: {integrity: sha512-0cbEnNKf0InmLkhj/+nVRmqEnWEoOE8Mh+2x1qOXI0qYpCnphq4RXknVJ8BvybKRXqYVvbmdMfiJSup+k4tm5w==}
engines: {node: '>=20.0'} engines: {node: '>=20.0'}
@@ -6784,6 +6794,47 @@ snapshots:
- uglify-js - uglify-js
- webpack-cli - webpack-cli
'@docusaurus/plugin-client-redirects@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)':
dependencies:
'@docusaurus/core': 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(debug@4.4.3)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
'@docusaurus/logger': 3.10.2
'@docusaurus/utils': 3.10.2(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.28))(html-minifier-terser@7.2.0)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@docusaurus/utils-common': 3.10.2(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.28))(html-minifier-terser@7.2.0)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@docusaurus/utils-validation': 3.10.2(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
eta: 2.2.0
fs-extra: 11.4.1
lodash: 4.18.1
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
tslib: 2.8.1
transitivePeerDependencies:
- '@docusaurus/faster'
- '@mdx-js/react'
- '@minify-html/node'
- '@napi-rs/image'
- '@parcel/css'
- '@rspack/core'
- '@swc/core'
- '@swc/css'
- '@swc/html'
- bufferutil
- clean-css
- cssnano
- csso
- debug
- esbuild
- html-minifier-terser
- imagemin
- lightningcss
- postcss
- sharp
- supports-color
- svgo
- typescript
- uglify-js
- utf-8-validate
- webpack-cli
'@docusaurus/plugin-content-blog@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)': '@docusaurus/plugin-content-blog@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)':
dependencies: dependencies:
'@docusaurus/core': 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(debug@4.4.3)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3) '@docusaurus/core': 3.10.2(@mdx-js/react@3.1.1(@types/react@19.1.13)(react@19.1.1))(debug@4.4.3)(postcss@8.5.28)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.3)
-5
View File
@@ -28,11 +28,6 @@
] ]
}, },
"pages": [ "pages": [
{
"id": "index",
"title": "AI adoption strategy",
"purpose": "Govern skills first; outcomes before activity; explicit target status."
},
{ {
"id": "target-operating-model", "id": "target-operating-model",
"title": "Target operating model", "title": "Target operating model",
+11 -3
View File
@@ -88,7 +88,10 @@ const fs = require('node:fs');
if (format.startsWith('svg')) { if (format.startsWith('svg')) {
const valid = await page.evaluate(xml => { const valid = await page.evaluate(xml => {
const doc = new DOMParser().parseFromString(xml, 'image/svg+xml'); const doc = new DOMParser().parseFromString(xml, 'image/svg+xml');
return !doc.querySelector('parsererror') && doc.documentElement.localName === 'svg' && doc.querySelectorAll('text').length > 0; if (doc.querySelector('[data-node-id="humans"], [data-edge-id="human-direction"]')) return false;
if (![...doc.querySelectorAll('[data-node-id="agent"] text')].some(n => n.textContent === 'Human Controlled')) return false;
if (doc.querySelectorAll('[data-node-id]').length !== 17 || doc.querySelectorAll('path[data-edge-id]').length !== 24) return false;
return !doc.querySelector('parsererror') && doc.documentElement.localName === 'svg' && doc.querySelectorAll('text').length > 0 && doc.querySelector('#eldorado-cycle-export')?.textContent.includes('stroke-dasharray: 3 9');
}, bytes.toString()); }, bytes.toString());
assert(valid, format); assert(valid, format);
} else { } else {
@@ -117,10 +120,15 @@ const fs = require('node:fs');
await close.focus(); await page.keyboard.press('Escape'); await close.focus(); await page.keyboard.press('Escape');
assert(await opener.evaluate(n => n === document.activeElement)); assert(await opener.evaluate(n => n === document.activeElement));
await iframe.scrollIntoViewIfNeeded(); await iframe.scrollIntoViewIfNeeded();
await page.evaluate(() => scrollTo(0, 0)); await page.evaluate(() => scrollTo({top: 0, behavior: 'instant'}));
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').click(); await theme('dark');
await page.locator('.strategy-content a[href$="/strategy/target-operating-model/"]').filter({visible:true}).click(); // Exercise keyboard navigation without racing the portal's smooth scroll.
await page.locator('.strategy-content a[href$="/strategy/skills-governance/"]').filter({visible:true}).focus();
await page.keyboard.press('Enter');
await page.waitForURL('**/strategy/skills-governance/');
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 operating model', 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'}`);
+41 -4
View File
@@ -19,7 +19,20 @@ const fs = require('node:fs');
await page.waitForURL('**/strategy/target-operating-model/'); await page.waitForURL('**/strategy/target-operating-model/');
for (const route of ['target-operating-model/', '']) { for (const route of ['target-operating-model/', '']) {
await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}`, {waitUntil:'networkidle'}); await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}`, {waitUntil:'networkidle'});
if (width === 1440) assert.equal(await page.locator('.theme-doc-sidebar-menu .menu__link').first().innerText(), 'Target operating model'); await page.waitForURL('**/strategy/target-operating-model/');
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});
await menu.first().waitFor({state:'visible'});
assert.deepEqual(await menu.allTextContents(), ['Target', 'Roadmap', 'Skills governance', 'Skills quality', 'Skills adoption', 'Measurement', 'Skills maintenance']);
assert((await menu.nth(0).getAttribute('href')).endsWith('/strategy/target-operating-model/'));
assert((await menu.nth(1).getAttribute('href')).endsWith('/strategy/roadmap/'));
assert.equal(await menu.filter({hasText:/^Target$/}).count(), 1);
await page.screenshot({path:`${output}/${width}-${route ? 'target' : 'landing'}-navigation.png`,fullPage:true,animations:'disabled'});
await menu.nth(1).click();
await page.waitForURL('**/strategy/roadmap/');
await page.getByRole('heading', {level:1,name:'Roadmap',exact:true}).waitFor();
await page.goBack({waitUntil:'domcontentloaded'});
await page.waitForURL('**/strategy/target-operating-model/');
const iframe = page.locator(`.archify-panel--story > .story-${width > 700 ? 'desktop' : 'mobile'}`); const iframe = page.locator(`.archify-panel--story > .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();
@@ -32,15 +45,39 @@ const fs = require('node:fs');
const box = n.querySelector('rect').getBoundingClientRect(); const box = n.querySelector('rect').getBoundingClientRect();
return [...n.querySelectorAll('text')].filter(t => {const b=t.getBoundingClientRect();return b.left<box.left||b.right>box.right||b.top<box.top||b.bottom>box.bottom;}).map(t=>t.textContent); return [...n.querySelectorAll('text')].filter(t => {const b=t.getBoundingClientRect();return b.left<box.left||b.right>box.right||b.top<box.top||b.bottom>box.bottom;}).map(t=>t.textContent);
}); });
return {labels,edges,overflow}; const relationships = [...svg.querySelectorAll('path[data-edge-id]')].map(n => ({id:n.dataset.edgeId,from:n.dataset.edgeFrom,to:n.dataset.edgeTo,dash:getComputedStyle(n).strokeDasharray,arrow:n.getAttribute('marker-end')}));
const nodes = [...svg.querySelectorAll('[data-node-id]')].map(n => {const r=n.querySelector('rect').getBoundingClientRect();return {id:n.dataset.nodeId,x:r.x+r.width/2,y:r.y+r.height/2};});
return {labels,edges,overflow,relationships,nodes};
}); });
const ids = ['scope','architecture','ui-ux','planning','delivery','uat','releases']; const ids = ['scope','architecture','ui-ux','planning','delivery','uat','security','releases'];
assert.deepEqual(metrics.edges.map(e=>e.slice(0,2)), ids.map((id,i)=>[id,ids[(i+1)%ids.length]])); assert.deepEqual(metrics.edges.map(e=>e.slice(0,2)), ids.map((id,i)=>[id,ids[(i+1)%ids.length]]));
assert(metrics.edges.every(e=>e[2]?.startsWith('url(')), 'all stages must have arrowheads'); assert(metrics.edges.every(e=>e[2]?.startsWith('url(')), 'all stages must have arrowheads');
assert.equal(metrics.nodes.length, 17);
assert(!metrics.nodes.some(n=>n.id==='humans'));
assert.equal(await frame.locator('[data-node-id="agent"] text').allTextContents().then(texts=>texts.includes('Human Controlled')), true);
assert.equal(metrics.relationships.length, 24);
const governs = metrics.relationships.filter(e=>e.id.startsWith('govern-'));
const contributions = metrics.relationships.filter(e=>e.id.startsWith('contribute-'));
assert.deepEqual(governs.map(e=>[e.from,e.to]), ids.map(id=>['agent',id]));
assert.deepEqual(contributions.map(e=>[e.from,e.to]), ids.map(id=>[`code-${id}`,id]));
assert(governs.every(e=>e.dash==='3px, 9px' && e.arrow?.startsWith('url(')));
assert(contributions.every(e=>e.dash==='12px, 8px' && e.arrow?.startsWith('url(')));
assert(!metrics.relationships.some(e=>e.id==='human-direction' || e.from==='humans' || e.to==='humans'));
if (width > 700) {
const agent = metrics.nodes.find(n=>n.id==='agent');
const phases = metrics.nodes.filter(n=>ids.includes(n.id));
for (const axis of ['x','y']) assert(Math.abs(agent[axis]-(Math.min(...phases.map(n=>n[axis]))+Math.max(...phases.map(n=>n[axis])))/2)<1);
for (const id of ids) {
const phase=phases.find(n=>n.id===id), code=metrics.nodes.find(n=>n.id===`code-${id}`);
assert(Math.hypot(code.x-agent.x,code.y-agent.y)>Math.hypot(phase.x-agent.x,phase.y-agent.y));
}
}
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, []);
assert(!await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth)); assert(!await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth));
await page.evaluate(()=>scrollTo(0,0)); await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));
await page.waitForFunction(()=>scrollY===0);
await page.evaluate(()=>new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve))));
await page.screenshot({path:`${output}/${width}-${route ? 'target' : 'landing'}.png`,fullPage:true}); await page.screenshot({path:`${output}/${width}-${route ? 'target' : 'landing'}.png`,fullPage:true});
results.push({width,route,...metrics}); results.push({width,route,...metrics});
fs.writeFileSync(`${output}/results.json`,JSON.stringify(results,null,2)); fs.writeFileSync(`${output}/results.json`,JSON.stringify(results,null,2));
+6 -3
View File
@@ -19,18 +19,21 @@ const fs=require('node:fs');
const nodes=[...svg.querySelectorAll('[data-node-id]')].map(n=>{const r=n.getBoundingClientRect();return {id:n.id,x:r.x,y:r.y,right:r.right,bottom:r.bottom};}); const nodes=[...svg.querySelectorAll('[data-node-id]')].map(n=>{const r=n.getBoundingClientRect();return {id:n.id,x:r.x,y:r.y,right:r.right,bottom:r.bottom};});
return {width:innerWidth,height:innerHeight,nodes,svg:svg.getBoundingClientRect().toJSON(),minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n=>parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))}; return {width:innerWidth,height:innerHeight,nodes,svg:svg.getBoundingClientRect().toJSON(),minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n=>parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))};
}); });
assert(geometry.nodes.length>=5 && geometry.nodes.length<=(['index','target-operating-model'].includes(id)?9:7),id); assert(geometry.nodes.length>=5 && geometry.nodes.length<=(['index','target-operating-model'].includes(id)?18:7),id);
for(const n of geometry.nodes) assert(n.x>=0 && n.y>=0 && n.right<=geometry.width+1 && n.bottom<=geometry.height+1,`${id} ${width} clipped ${JSON.stringify(n)} / ${geometry.height}`); 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<=200,id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id); assert(data.words<=200,id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
await page.evaluate(()=>scrollTo(0,0));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true}); 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'});
assert.equal(await close.innerText(),'×');assert(await close.evaluate(n=>n===document.activeElement)); assert.equal(await close.innerText(),'×');assert(await close.evaluate(n=>n===document.activeElement));
const box=await close.boundingBox();assert.equal(box.width,44);assert.equal(box.height,44); const box=await close.boundingBox();assert.equal(box.width,44);assert.equal(box.height,44);
await close.click();assert(await opener.evaluate(n=>n===document.activeElement)); await close.click();assert(await opener.evaluate(n=>n===document.activeElement));
await opener.click();await close.waitFor({state:'visible'});await page.keyboard.press('Escape');await page.waitForFunction(()=>!document.querySelector('.archify-panel--story dialog').open);assert(await opener.evaluate(n=>n===document.activeElement)); await opener.click();await close.waitFor({state:'visible'});await page.keyboard.press('Escape');await page.waitForFunction(()=>!document.querySelector('.archify-panel--story dialog').open);assert(await opener.evaluate(n=>n===document.activeElement));
const summary=page.locator('.strategy-content > details > summary').first();await summary.click();assert(await summary.evaluate(n=>n.parentElement.open));await summary.click(); const summary=page.locator('.strategy-content > details > summary').first();
await summary.focus();await page.keyboard.press('Enter');
await page.waitForFunction(()=>document.querySelector('.strategy-content > details').open);
await page.keyboard.press('Enter');
results.push({id,width,...data,geometry,modalClick:true,modalEscape:true,focusRestored:true,details:true});fs.writeFileSync(`.cache/story-${label}/results.json`,JSON.stringify(results,null,2)); results.push({id,width,...data,geometry,modalClick:true,modalEscape:true,focusRestored:true,details:true});fs.writeFileSync(`.cache/story-${label}/results.json`,JSON.stringify(results,null,2));
} }
await page.goto(`${base}/eldorado-v1/documentation/strategy/measurement/#validated-task-success`,{waitUntil:'networkidle'}); await page.goto(`${base}/eldorado-v1/documentation/strategy/measurement/#validated-task-success`,{waitUntil:'networkidle'});
+9 -1
View File
@@ -37,7 +37,15 @@ for (const file of readdirSync('diagrams').sort()) {
if (start < 0 || end < start || preset.split(guard).length !== 3) throw new Error('Archify preset integration drift'); if (start < 0 || end < start || preset.split(guard).length !== 3) throw new Error('Archify preset integration drift');
viewer = viewer.slice(0, start) + preset.replaceAll(guard, '') + viewer.slice(end); viewer = viewer.slice(0, start) + preset.replaceAll(guard, '') + viewer.slice(end);
if (!viewer.includes('</head>') || !viewer.includes('</body>')) throw new Error(`Invalid viewer: ${output}`); if (!viewer.includes('</head>') || !viewer.includes('</body>')) throw new Error(`Invalid viewer: ${output}`);
const storyStyles = ['strategy-target', 'strategy-target-mobile'].includes(name) ? cycleStyles : ''; const storyStyles = ['strategy-target', 'strategy-target-mobile'].includes(name)
? `${name === 'strategy-target' ? ':root {--cycle-label: 27px; --cycle-detail: 21px;}' : ':root {--cycle-label: 38px; --cycle-detail: 28px;}'}${cycleStyles}` : '';
if (storyStyles) {
// Keep typography and relationship styles inside exported standalone SVGs.
const diagramRoot = /<svg\b[^>]*role="img"[^>]*>/g;
if ([...viewer.matchAll(diagramRoot)].length !== 1) throw new Error('Cycle SVG integration drift');
const exportStyles = storyStyles.replaceAll(':root', 'svg[role="img"]').replaceAll('.diagram-container > svg', 'svg[role="img"]');
viewer = viewer.replace(diagramRoot, root => `${root}<style id="eldorado-cycle-export">${exportStyles}</style>`);
}
writeFileSync(output, viewer.replace('</head>', `<style id="eldorado-inline-controls">${inlineStyles}</style><style id="eldorado-cycle-labels">${storyStyles}</style></head>`) writeFileSync(output, viewer.replace('</head>', `<style id="eldorado-inline-controls">${inlineStyles}</style><style id="eldorado-cycle-labels">${storyStyles}</style></head>`)
.replace('</body>', `<script>${themeBridge}</script></body>`)); .replace('</body>', `<script>${themeBridge}</script></body>`));
renameSync(`static/diagrams/${name}/index.delivery.json`, `.cache/archify/${name}.delivery.json`); renameSync(`static/diagrams/${name}/index.delivery.json`, `.cache/archify/${name}.delivery.json`);
+10 -5
View File
@@ -2,13 +2,18 @@
.diagram-container > svg text { .diagram-container > svg text {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
letter-spacing: 0; letter-spacing: 0;
font-size: 18px; font-size: 30px;
} }
.diagram-container > svg text[data-node-label] { .diagram-container > svg text[data-node-label] {
font-size: 24px; font-size: var(--cycle-label);
transform: translateY(-3px); transform: translateY(-6px);
} }
.diagram-container > svg text[data-detail="context"] { .diagram-container > svg text[data-detail="context"] {
font-size: 18px; font-size: var(--cycle-detail);
transform: translateY(7px); transform: translateY(16px);
} }
/* Edge semantics stay in SVG metadata; one page legend avoids repeated labels. */
.diagram-container > svg g[data-edge-id] {display: none;}
.diagram-container > svg path[data-edge-id^="stage-"] {stroke-width: 2.5;}
.diagram-container > svg path[data-edge-id^="govern-"] {stroke-dasharray: 3 9; stroke-width: 3;}
.diagram-container > svg path[data-edge-id^="contribute-"] {stroke-dasharray: 12 8; stroke-width: 3;}
+37 -12
View File
@@ -2,35 +2,60 @@ import {test} from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import {readFileSync} from 'node:fs'; 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', 'Releases']; const stages = ['Scope', 'Architecture', 'UI/UX', 'Planning', 'Delivery', 'UAT', 'Security', 'Releases'];
test('Strategy opens at the autonomous lifecycle, with a matching direct landing story', () => { test('Strategy opens at the canonical autonomous lifecycle', () => {
assert.match(read('sidebars/strategy.ts'), /strategySidebar: \['target-operating-model', 'index'/); assert.match(read('sidebars/strategy.ts'), /strategySidebar: \['target-operating-model', 'roadmap'/);
for (const id of ['index', 'target-operating-model']) { 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 page = read(`docs/strategy/${id}.mdx`);
const primary = page.split('<details>')[0]; const primary = page.split('<details>')[0];
assert(primary.includes('name="strategy-target"')); assert(primary.includes('name="strategy-target"'));
assert(primary.includes('autonomous agent')); assert(primary.includes('autonomous agent'));
assert(primary.includes('direct, guide and review')); assert(primary.includes('direct, guide and review'));
assert(primary.includes('Scope → Architecture → UI/UX → Planning → Delivery → UAT → Releases → Scope')); assert(primary.includes('Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope'));
assert(primary.includes('human-controlled code agent'));
assert(primary.includes('TO-BE')); assert(primary.includes('TO-BE'));
assert(!/only routes|People authorize|independent gates protect release/.test(primary)); assert(!/only routes|People authorize|independent gates protect release/.test(primary));
} }
}); });
test('both target diagrams have exactly seven sequential stages and a Releases to Scope return', () => { test('both target diagrams have eight stages, eight governed phases and eight human-controlled contributors', () => {
for (const suffix of ['', '-mobile']) { for (const suffix of ['', '-mobile']) {
const d = JSON.parse(read(`diagrams/strategy-target${suffix}.architecture.json`)); const d = JSON.parse(read(`diagrams/strategy-target${suffix}.architecture.json`));
const ids = stages.map(label => d.components.find(n => n.label === label)?.id); const ids = stages.map(label => d.components.find(n => n.label === label)?.id);
assert(ids.every(Boolean)); assert(ids.every(Boolean));
assert.equal(new Set(ids).size, 7); assert.equal(new Set(ids).size, 8);
const flow = d.connections.filter(e => ids.includes(e.from) && ids.includes(e.to)); const flow = d.connections.filter(e => ids.includes(e.from) && ids.includes(e.to));
assert.deepEqual(flow.map(e => [e.from, e.to]), ids.map((id, i) => [id, ids[(i + 1) % ids.length]])); assert.deepEqual(flow.map(e => [e.from, e.to]), ids.map((id, i) => [id, ids[(i + 1) % ids.length]]));
assert.match(flow.at(-1).label, /Repeat/); assert.match(flow.at(-1).label, /Repeat/);
assert(flow.at(-1).via.length >= 2, 'explicit outside return corridor');
assert(d.components.some(n => n.label === 'Autonomous agent' && /Executes.*governs/.test(n.sublabel))); assert(d.components.some(n => n.id === 'agent' && n.label === 'Autonomous agent' && n.sublabel === 'Human Controlled'));
assert(d.components.some(n => n.label === 'Humans' && n.sublabel === 'Direct, guide and review')); assert(!d.components.some(n => n.id === 'humans' || n.label === 'Humans'));
assert(d.connections.some(e => e.from === 'humans' && e.to === 'agent')); assert(!d.connections.some(e => e.id === 'human-direction' || e.from === 'humans' || e.to === 'humans'));
assert(d.connections.some(e => e.from === 'agent' && e.to === ids[0])); assert.equal(d.connections.length, 24);
assert.deepEqual(d.connections.filter(e => e.from === 'agent').map(e => e.to), ids);
const contributors = d.components.filter(n => n.id.startsWith('code-'));
assert.equal(contributors.length, 8);
assert(contributors.every(n => n.label === 'Code agent' && n.sublabel === 'Human-controlled'));
for (const id of ids) {
assert(d.connections.some(e => e.from === `code-${id}` && e.to === id && e.variant === 'dashed'));
assert(d.connections.some(e => e.from === 'agent' && e.to === id && e.variant === 'security'));
}
assert.equal(d.components.length, 17);
if (!suffix) {
const center = n => n.pos.map((v, i) => v + n.size[i] / 2);
const agent = center(d.components.find(n => n.id === 'agent'));
const phaseCenters = ids.map(id => center(d.components.find(n => n.id === id)));
for (const axis of [0, 1]) {
const values = phaseCenters.map(c => c[axis]);
assert.equal(agent[axis], (Math.min(...values) + Math.max(...values)) / 2);
}
for (const code of contributors) {
const phase = d.components.find(n => n.id === code.id.slice(5));
const distance = n => Math.hypot(...center(n).map((v, i) => v - agent[i]));
assert(distance(code) > distance(phase), `${code.id} is exterior`);
}
}
} }
}); });
+19
View File
@@ -0,0 +1,19 @@
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync, existsSync} from 'node:fs';
const read = p => readFileSync(p, 'utf8');
test('Strategy has one canonical Target, then Roadmap, without a landing menu duplicate', () => {
const sidebar = read('sidebars/strategy.ts').split('strategySidebar: [')[1].split(']')[0];
const ids = [...sidebar.matchAll(/'([^']+)'/g)].map(match => match[1]);
assert.deepEqual(ids, ['target-operating-model', 'roadmap', 'skills-governance', 'skills-quality', 'skills-adoption', 'measurement', 'skills-maintenance']);
assert.equal(ids.filter(id => id === 'target-operating-model').length, 1);
assert.match(read('docs/strategy/target-operating-model.mdx'), /^sidebar_label: Target$/m);
assert.match(read('docusaurus.config.ts'), /type: 'docSidebar', docsPluginId: 'strategy', sidebarId: 'strategySidebar', label: 'Strategy'/);
});
test('old Strategy entry redirects to Target instead of maintaining a second document', () => {
assert(!existsSync('docs/strategy/index.mdx'));
assert.match(read('docusaurus.config.ts'), /'@docusaurus\/plugin-client-redirects'/);
assert.match(read('docusaurus.config.ts'), /from: '\/strategy\/', to: '\/strategy\/target-operating-model\/'/);
});
+2 -2
View File
@@ -28,10 +28,10 @@ test('mobile story diagrams preserve the same nodes and directed relationships',
const name = /<ArchifyDiagram name="([^"]+)"[^>]+ story/.exec(page)[1]; const name = /<ArchifyDiagram name="([^"]+)"[^>]+ story/.exec(page)[1];
const desktop = JSON.parse(read(`diagrams/${name}.architecture.json`)); const desktop = JSON.parse(read(`diagrams/${name}.architecture.json`));
const mobile = JSON.parse(read(`diagrams/${name}-mobile.architecture.json`)); const mobile = JSON.parse(read(`diagrams/${name}-mobile.architecture.json`));
assert(desktop.components.length >= 5 && desktop.components.length <= (name === 'strategy-target' ? 9 : 7), name); assert(desktop.components.length >= 5 && desktop.components.length <= (name === 'strategy-target' ? 18 : 7), name);
const semantic = d => ({nodes:d.components.map(({pos,size,...n})=>n),edges:d.connections.map(({fromSide,toSide,via,labelAt,...e})=>e)}); const semantic = d => ({nodes:d.components.map(({pos,size,...n})=>n),edges:d.connections.map(({fromSide,toSide,via,labelAt,...e})=>e)});
assert.deepEqual(semantic(desktop), semantic(mobile), name); assert.deepEqual(semantic(desktop), semantic(mobile), name);
assert(desktop.connections.every(e => e.label && e.from !== e.to), name); assert(desktop.connections.every(e => (e.label || e.id.startsWith('govern-')) && e.from !== e.to), name);
assert.equal(desktop.meta.legend.mode, 'hidden'); assert.equal(desktop.meta.legend.mode, 'hidden');
} }
}); });
+3 -3
View File
@@ -3,9 +3,9 @@ import assert from 'node:assert/strict';
import {readFileSync, readdirSync} from 'node:fs'; import {readFileSync, readdirSync} from 'node:fs';
const read = p => readFileSync(p, 'utf8'); const read = p => readFileSync(p, 'utf8');
const model = JSON.parse(read('research/ai-adoption/strategy-model.json')); const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
test('eight fixed strategy pages preserve target boundary and separate evidence', () => { test('seven canonical strategy pages preserve target boundary and separate evidence', () => {
assert.equal(model.pages.length, 8); assert.equal(model.pages.length, 7);
assert.equal(readdirSync('docs/strategy').length, 8); assert.equal(readdirSync('docs/strategy').length, 7);
for (const {id} of model.pages) { for (const {id} of model.pages) {
const page = read(`docs/strategy/${id}.mdx`); const page = read(`docs/strategy/${id}.mdx`);
assert(page.includes(`id: ${id}`)); assert(page.includes(`id: ${id}`));
+3
View File
@@ -18,6 +18,9 @@ assert(workflow.includes("gitea.event_name == 'push' && gitea.ref == 'refs/heads
if (process.argv.includes('--build')) { if (process.argv.includes('--build')) {
const model = JSON.parse(read('research/ai-adoption/strategy-model.json')); const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
const indexes = readdirSync('build').filter(f => /^search-index.*\.json$/.test(f)).map(f => read(join('build',f))).join('\n'); const indexes = readdirSync('build').filter(f => /^search-index.*\.json$/.test(f)).map(f => read(join('build',f))).join('\n');
const redirect = read('build/strategy/index.html');
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');
for (const {id, title} of model.pages) { for (const {id, title} of model.pages) {
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));
+1 -1
View File
@@ -1,2 +1,2 @@
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
export default {strategySidebar: ['target-operating-model', 'index', 'skills-governance', 'skills-quality', 'skills-adoption', 'measurement', 'skills-maintenance', 'roadmap']} satisfies SidebarsConfig; export default {strategySidebar: ['target-operating-model', 'roadmap', 'skills-governance', 'skills-quality', 'skills-adoption', 'measurement', 'skills-maintenance']} satisfies SidebarsConfig;
+2 -2
View File
@@ -110,7 +110,7 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
.archify-panel--story {max-width: 740px;} .archify-panel--story {max-width: 740px;}
.archify-panel--story > iframe {height: auto; aspect-ratio: 480 / 408;} .archify-panel--story > iframe {height: auto; aspect-ratio: 480 / 408;}
.archify-panel--story > .story-mobile {display: none;} .archify-panel--story > .story-mobile {display: none;}
.archify-panel--story[data-diagram="strategy-target"] > iframe {aspect-ratio: 960 / 708;} .archify-panel--story[data-diagram="strategy-target"] > iframe {aspect-ratio: 1620 / 1430;}
.archify-panel--story[data-diagram="strategy-adoption"] > iframe {aspect-ratio: 545 / 408;} .archify-panel--story[data-diagram="strategy-adoption"] > iframe {aspect-ratio: 545 / 408;}
.archify-panel--story[data-diagram="strategy-maintenance"] > iframe {aspect-ratio: 524 / 408;} .archify-panel--story[data-diagram="strategy-maintenance"] > iframe {aspect-ratio: 524 / 408;}
.strategy-content > details {margin: .65rem 0; border: 1px solid var(--line); padding: .8rem 1rem; background: var(--surface);} .strategy-content > details {margin: .65rem 0; border: 1px solid var(--line); padding: .8rem 1rem; background: var(--surface);}
@@ -124,7 +124,7 @@ a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offse
.archify-panel--story[data-diagram="strategy-roadmap"] > .story-mobile {aspect-ratio: 240 / 628;} .archify-panel--story[data-diagram="strategy-roadmap"] > .story-mobile {aspect-ratio: 240 / 628;}
.archify-panel--story[data-diagram="strategy-adoption"] > .story-mobile {aspect-ratio: 305 / 748;} .archify-panel--story[data-diagram="strategy-adoption"] > .story-mobile {aspect-ratio: 305 / 748;}
.archify-panel--story[data-diagram="strategy-maintenance"] > .story-mobile {aspect-ratio: 284 / 748;} .archify-panel--story[data-diagram="strategy-maintenance"] > .story-mobile {aspect-ratio: 284 / 748;}
.archify-panel--story[data-diagram="strategy-target"] > .story-mobile {aspect-ratio: 340 / 1520;} .archify-panel--story[data-diagram="strategy-target"] > .story-mobile {aspect-ratio: 680 / 2340;}
} }
.archify-expand {display: grid; place-items: center; width: 44px; height: 44px; border: 0; padding: 0; background: transparent; color: var(--ifm-link-color); cursor: pointer;} .archify-expand {display: grid; place-items: center; width: 44px; height: 44px; border: 0; padding: 0; background: transparent; color: var(--ifm-link-color); cursor: pointer;}
.archify-expand:hover {background: var(--ifm-hover-overlay);} .archify-expand:hover {background: var(--ifm-hover-overlay);}
+1 -1
View File
@@ -25,7 +25,7 @@ export default function Home(): React.ReactElement {
<div className="section-heading"><div><p className="eyebrow">START HERE</p><h2 id="start-title">A clear place to begin.</h2></div><span className="foundation-badge">Foundation · v1</span></div> <div className="section-heading"><div><p className="eyebrow">START HERE</p><h2 id="start-title">A clear place to begin.</h2></div><span className="foundation-badge">Foundation · v1</span></div>
<div className="start-grid"> <div className="start-grid">
<Link className="start-card" to="/organization/structure/"><span className="card-number">01 / ORGANIZATION</span><h3>Organization</h3><p>Explore the structure workspace and its first interactive diagram.</p><span className="card-action">Explore structure <span aria-hidden="true">↗</span></span></Link> <Link className="start-card" to="/organization/structure/"><span className="card-number">01 / ORGANIZATION</span><h3>Organization</h3><p>Explore the structure workspace and its first interactive diagram.</p><span className="card-action">Explore structure <span aria-hidden="true">↗</span></span></Link>
<Link className="start-card" to="/strategy/"><span className="card-number">02 / STRATEGY</span><h3>Strategy</h3><p>Shape the direction for an AI-powered Eldorado.</p><span className="card-action">View the direction <span aria-hidden="true">↗</span></span></Link> <Link className="start-card" to="/strategy/target-operating-model/"><span className="card-number">02 / STRATEGY</span><h3>Strategy</h3><p>Shape the direction for an AI-powered Eldorado.</p><span className="card-action">View the direction <span aria-hidden="true">↗</span></span></Link>
<Link className="start-card" to="/contribution/"><span className="card-number">03 / CONTRIBUTION</span><h3>Contribution</h3><p>Contribute evidence, proposals, documentation, and diagrams.</p><span className="card-action">Start contributing <span aria-hidden="true">↗</span></span></Link> <Link className="start-card" to="/contribution/"><span className="card-number">03 / CONTRIBUTION</span><h3>Contribution</h3><p>Contribute evidence, proposals, documentation, and diagrams.</p><span className="card-action">Start contributing <span aria-hidden="true">↗</span></span></Link>
</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>