Files
homepage/AGENTS.md
T
ducoterra a03dcc9e7e add validate.sh pipeline gate and audit convention notes
.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
2026-10-23 13:27:40 -04:00

4.9 KiB

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 includes 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.