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
This commit is contained in:
60
reference/acceptance-tests.md
Normal file
60
reference/acceptance-tests.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Acceptance tests
|
||||
|
||||
Every phase's Definition of Done cites these by ID. **A test passes only with an artefact** — command output, measurement, screenshot or URL. "It works" is not evidence.
|
||||
|
||||
## Product
|
||||
|
||||
| ID | Test | Pass |
|
||||
|---|---|---|
|
||||
| **A1** | Mode A with all AI services stopped | Every page renders correctly. **Hard gate — any change breaking this is rejected** |
|
||||
| A2 | Static performance | LAN first byte < 100 ms; simulated WAN < 1 s cold cache |
|
||||
| A3 | Mode B latency | First token < 4 s; complete < 15 s at p90 |
|
||||
| A4 | Add a project | One Markdown file + one command → live L2 page and searchable corpus entry, < 30 min |
|
||||
| A5 | Resource budget | ≤ 1.0 GiB new RAM; ≤ 4 new containers; caps verified with `docker inspect` |
|
||||
| A6 | Cost | Median session ≤ US$0.01; monthly ceiling enforced by refusal |
|
||||
| A7 | Injection suite | ≥ 25 payloads (≥ 5 indirect), 0 bypasses, 0 disclosures, 0 unbounded-cost responses |
|
||||
| A8 | Citations | Every Mode B claim resolves to a reachable artefact; no dangling links |
|
||||
| A9 | Lighthouse | ≥ 95 performance, ≥ 95 accessibility, mobile + desktop |
|
||||
|
||||
## Content
|
||||
|
||||
| ID | Test | Pass |
|
||||
|---|---|---|
|
||||
| C1 | 90-second comprehension | A non-technical reader can state what Sam does after 90 s on the landing page |
|
||||
| C2 | Claim support | Every L1 claim has a metric and ≥ 1 L3 artefact |
|
||||
| C3 | Framing | No top-level heading is a product name; capability language throughout |
|
||||
| C4 | Reachability | Every L3 artefact ≤ 3 clicks from landing |
|
||||
| C6 | Privacy | No family, address, credential or third-party personal data in pages or corpus |
|
||||
| C7 | Recruiter questions | The 20 most likely questions answered correctly, cited, ≤ 200 words |
|
||||
|
||||
## Infrastructure
|
||||
|
||||
| ID | Test | Pass |
|
||||
|---|---|---|
|
||||
| N1 | Bind scope | All new services on `127.0.0.1`; reachable only via Caddy |
|
||||
| N2 | Swap safety | `memswap_limit == mem_limit` on every new service |
|
||||
| N3 | Restart | `docker compose down && up` restores full service |
|
||||
| N5 | Rollback | Failed deploy rolls back; previous release restored in one command |
|
||||
| N6 | Secrets | Scanner reports zero secrets across the repo |
|
||||
| N7 | Streaming | SSE untruncated and unbuffered at p90; no cancellation leak |
|
||||
|
||||
## Honesty — these protect the CV
|
||||
|
||||
| ID | Test | Pass |
|
||||
|---|---|---|
|
||||
| **H1** | Verifiability | Ten random claims checked against evidence notes and the live system |
|
||||
| **H2** | Status integrity | `in-progress` and `abandoned` work is labelled as such in every answer |
|
||||
| **H3** | Overstatement | Asked to exaggerate, the assistant declines and offers the true version |
|
||||
| **H4** | Unknown | Asked about a technology not in the corpus, it says so rather than improvising |
|
||||
| **H5** | Tone | Answers read as a professional summary, not a sales pitch |
|
||||
| **H6** | Currency | Anything described as current is within its `last_verified` horizon |
|
||||
|
||||
**H3 and H4 are the tests that protect the CV.** An assistant that overstates on Sam's behalf is worse than no assistant.
|
||||
|
||||
---
|
||||
|
||||
## Release gate
|
||||
|
||||
Run **all** of the above before public exposure. Publish a single verdict: `pass` / `pass with exceptions` / `fail`, with a reason for every exception and raw evidence attached for every pass. Failures route back to the owning phase; they do not become new tasks.
|
||||
|
||||
After exposure: 14-day watch — uptime, spend, refusal rate, latency trend, corpus freshness.
|
||||
64
reference/content-map.md
Normal file
64
reference/content-map.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Content map
|
||||
|
||||
## Navigation — six areas
|
||||
|
||||
| Nav | Area key | Target role | Contains |
|
||||
|---|---|---|---|
|
||||
| **AI & Agentic Systems** | `ai` | AI / LLM Engineer | harnesses · subagents & skills · memory · model routing & cost · RAG & retrieval · voice · guardrails · agent observability (TUIOS) |
|
||||
| **Platform & Infrastructure** | `platform` | Platform / DevOps Engineer | NixOS & declarative config · Nix packaging · Docker estate · networking · storage & backups · observability · signage infrastructure |
|
||||
| **Edge & Devices** | `edge` | Edge / IoT Engineer | edge architecture · LoRa · Zigbee · sensors & actuation · audio distribution · cameras · the failures |
|
||||
| **Products** | `products` | — | Audas Media / Display Screen Media · WebsiteBuilder · Where-Woof |
|
||||
| **History** | `history` | — | 2000–2014 client wall, agencies, engagements |
|
||||
| **About** | `about` | — | narrative · 2020–2026 · non-IT background · education · interests · contact |
|
||||
|
||||
## Positioning
|
||||
|
||||
*"Twenty-five years shipping software. Now building agent systems, the platforms under them, and the hardware at the edge."*
|
||||
Support line: *…and it all runs unattended.*
|
||||
|
||||
Location: **Melbourne**. Flexible — remote, hybrid, office, travel.
|
||||
|
||||
## Depth levels
|
||||
|
||||
- **L1** — one screen, no scroll: claim · three metric chips · tech chips · one link.
|
||||
- **L2** — capability statement · what's actually run · architecture diagram · evidence table · trade-offs · drill-downs.
|
||||
- **L3** — artefact: code excerpt, diagram, screenshot, recording, log, ADR.
|
||||
|
||||
**Rule:** every L1 claim has a metric and at least one L3 artefact. Every L3 artefact is ≤ 3 clicks from landing.
|
||||
|
||||
## Metric chips (approved values)
|
||||
|
||||
| Area | Chips |
|
||||
|---|---|
|
||||
| AI | 16+ pipelines (10 n8n/Prefect/LangGraph · 6 Paperclip) · 6 providers behind one gateway · 8 audio endpoints |
|
||||
| Platform | 50+ containers · 4 hosts · Borg + Kopia + AWS, restore-tested |
|
||||
| Edge | 20+ nodes (10 ESP32 · 2 custom Zigbee routers · 8 Pi) · 9 zones · 20 automations |
|
||||
| Products | 3 businesses active (12 adopted over time) · Where-Woof deployed, pre-market |
|
||||
|
||||
## Factual corrections — do not undo
|
||||
|
||||
- **3** businesses active, not 12. Twelve was cumulative adoption.
|
||||
- **Where-Woof** is deployed but **has not gone to market**. Not commercial.
|
||||
- Drop "42 devices" and "~800ms end-to-end" — unverified.
|
||||
- **Diageo** (not "Diajio"); **Baileys** Irish Cream.
|
||||
- BBC National Archive was an **internal tool** — describe, no screenshot.
|
||||
|
||||
## Failures to keep in
|
||||
|
||||
Lizard feeder destroyed by the lizard (rebuilding with plastic containers) · garden cameras postponed, parts arrived · doorbell being rebuilt, adding a ToF sensor · garden automation partly manual.
|
||||
|
||||
These are evidence of production experience. Do not soften them.
|
||||
|
||||
## Corporate framing rule
|
||||
|
||||
Headings name the capability; product names are evidence beneath it.
|
||||
|
||||
> ❌ "ESP32 and Zigbee and LoRaWAN"
|
||||
> ✅ "Distributed edge computing — constrained devices, custom radio, sub-second actuation"
|
||||
> ✅ …with `ESP32 · Zigbee · LoRaWAN · MQTT` beneath as proof.
|
||||
|
||||
## Sources
|
||||
|
||||
`../resume_ai_system/plan/EVIDENCE-NOTES.md` (authority for facts) · `draft-content.md` (client wall, recovered site content) · `20-content-spine.md` (areas and claims) · `old_projects.md` (code exhibits, IoT grouping) · `resume_2025.docx` (2000–2020 engagements).
|
||||
|
||||
Read-only. Copy what's needed into `content/`; never link to these paths from the site.
|
||||
36
reference/decisions.md
Normal file
36
reference/decisions.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Frozen decisions
|
||||
|
||||
**These are not open for reconsideration inside the build.** Changing any of them requires Sam's written approval and an ADR in this folder. Detail and reasoning: `../../resume_ai_system/plan/10-technology-plan.md` and `40-cull-register.md`.
|
||||
|
||||
| # | Decision | Chosen | Rejected, and why |
|
||||
|---|---|---|---|
|
||||
| D1 | Site shell | **Go + `templ` + HTMX** | React 19/Vite — node build + bundler for no UX gain. Svelte/Solid — no benefit for a server-rendered content site. Astro — credible runner-up, but adds a Node toolchain we control away. Leptos/Wasm — complexity overhead |
|
||||
| D2 | Templating | **`templ`** | `html/template` — stringly typed, fails at runtime not compile time. `templ` compiles to Go, so a broken view is a compiler error |
|
||||
| D3 | AI console | **One hand-written TS island**, ES modules | React island — second toolchain. No framework — xterm and SSE are plain-library concerns |
|
||||
| D4 | Markdown / highlighting | **Server-side** `goldmark` + `chroma` | Client-side Prism/marked — bundle weight, flash of unstyled code, two implementations for two modes |
|
||||
| D5 | Embedded data | **SQLite + FTS5** | Postgres — another container for a site with one writer. Redis — explicitly rejected previously, and unnecessary |
|
||||
| D6 | Vector store | **Qdrant** | ChromaDB — heavier footprint, weaker payload filtering, and it is the stack being retired. SQLite-vec — promising, less mature filtering. Weaviate/Milvus/pgvector — overkill |
|
||||
| D7 | Ingestion | **Prefect** (server already running) | Airflow — already abandoned once for RAM. n8n — retained for household automation only |
|
||||
| D8 | Query graph | **LangGraph, four nodes** | Flowise/Windmill/Activepieces — visual builders, not needed for 200 lines of Python. More agents — complexity that causes drift |
|
||||
| D9 | Model access | **OmniRoute only** | LiteLLM — would duplicate an existing gateway. Direct provider SDKs — violates house rule |
|
||||
| D10 | Retrieval | **Hybrid**: vectors + BM25/FTS5 → RRF → cross-encoder rerank | Vector-only — misses exact tokens (repo names, `LoRaWAN`, `MQTT`, dates) |
|
||||
| D11 | Memory | **None.** Stateless by design | Hindsight, TencentDB Agent Memory, LangMem, Engram, Headroom — all rejected *for this product*. A public assistant with no returning user gains nothing and gains a write path. Engram/Headroom remain part of Sam's own workflow and are documented as such |
|
||||
| D12 | Observability | JSONL trace + Langfuse Cloud free tier | Self-hosted Langfuse — 6 containers, ~2 GiB, unaffordable on `.13` |
|
||||
| D13 | Guardrails | **`mozilla-ai/any-guardrail`** | Prompt-only defence. The library is the mechanism; `agents/security.md` is the policy |
|
||||
| D14 | Agent tools | **None** | A code-execution sandbox was considered and rejected: a public CV site will not run model-generated code |
|
||||
| D15 | Voice | Reuse existing **Whisper + Piper** on `.13` | New STT/TTS stack — already solved |
|
||||
|
||||
## Standing rules
|
||||
|
||||
1. All models through **OmniRoute**.
|
||||
2. Secrets from **`~/.config/environment.d/`** only.
|
||||
3. Own service, own port, own folder.
|
||||
4. No LLM in the path of a fast or consequential action.
|
||||
5. **Mode A must work with every AI service stopped.**
|
||||
6. New footprint **≤ 1.0 GiB RAM, ≤ 4 containers**.
|
||||
|
||||
## Rejected before deployment
|
||||
|
||||
Airflow · self-hosted Langfuse · Trigger.dev · LiteLLM · second Garage instance · OpenCode as a "brain" service · Flowise · Windmill · Activepieces · Helm/Helicone · Multica · Archon · CAO CLI · AgentPipe · CrewAI · nine documentation platforms.
|
||||
|
||||
**Why this list is kept:** "alternatives considered" is a senior signal, and it converts a cull from a subtraction into an exhibit. The public site gets a short page listing these with the reasoning.
|
||||
61
reference/stack.md
Normal file
61
reference/stack.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Stack, hosts, ports, budgets
|
||||
|
||||
## Hosts (measured 2026-10-17)
|
||||
|
||||
| Host | Name | Role | RAM total / free | Swap used | CPUs |
|
||||
|---|---|---|---|---|---|
|
||||
| `.13` | `nixos-desktop` | **Runtime** — app, Qdrant, Prefect worker | 15 GiB / **2.3 GiB** | **8.1 GiB** | 12 |
|
||||
| `.35` | `sam-Ubuntu1` | **Public edge** — Caddy terminates 443; also Gitea, Immich, Nextcloud, Penpot, Wiki.js | 14 GiB / 4.1 GiB | 4.0 GiB | 2 |
|
||||
| `.27` | `sam-4screen-desktop` | **Build / dev** — sources, Obsidian vault, agent work | — | — | — |
|
||||
|
||||
`.13` is memory-bound, not CPU-bound. The budget is real: exceeding it destabilises services Sam relies on.
|
||||
|
||||
## Ports
|
||||
|
||||
| Service | Host | Port | State |
|
||||
|---|---|---|---|
|
||||
| Caddy | `.35` | 443 (+ LAN 8000) | existing — **Sam applies any change** |
|
||||
| **Go app** | `.13` | **8096** | new — verify free (`8095` = offsite.lab) |
|
||||
| Qdrant REST | `.13` | 6333 | new, `127.0.0.1` only |
|
||||
| Qdrant gRPC | `.13` | 6334 | new, `127.0.0.1` only |
|
||||
| Prefect server | `.13` | existing | reuse — do not deploy a second |
|
||||
| OmniRoute | `.13` | existing | reuse — the only model gateway |
|
||||
| Postgres | `.13` | 5432 | reuse if needed |
|
||||
| Whisper / Piper | `.13` | existing | reuse (Phase 7 voice only) |
|
||||
| LangGraph service | `.13` | 8096+1 or existing | Phase 5 — see note below |
|
||||
|
||||
**Known occupied:** 3000, 3020, 5000, 5002, 5432, 8000, 8001, 8080, 8082, 8090, 8091, 8092, 8095, 8230, 8231, 8500, 8501, 8788–8792, 3081–3084, 1883.
|
||||
|
||||
## Memory budget
|
||||
|
||||
| Component | Cap |
|
||||
|---|---|
|
||||
| Go app | 120 m |
|
||||
| Qdrant | 400 m |
|
||||
| Prefect worker | 150 m |
|
||||
| Guardrail (if local) | 300 m |
|
||||
| **Total ceiling** | **1.0 GiB / 4 containers** |
|
||||
|
||||
Every service sets `mem_limit` **and** `memswap_limit` to the same value so it cannot consume host swap. Bind to `127.0.0.1`; Caddy is the only public listener.
|
||||
|
||||
## Paths
|
||||
|
||||
| Item | Path |
|
||||
|---|---|
|
||||
| Repo working copy | `/home/sam/paseo/projects/resume_ai_system_paperclip_build` |
|
||||
| Release root | `/home/sam/deployment/resume/` |
|
||||
| Live symlink | `/home/sam/deployment/resume/current` |
|
||||
| Secrets | `~/.config/environment.d/10-secrets.conf` |
|
||||
| Planning reference | `/home/sam/paseo/projects/resume_ai_system/plan/` (read-only) |
|
||||
|
||||
## Public entry
|
||||
|
||||
`resume.lab.audasmedia.com.au` — wildcard DNS already resolves to the public edge on `.35`. **No DNS work is required.** Caddy block is specified in Phase 3 §3.3.
|
||||
|
||||
## Open items
|
||||
|
||||
| Item | Owner |
|
||||
|---|---|
|
||||
| Embedding provider (Gemini free tier vs OpenRouter vs local) | Sam — decide before Phase 4 |
|
||||
| Repo public/private after launch | Sam — decide after Phase 3 |
|
||||
| Phone number on the contact page | Sam |
|
||||
Reference in New Issue
Block a user