Files
ai-resume/AGENTS.md
Sam Rolfe b267e55f8c Replace Vite/React scaffold with Go build spec
- 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
2026-10-26 16:02:35 +11:00

8.9 KiB
Raw Blame History

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.

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