chore: bootstrap agent-ready docs and rules
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
10ce858b31
commit
80f6c97127
17 files changed
+486
No files matched your search
@@ -0,0 +1,48 @@
|
||||
# Architecture
|
||||
|
||||
How `epic-the-musical-timeline` is built today. Update in the same commit as any structural change.
|
||||
|
||||
## Overview
|
||||
A Bun server (`Bun.serve`) with HTML-import routes serves an index page and seven mockup pages. Bun's bundler
|
||||
turns each HTML page and its imported TS/CSS into hashed assets. `bun run build` bundles the server and every
|
||||
page into `dist/`; the Docker image runs that bundle. All pages read one typed sample dataset and mount one
|
||||
shared credits snippet.
|
||||
|
||||
## Map
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/server.ts` | `startServer(port)`: routes `/`, `/mockups/NN-slug/` (+ 302 from the no-slash form), 404 otherwise. Runs when `import.meta.main`; `PORT` env, default 3000. |
|
||||
| `src/index.html`, `src/index.ts`, `src/index.css` | Index page: static cards linking each mockup, then `mountCredits()`. |
|
||||
| `src/mockups/registry.ts` | `mockups: MockupInfo[]` — slug, number, name, pitch, what to try. |
|
||||
| `src/mockups/NN-slug/` | One design direction: `index.html` (links `../../shared/credits.css`, has `<footer data-fan-credits>`), `main.ts`, `style.css`. |
|
||||
| `src/data/types.ts` | `Saga`, `Song`, `Part`, `Motif`, `StoryTime`, `OdysseyRef`, `Video`. |
|
||||
| `src/data/sample.ts` | `sagas`, `motifs`, `songs`. Placeholder lyrics; unverified fields `// TODO(verify)`. |
|
||||
| `src/data/query.ts` | `songsWithMotif`, `motifsInSong`, `gapYears`, `sagaOf`. |
|
||||
| `src/shared/credits.ts` | `FAN_NOTICE`, `mountCredits(target?)`. |
|
||||
| `src/shared/audio-slot.ts` | `createAudioSlot(song)`: `<audio>` for `song.audio`, else an empty-state slot. |
|
||||
| `src/shared/video-cards.ts` | `createVideoCards(song)`: YouTube link cards, no embeds. |
|
||||
| `src/shared/credits.css` | Styles for credits, audio slot, video cards. |
|
||||
| `tests/` | `data.test.ts` (dataset invariants), `shared.test.ts` (DOM modules under happy-dom), `server.test.ts` (every route 200s, index links every registry slug, each mockup has the credits hook). |
|
||||
| `Dockerfile` | Two-stage `oven/bun:1.3`: install + build, then copy `dist/` and run from `WORKDIR /app/dist`. |
|
||||
|
||||
## Data flow
|
||||
1. Request hits `Bun.serve`; an HTML-import route returns the bundled page (dev: bundled on demand with HMR
|
||||
via `bun --hot`; production: prebuilt assets from `dist/`).
|
||||
2. The page's `main.ts` imports `src/data/*` and `src/shared/*` (bundled in; no runtime API).
|
||||
3. `main.ts` renders the direction and calls `mountCredits()` into `<footer data-fan-credits>`.
|
||||
|
||||
## External dependencies
|
||||
None at runtime. Fonts (`@fontsource/*`) and three.js are bundled from npm. Outbound links only: YouTube
|
||||
(video cards) and Project Gutenberg (Odyssey references) — the site works without them.
|
||||
|
||||
## Invariants
|
||||
- Every page renders `FAN_NOTICE` via `mountCredits()`.
|
||||
- `src/server.ts` routes, `src/mockups/registry.ts` and the cards in `src/index.html` list the same slugs
|
||||
(`tests/server.test.ts`).
|
||||
- Every motif id used by a part exists; every motif appears in at least one song (`tests/data.test.ts`).
|
||||
- No two mockups ship byte-identical `style.css` (the build fails otherwise).
|
||||
|
||||
## Known rough edges
|
||||
- The production bundle only runs with `dist/` as the cwd (`bun run start`, Docker `WORKDIR /app/dist`);
|
||||
`bun dist/server.js` from the repo root crashes. See `docs/TODO.md`.
|
||||
- Routes, registry and index cards are three hand-maintained lists. See `docs/TODO.md`.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Decisions
|
||||
|
||||
Append-only. Never edit or delete an entry — supersede it with a new one that links back.
|
||||
One entry per decision a future maintainer would otherwise have to reverse-engineer.
|
||||
No index: `grep -n '^## ' docs/DECISIONS.md` lists every entry (date, title, line number).
|
||||
|
||||
## 2026-10-23 — Mockups are committed and served, not throwaway
|
||||
**Status:** accepted
|
||||
**Context:** The agent-repo playbook keeps mockups gitignored in `design/mockups/`, never wired into the app.
|
||||
Spec 001 asks for 7 design-direction mockups that run in the Docker image for the maintainer to compare.
|
||||
**Decision:** (maintainer decision) Mockups live in `src/mockups/NN-slug/`, are committed, served by the
|
||||
Bun server and covered by route smoke tests. Mockup agents edit only their own folder.
|
||||
**Alternatives:** Gitignored `design/mockups/` (can't ship in the image or be reviewed from the remote).
|
||||
**Consequences:** Mockup code is in the bundle and the history; when a direction is chosen, the unused
|
||||
mockups need an explicit removal decision (`docs/TODO.md`).
|
||||
|
||||
## 2026-10-23 — Production bundle runs from `dist/`
|
||||
**Status:** accepted
|
||||
**Context:** With Bun 1.3.14, a `--production` bundle of HTML imports resolves its assets relative to the
|
||||
current working directory; `bun dist/server.js` from the repo root throws "Bundled file … not found".
|
||||
**Decision:** `bun run start` is `cd dist && bun server.js`; the Docker runtime stage uses `WORKDIR /app/dist`.
|
||||
**Alternatives:** Not recorded (e.g. `--asset-naming`/`naming` options were not explored).
|
||||
**Consequences:** Any new run script or deploy target must set the cwd to `dist/`.
|
||||
|
||||
## 2026-10-23 — Bun only, self-contained assets
|
||||
**Status:** accepted
|
||||
**Context:** Spec 001 constraints.
|
||||
**Decision:** Bun's own server, bundler and test runner with HTML imports; no Vite/Next. Fonts and three.js
|
||||
bundled from npm, no CDN. YouTube as link cards, not embeds. three.js only in the 3D mockups (06, 07).
|
||||
**Alternatives:** Not recorded.
|
||||
**Consequences:** The image works offline apart from outbound links.
|
||||
|
||||
## 2026-10-23 — Placeholder lyrics, unverified facts marked
|
||||
**Status:** accepted
|
||||
**Context:** Lyrics recalled from memory risk inaccuracy, and their copyright question is open.
|
||||
**Decision:** Sample data uses clearly marked placeholder lyric lines in the real data shape; any fact,
|
||||
story time or Odyssey reference not confirmed carries `// TODO(verify)`.
|
||||
**Alternatives:** Real lyrics (deferred by the maintainer).
|
||||
**Consequences:** Nothing in `src/data/sample.ts` may be presented as fact-checked.
|
||||
|
||||
## 2026-10-23 — Adopt AGENTS.md as single source of truth
|
||||
**Status:** accepted
|
||||
**Context:** Agents had no durable project context and no consistent workflow between sessions.
|
||||
**Decision:** `AGENTS.md` is canonical; `CLAUDE.md`/`GEMINI.md` are pointers. Specs are permanent in
|
||||
`docs/specs/`. Plans live in `docs/plans/` only while work is in progress and are removed before the
|
||||
merge request. Both override the superpowers default paths.
|
||||
**Alternatives:** Per-tool rule files (drift, synchronisation debt); no rules file (agents re-explore
|
||||
the repo every session — measurably slower and more tokens).
|
||||
**Consequences:** Rule changes happen in one file; pointer files must stay thin. Plans are working
|
||||
artefacts: kept after merge they go stale and contradict the code, so the spec is the record.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Agent permissions
|
||||
|
||||
Source of truth for what AI coding agents may run here. Tool files are renderings of this page:
|
||||
`.claude/settings.json`, `.codex/config.toml`, `.codex/rules/project.rules`, `.gemini/settings.json`.
|
||||
Change this page and every tool file in the same commit.
|
||||
|
||||
## Verified commands
|
||||
|
||||
Run 2026-10-23 with Bun 1.3.14, each in a fresh shell. Only `worked` rows may appear in a tier, a tool file,
|
||||
or `AGENTS.md` Commands.
|
||||
|
||||
| Command | Result |
|
||||
|---|---|
|
||||
| `bun install --frozen-lockfile` | worked (no changes) |
|
||||
| `bun test` | worked — 32 pass, 0 fail, 3 files |
|
||||
| `bun test tests/data.test.ts` | worked — 10 pass |
|
||||
| `bun test -t "registry has 7"` | worked — 1 pass |
|
||||
| `bun run typecheck` | worked (`tsc --noEmit`, exit 0) |
|
||||
| `bun run build` | worked — `dist/server.js` + hashed page assets |
|
||||
| `bun run dev` (`PORT=3113`) | worked — `/` and all mockup routes 200, no-slash form 302 |
|
||||
| `bun run start` (`PORT=3112`) | worked — same route results as dev |
|
||||
| `bun dist/server.js` (from repo root) | failed — `TypeError: Bundled file "./index-….js" not found`; assets resolve from cwd |
|
||||
| `docker build -t epic-timeline .` | worked |
|
||||
| `docker run --rm -p 3000:3000 epic-timeline` | worked — `/mockups/06-constellation/` 200 |
|
||||
| `docker run -e PORT=8080 -p 8099:8080 epic-timeline` | worked — `/` and all 7 mockups 200, credits hook present (host port 8080 was taken on this machine) |
|
||||
| `google-chrome --headless --window-size=1440,900 --screenshot=… <url>` | worked (no `chromium` binary on this machine) |
|
||||
| `codex execpolicy check --rules .codex/rules/project.rules -- <cmd>` | worked — deny/ask rules match as intended |
|
||||
| Lint / format | not run — no linter or formatter configured |
|
||||
|
||||
TODO(maintainer): confirm whether a linter/formatter should be added.
|
||||
|
||||
## Tiers
|
||||
|
||||
| Tier | Commands | Why |
|
||||
|---|---|---|
|
||||
| Allow | `git status`, `git diff`, `git log`, `git show`, `git branch --list`, `git rev-parse`, `git add`, `git commit`; `bun install --frozen-lockfile`, `bun test`, `bun run typecheck`, `bun run build`, `bun run dev`, `bun run start` | Inspection and the verified dev loop; no prompt needed. |
|
||||
| Ask | `git push`, `git merge`, `git rebase`, `git switch`, `git restore`, `git commit --amend`, `rm` (any); `bun add`, `bun remove`, `bun update`, `bun upgrade`, `bunx`, `npx`; `docker` (any) | Leaves the machine, rewrites work, changes dependencies, downloads and runs code, or touches containers — a human decides. |
|
||||
| Deny | `git push --force` / `-f` / `--force-with-lease`, `git reset --hard`, `git clean`, `git add -f` / `--force`, `git commit --no-verify` / `-n`, `rm -r` / `-R` / `-rf` / `-fr` / `-Rf` / `-fR` / `--recursive`, `sudo`; reading `.env`, `.env.*`, `secrets/**` | Destroys work, skips checks, or exposes secrets. |
|
||||
|
||||
`docker build`/`docker run` are verified but stay in Ask because they touch containers.
|
||||
|
||||
## Known gaps
|
||||
- Allowlists save prompts; they are not a security boundary. Use the tool's sandbox for isolation.
|
||||
- Prefix rules are bypassable: `git -C dir push`, flags placed later (`git push origin main --force`),
|
||||
`+refspec` pushes. Claude Code's `:*` matches at a word boundary, so each flag cluster must be
|
||||
listed — which is why `git clean` is denied whole and `rm` always asks.
|
||||
- Allowed test, typecheck, and build commands run code from the repo; an agent that can edit
|
||||
`package.json` or the tests can run anything through them (`bun run dev`/`start` run the server).
|
||||
- Denying reads of `.env` does not stop a script that opens it itself, and
|
||||
git can print staged or committed secrets (`git show HEAD:.env`). `git add -f` is denied so an agent
|
||||
cannot stage an ignored secret; keep real secrets out of the working tree.
|
||||
- Codex: loaded only once the user trusts the project; `approval_policy` here can loosen a stricter user
|
||||
setting. No `allow` rules (allow = run outside the sandbox). In `workspace-write`, `.git/` is read-only, so
|
||||
`git add`/`git commit` ask for escalation, and `bun install` needs network and asks too. Codex rules cannot
|
||||
deny file reads. `--force-with-lease=<ref>`, `+refspec` and later-placed flags only hit the Ask rule.
|
||||
- Gemini CLI: ignored until the folder is trusted. `tools.exclude` is deprecated but is the only
|
||||
project-level deny. No Ask tier (anything not allowed asks). Cannot deny file reads.
|
||||
- Cursor and Copilot: not configured — no sign the team uses them.
|
||||
@@ -0,0 +1,43 @@
|
||||
# TODO
|
||||
|
||||
Durable backlog. Agents append here instead of leaving `TODO` comments in source.
|
||||
Small, specific, independently actionable. Remove only when actually done.
|
||||
|
||||
## Now
|
||||
- [ ] Verify every `// TODO(verify)` field in `src/data/sample.ts` (48 at bootstrap: saga names, singers,
|
||||
story times, Odyssey book/lines, motif descriptions, facts) before any content leaves mockup stage.
|
||||
|
||||
## Next
|
||||
- [ ] After a direction is chosen: decide whether the unused mockups are deleted or kept, and record the
|
||||
chosen direction in `DESIGN.md`.
|
||||
- [ ] Add CI under `.gitea/workflows/` (none exists): `bun install --frozen-lockfile`, `bun test`,
|
||||
`bun run typecheck`, `bun run build`; plus a check that `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` and the
|
||||
`docs/` paths exist and `AGENTS.md` is under 150 lines. Proposed, not added.
|
||||
|
||||
## Someday
|
||||
- [ ] Make `bun dist/server.js` work from any cwd (Bun 1.3.14 resolves bundled assets relative to cwd;
|
||||
try `--asset-naming` / `naming`, or re-check on a newer Bun). Today `bun run start` and Docker
|
||||
work around it.
|
||||
- [ ] Derive `src/server.ts` routes and `src/index.html` cards from `src/mockups/registry.ts` instead of
|
||||
three hand-kept lists (tests catch drift today).
|
||||
- [ ] Decide whether real lyrics may be shown (copyright question, deferred).
|
||||
|
||||
## Recurring
|
||||
- [ ] Maintain `AGENTS.md`:
|
||||
- **Add a rule only in response to a real failure.** When an agent repeatedly gets something wrong,
|
||||
that is a gap; add one line, ideally with a code example. Do not pre-empt hypothetical mistakes.
|
||||
- **Update in the same PR as the convention change.** A stale rules file is worse than none — it
|
||||
actively misleads.
|
||||
- **Prune quarterly.** Delete rules whose convention has changed or whose mistake no longer occurs.
|
||||
- **Optional, cheap validation:** run the same task twice in clean sessions, with and without the
|
||||
file, and compare steps and token use. This is how the published numbers were produced, and it is
|
||||
the only way to know your file is helping rather than costing 20% for nothing.
|
||||
|
||||
## Known issues
|
||||
- [ ] `bun dist/server.js` from the repo root crashes: `TypeError: Bundled file "./index-….js" not found`.
|
||||
Repro: `bun run build && bun dist/server.js`. Workaround: `bun run start`.
|
||||
- [ ] Two mockups with byte-identical `style.css` fail `bun run build` with "Multiple files share the same
|
||||
output path" (reproduced by copying `01-editorial/style.css` over `02-vertical-story/style.css`).
|
||||
Identical `main.ts` files do not trigger it.
|
||||
- [ ] `docs/plans/001-timeline-mockups.md` tells mockup agents to start `bun dist/server.js`, which hits
|
||||
the issue above; use `bun run start` instead.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Plans
|
||||
|
||||
Implementation plans from the superpowers writing-plans workflow. **Transient:** a plan lives only on
|
||||
its feature branch and is removed with `git rm` before the merge request is opened. This README stays.
|
||||
|
||||
- Naming: `NNN-short-slug.md`, matching its spec number.
|
||||
- Links back to its spec. Bite-sized checkbox tasks with exact file paths, test commands, and
|
||||
commit checkpoints.
|
||||
- Written for an engineer with zero context for this codebase — spell out the obvious.
|
||||
- Tick checkboxes as you go so another agent can resume an interrupted session.
|
||||
- Front matter: `status: draft | approved | in-progress`. There is no `done` — a finished plan is deleted.
|
||||
@@ -0,0 +1,10 @@
|
||||
# Specs
|
||||
|
||||
Approved specifications from the superpowers brainstorming workflow. Nothing non-trivial gets
|
||||
implemented without one.
|
||||
|
||||
- Naming: `NNN-short-slug.md`, zero-padded, sequential.
|
||||
- A spec states **what** and **why**, plus acceptance criteria. Not **how**.
|
||||
- Front matter: `status: draft | approved | implemented | superseded`. No link to a plan — plans are
|
||||
removed before merge.
|
||||
- Never delete an implemented spec; it is the record of intent.
|
||||
Reference in new issue
Block a user