Spec
Intent
DoCoDeGo replaces the 2-week sprint with a continuous loop running at the cadence of validation. Render the five stations as a closed circuit with an orbiting indicator — the system never stops, it converges.
Acceptance Criteria
[ ] Five labelled stations: spec / compose / validate / ship / learn
[ ] Visual indication of continuous flow (looping arrow or orbit)
[ ] Loop closes back to spec
Constraints
CSS keyframe rotation acceptable
No timebox labels — that's the point
// sprint-replacement-loop.astro copy
---
import type { CompendiumMeta } from '../../../data/types';
export const meta: CompendiumMeta = {
id: 30,
slug: 'sprint-replacement-loop',
name: 'Sprint Replacement Loop',
category: 'maturity-process',
subcategory: 'flow',
pillar: 'de',
description: 'Why sprints are obsolete: a continuous spec → compose → validate → ship → loop, no timeboxes.',
spec: `## Intent
DoCoDeGo replaces the 2-week sprint with a continuous loop running at the cadence of validation. Render the five stations as a closed circuit with an orbiting indicator — the system never stops, it converges.
## Acceptance Criteria
- [ ] Five labelled stations: spec / compose / validate / ship / learn
- [ ] Visual indication of continuous flow (looping arrow or orbit)
- [ ] Loop closes back to spec
## Constraints
- CSS keyframe rotation acceptable
- No timebox labels — that's the point`,
tags: ['svg', 'animated', 'reduced-motion', 'real-content', 'dark-mode-tested'],
status: 'stable',
health: { ics: 86, a11y: 'aa', themed: true, animated: true },
};
const stations = [
{ i: 1, label: 'SPEC', tone: 'do' },
{ i: 2, label: 'COMPOSE', tone: 'co' },
{ i: 3, label: 'VALIDATE', tone: 'de' },
{ i: 4, label: 'SHIP', tone: 'success' },
{ i: 5, label: 'LEARN', tone: 'go' },
];
const toneClass: Record<string,string> = {
do: 'bg-do', co: 'bg-co', de: 'bg-de', success: 'bg-success', go: 'bg-go',
};
---
<div data-this-component class="w-full bg-paper text-ink border-4 border-ink overflow-hidden">
<header class="flex items-baseline justify-between px-3 py-2 border-b-2 border-ink">
<span class="font-mono text-[10px] uppercase tracking-widest opacity-60">// continuous loop</span>
<span class="font-mono text-[10px] uppercase tracking-widest">no timebox</span>
</header>
<div class="p-3 overflow-hidden">
<div class="relative mx-auto loop-orbit" style="width:200px;height:200px;max-width:100%;">
<svg viewBox="0 0 200 200" class="absolute inset-0 w-full h-full" aria-hidden="true">
<circle cx="100" cy="100" r="62" fill="none" stroke="var(--color-ink)" stroke-width="3" stroke-dasharray="4 4" />
<circle cx="100" cy="100" r="62" fill="none" stroke="var(--color-de)" stroke-width="4" stroke-dasharray="20 380" pathLength="400" class="orbit-dot" />
</svg>
{stations.map((s, idx) => {
const angle = (idx / stations.length) * 360 - 90;
const rad = (angle * Math.PI) / 180;
const x = 100 + Math.cos(rad) * 62;
const y = 100 + Math.sin(rad) * 62;
return (
<div
class:list={[
'absolute -translate-x-1/2 -translate-y-1/2 border-2 border-ink px-1.5 py-0.5 font-black text-[9px] tracking-widest text-ink',
toneClass[s.tone],
]}
style={`left:${x}px;top:${y}px;`}
>{s.label}</div>
);
})}
</div>
</div>
</div>
<style>
[data-this-component] .orbit-dot {
animation: loop-spin 6s linear infinite;
transform-origin: 100px 100px;
}
@keyframes loop-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
[data-this-component] .orbit-dot { animation: none; }
}
</style>