Compare commits

...
Author SHA1 Message Date
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
jarvis-at-skic 29beebb379 docs: lead Strategy with autonomous SDLC cycle
Build and publish Eldorado documentation / build (pull_request) Successful in 51s
2026-10-05 16:32:51 +00:00
jarvis-at-skic e95b85afee Merge pull request 'fix: right-align inline diagram controls' (#17) from fix/right-align-inline-controls into main
Build and publish Eldorado documentation / build (push) Successful in 45s
2026-10-05 05:51:58 -07:00
14 changed files with 309 additions and 339 deletions

No files matched your search

+44 -148
View File
@@ -1,156 +1,52 @@
{ {
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target-mobile/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}},
"title": "TO-BE: coordination without authority transfer",
"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":[140,20],"size":[360,100]},
"id": "people", {"id":"agent","type":"security","label":"Autonomous agent","sublabel":"Executes / governs SDLC","pos":[140,200],"size":[360,120]},
"type": "backend", {"id":"scope","type":"backend","label":"Scope","sublabel":"01","pos":[100,440],"size":[240,100]},
"label": "People authorize", {"id":"architecture","type":"backend","label":"Architecture","sublabel":"02","pos":[100,660],"size":[240,100]},
"sublabel": "Retain accountability", {"id":"ui-ux","type":"backend","label":"UI/UX","sublabel":"03","pos":[100,880],"size":[240,100]},
"pos": [ {"id":"planning","type":"backend","label":"Planning","sublabel":"04","pos":[100,1100],"size":[240,100]},
40, {"id":"delivery","type":"backend","label":"Delivery","sublabel":"05","pos":[100,1320],"size":[240,100]},
20 {"id":"uat","type":"backend","label":"UAT","sublabel":"06","pos":[100,1540],"size":[240,100]},
], {"id":"security","type":"backend","label":"Security","sublabel":"07","pos":[100,1760],"size":[240,100]},
"size": [ {"id":"releases","type":"backend","label":"Releases","sublabel":"08","pos":[100,1980],"size":[240,100]},
180, {"id":"code-scope","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,440],"size":[240,100]},
60 {"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": "coordinator", {"id":"code-uat","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1540],"size":[240,100]},
"type": "backend", {"id":"code-security","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1760],"size":[240,100]},
"label": "SDLC coordinator", {"id":"code-releases","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[400,1980],"size":[240,100]}
"sublabel": "Routes approved work",
"pos": [
40,
260
],
"size": [
180,
60
]
},
{
"id": "clients",
"type": "backend",
"label": "Local coding agents",
"sublabel": "Propose changes",
"pos": [
40,
380
],
"size": [
180,
60
]
},
{
"id": "gates",
"type": "security",
"label": "Repository + CI",
"sublabel": "Verify exact revision",
"pos": [
40,
500
],
"size": [
180,
60
]
},
{
"id": "registry",
"type": "backend",
"label": "Governed skills",
"sublabel": "Pinned + qualified",
"pos": [
40,
140
],
"size": [
180,
60
]
},
{
"id": "approval",
"type": "security",
"label": "Human approval",
"sublabel": "Exact artifact + scope",
"pos": [
40,
620
],
"size": [
180,
60
]
},
{
"id": "release",
"type": "security",
"label": "Release service",
"sublabel": "Production credentials",
"pos": [
40,
740
],
"size": [
180,
60
]
}
], ],
"connections": [ "connections": [
{ {"id":"human-direction","from":"humans","to":"agent","label":"Guide","fromSide":"bottom","toSide":"top"},
"id": "flow-0", {"id":"govern-scope","from":"agent","to":"scope","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,490]]},
"from": "people", {"id":"govern-architecture","from":"agent","to":"architecture","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,710]]},
"to": "coordinator", {"id":"govern-ui-ux","from":"agent","to":"ui-ux","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,930]]},
"label": "Authorize scope" {"id":"govern-planning","from":"agent","to":"planning","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1150]]},
}, {"id":"govern-delivery","from":"agent","to":"delivery","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1370]]},
{ {"id":"govern-uat","from":"agent","to":"uat","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1590]]},
"id": "flow-1", {"id":"govern-security","from":"agent","to":"security","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,1810]]},
"from": "coordinator", {"id":"govern-releases","from":"agent","to":"releases","label":"","variant":"security","fromSide":"left","toSide":"left","via":[[60,260],[60,2030]]},
"to": "clients", {"id":"stage-1","from":"scope","to":"architecture","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
"label": "Route tasks" {"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": "flow-2", {"id":"stage-5","from":"delivery","to":"uat","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
"from": "registry", {"id":"stage-6","from":"uat","to":"security","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
"to": "coordinator", {"id":"stage-7","from":"security","to":"releases","label":"Then","variant":"emphasis","fromSide":"bottom","toSide":"top"},
"label": "Guide" {"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": "flow-3", {"id":"contribute-ui-ux","from":"code-ui-ux","to":"ui-ux","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
"from": "registry", {"id":"contribute-planning","from":"code-planning","to":"planning","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
"to": "clients", {"id":"contribute-delivery","from":"code-delivery","to":"delivery","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right"},
"label": "Guide" {"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"}
"id": "flow-4",
"from": "clients",
"to": "gates",
"label": "Propose"
},
{
"id": "flow-5",
"from": "gates",
"to": "approval",
"label": "Evidence"
},
{
"id": "flow-6",
"from": "approval",
"to": "release",
"label": "Authorize"
}
] ]
} }
+44 -148
View File
@@ -1,156 +1,52 @@
{ {
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {"title": "TO-BE: autonomous SDLC, human direction", "output": "static/diagrams/strategy-target/index.html", "quality_profile": "showcase", "legend": {"mode": "hidden"}},
"title": "TO-BE: coordination without authority transfer",
"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":[465,322.5],"size":[270,75]},
"id": "people", {"id":"agent","type":"security","label":"Autonomous agent","sublabel":"Executes / governs SDLC","pos":[465,450],"size":[270,90]},
"type": "backend", {"id":"scope","type":"backend","label":"Scope","sublabel":"01","pos":[510,187.5],"size":[180,75]},
"label": "People authorize", {"id":"architecture","type":"backend","label":"Architecture","sublabel":"02","pos":[780,187.5],"size":[180,75]},
"sublabel": "Retain accountability", {"id":"ui-ux","type":"backend","label":"UI/UX","sublabel":"03","pos":[780,457.5],"size":[180,75]},
"pos": [ {"id":"planning","type":"backend","label":"Planning","sublabel":"04","pos":[780,727.5],"size":[180,75]},
20, {"id":"delivery","type":"backend","label":"Delivery","sublabel":"05","pos":[510,727.5],"size":[180,75]},
20 {"id":"uat","type":"backend","label":"UAT","sublabel":"06","pos":[240,727.5],"size":[180,75]},
], {"id":"security","type":"backend","label":"Security","sublabel":"07","pos":[240,457.5],"size":[180,75]},
"size": [ {"id":"releases","type":"backend","label":"Releases","sublabel":"08","pos":[240,187.5],"size":[180,75]},
180, {"id":"code-scope","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[510,37.5],"size":[180,75]},
60 {"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": "coordinator", {"id":"code-uat","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[240,877.5],"size":[180,75]},
"type": "backend", {"id":"code-security","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[15,457.5],"size":[180,75]},
"label": "SDLC coordinator", {"id":"code-releases","type":"frontend","label":"Code agent","sublabel":"Human-controlled","pos":[240,37.5],"size":[180,75]}
"sublabel": "Routes approved work",
"pos": [
20,
140
],
"size": [
180,
60
]
},
{
"id": "clients",
"type": "backend",
"label": "Local coding agents",
"sublabel": "Propose changes",
"pos": [
20,
260
],
"size": [
180,
60
]
},
{
"id": "gates",
"type": "security",
"label": "Repository + CI",
"sublabel": "Verify exact revision",
"pos": [
20,
380
],
"size": [
180,
60
]
},
{
"id": "registry",
"type": "backend",
"label": "Governed skills",
"sublabel": "Pinned + qualified",
"pos": [
260,
140
],
"size": [
180,
60
]
},
{
"id": "approval",
"type": "security",
"label": "Human approval",
"sublabel": "Exact artifact + scope",
"pos": [
260,
380
],
"size": [
180,
60
]
},
{
"id": "release",
"type": "security",
"label": "Release service",
"sublabel": "Production credentials",
"pos": [
260,
500
],
"size": [
180,
60
]
}
], ],
"connections": [ "connections": [
{ {"id":"human-direction","from":"humans","to":"agent","label":"Guide","fromSide":"bottom","toSide":"top"},
"id": "flow-0", {"id":"govern-scope","from":"agent","to":"scope","label":"","variant":"security","fromSide":"right","toSide":"bottom","via":[[750,495],[750,292.5],[600,292.5]]},
"from": "people", {"id":"govern-architecture","from":"agent","to":"architecture","label":"","variant":"security","fromSide":"right","toSide":"bottom","via":[[765,495],[765,345],[870,345]]},
"to": "coordinator", {"id":"govern-ui-ux","from":"agent","to":"ui-ux","label":"","variant":"security","fromSide":"right","toSide":"left"},
"label": "Authorize scope" {"id":"govern-planning","from":"agent","to":"planning","label":"","variant":"security","fromSide":"right","toSide":"top","via":[[765,495],[765,690],[870,690]]},
}, {"id":"govern-delivery","from":"agent","to":"delivery","label":"","variant":"security","fromSide":"bottom","toSide":"top"},
{ {"id":"govern-uat","from":"agent","to":"uat","label":"","variant":"security","fromSide":"left","toSide":"top","via":[[435,495],[435,690],[330,690]]},
"id": "flow-1", {"id":"govern-security","from":"agent","to":"security","label":"","variant":"security","fromSide":"left","toSide":"right"},
"from": "coordinator", {"id":"govern-releases","from":"agent","to":"releases","label":"","variant":"security","fromSide":"left","toSide":"bottom","via":[[435,495],[435,345],[330,345]]},
"to": "clients", {"id":"stage-1","from":"scope","to":"architecture","label":"Then","variant":"emphasis","fromSide":"right","toSide":"left"},
"label": "Route tasks" {"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": "flow-2", {"id":"stage-5","from":"delivery","to":"uat","label":"Then","variant":"emphasis","fromSide":"left","toSide":"right"},
"from": "registry", {"id":"stage-6","from":"uat","to":"security","label":"Then","variant":"emphasis","fromSide":"top","toSide":"bottom"},
"to": "coordinator", {"id":"stage-7","from":"security","to":"releases","label":"Then","variant":"emphasis","fromSide":"top","toSide":"bottom"},
"label": "Guide" {"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": "flow-3", {"id":"contribute-ui-ux","from":"code-ui-ux","to":"ui-ux","label":"Contribute","variant":"dashed","fromSide":"left","toSide":"right","labelAt":[990,570]},
"from": "registry", {"id":"contribute-planning","from":"code-planning","to":"planning","label":"Contribute","variant":"dashed","fromSide":"top","toSide":"bottom"},
"to": "clients", {"id":"contribute-delivery","from":"code-delivery","to":"delivery","label":"Contribute","variant":"dashed","fromSide":"top","toSide":"bottom"},
"label": "Guide" {"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"}
"id": "flow-4",
"from": "clients",
"to": "gates",
"label": "Propose"
},
{
"id": "flow-5",
"from": "gates",
"to": "approval",
"label": "Evidence"
},
{
"id": "flow-6",
"from": "approval",
"to": "release",
"label": "Authorize"
}
] ]
} }
+12 -10
View File
@@ -1,7 +1,7 @@
--- ---
id: index id: index
title: AI adoption strategy title: AI adoption strategy
description: Govern skills first; outcomes before activity; explicit target status. description: An autonomous SDLC cycle directed, guided and reviewed by humans, supported by governed skills.
slug: / slug: /
hide_table_of_contents: true hide_table_of_contents: true
--- ---
@@ -12,15 +12,17 @@ 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.**
## How do we reach dependable AI-assisted work? ## Autonomous SDLC, human direction
Start with governed skills, then widen coordination only when evidence supports it. The destination is one logical SDLC coordinator alongside people using qualified local coding agents. <ArchifyDiagram name="strategy-target" title="Autonomous agent executes and governs the SDLC; humans direct, guide and review" story />
<ArchifyDiagram name="strategy-journey" title="Skills and quality evidence precede wider coordination" story /> 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.
- **Skills first:** reusable working knowledge, not permission to act. **Solid arrows:** lifecycle · **Dotted spokes:** execution and governance · **Dashed arrows:** contributions.
- **People stay accountable:** the six departments and eleven teams keep their decisions.
- **Outcomes before activity:** quality, risk and total cost determine whether to continue. **Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → 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> <details>
<summary>Strategy rationale and reading map</summary> <summary>Strategy rationale and reading map</summary>
@@ -31,7 +33,7 @@ Start with governed skills, then widen coordination only when evidence supports
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 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 one logical SDLC coordinating agent with developer choice on local laptops. Copilot, Claude Code and Cline remain client options within a qualified support matrix. They receive the same reviewed portable skill content through client-specific adapters. Repository, CI and release services remain the enforcement points, independently of what any agent says or which local tool produced a change. 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. 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.
@@ -39,7 +41,7 @@ Success means accepted outcomes with maintained quality, controlled risk and und
## Navigate the strategy ## Navigate the strategy
- [Target operating model](./target-operating-model.mdx) — One logical coordinator; local client choice; independent authority; all departments. - [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 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.
@@ -49,6 +51,6 @@ Success means accepted outcomes with maintained quality, controlled risk and und
</details> </details>
**Next:** [See how people, skills and delivery controls connect →](./target-operating-model.mdx) **Next:** [Explore the autonomous SDLC cycle →](./target-operating-model.mdx)
</div> </div>
+24 -19
View File
@@ -1,7 +1,8 @@
--- ---
id: target-operating-model id: target-operating-model
title: Target operating model title: Target operating model
description: One logical coordinator; local client choice; independent authority; all departments. sidebar_label: Target
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
--- ---
@@ -9,42 +10,44 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
<div className="strategy-content"> <div className="strategy-content">
**TO-BE · Target operating model — not installed controls or company results.** **TO-BE · Target operating model — the intended strategy, not a deployed system.**
## Who coordinates, and who can authorize delivery? ## Autonomous SDLC, human direction
One logical coordinator routes work; people retain authority. Local agents propose changes, while independent CI and human approval govern what the release service can execute. <ArchifyDiagram name="strategy-target" title="Autonomous agent executes and governs the SDLC; humans direct, guide and review" story />
<ArchifyDiagram name="strategy-target" title="People authorize; skills guide; independent gates protect release" story /> 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.
- **Local choice:** Copilot, Claude Code and Cline use qualified adapters and pinned skills. **Solid arrows:** lifecycle · **Dotted spokes:** execution and governance · **Dashed arrows:** contributions.
- **Central controls:** neither laptops nor the coordinator hold production credentials.
- **Existing organization:** six departments, eleven teams; Data &amp; AI owns coordination, not their decisions. **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.
<details> <details>
<summary>Trust boundaries, recovery and detailed delivery path</summary> <summary>Supporting implementation options: trust boundaries and recovery</summary>
## Coordination without transferred authority ## Controls that support autonomous execution
The diagram is an overview; the equivalent delivery path below remains readable on narrow screens. Expand the diagram to inspect its trust boundaries and use its zoom controls for individual relationships. The lifecycle above is the strategic direction. The earlier control design below is a supporting implementation option, not an agreed assignment of approval roles or a claim of installed controls. Detailed approval policy and responsibilities remain to be defined with humans.
1. Accountable people authorize the work scope; one logical coordinator routes tasks. 1. Humans direct, guide and review; the autonomous agent executes and governs work across the lifecycle.
2. The reviewed registry supplies pinned skills and qualified adapters to coordinator and local clients. 2. The reviewed registry supplies pinned skills and qualified adapters to coordinator and local clients.
3. Laptop contributors propose changes; independent repository and CI checks verify the exact revision. 3. Laptop contributors can participate alongside the agent; independent repository and CI checks verify the exact revision.
4. A human approves that artifact; only the release service holds production credentials. 4. A separate release service and artifact-scoped approval are possible controls, subject to the policy humans define.
5. Restricted audit and measurement evidence returns to people and informs the next authorized task. 5. Restricted audit and measurement evidence supports human review and the next Scope iteration.
<ArchifyDiagram name="ai-adoption-target" title="TO-BE AI adoption: human accountability, no direct production authority for laptops or coordinator" /> <ArchifyDiagram name="ai-adoption-target" title="Supporting control option, not agreed approval policy: isolated release authority" />
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results. **TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results.
### One coordination function, distributed contributions ### One coordination function, distributed contributions
Data & AI owns the coordinating function, with the existing AI Architect function connecting it to Technology leadership. The logical coordinator maintains approved work records, dependencies, evidence requests, bounded retries and escalation. It can summarize, propose work and route decisions. It cannot declare its own work approved, change protected checks, authorize production release or replace the responsible human. The autonomous agent is more than a task router: it executes and governs the repeating SDLC under human direction, guidance and review. A coordinating function maintains work records, dependencies, evidence requests, bounded retries and escalation. Data & AI and the existing AI Architect function are possible implementation contributors, not newly assigned approval authorities. Autonomous execution does not remove human involvement or allow the agent to redefine its own controls.
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.
The delivery path is: an approved problem and acceptance criteria; an authorized task; local or isolated worker proposals; independently reviewed repository changes; exact-revision CI evidence; a human release decision; execution by the release service; then operational feedback. Product Management accepts the outcome hypothesis and business result. Product Design reviews experience and accessibility. Product Engineering owns the code and maintainability. Quality Engineering assesses quality independently. Architecture & Security assesses risk. Platform & IT operates the delivery boundary. No arrow from a laptop or coordinator goes directly to production authority. 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
@@ -57,10 +60,12 @@ Central controls verify protected-branch review, actual artifact identity, exact
</details> </details>
<details> <details>
<summary>Responsibilities and first workflows for all eleven teams</summary> <summary>Candidate contributions and first workflows for all eleven teams</summary>
### 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.
### Product / Product Management ### Product / Product Management
**Contribution and retained human decision** — Own pilot priorities, acceptance criteria and outcome hypotheses; decide product value. **Contribution and retained human decision** — Own pilot priorities, acceptance criteria and outcome hypotheses; decide product value.
+1 -1
View File
@@ -15,7 +15,7 @@
"verify:build": "node scripts/verify.mjs --build", "verify:build": "node scripts/verify.mjs --build",
"diagrams:build": "node scripts/build-diagrams.mjs", "diagrams:build": "node scripts/build-diagrams.mjs",
"test": "node --test scripts/*.test.mjs", "test": "node --test scripts/*.test.mjs",
"test:browser": "node scripts/browser/strategy-story.cjs && node scripts/browser/inline-controls.cjs", "test:browser": "node scripts/browser/strategy-story.cjs && node scripts/browser/inline-controls.cjs && node scripts/browser/sdlc-cycle.cjs",
"kpi:example": "node scripts/ai-kpi.mjs" "kpi:example": "node scripts/ai-kpi.mjs"
}, },
"dependencies": { "dependencies": {
+8 -3
View File
@@ -88,7 +88,7 @@ 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; 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 +117,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/target-operating-model/"]').filter({visible:true}).focus();
await page.keyboard.press('Enter');
await page.waitForURL('**/strategy/target-operating-model/');
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'}`);
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');
+74
View File
@@ -0,0 +1,74 @@
const {chromium} = require('playwright');
const assert = require('node:assert/strict');
const fs = require('node:fs');
(async () => {
const base = process.argv[2] || 'http://127.0.0.1:4173';
const output = `.cache/cycle-${process.argv[3] || 'local'}`;
fs.mkdirSync(output, {recursive:true});
const browser = await chromium.launch({headless:true, executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args:['--no-sandbox']});
const results = [];
try {
for (const width of [1440, 390, 320]) {
const context = await browser.newContext({viewport:{width,height:1000}, colorScheme:'light'});
const page = await context.newPage();
await page.goto(`${base}/eldorado-v1/documentation/`, {waitUntil:'networkidle'});
if (width < 700) await page.getByRole('button', {name:'Toggle navigation bar'}).click();
const nav = page.getByRole('link', {name:'Strategy', exact:true}).filter({visible:true});
assert((await nav.getAttribute('href')).endsWith('/strategy/target-operating-model/'));
await nav.click();
await page.waitForURL('**/strategy/target-operating-model/');
for (const route of ['target-operating-model/', '']) {
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');
const iframe = page.locator(`.archify-panel--story > .story-${width > 700 ? 'desktop' : 'mobile'}`);
await iframe.scrollIntoViewIfNeeded();
const frame = await (await iframe.elementHandle()).contentFrame();
await frame.locator('svg[role="img"]').waitFor();
const metrics = await frame.evaluate(() => {
const svg = document.querySelector('svg[role="img"]');
const labels = [...svg.querySelectorAll('text[data-node-label]')].map(n => ({text:n.textContent,px:parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a}));
const edges = [...svg.querySelectorAll('path[data-edge-id^="stage-"]')].map(n => [n.dataset.edgeFrom,n.dataset.edgeTo,n.getAttribute('marker-end')]);
const overflow = [...svg.querySelectorAll('[data-node-id]')].flatMap(n => {
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);
});
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','security','releases'];
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.equal(metrics.nodes.length, 18);
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.from==='humans' && e.to==='agent'));
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.deepEqual(metrics.overflow, []);
assert(!await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth));
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});
results.push({width,route,...metrics});
fs.writeFileSync(`${output}/results.json`,JSON.stringify(results,null,2));
}
await context.close();
}
assert.equal(results.length,6);
console.log('PASS 6 cycle routes/viewports: navigation, sidebar order, exact directed loop, arrowheads, >=14px labels, text bounds and no overflow');
} finally {await browser.close();}
})().catch(error=>{console.error(error);process.exitCode=1;});
+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<=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'});
+11 -1
View File
@@ -4,6 +4,7 @@ import {execFileSync} from 'node:child_process';
const cli = 'vendor/archify/bin/archify.mjs'; const cli = 'vendor/archify/bin/archify.mjs';
const types = new Set(['architecture','workflow','sequence','dataflow','lifecycle']); const types = new Set(['architecture','workflow','sequence','dataflow','lifecycle']);
const inlineStyles = readFileSync(new URL('./inline-viewer.css', import.meta.url), 'utf8'); const inlineStyles = readFileSync(new URL('./inline-viewer.css', import.meta.url), 'utf8');
const cycleStyles = readFileSync(new URL('./cycle-viewer.css', import.meta.url), 'utf8');
const themeBridge = readFileSync(new URL('./viewer-theme-bridge.js', import.meta.url), 'utf8'); const themeBridge = readFileSync(new URL('./viewer-theme-bridge.js', import.meta.url), 'utf8');
// This directory is generated-only and ignored by Git. Remove stale artifacts. // This directory is generated-only and ignored by Git. Remove stale artifacts.
rmSync('static/diagrams', {recursive: true, force: true}); rmSync('static/diagrams', {recursive: true, force: true});
@@ -36,7 +37,16 @@ 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}`);
writeFileSync(output, viewer.replace('</head>', `<style id="eldorado-inline-controls">${inlineStyles}</style></head>`) 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>`)
.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`);
} }
+19
View File
@@ -0,0 +1,19 @@
/* Readable lifecycle story at inline scale, isolated from other diagrams. */
.diagram-container > svg text {
font-family: Arial, sans-serif;
letter-spacing: 0;
font-size: 30px;
}
.diagram-container > svg text[data-node-label] {
font-size: var(--cycle-label);
transform: translateY(-6px);
}
.diagram-container > svg text[data-detail="context"] {
font-size: var(--cycle-detail);
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;}
+60
View File
@@ -0,0 +1,60 @@
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync} from 'node:fs';
const read = p => readFileSync(p, 'utf8');
const stages = ['Scope', 'Architecture', 'UI/UX', 'Planning', 'Delivery', 'UAT', 'Security', 'Releases'];
test('Strategy opens at the autonomous lifecycle, with a matching direct landing story', () => {
assert.match(read('sidebars/strategy.ts'), /strategySidebar: \['target-operating-model', 'index'/);
assert.match(read('docs/strategy/target-operating-model.mdx'), /^sidebar_label: Target$/m);
for (const id of ['index', 'target-operating-model']) {
const page = read(`docs/strategy/${id}.mdx`);
const primary = page.split('<details>')[0];
assert(primary.includes('name="strategy-target"'));
assert(primary.includes('autonomous agent'));
assert(primary.includes('direct, guide and review'));
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(!/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', () => {
for (const suffix of ['', '-mobile']) {
const d = JSON.parse(read(`diagrams/strategy-target${suffix}.architecture.json`));
const ids = stages.map(label => d.components.find(n => n.label === label)?.id);
assert(ids.every(Boolean));
assert.equal(new Set(ids).size, 8);
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.match(flow.at(-1).label, /Repeat/);
assert(d.components.some(n => n.label === 'Autonomous agent' && /Executes.*governs/.test(n.sublabel)));
assert(d.components.some(n => n.label === 'Humans' && n.sublabel === 'Direct, guide and review'));
assert(d.connections.some(e => e.from === 'humans' && e.to === 'agent'));
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, 18);
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`);
}
}
}
});
+3 -3
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 <= 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,...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');
} }
}); });
+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: ['index', 'target-operating-model', 'skills-governance', 'skills-quality', 'skills-adoption', 'measurement', 'skills-maintenance', 'roadmap']} satisfies SidebarsConfig; export default {strategySidebar: ['target-operating-model', 'index', 'skills-governance', 'skills-quality', 'skills-adoption', 'measurement', 'skills-maintenance', 'roadmap']} 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: 480 / 628;} .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: 301 / 868;} .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);}