- AGENTS.md: build spec for Paperclip (constraints, conventions, 7 phases) - docs/phase-1..7: per-phase work, DoD, out-of-scope, risks - reference/: frozen decisions, stack+ports+budgets, content map, acceptance tests - agents/: persona and security policy drafts - Retires the React scaffold; history retained as record of the false start
169 lines
8.9 KiB
Markdown
169 lines
8.9 KiB
Markdown
# Ai Resume — Build Spec
|
||
|
||
> Build spec for Paperclip. Follow the phases in section 11 in order. Do not skip a
|
||
> phase's Definition of Done. When something is unclear, ask Sam — do not guess.
|
||
|
||
**Project:** `Resume Ai` (Paperclip project `aeea3686-b9fb-4e20-aaaa-4d970f7aeb64`)
|
||
**Repo:** `sam/ai-resume` — this working copy. One repo, one product.
|
||
**Planning folder (read-only reference, do not edit):** `/home/sam/paseo/projects/resume_ai_system/`
|
||
|
||
---
|
||
|
||
## 1. Purpose and outcome
|
||
|
||
A public portfolio site for Sam Rolfe, aimed at three roles: **AI / LLM Engineer**, **Platform / DevOps Engineer**, **Edge / IoT Engineer**. It must present 25 years of delivery, a homelab, an edge fleet and an AI estate in a form a hiring manager can judge in 90 seconds and an engineer can verify in 30 minutes.
|
||
|
||
**The single success statement:**
|
||
|
||
> A recruiter opens the link, understands within 90 seconds that Sam builds AI systems, the platforms under them and the hardware at the edge — and can drill from any claim to the code, diagram or device that proves it. Separately, they can ask a question in plain English and get a short, honest, cited answer.
|
||
|
||
If those two things work, the project succeeded. Everything else is polish.
|
||
|
||
---
|
||
|
||
## 2. The two-mode rule — non-negotiable
|
||
|
||
The site has **two delivery modes over one body of content**. Both are mandatory.
|
||
|
||
**Mode A — prebuilt static content.** Conventional navigation into fixed, pre-rendered pages. No LLM call, no embedding lookup. This is the fallback and the first impression. It must work with every AI service stopped.
|
||
|
||
**Mode B — AI conversational retrieval.** A prompt box; answers generated from the corpus, streamed; the AI can push artefacts (code, diagrams, images) into the presentation panel.
|
||
|
||
**One source of truth, two renderers.** `content/` (Markdown + front-matter + assets) is authoritative. A build step emits both (a) the static pages and (b) the chunked, metadata-tagged corpus. Content is never authored twice, and the two modes can never drift.
|
||
|
||
**Acceptance test A1 *(hard gate)*:** stop Qdrant, OmniRoute and the query service. Every page must still render correctly. Any change that breaks this is rejected.
|
||
|
||
---
|
||
|
||
## 3. Scope
|
||
|
||
**In scope**
|
||
- The static site: navigation, six top-level areas, drill-down pages, print/accessible.
|
||
- The content pipeline: `content/` → static render + corpus.
|
||
- The AI overlay: query graph, retrieval, streaming, citations, guardrails, cost caps.
|
||
- Public deployment behind the existing Caddy edge.
|
||
- Honest labelling of in-progress and abandoned work.
|
||
|
||
**Out of scope**
|
||
- Changing, stopping or "cleaning up" any other system on any host. See §4.
|
||
- Family/household systems, the Hub, Paperclip itself, the model gateway's internals.
|
||
- A CMS, admin editor, user accounts, comments, analytics dashboards.
|
||
- Native apps, voice *output* beyond the optional last phase.
|
||
|
||
---
|
||
|
||
## 4. Hard constraints
|
||
|
||
1. **Stack is frozen.** Go + `templ` + HTMX + SQLite; one hand-written TypeScript island; Qdrant; Prefect; LangGraph; OmniRoute. React, Vite and `node_modules` do not enter this repo. Reopening a frozen decision requires Sam's written approval, not a judgement call.
|
||
2. **Do not touch other systems.** Nothing outside this repo and the deploy path. No stopping containers, no editing other projects' compose files, no changes to Caddy beyond the single block specified in Phase 3, no `nixos-rebuild`. If a task appears to require it, stop and ask.
|
||
3. **Memory ceiling.** New footprint ≤ **1.0 GiB** and ≤ **4 containers**. Every new service sets `mem_limit` **and** `memswap_limit` to the same value, so it cannot consume the host's swap.
|
||
4. **Secrets** come from `~/.config/environment.d/` only. Never in the repo, never in logs, never echoed. A secret-scanning pre-commit hook is mandatory.
|
||
5. **All model calls go through OmniRoute.** No direct provider SDK or HTTP call anywhere in this codebase.
|
||
6. **No LLM in the path of a consequential action.** Deployments are executed by a script, not decided by a model.
|
||
7. **The public AI has no tools.** No shell, no filesystem, no network fetch, no write path, no memory between visitors. This is architectural, not a prompt instruction.
|
||
|
||
---
|
||
|
||
## 5. Where it runs
|
||
|
||
| Host | Role | Notes |
|
||
|---|---|---|
|
||
| `.27` | Build / dev | Source, builds, agent work |
|
||
| `.13` | Runtime | Go app, Qdrant, Prefect worker. **2.3 GiB free, 8 GiB swap in use — respect the ceiling** |
|
||
| `.35` | Public ingress | Caddy terminates 443 for `*.lab.audasmedia.com.au` |
|
||
|
||
| Item | Value |
|
||
|---|---|
|
||
| App port | **8096** (verify free; 8095 is taken by `offsite.lab`) |
|
||
| Qdrant | 6333 / 6334, bound to `127.0.0.1` |
|
||
| Public hostname | `resume.lab.audasmedia.com.au` (wildcard DNS already resolves) |
|
||
| Release path | `/home/sam/deployment/resume/releases/<timestamp>` + `current` symlink |
|
||
| Edge proxy | Caddy on `.35` — **Sam applies this change, not the agent** |
|
||
|
||
Bind every new service to `127.0.0.1`. Caddy is the only public listener.
|
||
|
||
---
|
||
|
||
## 6. Repository rules
|
||
|
||
- `main` is always deployable. Work on branches; merge when the phase's DoD passes.
|
||
- The repo **is** the content source of truth. `content/` lives here.
|
||
- No generated artefacts committed (build output, `node_modules`, `.venv`, binaries).
|
||
- Every phase ends with a commit that states which DoD items it satisfies.
|
||
- The repo stays **private until Phase 3 passes**, then visibility is Sam's decision.
|
||
|
||
---
|
||
|
||
## 7. Content conventions
|
||
|
||
Every content file carries front-matter. Both renderers read it.
|
||
|
||
```yaml
|
||
id: edge-snapcast
|
||
area: ai | platform | edge | products | history | about
|
||
level: 1 | 2 | 3
|
||
title: "Distributed Audio"
|
||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||
confidence: delivered | running | in-progress | abandoned | historic
|
||
period: "2023–"
|
||
tech: [Snapcast, Mopidy, Spotify, Raspberry Pi]
|
||
metrics: [{label: "endpoints", value: 8}]
|
||
artefacts: [{type: repo|image|video|doc, label: "...", url: "..."}]
|
||
public: true
|
||
last_verified: 2026-10-20
|
||
tags: [audio, snapcast, voice]
|
||
```
|
||
|
||
**`confidence` is displayed on the page.** `running` and `delivered` are claims; `in-progress` and `abandoned` are stated as such. Never promote a value to make a page read better — that is a defect, not a style choice.
|
||
|
||
**Framing rule:** headings describe capabilities in corporate language. Product names are supporting evidence, never the heading. `ESP32` → *distributed edge computing under power and latency constraints*.
|
||
|
||
---
|
||
|
||
## 8. Quality bar
|
||
|
||
- Renders correctly with JavaScript disabled, except the AI console.
|
||
- Lighthouse ≥ 95 performance and ≥ 95 accessibility, mobile and desktop.
|
||
- Every page printable.
|
||
- Markdown and code highlighting rendered server-side (`goldmark`, `chroma`) — not in the browser.
|
||
- No page requires an AI call to be useful.
|
||
- Server-rendered HTML validated; no unescaped user input reaches a template.
|
||
|
||
---
|
||
|
||
## 9. What is explicitly out of scope for the agent
|
||
|
||
- Deciding what is true about Sam's career. If the evidence is not in `reference/` or `content/`, ask.
|
||
- Naming clients that Sam has not approved.
|
||
- Publishing personal details: family, address, phone.
|
||
- Changing the stack, the ports, the host allocation or the public hostname.
|
||
- Deleting anything outside this repo.
|
||
|
||
---
|
||
|
||
## 10. When something is unclear
|
||
|
||
Ask Sam. Do not guess, do not invent a plausible answer, do not silently choose an alternative. A blocked task that gets answered in a minute is cheaper than a completed task built on an assumption.
|
||
|
||
Escalate in this order: (1) the phase document, (2) `reference/`, (3) Sam.
|
||
|
||
---
|
||
|
||
## 11. Phases
|
||
|
||
Each phase is one Paperclip issue. Each has a Definition of Done that must be demonstrated with an artifact — command output, screenshot, measurement or URL — not asserted.
|
||
|
||
| # | Phase | Doc | Depends on |
|
||
|---|---|---|---|
|
||
| 1 | **Content source of truth** — schema, validator, `content/` populated for all six areas | `docs/phase-1-content-source.md` | — |
|
||
| 2 | **Mode A static site** — Go + templ + HTMX, nav, stage panel, drill-downs | `docs/phase-2-static-site.md` | 1 |
|
||
| 3 | **Public deployment** — `deploy.sh`, releases, Caddy block, live URL | `docs/phase-3-deploy.md` | 2 |
|
||
| 4 | **Corpus and retrieval** — chunk, tag, embed, upsert Qdrant; freshness audit | `docs/phase-4-corpus.md` | 1, 2 |
|
||
| 5 | **Mode B console** — SSE, query graph, citations, panel takeover | `docs/phase-5-ai-overlay.md` | 3, 4 |
|
||
| 6 | **Guardrails, cost and kill switch** — any-guardrail, persona, caps, red-team | `docs/phase-6-guardrails.md` | 5 |
|
||
| 7 | **Polish** — logos, diagrams, code exhibits; optional voice | `docs/phase-7-polish.md` | 3 |
|
||
|
||
**Phase order is deliberate.** Content first because both renderers depend on it. Deploy at Phase 3, not last, because a live URL that is half-built is worth more than a perfect site that never ships. AI after deployment so it can never block launch.
|
||
|
||
Reference material: `reference/decisions.md` (why the stack is what it is), `reference/stack.md` (topology, ports, budgets), `reference/content-map.md` (what goes where), `reference/acceptance-tests.md` (the full test list).
|