Compare commits
3 Commits
feat/phase
...
content/ph
| Author | SHA1 | Date | |
|---|---|---|---|
| 72edfec59c | |||
|
|
00fa15f98f | ||
| 0eb151117e |
4
.gitignore
vendored
@@ -1,3 +1,7 @@
|
||||
# python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# build output
|
||||
/dist/
|
||||
/current/
|
||||
|
||||
19
Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Ai Resume - build entry points.
|
||||
#
|
||||
# `make validate` is the single gate: it is what CI and deploy.sh call.
|
||||
# It exits 0 only on a clean content tree.
|
||||
|
||||
PYTHON ?= python3
|
||||
VALIDATOR := $(PYTHON) tools/validate_content.py
|
||||
|
||||
.PHONY: validate test help
|
||||
|
||||
help:
|
||||
@echo "make validate validate content/** front-matter against the frozen schema"
|
||||
@echo "make test run the validator self-test (fixtures under test/fixtures/)"
|
||||
|
||||
validate:
|
||||
@$(VALIDATOR)
|
||||
|
||||
test:
|
||||
@$(VALIDATOR) --self-test
|
||||
75
content/about/about-narrative.md
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
id: about-narrative
|
||||
area: about
|
||||
level: 2
|
||||
title: "The narrative — including the years that need explaining"
|
||||
claim: "A self-taught career across six technology eras — interrupted on purpose by a non-IT working life and five years overseas — with 2020 to 2026 spent raising two children while building a business."
|
||||
confidence: running
|
||||
period: "1999–"
|
||||
tech: [NixOS, Neovim, Python, JavaScript, React, Go, HTMX]
|
||||
metrics: [{label: "years shipping software", value: 25}, {label: "years spent overseas", value: 5}, {label: "non-IT roles worked", value: 6}]
|
||||
artefacts: [{type: doc, label: "Non-IT working history", url: "content/about/l3/about-non-it-work.md"}, {type: doc, label: "Education", url: "content/about/l3/about-education.md"}, {type: doc, label: "Interests — one honest line each", url: "content/about/l3/about-interests.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [about, narrative, 2020-2026]
|
||||
---
|
||||
|
||||
# The narrative — including the years that need explaining
|
||||
|
||||
**Capability statement.** Someone who learned by doing, in public, on deadlines, and who has kept learning after the deadlines stopped being someone else's. The range is real and the gaps are stated.
|
||||
|
||||
## The beginning
|
||||
|
||||
Programming started as a childhood interest in the 1980s, self-taught alongside art, music, philosophy and sport. The career proper started in the late 1990s building websites for an Australian car marketplace. When interactive front ends arrived — a creative layer that needed a technical spine — there was no course to take, so it was learned directly and immediately put into commercial work. That combination, creative front end with engineering underneath, has been the shape of the work ever since.
|
||||
|
||||
## The agency years
|
||||
|
||||
Freelance in Melbourne, then full-time roles in the United Kingdom during the emergence of online gaming and interactive advertising, then back to freelance where the work was with the largest agencies and their clients — banks, broadcasters, drinks brands, publishers, a global energy company, a design software vendor. Most of it was delivered under deadlines that could not move, and a meaningful share of it was rescue work: rewriting someone else's stalled project and shipping it on their date.
|
||||
|
||||
## The other working life
|
||||
|
||||
Not all of it was software, and that is worth stating rather than hiding. Six roles outside technology — a ski chalet kitchen in the French Alps, wine service, guided horse tours in the Victorian high country, building a stable complex, state government administration, and thoroughbred stable work. They are the reason the engineering reads as practical: a kitchen at service and a production incident have the same shape.
|
||||
|
||||
## The education
|
||||
|
||||
A fine arts degree with philosophy, a master's in international relations and contemporary political theory, and study in music composition and economics. None of it is computer science, and all of it is used: systems thinking, argument, aesthetics, and the habit of asking what a thing is actually for.
|
||||
|
||||
## 2020 to 2026 — stated plainly
|
||||
|
||||
This period is on the page because a résumé that hides it invites the wrong question. It was spent as a full-time parent to two children while building in parallel:
|
||||
|
||||
- A digital signage business taken from idea to customers — the product, the deployments, the support.
|
||||
- A site builder and CMS that carried the marketing for it.
|
||||
- A lost-property tag system, deployed.
|
||||
- A homelab that became the platform for everything else: declarative configuration, containers, backups, networking, public ingress.
|
||||
- An AI estate — pipelines, routing, retrieval, voice, guardrails — built and operated on the same hardware.
|
||||
- A deliberate move from PHP and front-end scripting into Go, systems work and platform engineering, and from hand-installed servers into reproducible configuration.
|
||||
|
||||
The honest framing is in the evidence notes and is repeated here: *full-time parent, building in parallel*. The output of those years is on the rest of this site and can be inspected.
|
||||
|
||||
## What next
|
||||
|
||||
The same three areas at a larger scale: AI and agentic systems, the platform engineering underneath them, and the constrained devices at the edge. Melbourne based and flexible about location and format — remote, hybrid, office, or travel.
|
||||
|
||||
## Contact policy
|
||||
|
||||
This site publishes no address, no phone number and no family details. Contact is by email, with the address supplied directly rather than scraped from a page. If a phone number belongs on the site, that is Sam's decision to make and it is not made here.
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **No computer science degree.** The trade is a longer, broader practical education; the pages on this site are the argument, not the certificate.
|
||||
- **A period of self-employment is described as such.** It is not dressed up as a sabbatical or as consulting.
|
||||
- **Interests are one honest sentence each.** The previous version of this site invented venues and results. That has been deleted rather than corrected in place.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [Non-IT working history](l3/about-non-it-work.md) — level 3
|
||||
- [Education](l3/about-education.md) — level 3
|
||||
- [Interests — one honest line each](l3/about-interests.md) — level 3
|
||||
- [The AI estate](../ai/ai-systems.md) — level 2
|
||||
- [The platform estate](../platform/platform-estate.md) — level 2
|
||||
- [The edge fleet](../edge/edge-fleet.md) — level 2
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 1999–`. Confidence is `running`: this is the current self-description, verified against the evidence notes on 2026-10-26.
|
||||
25
content/about/about-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: about-overview
|
||||
area: about
|
||||
level: 1
|
||||
title: "About"
|
||||
claim: "Twenty-five years of shipping software — built through self-teaching · a non-IT working life · and five years overseas — now aimed at AI systems · the platforms under them and the devices at the edge."
|
||||
confidence: running
|
||||
period: "1999–"
|
||||
tech: [NixOS, Neovim, Python, JavaScript, React, Go, HTMX]
|
||||
metrics: [{label: "years shipping software", value: 25}, {label: "years spent overseas", value: 5}, {label: "non-IT roles worked", value: 6}]
|
||||
artefacts: [{type: doc, label: "Non-IT working history", url: "content/about/l3/about-non-it-work.md"}, {type: doc, label: "Education", url: "content/about/l3/about-education.md"}, {type: doc, label: "Interests — one honest line each", url: "content/about/l3/about-interests.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [about, narrative, background]
|
||||
---
|
||||
|
||||
# About
|
||||
|
||||
**Claim.** A career built by self-teaching — from a childhood in the 1980s with a borrowed language reference, through fifteen years of agency delivery, a working life outside technology, and five years overseas — now concentrated on AI systems, the platforms they run on, and the hardware at the edge.
|
||||
|
||||
**Status.** Current. Melbourne based, and flexible about how the work is done — remote, hybrid, office, or travel.
|
||||
|
||||
**What this page is for.** The other five areas prove what can be built. This one explains where the judgement came from: a non-technical working life, a fine-arts and philosophy education, and a period spent building a business while raising two children.
|
||||
|
||||
**Start here.** [The narrative](about-narrative.md) — including an honest account of 2020 to 2026.
|
||||
37
content/about/l3/about-education.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: about-education
|
||||
area: about
|
||||
level: 3
|
||||
title: "Artefact — Education"
|
||||
claim: "A fine arts degree with philosophy · a master's in international relations and contemporary political theory · and study in music composition and economics."
|
||||
confidence: historic
|
||||
period: "1997–"
|
||||
tech: []
|
||||
metrics: [{label: "tertiary qualifications completed", value: 2}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [about, education, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Education
|
||||
|
||||
**Status: stub.** Formal presentation lands in Phase 7. No certificates, transcripts or student identifiers are published.
|
||||
|
||||
## The record
|
||||
|
||||
- **Master of International Relations and Contemporary Political Theory** — University of Westminster, Centre for the Study of Democracy.
|
||||
- **Bachelor of Visual Communication and Fine Arts** — RMIT (Melbourne) and the University of South Australia, 1997–1999.
|
||||
- **Music composition and economics** — studied at La Trobe University alongside the composition work described under interests.
|
||||
|
||||
## What it proves
|
||||
|
||||
Two things the technical record cannot: formal training in argument and political economy, and formal training in visual judgement. Domain-switching is a habit rather than a claim — the degrees are in different fields from each other and from the career.
|
||||
|
||||
## Why no computer science degree
|
||||
|
||||
Because there is not one, and saying so is cheaper than having it discovered. The self-taught path is documented across this site: the History pages show the eras, the Platform and Edge pages show what came of them.
|
||||
|
||||
## Coverage limit
|
||||
|
||||
Qualification names, awarding institutions and the years the résumé states are published. Grades, student numbers and the master's completion year are not in the sources and are therefore not stated.
|
||||
72
content/about/l3/about-interests.md
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
id: about-interests
|
||||
area: about
|
||||
level: 3
|
||||
title: "Artefact — Interests · one honest line each"
|
||||
claim: "Fourteen pursuits with one true sentence each — and the invented venues · results and trips from the previous version of this site deleted rather than restated."
|
||||
confidence: running
|
||||
period: "1980–"
|
||||
tech: []
|
||||
metrics: [{label: "pursuits listed", value: 15}, {label: "bands played in", value: 2}, {label: "bee hives kept", value: 2}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [about, interests, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Interests · one honest line each
|
||||
|
||||
**Status: stub for the visual treatment.**
|
||||
|
||||
## Music
|
||||
Blues and jazz piano and blues harp; played in two bands. Studied music composition at university and kept the piano as the thing that resets the week.
|
||||
|
||||
## Fine art
|
||||
A fine arts degree and a continuing practice. Drawing and painting taught patience with iteration, which is most of debugging.
|
||||
|
||||
## Philosophy
|
||||
A degree's worth of it, and it is where the habit of asking what a thing is actually for came from.
|
||||
|
||||
## Skiing
|
||||
Italy, France, Japan and Australia. Six months based in Meribel in the French Alps as a chalet chef, including the Vallée Blanche glacier run.
|
||||
|
||||
## Camping
|
||||
Hiking, camping and canoeing, mostly in Victoria. Most recent: a two-day hike through Wilsons Promontory with a group of teenagers in tow.
|
||||
|
||||
## Canoeing
|
||||
The Yarra, the Otways and the Murray.
|
||||
|
||||
## Horse riding
|
||||
Grew up riding in the Otways; broke horses from track work back to dressage; guided tours in the Victorian high country; competed in dressage for two years.
|
||||
|
||||
## Surfing
|
||||
Grew up between Lorne and the Otways, on waves and horses.
|
||||
|
||||
## Hiking
|
||||
The walking version of the camping answer: long days, small pack, no phone signal.
|
||||
|
||||
## Global politics
|
||||
The master's was in it. Reading it is a habit, not a credential to display.
|
||||
|
||||
## Reading
|
||||
History, philosophy, politics, economics — the same four subjects as the degrees, which is either consistency or a rut.
|
||||
|
||||
## Cooking
|
||||
Worked in many restaurants and as chef in a five-star chalet in Meribel, France.
|
||||
|
||||
## Gardening
|
||||
Permaculture and a wood-chip, low-input approach to self-sufficiency, with sensors and automation doing the boring parts.
|
||||
|
||||
## Food production
|
||||
Bees, salami and cheese. Two hives, and salami made annually from four pigs with Italian friends in Benalla.
|
||||
|
||||
## Italy and travel
|
||||
Five years spent overseas, travelling extensively, with Italy as the standing preference.
|
||||
|
||||
## What was deleted, and why
|
||||
|
||||
The previous site claimed venues, competition results, swell sizes, distances and named restaurants. None of it could be traced. It has been cut rather than corrected: a single true sentence is worth more than ten specific ones that cannot be substantiated, and an interviewer who asks a follow-up question is entitled to an answer that survives it.
|
||||
|
||||
## Coverage limit
|
||||
|
||||
Everything above traces to Sam's own notes. Anything not in those notes is absent, not paraphrased.
|
||||
42
content/about/l3/about-non-it-work.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
id: about-non-it-work
|
||||
area: about
|
||||
level: 3
|
||||
title: "Artefact — Non-IT working history"
|
||||
claim: "Six roles outside technology — a chalet kitchen in the French Alps · wine service · guided horse tours · a stable build · government administration · thoroughbred stable work."
|
||||
confidence: historic
|
||||
period: "1990–2010"
|
||||
tech: []
|
||||
metrics: [{label: "non-IT roles worked", value: 6}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [about, history, work, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Non-IT working history
|
||||
|
||||
**Status: stub for the visual treatment.** The roles are final; the presentation lands in Phase 7.
|
||||
|
||||
## The roles
|
||||
|
||||
| Role | Where | What it involved |
|
||||
|---|---|---|
|
||||
| Chalet chef | Merribel, France | Meals for chalet guests, kitchen operations, menu planning, dietary requirements, in a high-pressure alpine season |
|
||||
| Wine waiter | South Australia and Victoria | Premium wine regions, varietals, food pairing |
|
||||
| Horseback tour guide | Victorian high country | Guided tours, rider safety, horse welfare, trail navigation |
|
||||
| Stable construction | Mount Beauty, Victoria | A 24-bay stable build — project management, budgeting, hands-on construction |
|
||||
| Civil servant | Victorian State Government, Melbourne | Administrative and operational support to state-level programs |
|
||||
| Horse trainer and stable hand | Sunbury, Victoria | Care and training of thoroughbreds, exercise, grooming, race-day preparation |
|
||||
|
||||
## What it proves
|
||||
|
||||
That the engineering sits on a wider working life. Kitchen service and production incidents share a shape; guiding strangers on horses in the high country is risk management with consequences; a stable build is a budget and a schedule held by hand. These are the reasons the technical pages read as practical rather than academic.
|
||||
|
||||
## Why this is on a technical site
|
||||
|
||||
Because leaving it out would make the career look narrower than it is, and because the years it occupies are otherwise unexplained.
|
||||
|
||||
## Coverage limit
|
||||
|
||||
Descriptions are limited to what the résumé and the evidence notes corroborate. Roles, employers' towns and the type of work are stated; no employer is named beyond the region, and no claim is made about scale, revenue or headcount that the sources do not carry.
|
||||
25
content/ai/ai-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: ai-overview
|
||||
area: ai
|
||||
level: 1
|
||||
title: "AI & Agentic Systems"
|
||||
claim: "Builds and operates sixteen or more AI pipelines — agent harnesses · model routing and cost control · retrieval over a tagged corpus · and a voice front-end that runs a house."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [LangGraph, Prefect, n8n, Qdrant, OmniRoute, Whisper, Piper, MiniMax]
|
||||
metrics: [{label: "pipelines maintained", value: 16}, {label: "model providers behind one gateway", value: 6}, {label: "audio endpoints for spoken output", value: 8}]
|
||||
artefacts: [{type: doc, label: "House AI hub — service topology", url: "content/ai/l3/ai-hub-architecture.md"}, {type: doc, label: "Model routing and cost control", url: "content/ai/l3/ai-omniroute-routing.md"}, {type: doc, label: "Voice pipeline — speech in and speech out", url: "content/ai/l3/ai-voice-pipeline.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, agents, routing, retrieval, voice]
|
||||
---
|
||||
|
||||
# AI & Agentic Systems
|
||||
|
||||
**Claim.** Sixteen or more AI pipelines are maintained in production — ten or more on n8n, Prefect and LangGraph, six on Paperclip — with one gateway in front of six model providers, retrieval over a metadata-tagged corpus, and a voice front-end that controls the house.
|
||||
|
||||
**Status.** Running. Every figure on this page traces to the evidence notes; the verification date is 2026-10-26.
|
||||
|
||||
**Why it reads as engineering rather than enthusiasm.** The pipelines run against real obligations — school portals, calendars, email, household audio — and they are operated: routed for cost, guarded before they act, and observed while they run.
|
||||
|
||||
**Start here.** [The capability page](ai-systems.md) explains what is actually run and what the trade-offs were. The three chips above resolve to artefacts below it.
|
||||
70
content/ai/ai-systems.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
id: ai-systems
|
||||
area: ai
|
||||
level: 2
|
||||
title: "Agent systems that are operated rather than demonstrated"
|
||||
claim: "Maintains sixteen or more production AI pipelines — agent harnesses · prompt-analysis routing across six providers · retrieval filtered by metadata before it searches · and a guarded voice front-end."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [LangGraph, Prefect, n8n, Paperclip, Qdrant, OmniRoute, Whisper, Piper, MiniMax, TUIOS]
|
||||
metrics: [{label: "pipelines maintained", value: 16}, {label: "model providers behind one gateway", value: 6}, {label: "audio endpoints for spoken output", value: 8}, {label: "hosts under standardised agent operations", value: 4}]
|
||||
artefacts: [{type: doc, label: "House AI hub — service topology", url: "content/ai/l3/ai-hub-architecture.md"}, {type: doc, label: "Model routing and cost control", url: "content/ai/l3/ai-omniroute-routing.md"}, {type: doc, label: "Paperclip and n8n pipelines in production", url: "content/ai/l3/ai-paperclip-pipelines.md"}, {type: doc, label: "Retrieval corpus and query graph", url: "content/ai/l3/ai-rag-corpus.md"}, {type: doc, label: "Voice pipeline — speech in and speech out", url: "content/ai/l3/ai-voice-pipeline.md"}, {type: doc, label: "Guardrails — hooks in the model path", url: "content/ai/l3/ai-guardrails.md"}, {type: doc, label: "Memory in two layers", url: "content/ai/l3/ai-memory-layers.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, agents, routing, retrieval, voice, guardrails]
|
||||
---
|
||||
|
||||
# Agent systems that are operated rather than demonstrated
|
||||
|
||||
**Capability statement.** This is a working estate, not a prototype: more than sixteen pipelines in production, six providers behind a single gateway, retrieval that filters on metadata before it searches, and a voice front-end used daily by people who did not build it.
|
||||
|
||||
## What is actually run
|
||||
|
||||
**Routing.** Every model call goes through one gateway — OmniRoute. Six providers sit behind it: DeepSeek, MiniMax, OpenRouter, OpenCode-Go, Gemini and OpenAI. Requests are classified before they are sent, so the cheapest model that can do the job gets the job. No project in the estate calls a provider directly; that is a rule, not a preference.
|
||||
|
||||
**Pipelines.** Ten or more are maintained on n8n, Prefect and LangGraph — email scanners, school-portal scanners, calendar scanners, project agents — plus six Paperclip pipelines that run work through a bench of narrow specialist agents behind human approval gates. The estate is registered in a dashboard built to keep track of it.
|
||||
|
||||
**Harnesses.** JEV is a custom harness with its own routing, tool set and memory rather than a wrapper around a vendor SDK. Work is executed as sequences of narrow agents instead of one large prompt; capability is loaded per task through a skill-selection step, so the agent gets what this job needs and not an enormous system prompt.
|
||||
|
||||
**Memory.** Two deliberate layers. Engram keeps what should persist — curated summaries, decisions, prompts and session handoffs in local SQLite, integrated with JEV for fast compaction. Headroom keeps what should not persist out of the window, stripping and compressing prompt context, tool output and logs before they reach the model. Storage and token control are separate problems and are solved separately.
|
||||
|
||||
**Retrieval.** ChromaDB first, then replaced with Qdrant for payload-filtered retrieval and a smaller footprint. LangGraph query graphs on top; Prefect and n8n for ingestion. The corpus is metadata-tagged at ingest, which means retrieval filters before it searches — the difference between a device answer and a work-history answer is a filter, not a better prompt.
|
||||
|
||||
**Voice.** Local Whisper for speech to text with a fallback, Piper for text to speech, MiniMax for a cloned voice with emotion and non-verbal cues. A custom wake word on an ESP32 with LED confirmation. Voice is a system front-end: it controls lighting, music, calendars, shopping, email, SMS and alerts, and it answers through eight Snapcast endpoints with music ducked underneath.
|
||||
|
||||
**Guardrails.** Custom hooks live in the model path and block injection and constrain tool use, built because the house voice channel is shared and unauthenticated and there was no vendor control to borrow. Consequential actions sit behind approval gates, and no model sits in the path of a fast or dangerous command. The public site applies the same reasoning from the other end: the assistant it exposes has no tools at all, so the attack surface is a conversation rather than a shell.
|
||||
|
||||
**Agent operations.** Agent sessions are standardised on TUIOS across four hosts — sessions survive a disconnect, agents report their own state, and approvals land in one inbox. TUIOS is a third-party tool: the contribution is operations and packaging, not authorship. It is pinned at 0.10.1 in a hand-written Nix derivation because nixpkgs lagged at 0.7.0, and its daemon is declared as a systemd user service so the fleet is reproducible rather than hand-installed.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|---|---|---|
|
||||
| Sixteen or more pipelines in production | Ten or more on n8n, Prefect and LangGraph plus six on Paperclip | [Paperclip and n8n pipelines](l3/ai-paperclip-pipelines.md) |
|
||||
| Six providers behind one gateway | DeepSeek, MiniMax, OpenRouter, OpenCode-Go, Gemini, OpenAI | [Model routing](l3/ai-omniroute-routing.md) |
|
||||
| Retrieval filters before it searches | Corpus tagged at ingest; Qdrant payload filters; LangGraph query nodes | [Corpus and query graph](l3/ai-rag-corpus.md) |
|
||||
| Spoken output reaches eight endpoints | Eight Snapcast clients with music ducking | [Voice pipeline](l3/ai-voice-pipeline.md) |
|
||||
| Guardrails are code in the path | Injection-blocking hooks and constrained tool use | [Guardrails](l3/ai-guardrails.md) |
|
||||
| Memory is two layers by design | Engram for persistence, Headroom for context control | [Memory layers](l3/ai-memory-layers.md) |
|
||||
| Agent operations are standardised | TUIOS across four hosts with one approval inbox | [House AI hub](l3/ai-hub-architecture.md) |
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **Local inference was measured, then demoted.** The estate started local on Ollama. Hardware constraints made local inference both slower and more expensive than partitioned remote calls, so heavy flows moved remote while sensitive and low-latency work stayed local. That is a documented comparison, not a taste in hardware.
|
||||
- **The retired stack is in the record.** Airflow DAGs were abandoned for RAM, ChromaDB was replaced by Qdrant, and a visual-builder layer was dropped. Each replacement is stated rather than hidden, because the reasoning is the transferable part.
|
||||
- **Not everything is automated.** Parts of the house are automated end to end and parts still need a person to press the button. The estate is described as it is run, not as it was imagined.
|
||||
- **Cost is bounded by routing, not by hope.** Caps and a refusal path exist so a runaway session cannot become a bill; the routing layer keeps the median request on a cheap model.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [House AI hub — service topology](l3/ai-hub-architecture.md) — level 3
|
||||
- [Model routing and cost control](l3/ai-omniroute-routing.md) — level 3
|
||||
- [Paperclip and n8n pipelines in production](l3/ai-paperclip-pipelines.md) — level 3
|
||||
- [Retrieval corpus and query graph](l3/ai-rag-corpus.md) — level 3
|
||||
- [Voice pipeline — speech in and speech out](l3/ai-voice-pipeline.md) — level 3
|
||||
- [Guardrails — hooks in the model path](l3/ai-guardrails.md) — level 3
|
||||
- [Memory in two layers](l3/ai-memory-layers.md) — level 3
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 2020–`. The start is anchored on the homelab year in the evidence notes, because the AI estate and the homelab have the same origin. Confidence is `running`: this is the current arrangement, verified 2026-10-26 against the evidence notes.
|
||||
31
content/ai/l3/ai-guardrails.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-guardrails
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Guardrails · hooks in the model path"
|
||||
claim: "Injection blocking and constrained tool use are code in the model path — built because the house voice channel is shared and unauthenticated."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [OmniRoute, Python]
|
||||
metrics: [{label: "tools exposed by the public assistant", value: 0}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, guardrails, security, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Guardrails · hooks in the model path
|
||||
|
||||
**Status: stub.** A redacted injection-test result lands in Phase 6, when the guardrail library is wired into this site's own assistant.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The hooks that run before a request reaches a provider and before a response reaches an actuator: injection patterns are blocked, tool use is constrained to a declared set, and consequential actions stop at an approval gate. Behind them, one rule that outranks every prompt — no model sits in the path of a fast or dangerous command.
|
||||
|
||||
## What it proves
|
||||
|
||||
Safety enforced by mechanism. A prompt instruction is a suggestion; a hook is a control.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
The test result in Phase 6, using the same library the house runs. The policy that the public assistant has no tools at all is a Phase 5 and 6 decision and is not negotiable at runtime.
|
||||
31
content/ai/l3/ai-hub-architecture.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-hub-architecture
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — House AI hub service topology"
|
||||
claim: "One hub fronts the AI estate — intake · routing · pipelines · retrieval · voice output · and a single set of network tools namespaced per household member."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [n8n, Prefect, LangGraph, OmniRoute, Qdrant, MQTT, Snapcast]
|
||||
metrics: [{label: "provider gateway entry points", value: 1}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, architecture, artefact]
|
||||
---
|
||||
|
||||
# Artefact — House AI hub service topology
|
||||
|
||||
**Status: stub.** The diagram and the generated topology dump land in Phase 7 (polish). This stub exists so the level 2 page has no dangling reference.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A one-page diagram of the hub: request intake (voice · chat · scheduled job), the gateway hop, the pipeline runners, the retrieval path, and the output paths (house speakers, phone alerts, dashboards). Every box is a service that runs; nothing on the diagram is aspirational.
|
||||
|
||||
## What it proves
|
||||
|
||||
That the estate is a designed system with a single gateway and a single set of namespaced tools — not a collection of scripts that happen to share a machine.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. The source facts are in the evidence notes (sections 2 and 4). Capture must be from the live estate, so no diagram is drawn from memory in Phase 1.
|
||||
31
content/ai/l3/ai-memory-layers.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-memory-layers
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Memory in two layers · Engram and Headroom"
|
||||
claim: "Memory is split by purpose — Engram stores what should persist and Headroom keeps what should not persist out of the context window."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Engram, Headroom, SQLite, JEV]
|
||||
metrics: [{label: "memory layers", value: 2}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, memory, context, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Memory in two layers · Engram and Headroom
|
||||
|
||||
**Status: stub.** A redacted session handoff and a before-and-after context measurement land in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
Engram is local-first storage for curated summaries, decisions, prompts and session handoffs in SQLite, so a conversation can be resumed in any project; it is integrated with JEV for fast compaction. Headroom is token control: it strips, cleanses and analyses code and logs before they reach the model, compressing rather than truncating.
|
||||
|
||||
## What it proves
|
||||
|
||||
Two distinct problems recognised as two — persistence and window economy — instead of one tool asked to do both.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Both tools are part of Sam's own workflow; they are deliberately not part of the public assistant, which is stateless by decision (see `reference/decisions.md` D11).
|
||||
31
content/ai/l3/ai-omniroute-routing.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-omniroute-routing
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Model routing and cost control"
|
||||
claim: "Every model call is classified first and sent to the cheapest capable provider — six providers behind one gateway with no direct SDK calls anywhere in the estate."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [OmniRoute, JEV, DeepSeek, MiniMax, OpenRouter, Gemini, OpenAI]
|
||||
metrics: [{label: "providers in rotation", value: 6}, {label: "gateways", value: 1}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, routing, cost, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Model routing and cost control
|
||||
|
||||
**Status: stub.** The routing decision path and a redacted cost table land in Phase 7. No keys or account identifiers are ever published.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The decision path: request arrives, a prompt-analysis step classifies it, the gateway selects a provider and model, and the response returns with its cost recorded. Plus the comparison that demoted local inference for heavy flows — local Ollama measured slower and more expensive under the available hardware than partitioned remote calls.
|
||||
|
||||
## What it proves
|
||||
|
||||
Cost control implemented as routing and measurement rather than as a monthly promise, and a single chokepoint where provider access can be audited.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. The evidence for the provider list and the local-versus-remote decision is in the evidence notes, section 2 and section 4.
|
||||
31
content/ai/l3/ai-paperclip-pipelines.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-paperclip-pipelines
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Paperclip and n8n pipelines in production"
|
||||
claim: "Sixteen or more pipelines run real work — scanners · schedulers · project agents — with specialist agents dispatched by task and human approval gates on anything consequential."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Paperclip, n8n, Prefect, LangGraph]
|
||||
metrics: [{label: "pipelines on n8n and Prefect and LangGraph", value: 10}, {label: "Paperclip pipelines", value: 6}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, pipelines, agents, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Paperclip and n8n pipelines in production
|
||||
|
||||
**Status: stub.** A redacted run log of one pipeline lands in Phase 7, alongside the pipeline inventory.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
One pipeline shown end to end: trigger, steps, the agent or model each step uses, the approval gate, and the run log with identifiers removed. Alongside it, the inventory of what the sixteen or more pipelines do — email scanners, school-portal scanners, calendar scanners, project oversight, and the household automations.
|
||||
|
||||
## What it proves
|
||||
|
||||
Volume with operations behind it: these are scheduled, logged and monitored, not run once for a demonstration.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Counts come from the evidence notes, section 3.
|
||||
31
content/ai/l3/ai-rag-corpus.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-rag-corpus
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Retrieval corpus and query graph"
|
||||
claim: "Retrieval is filtered by metadata before it searches — a tagged corpus · a four-node LangGraph query graph · and a deliberate replacement of ChromaDB with Qdrant."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Qdrant, LangGraph, Prefect, n8n, ChromaDB]
|
||||
metrics: [{label: "retrieval stores used over time", value: 2}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, retrieval, rag, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Retrieval corpus and query graph
|
||||
|
||||
**Status: stub.** The query graph diagram and an ingest run log land later; this site's own corpus build is Phase 4.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The ingest and query path: documents are chunked and tagged with metadata at ingest, stored in Qdrant, and filtered on that metadata before a similarity search runs. The LangGraph graph has four nodes; the fourth decides whether the answer can be given from what was retrieved.
|
||||
|
||||
## What it proves
|
||||
|
||||
Retrieval designed around payload filtering and a hard stop, plus the reasoning for moving off ChromaDB — heavier footprint and weaker filtering — recorded as a decision rather than a migration.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
The query graph diagram in Phase 7. The live demonstration of the same pattern is this site's own retrieval, delivered in Phase 4 and Phase 5.
|
||||
31
content/ai/l3/ai-voice-pipeline.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: ai-voice-pipeline
|
||||
area: ai
|
||||
level: 3
|
||||
title: "Artefact — Voice pipeline · speech in and speech out"
|
||||
claim: "Speech in on a custom wake word · local transcription · a cloned voice out · and music ducked under every announcement across eight endpoints."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Whisper, Piper, MiniMax, ESP32, Snapcast, Mopidy, Home Assistant]
|
||||
metrics: [{label: "audio endpoints", value: 8}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [ai, voice, audio, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Voice pipeline · speech in and speech out
|
||||
|
||||
**Status: stub.** A short recording of music ducking under a spoken announcement lands in the optional voice phase. Text describes the chain until then.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The chain: an ESP32 device with a microphone detects the wake word and confirms with an LED, audio is transcribed locally with Whisper, the request goes through the gateway, and the reply is spoken through Piper or the MiniMax cloned voice over all eight Snapcast endpoints, with music lowered for the announcement and restored afterwards.
|
||||
|
||||
## What it proves
|
||||
|
||||
Voice treated as a system front-end with latency and reliability requirements — not a party trick bolted onto a chatbot.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Recording in the optional voice phase (Phase 7). The endpoint count and the ducking behaviour are from the evidence notes, sections 1 and 2.
|
||||
0
content/assets/.gitkeep
Normal file
65
content/edge/edge-fleet.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: edge-fleet
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Constrained devices · custom radio · and a record of what broke"
|
||||
claim: "Twenty or more edge nodes across nine zones and twenty automations — solar power · deep sleep · LoRa and hand-built Zigbee — reporting into one automation layer with voice control on top."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, LoRa, Zigbee, MQTT, Home Assistant, Snapcast, Pi, PIR, mmWave]
|
||||
metrics: [{label: "edge nodes", value: 20}, {label: "lighting zones", value: 9}, {label: "automations", value: 20}, {label: "hand-built Zigbee routers", value: 2}]
|
||||
artefacts: [{type: doc, label: "Edge architecture — power · radio · deep sleep", url: "content/edge/l3/edge-architecture.md"}, {type: doc, label: "LoRa irrigation under solar power", url: "content/edge/l3/edge-lora-sprinkler.md"}, {type: doc, label: "Hand-built Zigbee routers and lighting", url: "content/edge/l3/edge-zigbee.md"}, {type: doc, label: "Distributed audio — eight endpoints with ducking", url: "content/edge/l3/edge-snapcast.md"}, {type: doc, label: "Front door — vision · voice · and a rebuild", url: "content/edge/l3/edge-front-door.md"}, {type: doc, label: "Sensors and actuation", url: "content/edge/l3/edge-sensors.md"}, {type: doc, label: "The failures, kept in the record", url: "content/edge/l3/edge-failures.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, iot, esp32, lora, zigbee, audio]
|
||||
---
|
||||
|
||||
# Constrained devices · custom radio · and a record of what broke
|
||||
|
||||
**Capability statement.** Devices that must run for months on a small battery, talk over radio that was chosen for range rather than convenience, and fail in ways that are visible. Twenty or more nodes, nine zones, twenty automations, and a voice layer on top of all of it.
|
||||
|
||||
## What is actually run
|
||||
|
||||
**Edge architecture.** Each node is designed around its power budget: a LiFePO battery with a solar controller where there is sun, deep sleep between wakes, and a wake source chosen per job. The sprinkler and the garden lights wake on radio rather than on a timer, so a command can arrive while the device is asleep.
|
||||
|
||||
**Radio.** Three links, each for a reason. LoRa for range and penetration on outdoor nodes — long enough to cover the garden and the shed without a repeater. Zigbee for the indoor lighting mesh, including two routers built by hand where the commercial mesh did not reach. Wi-Fi where a device is mains-powered and needs bandwidth, such as the audio endpoints and the camera path.
|
||||
|
||||
**Sensors and actuation.** PIR for movement, radar and mmWave for presence that a PIR cannot see — including a presence sensor built for a bathroom and a child's bedroom because the off-the-shelf options were wrong for the space. Relays and step-down converters for 240V loads, servos and a 16-channel PWM driver for mechanical jobs, solenoids for water, load cells for weight.
|
||||
|
||||
**Audio distribution.** Eight Snapcast endpoints on Pi hardware, fed by a Snapserver, with Spotify and a music server as sources. Every spoken announcement — automation notices, assistant replies, doorbell messages — plays across all eight endpoints with the music ducked underneath and restored afterwards.
|
||||
|
||||
**The automation layer.** Home Assistant holds the state and the routines; MQTT carries the messages. Nine lighting zones and twenty automations, with voice control on top, so a request spoken in one room is answered through the speakers in whichever room a person is standing.
|
||||
|
||||
**Cameras and vision.** The front door takes an image, logs it, has the image described, and speaks the result into the house before deciding what to do next. RFID tags on boxes and on trees resolve to records — inventory with prices for the boxes, care notes for the trees — written by an automation rather than typed by hand.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|---|---|---|
|
||||
| Twenty or more nodes | Ten ESP32 devices · two hand-built Zigbee routers · eight Pi audio endpoints | [Edge architecture](l3/edge-architecture.md) |
|
||||
| Radio chosen per job | LoRa outdoors with radio wake from deep sleep; Zigbee indoors with hand-built routers | [Irrigation](l3/edge-lora-sprinkler.md) · [Zigbee](l3/edge-zigbee.md) |
|
||||
| Nine zones and twenty automations | Lighting zones and routines in the automation layer | [Zigbee and lighting](l3/edge-zigbee.md) |
|
||||
| Eight endpoints with ducking | Snapcast clients on Pi hardware with music lowered under speech | [Distributed audio](l3/edge-snapcast.md) |
|
||||
| Vision and voice at the door | Image capture · description · spoken response · two-way audio | [Front door](l3/edge-front-door.md) |
|
||||
| Failures are stated | Lizard feeder destroyed · garden cameras postponed · doorbell being rebuilt | [Failures](l3/edge-failures.md) |
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **Power decides the design.** Deep sleep means a device is unreachable for most of its life, so every routine has to tolerate a node that is asleep. That constraint is why radio wake exists at all.
|
||||
- **Range over bandwidth.** LoRa is slow and payload-limited. It is chosen where a hundred bytes a day is enough and the alternative is a Wi-Fi access point in a garden bed.
|
||||
- **Some things are still manual.** The garden automation is partly manual — some watering and lighting is scheduled, some is a person turning something on. The page says which is which instead of implying full coverage.
|
||||
- **The failures cost money and are kept.** A lizard destroyed a feeder built for it. The garden cameras were postponed with the parts already bought. The doorbell is being rebuilt rather than declared finished. Those are the most honest evidence of production experience on this site.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [Edge architecture — power · radio · deep sleep](l3/edge-architecture.md) — level 3
|
||||
- [LoRa irrigation under solar power](l3/edge-lora-sprinkler.md) — level 3
|
||||
- [Hand-built Zigbee routers and lighting](l3/edge-zigbee.md) — level 3
|
||||
- [Distributed audio — eight endpoints with ducking](l3/edge-snapcast.md) — level 3
|
||||
- [Front door — vision · voice · and a rebuild](l3/edge-front-door.md) — level 3
|
||||
- [Sensors and actuation](l3/edge-sensors.md) — level 3
|
||||
- [The failures, kept in the record](l3/edge-failures.md) — level 3
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 2020–`, anchored on the homelab year in the evidence notes. Confidence is `running` for the fleet as a whole; individual nodes carry their own label, and the ones being rebuilt or postponed are labelled that way on their pages.
|
||||
25
content/edge/edge-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: edge-overview
|
||||
area: edge
|
||||
level: 1
|
||||
title: "Edge & Devices"
|
||||
claim: "Builds and maintains a twenty-node edge fleet — constrained devices · custom radio · solar power · deep sleep · and sensors — reporting into a single automation layer."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, LoRa, Zigbee, MQTT, Home Assistant, Snapcast, Raspberry Pi]
|
||||
metrics: [{label: "edge nodes", value: 20}, {label: "lighting zones", value: 9}, {label: "automations", value: 20}]
|
||||
artefacts: [{type: doc, label: "Edge architecture — power · radio · deep sleep", url: "content/edge/l3/edge-architecture.md"}, {type: doc, label: "The failures, kept in the record", url: "content/edge/l3/edge-failures.md"}, {type: doc, label: "Distributed audio — eight endpoints with ducking", url: "content/edge/l3/edge-snapcast.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, iot, esp32, lora, zigbee]
|
||||
---
|
||||
|
||||
# Edge & Devices
|
||||
|
||||
**Claim.** Twenty or more nodes — ten ESP32 devices, two hand-built Zigbee routers and eight Pi audio endpoints — across nine lighting zones and twenty automations, all reporting into one automation layer.
|
||||
|
||||
**Status.** Running. Some of it is finished, some is being rebuilt, and at least one thing was destroyed by the animal it was built for. All three states are shown.
|
||||
|
||||
**Why it is credible.** These devices are outdoors, on solar, in deep sleep, and they must keep working when nobody is looking. The failures on this page cost real time and are documented as failures.
|
||||
|
||||
**Start here.** [The capability page](edge-fleet.md) covers the architecture, the radio, the audio and what broke.
|
||||
31
content/edge/l3/edge-architecture.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: edge-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — Edge architecture · power · radio · deep sleep"
|
||||
claim: "Each node is designed around its power budget — battery and solar · deep sleep between wakes · and a deliberate choice of wake source per job."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, LoRa, Zigbee, LiFePO, MQTT, Home Assistant]
|
||||
metrics: [{label: "edge nodes", value: 20}, {label: "ESP32 devices", value: 10}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, architecture, power, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Edge architecture · power · radio · deep sleep
|
||||
|
||||
**Status: stub.** One annotated diagram of a representative node and the radio path lands in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The per-node pattern: 240V step-down or solar with a LiFePO battery and charge controller, an ESP32 in deep sleep, a wake source (timer, radio, or a physical input), a relay or driver for the load, and an MQTT message into the automation layer. Around it, the reason each node uses LoRa, Zigbee or Wi-Fi.
|
||||
|
||||
## What it proves
|
||||
|
||||
Power budgeting and remote wake as design decisions, not hobby wiring — and an architecture that survived being repeated across twenty nodes.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: evidence notes section 1.
|
||||
39
content/edge/l3/edge-failures.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: edge-failures
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — The failures · kept in the record"
|
||||
claim: "Three things did not go to plan — a feeder the animal destroyed · cameras postponed with the parts already bought · and a doorbell being rebuilt instead of declared finished."
|
||||
confidence: in-progress
|
||||
period: "2020–"
|
||||
tech: [ESP32, Servo, PWM, Camera]
|
||||
metrics: [{label: "crickets released per day by the feeder", value: 10}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, failures, artefact]
|
||||
---
|
||||
|
||||
# Artefact — The failures · kept in the record
|
||||
|
||||
**Status: in progress.** Two items are being rebuilt, one is postponed. The page is not finished because the work is not finished.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A short, unpolished register of what did not work, in the order it broke.
|
||||
|
||||
**The lizard feeder.** Servo motors on a 16-channel PWM driver, rubber-band spring-loaded boxes, an ESP32 — one box opened per day to release ten crickets for the bearded dragon it was built for. The lizard attacked the boxes and destroyed the mechanism. Version one is abandoned; it is being rebuilt with plastic containers.
|
||||
|
||||
**The garden cameras.** Postponed. The parts have arrived and are sitting in a box. No photographs and no claim until they are installed.
|
||||
|
||||
**The front door.** Built, then found to greet people who were not at the door. It is being rebuilt with a time-of-flight ranging sensor rather than being described as complete.
|
||||
|
||||
**The garden automation.** Partly manual. Some of it runs on schedule and some of it is a person. Both are true and the page says so.
|
||||
|
||||
## What it proves
|
||||
|
||||
That this is a working estate and not a rendering: things break, budgets get spent on parts that are not installed yet, and hardware has to be designed around an animal's behaviour. Production experience is measured in rebuilds as much as in launches.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7, with photographs of the rebuilt feeder and the installed cameras if they exist by then. If they do not, the entry stays as written — labelled rather than deleted.
|
||||
35
content/edge/l3/edge-front-door.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: edge-front-door
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — Front door · vision · voice · and a rebuild"
|
||||
claim: "A doorbell that sees a person · describes the image · speaks to the house and to the visitor · and is currently being rebuilt with a time-of-flight sensor."
|
||||
confidence: in-progress
|
||||
period: "2020–"
|
||||
tech: [ESP32, ESP32-CAM, PIR, mmWave, VL53L0X, MiniMax, Piper, Whisper, Apprise]
|
||||
metrics: [{label: "voice engines in use", value: 2}, {label: "presence sensing inputs", value: "PIR · mmWave · time-of-flight"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, doorbell, vision, voice, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Front door · vision · voice · and a rebuild
|
||||
|
||||
**Status: in progress.** The device was built and is being rebuilt. The page states this rather than describing it as finished.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A door unit with microphone, speaker, camera, button, PIR and mmWave presence. It detects a person, captures an image, logs it, has the image described, and announces to the house who is at the door before offering a spoken greeting; the visitor's reply is captured and played over the house speakers, with an alert pushed to a phone. Voice output ran on one provider and now runs on a cloned voice with a fallback to a local synthesiser.
|
||||
|
||||
## What it proves
|
||||
|
||||
Vision, voice and actuation in one device under real constraints — latency that a person at a door will tolerate, and a failure mode that must be polite.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
The measurement it is being rebuilt around: presence detection with a time-of-flight ranging sensor, to stop the unit greeting people who are walking past rather than standing at the door. Until the rebuild is finished the honest label is `in-progress`.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7 for photos and the sensor change. Source: evidence notes section 1.
|
||||
35
content/edge/l3/edge-lora-sprinkler.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: edge-lora-sprinkler
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — LoRa irrigation under solar power"
|
||||
claim: "A solar-powered controller that sleeps · wakes on radio · and drives a solenoid — with the first version polling over a message queue instead."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, LoRa, LiFePO, Solenoid, Home Assistant, RabbitMQ]
|
||||
metrics: [{label: "major revisions", value: 2}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, lora, solar, irrigation, artefact]
|
||||
---
|
||||
|
||||
# Artefact — LoRa irrigation under solar power
|
||||
|
||||
**Status: stub.** The bill of materials and the wake-on-radio change land in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The build: solar panel, charge controller, LiFePO battery, ESP32, LoRa module, relay and solenoid valve. Version one woke on a schedule and polled through a message queue to learn whether it should run. Version two is better: a LoRa packet can wake the ESP32 from deep sleep and switch the valve directly, so on-time is short and the battery is not spent asking whether there is work.
|
||||
|
||||
## What it proves
|
||||
|
||||
Iteration on a real constraint. The first version worked; the second version was designed around the power cost of asking, which is the kind of decision you only make if you are watching the battery.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
Watering is partly scheduled and partly a person. The routine lives in the automation layer and the voice assistant can trigger it, but the garden is not fully automatic and the page does not pretend otherwise.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: evidence notes section 1.
|
||||
31
content/edge/l3/edge-sensors.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: edge-sensors
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — Sensors and actuation"
|
||||
claim: "Movement · presence · weight · temperature · water and mechanical actuation — chosen per job and integrated into one automation layer."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, PIR, Radar, mmWave, Load cell, Servo, Solenoid, MQTT]
|
||||
metrics: [{label: "automations", value: 20}, {label: "PWM channels on the feeder driver", value: 16}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, sensors, actuation, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Sensors and actuation
|
||||
|
||||
**Status: stub.** A sensor and actuator table lands in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The parts list of the fleet in the way an engineer would want it: what is sensed, which device senses it, what is actuated, and how the decision reaches a physical action — a relay, a solenoid, a servo, a step-down converter switching 240V, a wheel that flicks food into a tank, an auger that dispenses it, a load cell that decides when to top up water.
|
||||
|
||||
## What it proves
|
||||
|
||||
Range across the awkward middle of embedded work: not just reading a sensor but choosing an actuator, sizing its driver, and making the whole loop recoverable when the network is absent.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: evidence notes section 1.
|
||||
31
content/edge/l3/edge-snapcast.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: edge-snapcast
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — Distributed audio · eight endpoints with ducking"
|
||||
claim: "Eight synchronised endpoints with music ducked under every spoken announcement and restored afterwards — driven by Home Assistant and the voice assistant."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Snapcast, Mopidy, Spotify, Raspberry Pi, Home Assistant]
|
||||
metrics: [{label: "audio endpoints", value: 8}, {label: "client hardware", value: "Pi 2W"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, audio, snapcast, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Distributed audio · eight endpoints with ducking
|
||||
|
||||
**Status: stub.** The topology diagram and a short recording of ducking land in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A Snapserver with eight Pi clients, Spotify and a local music server as sources, and one behaviour that matters more than the rest: when the house needs to speak, the music drops and the announcement plays everywhere, then the music returns to its previous level. Requests arrive by voice, so the same system that plays music is also the output for every automation and every answer.
|
||||
|
||||
## What it proves
|
||||
|
||||
Multi-room audio treated as infrastructure with a predictable interruption behaviour — and the difference between "the speakers work" and "the speakers can be interrupted safely". Mains-powered nodes, bandwidth-heavy work, and a state machine for volume: the opposite design constraints to the battery nodes.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: evidence notes section 1.
|
||||
31
content/edge/l3/edge-zigbee.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: edge-zigbee
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Artefact — Hand-built Zigbee routers and lighting"
|
||||
claim: "Two routers built by hand to extend an indoor mesh · feeding nine lighting zones with presence sensing and voice control."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, Zigbee, Relay, PIR, Radar, Home Assistant]
|
||||
metrics: [{label: "hand-built Zigbee routers", value: 2}, {label: "lighting zones", value: 9}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [edge, zigbee, lighting, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Hand-built Zigbee routers and lighting
|
||||
|
||||
**Status: stub.** The router build and a zone map land in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
Two Zigbee routers on ESP32 hardware, built because the commercial mesh did not cover the house and a repeater would have been a black box. Behind them, nine lighting zones: custom presence sensors with PIR and radar for the bathroom and a child's bedroom, a central light controller with a readout and a potentiometer, and a three-button remote with a dial — click on, double click off, dial for level.
|
||||
|
||||
## What it proves
|
||||
|
||||
Mesh networking understood at the level where you can add a node instead of buying one, and lighting built for how a house is used rather than for a product category.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: evidence notes section 1.
|
||||
63
content/history/history-engagements.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
id: history-engagements
|
||||
area: history
|
||||
level: 2
|
||||
title: "Fifteen years of delivery for agencies and their clients"
|
||||
claim: "Twenty-two agencies and twenty-three brands · national campaigns · bank and broadcaster platforms · betting front-ends · and a habit of being called in to rescue work someone else could not finish."
|
||||
confidence: historic
|
||||
period: "1999–2014"
|
||||
tech: [ActionScript, PHP, JavaScript, MySQL, XML, SOAP, React, Python]
|
||||
metrics: [{label: "agencies on the client wall", value: 22}, {label: "brands delivered for", value: 23}, {label: "code exhibits kept", value: 6}]
|
||||
artefacts: [{type: doc, label: "The client wall", url: "content/history/l3/history-client-wall.md"}, {type: doc, label: "Six code exhibits across five eras", url: "content/history/l3/history-code-exhibits.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [history, agencies, brands, exhibits]
|
||||
---
|
||||
|
||||
# Fifteen years of delivery for agencies and their clients
|
||||
|
||||
**Capability statement.** Range under deadline. The work in this period ran from car classifieds and online betting to a bank's pitch piece, a broadcaster's on-demand banners and a publisher's education platform — usually with a date attached that could not move.
|
||||
|
||||
## The eras, briefly
|
||||
|
||||
**1999–2002 — the start.** Web design and development for a high-volume car marketplace, then freelance work building sites, applications, interfaces and database back ends for small agencies.
|
||||
|
||||
**2002–2005 — London, full time.** Online gaming: lead front-end developer on a synchronous multi-game platform handling a thousand simultaneous clients, integrating against Java back ends and XML sockets. Then the emerging interactive advertising industry, where a creative front end with a technical spine was scarce.
|
||||
|
||||
**2006–2009 — the agency run.** The bulk of the client wall: bank pitch work delivered in weeks, broadcaster promotions, a global oil company's re-brand site, premium drinks campaigns, a news organisation's media presentation layer, a publisher's education platform, and a global computer-aided design vendor's localised site. Several of these were rescues — brought in on a short deadline to rewrite work another team could not land.
|
||||
|
||||
**2009–2012 — product and campaign.** A standalone encrypted presentation builder with its own media library and remote update path. A national beer campaign with video submissions, cross-brand promotion, in-store mechanics and authorisation over SOAP. Interactive launches with 3D content in the browser.
|
||||
|
||||
**2012–2014 — small products for small business.** Online book building, a reactive design system, and art applications for a motion-sensing controller, transitioned toward mobile.
|
||||
|
||||
**2014–2020 — the workshop years.** The site builder and the signage product (see [Products](../products/products-business.md)), which is where the work moved from delivering campaigns for other people's brands to owning software and supporting customers.
|
||||
|
||||
## Languages across the eras
|
||||
|
||||
The point of the exhibit set is that the tooling changed repeatedly and the delivery discipline did not: ActionScript 3 with class-based architecture, hand-written JavaScript engines, PHP media pipelines, TypeScript with typed service layers and a relational schema, embedded C++ for firmware, and now declarative infrastructure as its own kind of code.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|---|---|---|
|
||||
| Twenty-two agencies and twenty-three brands | The client wall, carried from the résumé and the recovered site content | [Client wall](l3/history-client-wall.md) |
|
||||
| Work across six technology eras | Six exhibits from OO ActionScript to a hand-written Nix package | [Code exhibits](l3/history-code-exhibits.md) |
|
||||
| Rescue work under immovable deadlines | Multiple engagements recorded as rewrites of stalled projects | [Client wall](l3/history-client-wall.md) |
|
||||
| Sponsorship of the later product era | 2014–2020 product work described in the résumé | [Products](../products/products-business.md) |
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **Historic work is labelled historic.** Nothing in this section is presented as current capability; where a technique is still used today, the page links to where it is used.
|
||||
- **One engagement has no screenshot.** The national archive work was an internal tool. It is described and not illustrated, because there is nothing legitimately publishable to show.
|
||||
- **No client has been named beyond a brand.** Brands are named because they were public campaigns. Individuals, internal contacts and unpublished commercial detail are excluded.
|
||||
- **The exhibits are excerpts.** Around forty lines each, chosen to show judgement — structure, error handling, an exit plan — not to demonstrate volume.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [The client wall](l3/history-client-wall.md) — level 3
|
||||
- [Six code exhibits across five eras](l3/history-code-exhibits.md) — level 3
|
||||
- [Products — the commercial era that followed](../products/products-business.md) — level 2
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 1999–2014`. Confidence is `historic`: this is work that is finished, and it is presented in the past tense throughout.
|
||||
25
content/history/history-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: history-overview
|
||||
area: history
|
||||
level: 1
|
||||
title: "History"
|
||||
claim: "Delivered interactive work for twenty-two agencies and twenty-three brands between 1999 and 2014 — the commercial apprenticeship that produced the range."
|
||||
confidence: historic
|
||||
period: "1999–2014"
|
||||
tech: [ActionScript, PHP, JavaScript, MySQL, XML, React, Python, Go, HTMX]
|
||||
metrics: [{label: "agencies on the client wall", value: 22}, {label: "brands delivered for", value: 23}, {label: "code exhibits kept", value: 6}]
|
||||
artefacts: [{type: doc, label: "The client wall", url: "content/history/l3/history-client-wall.md"}, {type: doc, label: "Six code exhibits across five eras", url: "content/history/l3/history-code-exhibits.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [history, agencies, brands, career]
|
||||
---
|
||||
|
||||
# History
|
||||
|
||||
**Claim.** Fifteen years of agency and product work — national campaigns, bank and broadcaster platforms, betting front-ends, and a lot of rescue missions — for twenty-two agencies and twenty-three brands.
|
||||
|
||||
**Status.** Historic. This is the 1999–2014 era, presented as what it was: the commercial apprenticeship that produced the range.
|
||||
|
||||
**What it is not.** It is not a Flash page. The languages changed six times across this period — ActionScript, PHP, JavaScript, React, Python, and now Go with HTMX — and the exhibits are chosen to show that rather than to show a decade.
|
||||
|
||||
**Start here.** [The engagement record](history-engagements.md) explains the eras, the work and what each exhibit demonstrates.
|
||||
41
content/history/l3/history-client-wall.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
id: history-client-wall
|
||||
area: history
|
||||
level: 3
|
||||
title: "Artefact — The client wall"
|
||||
claim: "Twenty-two agencies and twenty-three brands — the delivery record carried from the résumé rather than reconstructed from memory."
|
||||
confidence: historic
|
||||
period: "1999–2014"
|
||||
tech: [ActionScript, PHP, JavaScript, MySQL, XML]
|
||||
metrics: [{label: "agencies on the client wall", value: 22}, {label: "brands on the client wall", value: 23}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [history, clients, artefact]
|
||||
---
|
||||
|
||||
# Artefact — The client wall
|
||||
|
||||
**Status: stub for the visual treatment.** The names are final; the layout, logo set and typography land in Phase 7 (the logo set is explicitly a Phase 7 decision).
|
||||
|
||||
## The agencies
|
||||
|
||||
Clemenger · Agency Republic · Brand Union · Jackpot Joy · Bryce Ford · RMG Connect · Sporting Index · Adventis Digital · Trinity Street · Inferno · SAS Design · Ogilvy · Wunderman · Illumina · Barkers · Mook · Pearsons · Penguin · Draft London · Behan Consulting · MCM Entertainment · Carsales
|
||||
|
||||
## The brands
|
||||
|
||||
Carlton Draught · Diageo · KPMG · McDonald's · Accenture · BBC National Archive · Bank of America · War of the Worlds · Madonna (Hard Candy) · PlayStation · HSBC · DHL · Reuters · Volvic · AutoCAD · Channel 4 · Pearsons · Shell · Stella Artois · Baileys Irish Cream · Parkgate Homes · Carlton Dry · Cottees Cordial
|
||||
|
||||
## Corrections carried into this list
|
||||
|
||||
- **Diageo**, not the "Diajio" spelling that appeared in the recovered site content.
|
||||
- **Baileys Irish Cream**, stated in full and spelled correctly.
|
||||
- The **BBC National Archive** engagement was an internal tool. It is described, and it is not illustrated with a screenshot, because no legitimately publishable image exists.
|
||||
|
||||
## Count discrepancy — recorded, not smoothed over
|
||||
|
||||
The summary material said twenty-three agencies. The recovered, verified list holds **twenty-two** names, and the count published above is the count of the list. If a name is missing, the number moves to twenty-three and this note is deleted; until then the smaller, checkable number is the one on the page.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7 for the visual treatment. Names and one-line descriptions are approved as recovered and corrected.
|
||||
40
content/history/l3/history-code-exhibits.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: history-code-exhibits
|
||||
area: history
|
||||
level: 3
|
||||
title: "Artefact — Six code exhibits across five eras"
|
||||
claim: "Six short excerpts spanning object-oriented ActionScript · a hand-written JavaScript animation engine · a PHP media pipeline · typed TypeScript · embedded C++ · and declarative Nix."
|
||||
confidence: historic
|
||||
period: "2006–2026"
|
||||
tech: [ActionScript, JavaScript, PHP, TypeScript, C++, Nix]
|
||||
metrics: [{label: "code exhibits", value: 6}, {label: "technology eras spanned", value: 5}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [history, code, exhibits, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Six code exhibits across five eras
|
||||
|
||||
**Status: stub.** The excerpts are selected from source that exists on disk; each one lands in Phase 7 with two sentences on why it is good code.
|
||||
|
||||
## The six
|
||||
|
||||
| # | Era | Source | What the excerpt shows |
|
||||
|---|---|---|---|
|
||||
| 1 | Object-oriented ActionScript | the brief-case builder and the national beer campaign | class design, imports, encapsulation |
|
||||
| 2 | Hand-written JavaScript engine | the text-effects engine from the site builder (about 2 200 lines) | easing and a timeline core |
|
||||
| 3 | PHP media pipeline | the media encoder from the site builder (about 3 400 lines) | one encode operation and the FFmpeg piping around it |
|
||||
| 4 | TypeScript | the vehicle-tracking application's schema and typed service layer | types, interfaces, a router |
|
||||
| 5 | Embedded C++ | the Wi-Fi manager interface and implementation | interface versus implementation in firmware |
|
||||
| 6 | Declarative infrastructure | the 25-line Nix package definition | pinned version, verified hash, written exit condition |
|
||||
|
||||
Total is roughly 225 lines across twenty years, which is the point: each excerpt is chosen to show judgement rather than volume.
|
||||
|
||||
## What it proves
|
||||
|
||||
That the stack changed six times and the discipline did not. Exhibit 6 is the least common of the six and the most current — a short, correct, self-documenting derivation with an exit plan is a stronger infrastructure signal than a long configuration file.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source paths are recorded in the planning notes; nothing is published from a path that has not been read at capture time.
|
||||
35
content/platform/l3/platform-backups.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: platform-backups
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — Backups and restore runbook"
|
||||
claim: "Three tiers — local snapshots · a copy on another machine · an offsite copy — with retention stated in the job and a restore runbook kept beside them."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Borg, Kopia, Backrest, AWS S3, systemd, NFS]
|
||||
metrics: [{label: "backup tiers", value: 3}, {label: "retention windows in the primary job", value: 3}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, backups, restore, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Backups and restore runbook
|
||||
|
||||
**Status: stub.** Redacted job definitions and the restore runbook land in Phase 7. Passphrase locations and remote paths are removed before publication.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The backup design: Borg jobs on the two desktop hosts to local storage with a network copy, Kopia and Backrest on the edge host to network storage, an offsite copy in object storage, and retention expressed in the job (seven daily, four weekly, three monthly, plus annual on the edge). Beside it, the restore runbook and the list of what is deliberately not covered.
|
||||
|
||||
## What it proves
|
||||
|
||||
That failure was designed for: three tiers cover disk loss, machine loss and site loss, and the restore path is written down rather than recovered from memory at the worst possible moment.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
Not everything is covered, and the page says so — one storage host is itself a single point of failure for some repositories, and the file server has no backup of its own. Those are known gaps with owners, not oversights to be hidden.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source: the infrastructure reference and the backup system notes, read 2026-10-26.
|
||||
31
content/platform/l3/platform-containers.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: platform-containers
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — Container inventory"
|
||||
claim: "Fifty or more containers across the estate — each with its own port · its own folder · and a memory cap equal to its swap cap."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Docker, Compose, Caddy, Proxmox]
|
||||
metrics: [{label: "containers in the estate", value: 50}, {label: "memory cap rule", value: "mem_limit equals memswap_limit"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, docker, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Container inventory
|
||||
|
||||
**Status: stub.** A digest of the inventory — grouped by purpose, with addresses removed — lands in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The inventory generated from the hosts, grouped by purpose: media and file services, home automation, the AI services, the public edge, and the build tooling. For each service the same three facts are recorded — port, configuration folder, memory cap.
|
||||
|
||||
## What it proves
|
||||
|
||||
That the estate is inventoried rather than accumulated, and that the resource rules are applied per service instead of being a policy on a wiki page.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7, generated from the live hosts. Counts follow the approved metric set; the exact number is regenerated at capture time.
|
||||
31
content/platform/l3/platform-network.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: platform-network
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — Network layout and remote access"
|
||||
claim: "A private mesh and SSH everywhere · services bound to loopback · and one public listener at the edge terminating TLS for the sites that are allowed to be seen."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [Tailscale, SSH, Caddy, DNS, Termux]
|
||||
metrics: [{label: "public listeners per service", value: 1}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, networking, security, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Network layout and remote access
|
||||
|
||||
**Status: stub.** The topology diagram lands in Phase 7 with addresses and hostnames redacted.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The layout: hosts on a private mesh for remote access, SSH on every machine, a phone used as a terminal, and an edge host that terminates TLS and proxies to loopback-bound services. New services bind to loopback by default; making something public is an explicit edge change, not a side effect of starting a container.
|
||||
|
||||
## What it proves
|
||||
|
||||
Security posture chosen rather than inherited: no service is reachable because it happened to bind to all interfaces, and there is exactly one place where the outside world meets the estate.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Internal addressing, hostnames and public DNS names are excluded from publication by the redaction pass.
|
||||
35
content/platform/l3/platform-nixos.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: platform-nixos
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — Declarative multi-host configuration"
|
||||
claim: "Machines are described rather than assembled — a shared NixOS base · a replicated desktop and terminal · and Proxmox underneath the virtualised side."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [NixOS, Niri, Proxmox, Neovim, Zsh, Ghostty]
|
||||
metrics: [{label: "hosts on the declarative base", value: 4}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, nixos, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Declarative multi-host configuration
|
||||
|
||||
**Status: stub.** A redacted excerpt of the configuration tree lands in Phase 7. No hostnames, addresses or keys are published.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The shape of the configuration: one shared base, per-host modules, and the parts that make the desktop and the terminal identical everywhere — window manager, editor, shell and the plugins that carry the work. Proxmox hosts the virtualised side, including the file server and the home automation appliance.
|
||||
|
||||
## What it proves
|
||||
|
||||
That a machine can be rebuilt from a description, and that the same environment follows the person between machines instead of being re-created by memory.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
The terminal-first setup is deliberate: a heavier desktop was downgraded to the terminal on one machine for memory headroom. A phone-as-server experiment is on hold, not shipped, and is described as on hold.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source facts: evidence notes section 3.
|
||||
31
content/platform/l3/platform-signage.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: platform-signage
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — Signage infrastructure · screens as a managed fleet"
|
||||
claim: "HDMI-CEC control of power · rotation · mirroring and multi-screen layout — so a display fleet is driven by the platform rather than by a remote control."
|
||||
confidence: delivered
|
||||
period: "2014–"
|
||||
tech: [HDMI-CEC, Raspberry Pi, Python, JavaScript, FFmpeg]
|
||||
metrics: [{label: "commercial deployments evidenced", value: "salon · financial services business"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, signage, hdmi-cec, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Signage infrastructure · screens as a managed fleet
|
||||
|
||||
**Status: stub.** The CEC command set and a layout diagram land in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The platform side of the signage product: the codes and control path that switch screens on and off, rotate and mirror output, and lay out multi-screen displays, including synchronised playback across screens in one site.
|
||||
|
||||
## What it proves
|
||||
|
||||
Device-level control combined with fleet management. This is the same skill the edge pages show on small devices, applied to physical displays that other people depend on.
|
||||
|
||||
## Confidence
|
||||
|
||||
`delivered` — this ran in commercial deployments. The product's business status is stated separately on the Products pages, where the honest position is that the software is being rebuilt and three businesses still run it.
|
||||
31
content/platform/l3/platform-tuios-package.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
id: platform-tuios-package
|
||||
area: platform
|
||||
level: 3
|
||||
title: "Artefact — A hand-written Nix package with an exit plan"
|
||||
claim: "Twenty-five lines of Nix that pin a tool at 0.10.1 over nixpkgs' 0.7.0 — with a verified hash · a written reason and a written condition for deleting the file."
|
||||
confidence: running
|
||||
period: "2026–"
|
||||
tech: [Nix, NixOS]
|
||||
metrics: [{label: "pinned version", value: "0.10.1"}, {label: "nixpkgs version it overrides", value: "0.7.0"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, nix, packaging, artefact]
|
||||
---
|
||||
|
||||
# Artefact — A hand-written Nix package with an exit plan
|
||||
|
||||
**Status: stub.** The whole file is short enough to publish verbatim; it lands in Phase 7.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A package definition for the agent operations console: `fetchurl` against a released artifact with a verified hash, a documented reason for overriding nixpkgs, an `installPhase` that stages the binary, and a comment stating the condition under which the file should be deleted.
|
||||
|
||||
## What it proves
|
||||
|
||||
More than knowing Nix exists. The signals are that someone noticed a version gap, fixed it locally instead of waiting, pinned it so the fleet is reproducible, and wrote down when to remove their own patch. Knowing when to delete your own override is the senior part.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. The file is in the infrastructure repository; source fact: content spine section 4.2.
|
||||
66
content/platform/platform-estate.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: platform-estate
|
||||
area: platform
|
||||
level: 2
|
||||
title: "A small estate run to a documented standard"
|
||||
claim: "Fifty or more containers on a four-host estate, all on declarative configuration — with packaging discipline · encrypted backups and a restore runbook · loopback-bound services · and one public listener."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [NixOS, Proxmox, Docker, Caddy, Tailscale, Borg, Kopia, AWS S3, HDMI-CEC]
|
||||
metrics: [{label: "containers in the estate", value: 50}, {label: "hosts", value: 4}, {label: "backup tiers", value: "Borg · Kopia · AWS"}, {label: "public listeners", value: 1}]
|
||||
artefacts: [{type: doc, label: "Declarative multi-host configuration", url: "content/platform/l3/platform-nixos.md"}, {type: doc, label: "A hand-written Nix package with an exit plan", url: "content/platform/l3/platform-tuios-package.md"}, {type: doc, label: "Container inventory", url: "content/platform/l3/platform-containers.md"}, {type: doc, label: "Backups and restore runbook", url: "content/platform/l3/platform-backups.md"}, {type: doc, label: "Network layout and remote access", url: "content/platform/l3/platform-network.md"}, {type: doc, label: "Signage infrastructure — screens as a managed fleet", url: "content/platform/l3/platform-signage.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, devops, nixos, docker, backups, networking]
|
||||
---
|
||||
|
||||
# A small estate run to a documented standard
|
||||
|
||||
**Capability statement.** Four hosts, fifty or more containers, configuration in version control instead of in a shell history, and one place where traffic enters. The estate is deliberately small because it is run rather than demonstrated.
|
||||
|
||||
## What is actually run
|
||||
|
||||
**Declarative configuration.** NixOS is the base on the machines that matter, with the desktop and the terminal replicated across them so an environment can be rebuilt from a description. Proxmox runs the virtualised side — Ubuntu file server and a Home Assistant appliance alongside the desktop hosts. The point of the arrangement is repeatability: a machine is a configuration, not a pet.
|
||||
|
||||
**Packaging.** When a tool is missing or stale in nixpkgs, it gets a derivation rather than a manual install. The TUIOS package pins 0.10.1 over nixpkgs' 0.7.0 with `fetchurl` and a verified hash, documents why the override exists, and states the condition for deleting it. A patch with an exit plan is maintenance; a patch without one is debt.
|
||||
|
||||
**Container estate.** Fifty or more containers run across the hosts — the file server and media services, the automation layer, the AI services, traffic for public ingress, and the tools used to build all of it. Each new service is given its own port, its own folder and a memory cap equal to its swap cap, so it cannot take the host's swap.
|
||||
|
||||
**Networking.** Remote access is a private mesh rather than an exposed SSH port: Tailscale across the machines, SSH on every host, and a phone used as a terminal. Services bind to loopback; Caddy is the only public listener, terminating TLS at the edge host and proxying the sites that are allowed to be seen.
|
||||
|
||||
**Storage and backups.** Three tiers, each covering a different failure: local snapshots on the machine, a copy on another machine over the network, and an offsite copy in object storage. Retention is stated in the job (daily, weekly, monthly, annual) and a restore runbook sits next to the jobs, because a backup nobody has restored from is an assumption.
|
||||
|
||||
**Observability and operations.** Resource use is watched at the host level, because the runtime host is memory-bound and a new service can destabilise the ones people rely on. The agent fleet is observed as a fleet through TUIOS — sessions, state and approvals in one console — rather than by tailing logs on four machines.
|
||||
|
||||
**Signage infrastructure.** The display work is treated as a fleet to be managed: HDMI-CEC control for power, rotation, mirroring and multi-screen layout, so screens are driven by the platform rather than by a person with a remote control.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|---|---|---|
|
||||
| Configuration is declarative and replicated | NixOS hosts with shared configuration; Proxmox for the virtualised side | [Declarative configuration](l3/platform-nixos.md) |
|
||||
| Tooling is packaged rather than hand-installed | `pkgs/tuios.nix` pinning 0.10.1 with a documented removal condition | [Nix package](l3/platform-tuios-package.md) |
|
||||
| Fifty or more containers are operated | Inventory by host and by purpose | [Container inventory](l3/platform-containers.md) |
|
||||
| Backups are three-tier with a restore runbook | Borg on two hosts, Kopia and Backrest on the edge host, offsite object storage | [Backups](l3/platform-backups.md) |
|
||||
| One public listener | Loopback-bound services behind Caddy at the edge | [Network](l3/platform-network.md) |
|
||||
| Screens are managed as a fleet | HDMI-CEC control of power, rotation and layout | [Signage infrastructure](l3/platform-signage.md) |
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **Memory over hardware.** The runtime host runs 15 GiB with little free and swap in use. The response was caps, fewer and smaller services, and moving heavy work to the gateway rather than buying another machine. Every new service is sized before it is deployed, and the ceiling for this site is one gigabyte and four containers.
|
||||
- **Self-hosting is a choice with a cost.** Monitoring, backups, ingress and the AI gateway are all operated here, which means the failure modes are also operated here. The mitigation is documentation and measurement, not optimism.
|
||||
- **Rejected on purpose.** A long list of tools was evaluated and refused — Airflow for RAM, self-hosted Langfuse for six containers it could not afford, LiteLLM because it would duplicate the existing gateway, and a pile of documentation platforms. "Alternatives considered" is kept because the reasoning is the senior artifact.
|
||||
- **Not everything is automated.** Some operations are still a documented command run by a person. The runbook exists precisely because the automations do not cover everything.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [Declarative multi-host configuration](l3/platform-nixos.md) — level 3
|
||||
- [A hand-written Nix package with an exit plan](l3/platform-tuios-package.md) — level 3
|
||||
- [Container inventory](l3/platform-containers.md) — level 3
|
||||
- [Backups and restore runbook](l3/platform-backups.md) — level 3
|
||||
- [Network layout and remote access](l3/platform-network.md) — level 3
|
||||
- [Signage infrastructure — screens as a managed fleet](l3/platform-signage.md) — level 3
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 2020–`, anchored on the homelab year in the evidence notes. Confidence is `running`: this is the current estate, verified 2026-10-26.
|
||||
25
content/platform/platform-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: platform-overview
|
||||
area: platform
|
||||
level: 1
|
||||
title: "Platform & Infrastructure"
|
||||
claim: "Runs a multi-machine NixOS and Proxmox estate — fifty-plus containers · declarative configuration · encrypted backups with a written restore runbook · and public ingress — sized to the hardware rather than the budget."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [NixOS, Proxmox, Docker, Caddy, Tailscale, Borg, Kopia, AWS S3]
|
||||
metrics: [{label: "containers in the estate", value: 50}, {label: "hosts", value: 4}, {label: "backup tiers", value: "Borg · Kopia · AWS"}]
|
||||
artefacts: [{type: doc, label: "Declarative multi-host configuration", url: "content/platform/l3/platform-nixos.md"}, {type: doc, label: "Backups and restore runbook", url: "content/platform/l3/platform-backups.md"}, {type: doc, label: "A hand-written Nix package with an exit plan", url: "content/platform/l3/platform-tuios-package.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [platform, devops, nixos, docker, backups]
|
||||
---
|
||||
|
||||
# Platform & Infrastructure
|
||||
|
||||
**Claim.** Fifty or more containers on a four-host estate, configuration declared rather than hand-applied, encrypted backups on three machines with a restore runbook beside them, and one public listener at the edge.
|
||||
|
||||
**Status.** Running. Figures trace to the approved metric set and the infrastructure reference; verified 2026-10-26.
|
||||
|
||||
**The constraint that shaped it.** The runtime host is memory-bound rather than CPU-bound. Every service in this estate carries a memory cap and is bound to loopback, which is why the platform reads as engineering under constraint instead of hardware shopping.
|
||||
|
||||
**Start here.** [The capability page](platform-estate.md) covers what runs, where, and what was rejected.
|
||||
35
content/products/l3/products-signage.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: products-signage
|
||||
area: products
|
||||
level: 3
|
||||
title: "Artefact — Commercial signage on commodity hardware"
|
||||
claim: "A digital signage platform built as market disruption — any HDMI screen · a small player · fleet control of power · rotation · layout and playback · sold to twelve businesses over time."
|
||||
confidence: delivered
|
||||
period: "2014–"
|
||||
tech: [Raspberry Pi, ESP32, HDMI-CEC, JavaScript, three.js, FFmpeg, Python]
|
||||
metrics: [{label: "businesses currently running the product", value: 3}, {label: "adoptions over time", value: 12}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [products, signage, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Commercial signage on commodity hardware
|
||||
|
||||
**Status: delivered, with a rebuild in progress.** The product shipped and customers still run it. The rebuild on the current stack is not finished and is labelled as unfinished everywhere it is mentioned.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The product in use: a player on commodity hardware — a small Raspberry Pi or a microcontroller class device — driving any HDMI screen, with fleet control from the platform: switch screens on and off, rotate, mirror, lay out multiple screens, coordinate boards, and synchronise playback across a site. Content is built by the customer from complex animation down to a simple image rotation, and the system adapts to the board it finds rather than demanding a specification.
|
||||
|
||||
## What it proves
|
||||
|
||||
The commercial read: a market was overpriced, the substitute was built on commodity hardware, and it was sold and operated for years. Twelve adoptions over time, three businesses still running. That is a product, not a project.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
Twelve is cumulative adoption and three is the current count — the distinction is kept because inflating it would be the easiest lie on this site. The rebuild is in progress. No revenue figures or customer names beyond type of business are published.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7 for screenshots and a demonstration recording, captured from the running product. The one-liners for reference customers are approved for the salon and the financial services business only.
|
||||
35
content/products/l3/products-websitebuilder.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: products-websitebuilder
|
||||
area: products
|
||||
level: 3
|
||||
title: "Artefact — The site builder behind the signage"
|
||||
claim: "A templated site builder and CMS with media editors — drawing · image · video · text animation · 3D import — that also produced the marketing sites and the social output."
|
||||
confidence: delivered
|
||||
period: "2014–"
|
||||
tech: [PHP, JavaScript, three.js, FFmpeg, ImageMagick, MySQL]
|
||||
metrics: [{label: "media editors in the product", value: "drawing · image · video · text animation · transitions · 3D import"}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [products, cms, media, artefact]
|
||||
---
|
||||
|
||||
# Artefact — The site builder behind the signage
|
||||
|
||||
**Status: delivered, retained.** Retired as a general-purpose product; kept as the content engine for the signage.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
The templated builder: pick a template, build the site, publish it — with editors for drawing, images, video and text animation, video effects and transitions, 3D object import and text extrusion, plus document and office-format handling. Image animation is composed in JavaScript and HTML and rendered on Raspberry Pi hardware through Python. Around the site itself sat the commercial scaffolding a small business actually needs: shop, invoicing, room and event management, presentations, document management, client records and bulk email and SMS.
|
||||
|
||||
## What it proves
|
||||
|
||||
Two things at once — depth in media pipelines (FFmpeg, ImageMagick, PDF and office formats, three.js) and the discipline of shipping a general product that strangers could operate without help.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
The surface was too large for one person to support indefinitely. The plan recorded here is to strip it back to signage plus the content engine and stop selling the rest, which is a decision about focus rather than a claim of failure.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7 for a screen recording of the editors. Source: résumé (2014–2020 freelance) and evidence notes section 3.
|
||||
35
content/products/l3/products-where-woof.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: products-where-woof
|
||||
area: products
|
||||
level: 3
|
||||
title: "Artefact — Where-Woof · deployed and pre-market"
|
||||
claim: "A QR and RFID tag system for lost property that is deployed and in use — and has not gone to market."
|
||||
confidence: running
|
||||
period: "2020–"
|
||||
tech: [QR, RFID, PHP, JavaScript]
|
||||
metrics: [{label: "market launch", value: 0}]
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [products, where-woof, artefact]
|
||||
---
|
||||
|
||||
# Artefact — Where-Woof · deployed and pre-market
|
||||
|
||||
**Status: running, pre-market.** This is the exact wording the site uses, deliberately: deployed is true, commercial is not.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
A tag system for lost property. A tag carries a QR code and an RFID identity; whoever finds the item resolves the tag and the owner is contacted. The system is running and being deployed now.
|
||||
|
||||
## What it proves
|
||||
|
||||
That a product can be taken into the field before it is monetised, and that the honest label for that state exists. The distinction matters on a CV because the alternative — calling a pre-launch product commercial — is the kind of claim a technical interviewer unpicks in one question.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
No customers, no revenue and no launch date are claimed. The metric recorded here is a zero on purpose.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
The tag and resolve-flow photographs land in Phase 7 if Sam chooses to publish them. Product name and description are approved; commercial framing is not.
|
||||
67
content/products/products-business.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: products-business
|
||||
area: products
|
||||
level: 2
|
||||
title: "Software sold and operated — with the status stated"
|
||||
claim: "Three product lines from one workshop — signage on commodity hardware · the site builder that produced the marketing · and a lost-property tag system — with three businesses still running the signage today."
|
||||
confidence: running
|
||||
period: "2014–"
|
||||
tech: [PHP, JavaScript, three.js, FFmpeg, ImageMagick, HDMI-CEC, Raspberry Pi, ESP32, QR, RFID]
|
||||
metrics: [{label: "businesses currently running the product", value: 3}, {label: "adoptions over time", value: 12}, {label: "product lines", value: 3}]
|
||||
artefacts: [{type: doc, label: "Commercial signage on commodity hardware", url: "content/products/l3/products-signage.md"}, {type: doc, label: "The site builder behind it", url: "content/products/l3/products-websitebuilder.md"}, {type: doc, label: "Where-Woof — deployed and pre-market", url: "content/products/l3/products-where-woof.md"}, {type: doc, label: "Signage infrastructure — screens as a managed fleet", url: "content/platform/l3/platform-signage.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [products, business, signage, where-woof, positioning]
|
||||
---
|
||||
|
||||
# Software sold and operated — with the status stated
|
||||
|
||||
**Capability statement.** Building software for a client and building software as a product are different jobs. This page is the second one: a market that was overpriced, a substitute built on hardware that costs a fraction of the incumbent systems, customers who adopted it, and the operational cost of keeping it running.
|
||||
|
||||
## The commercial story
|
||||
|
||||
The digital signage market sells walls: thousands of dollars of hardware with fans, cooling and glass, locked to monopoly software. The product was built as a deliberate inversion of that — a system that runs on a small Raspberry Pi or a microcontroller, drives any HDMI screen including an ordinary monitor, and adapts to the board rather than requiring the board to adapt to it.
|
||||
|
||||
It manages screens as a fleet: power on and off, rotation, mirroring, multi-screen layout, coordinated boards, and synchronised playback across screens in one site or across sites. Users build complex animations or simple image rotations, and the system presents whatever suits the display it finds.
|
||||
|
||||
Demonstrations were rolled out in a hair salon and a financial services business. Around twelve businesses adopted it over time and three still run it today. That number is deliberately specific: twelve is cumulative adoption, three is current, and the difference is the honest measure of a product that was sold but not scaled.
|
||||
|
||||
The same workshop produced the CMS behind the marketing — a templated site builder with editors for drawing, image, video and text animation, video effects and transitions, 3D object import and text extrusion — built on JavaScript and three.js with FFmpeg, ImageMagick and PHP tools for documents, and rendering image animation on Raspberry Pi hardware.
|
||||
|
||||
The third product is different in kind: Where-Woof is a QR and RFID tag system for lost property. It is deployed and being deployed now. It has **not** gone to market, and this page will not call it commercial until it has.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|---|---|---|
|
||||
| Signage replaced thousand-dollar wall systems with commodity hardware | Any HDMI screen · Raspberry Pi or ESP32 class player · fleet control | [Signage product](l3/products-signage.md) |
|
||||
| Twelve adoptions over time, three businesses running now | Adoption history and current customers | [Signage product](l3/products-signage.md) |
|
||||
| A templated builder produced the marketing sites | Editors for drawing · video · image and animation; FFmpeg and ImageMagick pipeline | [WebsiteBuilder](l3/products-websitebuilder.md) |
|
||||
| Where-Woof is deployed and pre-market | Device and tag system in use; no market launch | [Where-Woof](l3/products-where-woof.md) |
|
||||
| Screens are managed as a fleet | HDMI-CEC control of power · rotation · layout | [Signage infrastructure](../platform/l3/platform-signage.md) |
|
||||
|
||||
## Product status — stated plainly
|
||||
|
||||
| Product | What it is | Status | Next |
|
||||
|---|---|---|---|
|
||||
| Display screen media (Audas Media) | Digital signage on commodity hardware with multi-screen fleet control | Delivered · three businesses running · being rebuilt with AI | Strip back to signage only and rebuild on the current stack |
|
||||
| WebsiteBuilder | Templated site builder and CMS with media editors and social output | Delivered · retained | Retired as a general product; kept as the content engine |
|
||||
| Where-Woof | QR and RFID tags for lost property | Deployed · pre-market | Take to market — not done yet |
|
||||
|
||||
## Trade-offs and limits
|
||||
|
||||
- **Scope discipline came late.** The builder carried a shop, invoicing, room management, calendars, presentations, documents, bulk messaging and client management. Product surface grew faster than a one-person support model could carry, which is why the plan now is to keep the signage and the content engine and retire the rest.
|
||||
- **The rebuild is unfinished.** "Rebuilding with AI" is a statement of work in progress, not a launch. It is labelled as such on every page that mentions it.
|
||||
- **One product is pre-revenue by design.** Where-Woof is deployed before it is sold. Describing it as commercial would be a lie that a careful reader would find in a minute.
|
||||
- **Support is the hidden cost.** Customers running the product for years is the strongest evidence of value and the strongest argument for keeping the surface small.
|
||||
|
||||
## Drill-downs
|
||||
|
||||
- [Commercial signage on commodity hardware](l3/products-signage.md) — level 3
|
||||
- [The site builder behind it](l3/products-websitebuilder.md) — level 3
|
||||
- [Where-Woof — deployed and pre-market](l3/products-where-woof.md) — level 3
|
||||
- [Signage infrastructure — screens as a managed fleet](../platform/l3/platform-signage.md) — level 3
|
||||
|
||||
## Period and confidence
|
||||
|
||||
`period: 2014–`, anchored on the first freelance product work in the résumé. Confidence is `running`: the products exist and customers still use one of them. Individual products carry their own status, and the two caveats — a rebuild in progress and a launch not yet made — are in the table above rather than in a footnote.
|
||||
25
content/products/products-overview.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: products-overview
|
||||
area: products
|
||||
level: 1
|
||||
title: "Products"
|
||||
claim: "Identified an overpriced market and shipped a cheaper substitute on commodity hardware — twelve adoptions over time and three businesses still running it."
|
||||
confidence: running
|
||||
period: "2014–"
|
||||
tech: [PHP, JavaScript, three.js, FFmpeg, ImageMagick, HDMI-CEC, Raspberry Pi, ESP32]
|
||||
metrics: [{label: "businesses currently running the product", value: 3}, {label: "adoptions over time", value: 12}, {label: "product lines", value: 3}]
|
||||
artefacts: [{type: doc, label: "Commercial signage on commodity hardware", url: "content/products/l3/products-signage.md"}, {type: doc, label: "The site builder behind it", url: "content/products/l3/products-websitebuilder.md"}, {type: doc, label: "Where-Woof — deployed and pre-market", url: "content/products/l3/products-where-woof.md"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
tags: [products, signage, business, where-woof]
|
||||
---
|
||||
|
||||
# Products
|
||||
|
||||
**Claim.** A digital signage product built as deliberate disruption to thousand-dollar wall systems — three businesses still run it — plus the site builder that produced the marketing sites and a lost-property tag system that is deployed but not yet sold.
|
||||
|
||||
**Status.** Running. The counts are the corrected ones: three businesses active now, twelve adoptions over time, and Where-Woof deployed without a market launch.
|
||||
|
||||
**Why it is on an engineering CV.** Selling, deploying and still supporting software for other businesses is a different discipline from writing it. Two of the three products carry honest caveats that are stated rather than hidden: the signage platform is being rebuilt, and Where-Woof has not gone to market.
|
||||
|
||||
**Start here.** [The commercial story](products-business.md) covers what each product is, what state it is in, and what it cost to run.
|
||||
64
docs/content-redaction.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Content redaction pass — what was excluded and why
|
||||
|
||||
**Scope:** every document under `content/`, authored in Phase 1 (issue AUD-131).
|
||||
**Date of pass:** 2026-10-26.
|
||||
**Sources read for this pass:** `../resume_ai_system/plan/EVIDENCE-NOTES.md`, `../resume_ai_system/plan/draft-content.md`, `../resume_ai_system/plan/20-content-spine.md`, `../resume_ai_system/old_projects.md`, `resume_2025.docx`, `reference/content-map.md`, `reference/decisions.md`, `reference/stack.md`, and the Obsidian backup notes.
|
||||
|
||||
Acceptance test C6 covers this: *no family, address, credential or third-party personal data in pages or corpus.* The list below is what was removed to satisfy it, and the reason for each removal.
|
||||
|
||||
## Excluded — personal identifiers
|
||||
|
||||
| Item | Where it appeared | Why excluded |
|
||||
|---|---|---|
|
||||
| Date of birth | `resume_2025.docx`, Personal Details | Not needed to assess capability. Age is a discriminator and an identity-theft input. |
|
||||
| Phone number | `resume_2025.docx`, Personal Details | Publishing a mobile exposes it to scrapers. Sam has not confirmed a phone number belongs on the site (`reference/stack.md` open items). |
|
||||
| Street address / suburb | `resume_2025.docx` ("live in Ivanhoe"), `draft-content.md` | Address-level detail is a safety issue and is irrelevant to the work. "Melbourne based" is the published granularity. |
|
||||
| Email address | `resume_2025.docx` | Kept off the pages in Phase 1. Contact details are an open decision for Sam; the narrative states the policy rather than the address. |
|
||||
| Passport and visa status | `resume_2025.docx` | Immigration status is not published. Working rights are a conversation, not a web page. |
|
||||
| Family names and details | `EVIDENCE-NOTES.md` (school portals, children, household) | Never published. The 2020–2026 period is described as "full-time parent to two children" with no names, ages, schools or locations. |
|
||||
|
||||
## Excluded — third-party personal data
|
||||
|
||||
| Item | Where it appeared | Why excluded |
|
||||
|---|---|---|
|
||||
| Names of individual client contacts, agency colleagues and referees | résumé prose | No third party has consented to being named. Clients are represented by brand only, which was public campaign work. |
|
||||
| Details identifying minors in a personal anecdote | `EVIDENCE-NOTES.md` interests ("a 2 day hike … with 7 13 year old boys") | Rewritten as "a group of teenagers in tow". A count of identifiable children is not needed to make the point. |
|
||||
| Names of household members appearing in automation examples | `EVIDENCE-NOTES.md` | Household automation is described by function (lighting, audio, doors) and never by person. |
|
||||
|
||||
## Excluded — credentials and infrastructure detail
|
||||
|
||||
| Item | Where it appeared | Why excluded |
|
||||
|---|---|---|
|
||||
| API keys, tokens, passphrases, secret file names | n/a — never copied | Nothing from `~/.config/environment.d/` was read or quoted. No key material enters the repo, per `AGENTS.md` §4.4. |
|
||||
| Backup passphrase file path and repository passphrase | Obsidian backup note | Publishing the location of a passphrase file is a hint worth withholding. Backups are described by tier, tool and retention only. |
|
||||
| Hostnames, internal IP addresses, ports-by-host, public DNS names | `reference/stack.md`, Obsidian notes, live inspection | Internal addressing is not needed to judge the platform work. Hosts are described by role ("the runtime host", "the edge host"). |
|
||||
| Internal service URLs and dashboards | `EVIDENCE-NOTES.md` (the pipeline dashboard) | Described as "a dashboard built to keep track of it". A private URL on a public page is an invitation. |
|
||||
| Third-party account identifiers, billing detail | n/a | Not in the sources and not wanted. |
|
||||
|
||||
## Excluded — unverifiable or invented content
|
||||
|
||||
| Item | Where it appeared | Why excluded |
|
||||
|---|---|---|
|
||||
| "42 devices" | recovered site content | Explicitly withdrawn in `draft-content.md`. Not used. |
|
||||
| "~800ms end-to-end" latency | recovered site content | Explicitly withdrawn. Not used. |
|
||||
| Invented venues, competition results, swell sizes, distances and restaurants | recovered pursuits content | Marked ❌ SUSPECT and confirmed as generated. Replaced with one honest line per pursuit. |
|
||||
| "Diajio" | recovered client list | Spelling error for **Diageo**. Corrected, not carried. |
|
||||
| Screenshot of the BBC National Archive engagement | recovered site content | The work was an internal tool. Described only; no image. |
|
||||
|
||||
## Metric discipline
|
||||
|
||||
Every numeric `metric` in `content/` is traced to a source line, and the trace is recorded per metric in the completion comment on AUD-131. Two figures were deliberately **not** promoted:
|
||||
|
||||
- **Businesses: 3 active, 12 cumulative.** The site says three are running now and twelve adopted it over time. Conflating them would be the easiest inflation available on this site.
|
||||
- **Where-Woof: deployed, pre-market.** The word "commercial" is not used about it anywhere.
|
||||
|
||||
## Two numbers reported, not smoothed
|
||||
|
||||
1. **Agencies: 22 published, 23 in the summary material.** The recovered, verified list holds twenty-two agency names. The published count is the count of the list. If a name is missing, the number rises to twenty-three and the note in `content/history/l3/history-client-wall.md` is deleted.
|
||||
2. **Period start dates.** Where the sources give no start date, the period is anchored on the homelab year (2020) and the page says so. Exact start dates are Sam's to correct.
|
||||
|
||||
## Open questions for Sam
|
||||
|
||||
- Contact details: email only, or also a phone number? (`about-narrative.md` states the current policy: email, supplied directly.)
|
||||
- Is a Melbourne suburb to be published? Currently excluded.
|
||||
- The missing twenty-third agency, if there is one.
|
||||
184
docs/content-schema.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Content schema (frozen)
|
||||
|
||||
This document states the front-matter schema that every file in `content/` must carry, and the rules the validator enforces. The schema is the one in [`AGENTS.md` §7](../AGENTS.md#7-content-conventions). Read that section first; this page is the exact, testable restatement of it.
|
||||
|
||||
**The schema is frozen.** Any change to the fields, their types, their enum values or the artefact rules is a **breaking change**: it invalidates every existing file in `content/` and both renderers. A change requires **Sam's written approval** before it is made. Do not widen or narrow the schema to make a document validate — fix the document.
|
||||
|
||||
---
|
||||
|
||||
## 1. How to validate
|
||||
|
||||
```
|
||||
make validate # the gate: exits 0 only on a clean tree
|
||||
make test # validator self-test, 20 fixture cases
|
||||
```
|
||||
|
||||
`make validate` is the command CI and `deploy.sh` call in later phases. Run it before every content commit.
|
||||
|
||||
Both targets invoke:
|
||||
|
||||
```
|
||||
python3 tools/validate_content.py [--root DIR] [--content DIR] [--quiet]
|
||||
```
|
||||
|
||||
Exit codes: `0` clean (also when `content/` does not exist yet), `1` at least one violation, `2` usage or internal error.
|
||||
|
||||
---
|
||||
|
||||
## 2. Document shape
|
||||
|
||||
* Every `.md` file under `content/` is a **document** and is validated. Other file types under `content/` (images, SVG, PDF) are **assets** and are not validated — they exist to be referenced.
|
||||
* A document starts with a front-matter block on line 1:
|
||||
|
||||
```
|
||||
---
|
||||
<fields>
|
||||
---
|
||||
```
|
||||
|
||||
* The closing delimiter is `---` (or `...`). Everything after it is the Markdown body and is not validated.
|
||||
* One document per file. One front-matter block per file.
|
||||
* `content/` is organised by area:
|
||||
|
||||
```
|
||||
content/
|
||||
ai/ platform/ edge/ products/ history/ about/ # documents, plus l3/ below each
|
||||
assets/ # diagrams, screenshots, logos
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Fields
|
||||
|
||||
All thirteen fields are **required on every document**, including L3 stubs (which use empty lists). Order does not matter.
|
||||
|
||||
| Field | Type | Rule |
|
||||
|---|---|---|
|
||||
| `id` | string | Lowercase kebab-case: `a-z`, `0-9`, single hyphens between parts. **Must equal the file name** without `.md`. **Unique** across all of `content/`. |
|
||||
| `area` | enum | One of `ai`, `platform`, `edge`, `products`, `history`, `about`. |
|
||||
| `level` | integer | `1`, `2` or `3` (depth level: L1 landing, L2 capability, L3 artefact). |
|
||||
| `title` | string | Non-empty. Corporate capability framing (see `AGENTS.md` §7); product names are evidence, not headings. |
|
||||
| `claim` | string | Non-empty. One sentence a hiring manager can verify. |
|
||||
| `confidence` | enum | One of `delivered`, `running`, `in-progress`, `abandoned`, `historic`. **Displayed on the page.** Never promote a value to make a page read better. |
|
||||
| `period` | string | Non-empty. Free text, e.g. `"2023–"`, `"2019–2024"`, `"2000–2014"`. |
|
||||
| `tech` | list of strings | Non-empty strings. May be `[]`. Product and technology names belong here, not in `title`. |
|
||||
| `metrics` | list of maps | May be `[]`. Each item is exactly `{label, value}`. Both non-empty. `value` may be a number (`8`) or a string (`"50+"`). Every value must trace to the evidence notes — the validator checks shape, not truth. |
|
||||
| `artefacts` | list of maps | May be `[]`. Each item is exactly `{type, label, url}`. See §4. |
|
||||
| `public` | boolean | `true` or `false`. `false` keeps the document out of the published output. |
|
||||
| `last_verified` | date | `YYYY-MM-DD` and a real calendar date. |
|
||||
| `tags` | list of strings | Non-empty strings. May be `[]`. |
|
||||
|
||||
**Unknown fields are rejected — at the top level and inside `metrics[]` and `artefacts[]`.** There is no extension point. A field that an author thinks is useful is a schema change (§6).
|
||||
|
||||
The one exception to "all required": nothing. `tech: []`, `metrics: []`, `artefacts: []` and `tags: []` are the correct way to say "this document has none". An omitted field is a violation; an empty list is not.
|
||||
|
||||
---
|
||||
|
||||
## 4. Artefact links — dangling references are fatal
|
||||
|
||||
Every `artefacts[].url` must resolve to a file that exists in this repository. This is the rule that keeps every claim one step away from its proof.
|
||||
|
||||
| `url` form | Resolves against | Example |
|
||||
|---|---|---|
|
||||
| `content/...` or any path without a leading `./` or `../` | the repository root | `content/edge/l3/audio-architecture.md` |
|
||||
| `./...` or `../...` | the directory of the document | `./l3/audio-architecture.md` |
|
||||
|
||||
Rules:
|
||||
|
||||
* The target must be an existing **file** — an L3 stub document (`.md`) or an asset (`.svg`, `.png`, `.pdf`, …). A directory is a violation.
|
||||
* **External URLs (`https://…`) are not allowed.** If the artefact lives outside the repository (a Gitea repo, a video), create an in-repo L3 stub document that describes and links it, and point `url` at that stub. This keeps every drill-down verifiable offline and keeps Mode A free of third-party dependencies.
|
||||
* Root-absolute paths (`/content/...`) are not allowed — they do not survive a release directory move.
|
||||
* A path that escapes the repository is a violation.
|
||||
|
||||
`type` is one of `repo`, `image`, `video`, `doc` and describes the artefact behind the link, not the file extension of the stub.
|
||||
|
||||
---
|
||||
|
||||
## 5. Cross-document rules
|
||||
|
||||
* **`id` is unique** across `content/`. Two files with the same `id` are a violation on the second file.
|
||||
* **`id` matches the file name.** `content/edge/snapcast.md` must have `id: snapcast`; an L3 stub `content/edge/l3/snapcast-code.md` must have `id: snapcast-code`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Changing the schema
|
||||
|
||||
Breaking (requires Sam's written approval, then a migration of every file):
|
||||
|
||||
* adding, removing or renaming a field
|
||||
* changing a field's type
|
||||
* adding or removing an enum value (`area`, `level`, `confidence`, artefact `type`)
|
||||
* relaxing or tightening a rule (e.g. allowing external artefact URLs)
|
||||
|
||||
Not a schema change: adding documents, filling empty lists, adding tags or metrics within the existing shape.
|
||||
|
||||
A change that supersedes this document must update, in one commit: `AGENTS.md` §7, this file, `tools/validate_content.py`, and the fixtures under `test/fixtures/`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Error output
|
||||
|
||||
One line per violation, on stdout:
|
||||
|
||||
```
|
||||
<path>:<line>: <field>: <rule broken>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
content/edge/audio.md:14: artefacts[0].url: dangling reference: 'content/edge/l3/not-written-yet.md' does not exist (create the L3 stub or asset)
|
||||
content/edge/audio.md:16: author: unknown field (the schema is frozen; see docs/content-schema.md)
|
||||
content/edge/audio.md:3: area: must be one of ai, platform, edge, products, history, about
|
||||
content/edge/audio.md:1: claim: missing required field
|
||||
```
|
||||
|
||||
A missing field is reported on line 1, because there is no line that carries it. A malformed front-matter block is reported as `<front-matter>: invalid YAML: …` and stops validation of that document only.
|
||||
|
||||
The final line is either `FAIL: N violation(s) in M document(s)` or `OK: M document(s) validated, 0 violations`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Front-matter dialect the parser accepts
|
||||
|
||||
The validator contains its own small YAML-subset parser so the repository needs no third-party dependency (`AGENTS.md` §4: the stack is frozen, and the `.27` build host has no Go toolchain yet). It accepts:
|
||||
|
||||
* block mappings, block sequences, and flow collections: `tech: [a, b]`, `metrics: [{label: "endpoints", value: 8}]`
|
||||
* single- and double-quoted scalars, plain scalars
|
||||
* literal (`|`) and folded (`>`) block scalars, including `|-` / `>-`
|
||||
* `#` comments outside quoted strings
|
||||
* blank lines
|
||||
|
||||
It does **not** accept: anchors/aliases (`&`, `*`), explicit tags (`!!str`), multi-document files, complex keys, tab indentation. Use two or four spaces, consistently within a block.
|
||||
|
||||
Two consequences worth knowing:
|
||||
|
||||
* A quoted string must be closed. `claim: "text # not a comment` is an error, not a comment.
|
||||
* `#` after a space ends a plain scalar, as in YAML. Quote values that contain ` #`.
|
||||
|
||||
---
|
||||
|
||||
## 9. What the validator does not check
|
||||
|
||||
Enforced elsewhere in Phase 1, and reviewed by Sam:
|
||||
|
||||
* that a `metric` value appears in the evidence notes (no invented numbers)
|
||||
* that `confidence` matches reality — the validator cannot know; it only forces an honest label to be present
|
||||
* the redaction pass (no family names, address, phone, credentials)
|
||||
* that every L1 claim has a metric and at least one L3 artefact
|
||||
* corporate framing of headings
|
||||
|
||||
---
|
||||
|
||||
## 10. Implementation and tests
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `tools/validate_content.py` | The validator. One file, Python 3 standard library only, no framework. |
|
||||
| `Makefile` | `validate` and `test` targets. |
|
||||
| `test/fixtures/<case>/content/` | Fixture trees. `ok-*` cases must pass, `fail-*` cases must fail. |
|
||||
| `test/fixtures/<case>/expect.txt` | Substrings that `fail-*` output must contain, one per line. |
|
||||
|
||||
Fixture cases cover: missing field, `area` enum, `level` enum, `confidence` enum, `last_verified` format and calendar validity, empty `metrics[].label`, artefact `type` enum, artefact missing `url`, dangling artefact, external artefact URL, duplicate `id`, `id`/filename mismatch, unknown top-level field, unknown nested artefact field, missing front-matter, malformed YAML. `ok-empty` proves an empty `content/` exits 0; `ok-block-scalars` proves the block-scalar and block-sequence dialects.
|
||||
|
||||
Fixtures live under `test/`, never under `content/`.
|
||||
1
test/fixtures/fail-area-enum/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-area-enum/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: security
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-area-enum/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-area-enum/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
area: must be one of ai, platform, edge, products, history, about
|
||||
1
test/fixtures/fail-artefact-external-url/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-artefact-external-url/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "https://example.invalid/rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-artefact-external-url/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-artefact-external-url/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
artefacts[1].url: must be an in-repo path to an L3 stub or asset, not an external URL
|
||||
1
test/fixtures/fail-artefact-missing-url/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-artefact-missing-url/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-artefact-missing-url/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-artefact-missing-url/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
artefacts[1].url: missing required field
|
||||
1
test/fixtures/fail-artefact-type-enum/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-artefact-type-enum/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: screenshot
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-artefact-type-enum/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-artefact-type-enum/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
artefacts[0].type: must be one of repo, image, video, doc
|
||||
1
test/fixtures/fail-bad-yaml/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-bad-yaml/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-bad-yaml/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-bad-yaml/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
invalid YAML: unterminated quoted string
|
||||
1
test/fixtures/fail-confidence-enum/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-confidence-enum/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: planned
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-confidence-enum/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-confidence-enum/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
confidence: must be one of delivered, running, in-progress, abandoned, historic
|
||||
1
test/fixtures/fail-dangling-artefact/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-dangling-artefact/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/not-written-yet.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-dangling-artefact/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-dangling-artefact/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
artefacts[0].url: dangling reference: 'content/edge/l3/not-written-yet.md' does not exist
|
||||
1
test/fixtures/fail-duplicate-id/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-duplicate-id/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-duplicate-id/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
21
test/fixtures/fail-duplicate-id/content/platform/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: platform
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
1
test/fixtures/fail-duplicate-id/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
duplicate id 'audio'
|
||||
1
test/fixtures/fail-filename-mismatch/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-filename-mismatch/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: edge-audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-filename-mismatch/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-filename-mismatch/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
must match the file name (expected 'audio', got 'edge-audio')
|
||||
1
test/fixtures/fail-last-verified-date/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-last-verified-date/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-13-45
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-last-verified-date/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-last-verified-date/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
last_verified: must be a real calendar date (YYYY-MM-DD)
|
||||
1
test/fixtures/fail-last-verified-format/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-last-verified-format/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: "20 October 2026"
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-last-verified-format/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-last-verified-format/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
last_verified: must be a date written as YYYY-MM-DD
|
||||
1
test/fixtures/fail-level-enum/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-level-enum/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 4
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-level-enum/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-level-enum/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
level: must be the integer 1, 2 or 3
|
||||
1
test/fixtures/fail-metrics-empty/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
21
test/fixtures/fail-metrics-empty/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
claim: "Eight synchronised endpoints with music ducking for voice."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||
17
test/fixtures/fail-metrics-empty/content/edge/l3/audio-architecture.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: audio-architecture
|
||||
area: edge
|
||||
level: 3
|
||||
title: "Audio architecture note"
|
||||
claim: "How the eight endpoints stay in sync."
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: []
|
||||
metrics: []
|
||||
artefacts: []
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio]
|
||||
---
|
||||
|
||||
# Audio architecture note
|
||||
1
test/fixtures/fail-metrics-empty/expect.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
metrics[0].label: must be non-empty
|
||||
1
test/fixtures/fail-missing-field/content/assets/audio-rack.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"/>
|
||||
|
After Width: | Height: | Size: 65 B |
20
test/fixtures/fail-missing-field/content/edge/audio.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: audio
|
||||
area: edge
|
||||
level: 2
|
||||
title: "Distributed Audio"
|
||||
confidence: running
|
||||
period: "2023-"
|
||||
tech: [Snapcast, Mopidy, Spotify]
|
||||
metrics: [{label: "endpoints", value: 8}]
|
||||
artefacts:
|
||||
- type: doc
|
||||
label: "Architecture note"
|
||||
url: "content/edge/l3/audio-architecture.md"
|
||||
- {type: image, label: "Rack diagram", url: "content/assets/audio-rack.svg"}
|
||||
public: true
|
||||
last_verified: 2026-10-20
|
||||
tags: [audio, snapcast]
|
||||
---
|
||||
|
||||
# Distributed Audio
|
||||