Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
changelog:
exclude:
labels:
- ignore-for-release
- skip-changelog
authors:
- dependabot
- dependabot[bot]
categories:
- title: "🚀 New Features"
labels:
- feature
- enhancement
- feat
- title: "🎨 Manifesto & UI"
labels:
- design
- ui
- manifesto
- content
- title: "🧹 Maintenance"
labels:
- chore
- refactor
- maintenance
- title: "🐛 Bug Fixes"
labels:
- bug
- fix
- title: "📚 Documentation"
labels:
- documentation
- docs
- title: "📦 Other Changes"
labels:
- "*"
124 changes: 124 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Release

on:
workflow_dispatch:
inputs:
version:
description: "Semver version without v, for example 1.1.0"
required: true
type: string
target:
description: "Commit, tag, or branch to release"
required: true
default: main
type: string
draft:
description: "Create the GitHub release as a draft"
required: true
default: true
type: boolean
prerelease:
description: "Mark the GitHub release as a prerelease"
required: true
default: false
type: boolean
notes:
description: "Optional release notes override. Leave empty to use GitHub generated notes."
required: false
type: string

concurrency:
group: release-${{ inputs.version }}
cancel-in-progress: false

permissions:
contents: write

jobs:
release:
name: Create GitHub release
runs-on: ubuntu-latest

steps:
- name: Guard release branch
if: github.ref != 'refs/heads/main'
run: |
echo "Releases must be started from the main branch workflow."
echo "Current ref: ${GITHUB_REF}"
exit 1

- name: Checkout target
uses: actions/checkout@v6
with:
ref: ${{ inputs.target }}
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "24"
cache: npm
cache-dependency-path: app/package-lock.json

- name: Install dependencies
working-directory: app
run: npm ci

- name: Build
working-directory: app
run: npm run build

- name: Test
working-directory: app
run: npm test

- name: Check component LOC budget
working-directory: app
run: bash tests/check-component-loc.sh

- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
DRAFT: ${{ inputs.draft }}
PRERELEASE: ${{ inputs.prerelease }}
NOTES: ${{ inputs.notes }}
run: |
set -euo pipefail

if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Version must be strict semver without a leading v, for example 1.1.0."
exit 1
fi

tag="v${VERSION}"
target_sha="$(git rev-parse HEAD)"

if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
echo "Tag ${tag} already exists on origin."
exit 1
fi

args=(
"$tag"
--target "$target_sha"
--title "AIDD Manifesto ${tag}"
)

if [[ "$DRAFT" == "true" ]]; then
args+=(--draft)
fi

if [[ "$PRERELEASE" == "true" ]]; then
args+=(--prerelease)
fi

if [[ -n "$NOTES" ]]; then
notes_file="$(mktemp)"
printf '%s\n' "$NOTES" > "$notes_file"
gh release create "${args[@]}" --notes-file "$notes_file"
else
gh release create "${args[@]}" --generate-notes
fi

echo "Created GitHub release ${tag} for ${target_sha}."
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ app/
- Edit mode parent iframe : sentinelle `/*EDITMODE-BEGIN*/…/*EDITMODE-END*/`
préservée dans `src/components/ClientApp.astro` (ne pas renommer).

## Illustrations des commitments

- Les démos des 12 commitments vivent dans `app/src/components/principles/PrincipleDemo.astro` et `app/src/styles/sections/principle-demos.css`.
- Elles doivent expliquer le principe par un mécanisme visuel minimal et animé, pas par des icônes décoratives, des faux terminaux, ou des cartes textuelles génériques.
- Une bonne démo montre une transformation lisible : bloc vers incréments vérifiés, spec qui s'écrit, plan qui relie humain/codebase, apprentissage capturé, etc.
- Ajouter du texte uniquement quand il rend le schéma plus évident. Les labels doivent nommer des objets réels du workflow AIDD (`DEV`, `Plan`, `Implement`, `Review`, `Test`, `compact`, `new chat`) plutôt que des lettres abstraites.
- Commitment 07 : représenter un développeur responsable de la revue et de la maintenance. Ne pas utiliser un hash ou une marque abstraite à la place de la personne.
- Commitment 08 : l'évaluation doit être explicite. Montrer que le développeur peut lire/tester avant de déléguer ; éviter les schémas ambigus de lentilles ou de sas sans contexte.
- Commitment 09 : nommer les phases d'implémentation (`Plan`, `Implement`, `Review`, `Test`) plutôt que des initiales.
- Commitment 10 : montrer la continuité de contexte sous forme de chat compacté ou de nouveau chat démarré depuis le contexte précédent.
- Commitment 11 : montrer l'échec IA comme un diagnostic actionnable, pas comme un effet décoratif. Le schéma doit faire comprendre qu'on inspecte scope, contexte, hypothèses et tests.
- Commitment 12 : pousser l'idée de transférabilité : plusieurs personnes/outils doivent passer par une même méthode et produire une qualité comparable.

## Édition du contenu

- Ajouter/modifier un principe : `app/src/content/principles.ts`.
Expand Down
3 changes: 1 addition & 2 deletions app/src/components/ClientApp.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
// EDIT MODE sentinel preserved verbatim (do not rename markers).
---
<script>
import { observeReveals, observeTerminals, observeValueArt, attachHeroParallax, observeSpecIndex, observeFocusBand } from '~/lib/observers';
import { observeReveals, observeValueArt, attachHeroParallax, observeSpecIndex, observeFocusBand } from '~/lib/observers';

observeReveals();
observeTerminals();
observeValueArt();
attachHeroParallax();
observeSpecIndex();
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/layout/Page.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import '~/styles/sections/chapters.css';
import '~/styles/sections/values.css';
import '~/styles/sections/value-art.css';
import '~/styles/sections/principles.css';
import '~/styles/sections/terminal.css';
import '~/styles/sections/principle-demos.css';
import '~/styles/sections/signature.css';
import '~/styles/sections/footer.css';
import '~/styles/sections/reveal.css';
Expand Down
8 changes: 3 additions & 5 deletions app/src/components/principles/PrincipleCard.astro
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
---
import type { Principle } from '~/content/principles';
import TerminalAnim from '~/components/terminal/TerminalAnim.astro';
import type { Term } from '~/content/terms';
import PrincipleDemo from '~/components/principles/PrincipleDemo.astro';
import Icon from '~/components/Icon.astro';
import type { PrincipleIconKey } from '~/content/icons';

interface Props {
principle: Principle;
index: number;
term?: Term;
}
const { principle: p, index: i, term } = Astro.props;
const { principle: p, index: i } = Astro.props;
---
<article id={`P-${p.n}`} class="principle reveal" data-idx={i} style={`--p-hue: ${p.hue}`}>
<span class="p-folio" aria-hidden="true">{p.r}</span>
Expand All @@ -19,5 +17,5 @@ const { principle: p, index: i, term } = Astro.props;
<p class="p-lead" set:html={p.lead} />
<p class="p-sub">{p.sub}</p>
</div>
{term && <TerminalAnim term={term} index={i} />}
<PrincipleDemo index={i} />
</article>
79 changes: 79 additions & 0 deletions app/src/components/principles/PrincipleDemo.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
interface Props {
index: number;
}

const { index } = Astro.props;
const number = String(index + 1).padStart(2, '0');
const verifiedCells = Array.from({ length: 24 }, (_, i) => {
const phase = i * 84;
return `<span class="micro-cell" style="--phase:${phase}ms" aria-hidden="true"></span>`;
}).join('');
const factoryDemo = `<div class="scene-factory micro-table" role="img" aria-label="One table row of tiny cells turning green from left to right">${verifiedCells}</div>`;
const asciiSpecLines = [
'+-- spec.md --------+',
'| goal: clear build |',
'| input: intent |',
'| steps: |',
'| [ ] scope |',
'| [ ] acceptance |',
'| [ ] review |',
'+-------------------+',
].map((line, i) => `<span class="ascii-line" style="--delay:${i * 280}ms">${line}</span>`).join('');
const specDemo = `<div class="scene-ascii-doc" role="img" aria-label="An ASCII specification document writing itself"><pre aria-hidden="true">${asciiSpecLines}<span class="ascii-cursor"></span></pre></div>`;
const planSignals = [
'<span class="handoff-token" style="--from-x:-56px;--mid-x:-20px;--delay:220ms"></span>',
'<span class="handoff-token" style="--from-x:56px;--mid-x:20px;--delay:330ms"></span>',
].join('');
const reqLines = Array.from({ length: 3 }, (_, i) => `<span class="req-line" style="--delay:${360 + i * 80}ms"></span>`).join('');
const codeTiles = Array.from({ length: 9 }, (_, i) => `<span class="code-tile" style="--delay:${420 + i * 45}ms"></span>`).join('');
const mapRows = Array.from({ length: 3 }, (_, i) => `<span class="map-row" style="--delay:${520 + i * 80}ms"><i></i><em></em><i></i></span>`)
.join('');
const planDemo = `<div class="scene-plan-v2" role="img" aria-label="Developer and project manager discuss the need, then an AI planning agent indexes the codebase, writes requirements, and maps functional intent to technical structure"><div class="human-dialog"><span class="plan-person plan-dev">DEV</span><span class="plan-talk plan-talk-dev"><i></i><i></i><i></i></span><span class="plan-talk plan-talk-pm"><i></i><i></i><i></i></span><span class="plan-person plan-pm">PM</span></div><div class="agent-zone">${planSignals}<span class="agent-core">AI PLAN</span></div><div class="planning-artifacts"><div class="plan-artifact req-artifact"><span class="artifact-label">REQ</span>${reqLines}</div><div class="plan-artifact code-artifact"><span class="artifact-label">CODE</span><span class="code-grid">${codeTiles}</span></div><div class="plan-artifact map-artifact"><span class="map-labels"><b>FUNC</b><b>TECH</b></span>${mapRows}</div></div></div>`;
const d04Chips = Array.from({ length: 16 }, (_, i) => {
const col = i % 4;
const row = Math.floor(i / 4);
const endCol = i % 8;
const endRow = Math.floor(i / 8);
return `<span class="d04-chip" style="--sx:${col * 12}px;--sy:${row * 12}px;--ex:${100 + endCol * 10}px;--ey:${35 + endRow * 34}px;--delay:${i * 34}ms"></span>`;
}).join('');
const d04Packets = Array.from({ length: 4 }, (_, i) => (
`<span class="d04-packet" style="--i:${i}"><i></i><i></i><i></i><b></b></span>`
)).join('');
const delegableDemo = `<div class="d04-fracture" role="img" aria-label="Large work fractures into tiny delegable increments that finish independently"><div class="d04-work" aria-hidden="true"><i></i><i></i><i></i><i></i></div><div class="d04-chip-field">${d04Chips}</div><div class="d04-packet-row">${d04Packets}</div></div>`;
const d05CodeLines = Array.from({ length: 5 }, (_, i) => `<i style="--i:${i}"></i>`).join('');
const d05MdLines = Array.from({ length: 5 }, (_, i) => `<i style="--i:${i}"></i>`).join('');
const contextCareDemo = `<div class="d05-atelier" role="img" aria-label="Code and markdown pass through the same quality scanner"><div class="d05-sheet d05-code"><b>code</b>${d05CodeLines}</div><span class="d05-beam" aria-hidden="true"></span><div class="d05-sheet d05-md"><b>md</b>${d05MdLines}</div><div class="d05-quality-bar" aria-hidden="true"><i></i><i></i><i></i></div></div>`;
const d06Reusable = Array.from({ length: 4 }, (_, i) => `<span style="--i:${i}"></span>`).join('');
const learningDemo = `<div class="d06-capture" role="img" aria-label="A chat produces a lesson that either gets lost or is captured into reusable project memory"><div class="d06-chat-source"><b>chat</b><i></i><i></i></div><span class="d06-lesson" aria-hidden="true"></span><span class="d06-lost" aria-hidden="true"></span><div class="d06-bin" aria-hidden="true"><i></i></div><div class="d06-memory" aria-hidden="true"><i></i><i></i><i></i><i></i></div><div class="d06-reuse">${d06Reusable}</div></div>`;
const ownershipDemo = `<div class="d07-ownership" role="img" aria-label="An AI draft is reviewed by a developer before becoming an owned shipped change"><div class="d07-draft"><b>AI</b><i></i><i></i><i></i></div><span class="d07-handoff" aria-hidden="true"></span><div class="d07-dev"><b>DEV</b><span></span><i></i></div><div class="d07-ledger"><i></i><i></i><i></i><span></span></div></div>`;
const d08Checks = ['READ', 'TEST'].map((label, i) => `<span style="--i:${i}"><b>${label}</b><i></i></span>`).join('');
const evaluationDemo = `<div class="d08-eval-lab" role="img" aria-label="A developer reads and tests AI output before delegation is unlocked"><div class="d08-output"><b>AI</b><i></i><i></i><i></i></div><span class="d08-token" aria-hidden="true"></span><div class="d08-dev-panel"><b>DEV</b>${d08Checks}</div><div class="d08-delegate"><b>DELEGATE</b><i></i></div></div>`;
const d09Pins = ['Plan', 'Implement', 'Review', 'Test'].map((label, i) => `<span style="--i:${i}">${label}</span>`).join('');
const systemDemo = `<div class="d09-system-lab" role="img" aria-label="The implementation system is tightened through Plan, Implement, Review, and Test before asking the model harder"><div class="d09-noise"><i></i><i></i><i></i></div><div class="d09-frame"><b>model</b>${d09Pins}</div><div class="d09-clean"><i></i><i></i><i></i></div></div>`;
const contextRebuildDemo = `<div class="d10-context-rebuild" role="img" aria-label="An old chat is compacted into context, then a new chat starts from that prior context"><div class="d10-chat d10-old"><b>chat</b><i></i><i></i><i></i></div><span class="d10-compact">compact</span><div class="d10-capsule"><i></i><i></i><i></i></div><div class="d10-chat d10-new"><b>new chat</b><i></i><i></i><i></i></div></div>`;
const d11Checks = ['scope', 'context', 'assumptions', 'tests']
.map((label, i) => `<span class="${label === 'context' ? 'is-hit' : ''}" style="--i:${i}"><b>${label}</b><i></i></span>`)
.join('');
const failureSignalDemo = `<div class="d11-diagnostic" role="img" aria-label="A stalled AI response is inspected through scope, context, assumptions, and tests until the failure reveals a context gap signal"><div class="d11-stuck"><b>AI stuck</b><i></i><i></i><em></em></div><span class="d11-pulse" aria-hidden="true"></span><div class="d11-inspect"><b>inspect</b>${d11Checks}</div><div class="d11-signal"><b>context</b><span>gap</span><i></i></div></div>`;
const d12Inputs = ['DEV', 'OPS', 'AI'].map((label, i) => `<span style="--i:${i}">${label}</span>`).join('');
const d12Files = ['memory.md', 'rules.md', 'skills.md']
.map((label, i) => `<span style="--i:${i}"><b>${label}</b><i></i><i></i><em></em></span>`)
.join('');
const transferableDemo = `<div class="d12-transfer-prism" role="img" aria-label="Developers, operators, and AI agents pass through the same method and write it into reusable memory files"><div class="d12-inputs">${d12Inputs}</div><div class="d12-method"><em>method</em><i></i><i></i><i></i><b></b></div><span class="d12-write" aria-hidden="true"></span><div class="d12-files">${d12Files}</div></div>`;
const demos = [
factoryDemo,
specDemo,
planDemo,
delegableDemo,
contextCareDemo,
learningDemo,
ownershipDemo,
evaluationDemo,
systemDemo,
contextRebuildDemo,
failureSignalDemo,
transferableDemo,
];
---
<div class={`p-demo demo-${number}`} aria-label={`Visual demonstration for commitment ${number}`} set:html={demos[index] ?? demos[0]} />
3 changes: 1 addition & 2 deletions app/src/components/principles/PrincipleGrid.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
import { PRINCIPLES } from '~/content/principles';
import { TERMS } from '~/content/terms';
import PrincipleCard from '~/components/principles/PrincipleCard.astro';
---
<div class="p-grid" id="pGrid">
{PRINCIPLES.map((p, i) => (
<PrincipleCard principle={p} index={i} term={TERMS[i]} />
<PrincipleCard principle={p} index={i} />
))}
</div>
2 changes: 1 addition & 1 deletion app/src/components/sections/Principles.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PrincipleGrid from '~/components/principles/PrincipleGrid.astro';
<section id="principles" class="principles">
<div class="chapter-open reveal">
<div class="chapter-body">
<h2>12 commitments to produce <em>high quality software</em>, using AI.</h2>
<h2>12 commitments for durable <em>AI-driven development.</em></h2>
<div class="chapter-lede">
<svg class="fleuron" width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
<path d="M4 22 L40 22 M22 4 L22 40 M10 10 L34 34 M34 10 L10 34" stroke="currentColor" stroke-width="0.8" opacity=".6"/>
Expand Down
13 changes: 0 additions & 13 deletions app/src/components/terminal/TerminalAnim.astro

This file was deleted.

Loading