.agents/validate.sh is the commit gate: full E2E suite, container security-header check, and repo-hygiene checks must all pass before a phase is committed. AGENTS.md now documents the audit-driven conventions (M-1 innerHTML/terminal input, M-2 simulated curl/wget, M-4 security-header snippet, L-2 server_tokens) and the test-locked featured-projects grid. LLM-Generated: true
83 lines
4.9 KiB
Markdown
83 lines
4.9 KiB
Markdown
# AGENTS.md
|
|
|
|
Rules for any agent working in this repository.
|
|
|
|
## Always
|
|
1. **Read `.agents/PLAN.md` first** — project goals, architecture, and the
|
|
**LOCKED DECISIONS** (Architectural Anchors) are binding.
|
|
2. **Follow the phased protocol** in `.agents/phases/`:
|
|
- `todo/NN_name/` — pending phases (`00_phase.md` overview + `NN_task.md`
|
|
task files; task sort order = execution order).
|
|
- `complete/` — finished phases (read-only history).
|
|
- New work is captured as a phase directory via the `phase-authoring`
|
|
skill; code changes flow through the `phased-execution` skill (each task
|
|
runs in a fresh subprocess behind the validation gate).
|
|
3. **Test before you ship:**
|
|
- `./build.sh` — rebuild `dist/` (tests run against `dist/`, the
|
|
deployed artifact — never test `src/` directly).
|
|
- `npm test` — the Playwright E2E suite (pinned `@playwright/test`
|
|
1.63.0; do not bump without re-checking the cached browser revision).
|
|
- `.agents/validate.sh` — the pipeline gate: full E2E suite + the container
|
|
security-header check + repo-hygiene checks; must exit 0 before a phase is
|
|
committed.
|
|
- For any `nginx.conf` / `nginx-security-headers.inc` / Dockerfile change:
|
|
`./scripts/check-headers.sh` (added by Phase 03, run automatically by
|
|
`.agents/validate.sh` when a container runtime exists). It builds the real
|
|
image, serves it on `127.0.0.1:18099` and must print
|
|
`HEADER CHECK PASSED`; don't substitute a hand-rolled `curl` for it.
|
|
|
|
## Never
|
|
- Modify `.agents/PLAN.md` except via an explicit user-approved change to the
|
|
LOCKED DECISIONS (record the approval in the PLAN's review history).
|
|
- Modify anything in `.agents/phases/complete/`.
|
|
- Edit files in `.agents/phases/todo/` without asking the user first
|
|
(phase rewrites are a `phase-authoring` action).
|
|
- Add runtime dependencies, CDNs, or a JS build toolchain (LOCKED: vanilla
|
|
HTML/CSS/JS, flat `src/*.js`, `build.sh` hashing).
|
|
- Add real network I/O to the fake terminal (LOCKED: simulated output only —
|
|
see Phase 02 and PLAN §2.5).
|
|
- Add `Strict-Transport-Security` inside the nginx container — TLS/HSTS are
|
|
the Caddy edge's job (the container serves plain HTTP on 8080).
|
|
|
|
## Conventions
|
|
- Static site: edits in `src/` → `./build.sh` → `dist/` (hash-cached names).
|
|
New root-level assets are picked up automatically by `build.sh`; nested
|
|
directories are **not** (keep JS files flat in `src/`).
|
|
- Terminal input is untrusted: never render typed input or `commandHistory`
|
|
with `innerHTML` — route it through `updateDisplay()`/`textContent`
|
|
(audit M-1, guarded by the markup-payload test in
|
|
`tests/e2e/02-terminal.spec.js`). The only `innerHTML` uses allowed in
|
|
`src/terminal.js` are static prompt literals, the `clear`/prank element
|
|
wipes, and the canned `neofetch` output (the `cmdText === 'neofetch'` branch —
|
|
every other command output goes through `textContent`). In
|
|
`terminal-vim.js`/`terminal-achievements.js` `innerHTML` is acceptable only
|
|
with static markup or `escapeHtml()`-escaped text.
|
|
- The fake terminal does zero network I/O: `curl`/`wget` render canned output
|
|
from `simulatedCurlOutput()` / `simulatedWgetOutput()` in
|
|
`src/terminal-commands.js` (pure string builders, no DOM, no network). Keep
|
|
any browser-side fetch call out of `src/` entirely (audit M-2, Phase 02).
|
|
Guarded by the curl/wget regression test in `tests/e2e/02-terminal.spec.js`,
|
|
which records every request whose URL falls outside `baseURL` from
|
|
`playwright.config.js` and fails the suite if the list is not empty.
|
|
- Security headers live in `nginx-security-headers.inc` (the Dockerfile copies
|
|
it to `/etc/nginx/snippets/security-headers.inc`) and **every** `location` in
|
|
`nginx.conf` `include`s it. nginx does not merge `add_header` across
|
|
configuration levels, so never rely on server-level inheritance and never add
|
|
inline security `add_header` lines to `nginx.conf` — put them in the snippet
|
|
(audit M-4, Phase 03). `server_tokens off;` stays in the `server` block
|
|
(audit L-2). `scripts/check-headers.sh` guards this rule: drop one `include`
|
|
from a location and the check fails for that path.
|
|
- Featured-projects content is test-locked: the `#projects` grid in
|
|
`src/index.html` (six cards in a fixed order — Brain of Reese first with its
|
|
Gitea source link, ServWaf last with no link because it is closed source) is
|
|
asserted by the `featured projects show the six updated cards in order` test
|
|
in `tests/e2e/01-page.spec.js`. Edit the cards in `src/index.html` and update
|
|
that test in the same change (Phase 05).
|
|
- Terminal modules: `terminal-commands.js` (canned data),
|
|
`terminal-achievements.js`, `terminal-vim.js`, `terminal.js` (core) — load
|
|
order is fixed in `index.html` (all `defer`); keep dependencies pointing
|
|
only at earlier files.
|
|
- Commits: small, imperative subject; one logical change per commit.
|
|
- `dist/`, `node_modules/`, `test-results/`, `playwright-report/` are
|
|
build/test artifacts — never edit them by hand.
|