Field Report — How This Site Is Built

AI builds this site. A person approves every page change.

Parallel AI builders work in isolated branches, an independent AI reviewer checks what they made, and no page change publishes until I say so. Here is the loop, the public record behind it, and a small gate you can try yourself.

Try the gate ↓

First published: 2026-10-19. Pull-request details and counts below were read from GitHub on 2026-10-19.

How is this site built?

By AI agents working under a written plan, each on its own Git branch, followed by an independent AI reviewer and then a human decision. The builders write the pages. A separate reviewer looks for what is wrong with them. I read the result and decide whether it merges. This site is hosted on GitHub Pages, so a merge to main is also a publish. For any change to a page, the merge is the control point, and it is mine.

The loop

The same cycle runs for every batch of changes. The AI does the volume work; the steps that carry authority stay with a person.

The build loop: plan, parallel AI builder lanes, independent AI review, fix rounds, human approval, merge and publish, live verification Step 1, plan: a written batch plan names the lanes and the files each may touch. Step 2, build: three AI builder lanes, A, B and C, work in parallel, each in its own isolated branch. Step 3, review: an independent AI reviewer checks the work. Findings go back to the builder lanes for a fix round, at most two rounds. Step 4, human nod: Tim approves every change to the site's pages; internal docs may merge without it. Step 5, merge equals publish: merging to the main branch deploys the live site. Step 6, live verification: the published page is checked. 1 · PLAN A written batch plan names the lanes and the files each lane may touch 2 · BUILD IN PARALLEL AI Lane A Lane B Lane C own branch own branch own branch Isolated from each other and from main 3 · INDEPENDENT REVIEW AI A separate reviewer, not the author, reads the change and reports findings FIX ROUNDS · MAX 2 4 · HUMAN NOD TIM I approve every page change. No nod, no page merge. 5 · MERGE = PUBLISH Merging to main deploys the live site (GitHub Pages) 6 · VERIFY THE LIVE PAGE
AI steps are labelled AI; the human step is highlighted. The dashed arrow is the fix loop, capped at two rounds.
  1. Plan. A written batch plan names the lanes and the files each lane may touch, so parallel work can't collide.
  2. Build in parallel. Each lane is an AI builder on its own branch. Branch names in the repository follow the work, such as pub/authorizations-record and pub/deck-fixes.
  3. Independent review. A separate AI reviewer, not the one that wrote the change, reads it and reports what's wrong.
  4. Fix rounds, at most two. Findings go back to the lane. If two rounds don't settle it, the question comes to me instead of looping.
  5. Human nod. I decide whether any change to a page merges: copy, content and visuals are mine to approve. Internal docs can merge without it.
  6. Merge is publish; then check the live page. Pushing to main is the deploy, so the check that matters is on the page a visitor sees.

What keeps the agents honest

Four mechanisms do most of the work. The method itself lives in private notes, because the site's repository is public. This is what each one does.

  • A written batch plan. Scope is decided before anyone writes, and each lane's allowed files are listed.
  • A facts file every public claim must trace to. Statements about my career have to match a private, source-checked facts file. Statements about the tooling have to match the field reports linked below.
  • A do-not-write list. Claims I've ruled out because they don't hold up are listed, and reviewers check drafts against the list.
  • One writer for shared state. Shared records have a single writer, so parallel lanes can't overwrite each other. The failures this prevents are documented in what breaks when two AI agents share a notepad.

The record is public

This site's repository is public, so the loop leaves a trail anyone can read. Four recent pull requests show it. Each description says what changed and who approved the merge, and each carries Claude Code's generation notice.

#9 · Authorizations-record field report

Merged 2026-10-13 · +767 / −0 · 3 files

A new field report, a homepage card and a sitemap entry. Independent review plus one fix round. The description lists what the round changed: the wording of the paper's limits, the order of the checks, the teaser counts and an example row. Every number was checked against the StrictLock commits and spec.

#10 · Plan-gate page refresh

Merged 2026-10-13 · +182 / −3 · 1 file

A short-answer box, an inline-SVG gate diagram and a decision-log update. Independent review plus two fix rounds. Review changed what the page claims: self-protection was scoped to file writes with the shell blind spot stated, and plan coverage stopped being described as exact-match.

#11 · Deck fixes

Merged 2026-10-13 · +260 / −72 · 2 files

The presentation deck now always starts, with instant cuts under reduced motion and phone fixes. Independent review with no blockers, plus two fix rounds; claims were checked against the private facts files.

#12 · Case-study rulings

Merged 2026-10-13 · +18 / −18 · 1 file

My seven rulings from an audit applied to the Transamerica case study, with unsourced phrases removed. The description records that the merge was approved on 2026-10-13.

What review catches is the point. In the pull requests above it tightened claims that had run ahead of the evidence. In the StrictLock build behind the authorizations-record report, three adversarial AI reviewers found a .. path trick that slipped past the log's self-protection; it was fixed the same day, as that report describes.

Three of these pull requests (#9, #10, #11) came from one batch, run as Lanes 2, 1 and 3 in the descriptions. The four merged between 00:08 and 10:53 UTC on 2026-10-13, adding 1,227 lines and removing 93 across seven files, as GitHub reports them on 2026-10-19. Line counts measure volume, not quality.

The repository is at github.com/downsmullen/downsmullen.github.io.

Simulation

Try a fail-closed gate

The loop above relies on one idea from my plan-gate field report: don't ask an agent to behave; put a check it doesn't control between its intent and its effect, and let that check default to deny. Propose an action below and see what a gate like that does.

A simplified illustration. This is a small script running in your browser, written to follow how the field reports describe the gate. It is not the StrictLock code, and nothing here touches a real system or a real log. It also leaves out the real gate's two deliberate exceptions: it fails open if it crashes, and a person can switch it off with an emergency bypass.

The approved plan in this simulation
  • Files that may be written, exact paths: plan-gate.html
  • Commands that may run, approved prefixes: git status, git diff, git add, git commit
  • The gate's own log directory: gate-logs/

The interactive version needs JavaScript. Here is what the gate decides for twelve example actions:

Example actions and the gate's decision
Proposed actionDecisionWhy
edit plan-gate.htmlALLOWEDThe plan names this exact path.
read README.mdALLOWEDRead-only; this demo does not gate reads.
git commit -m "update"ALLOWEDMatches the approved prefix git commit.
edit index.htmlHELD FOR HUMANNot in the plan. Denied by default; a person decides.
git push --force origin mainHELD FOR HUMANNo approved prefix covers it. Denied by default.
rm -rf docs/HELD FOR HUMANNo approved prefix covers it. Denied by default.
merge to main (publishes live)HELD FOR HUMANNot in the plan, and on this site a merge that changes a page also needs Tim's nod.
git status && rm -rf .HELD FOR HUMANChained command: can't tell it stays inside one approved command, so deny.
edit gate-logs/decisions.jsonlBLOCKEDThe gate never authorizes writes to its own log.
edit plans/../gate-logs/decisions.jsonlBLOCKEDThe path resolves into the log directory; the gate checks the resolved path too.
edit ../plan-gate.htmlHELD FOR HUMANContains "..": the gate won't guess it means the plan's path. Ambiguous means deny.
read ../../etc/passwdHELD FOR HUMANContains "..": the gate won't guess where it points. Ambiguous means deny.

The rules, in the order the gate applies them

First matching rule wins
#If the action…DecisionSource in the field reports
1is a file write (edit, write, delete and similar) that targets the log directory gate-logs, as written or once .. is resolvedBLOCKEDAuthorizations record: the gate never authorizes a file write into its own log, and resolved paths are checked after a .. bypass was found in review. The protection covers file writes only. A shell command that touches the log is decided by the rules below, and the result says the shell is a documented blind spot where the human reviewing the plan is the control.
2chains or redirects commands (; && || | > and similar)HELD FOR HUMANPlan-gate: ambiguous actions are denied and the agent stops for a human.
3only reads (read, cat, ls, grep and similar), with plain relative paths. A read whose path is absolute, or contains .. or a backslash, is held instead.ALLOWEDDemo simplification. Plan-gate describes gating consequential calls such as writes and commands. The held case follows "ambiguous means deny".
4edits a file by an absolute path, or a path containing .. or a backslashHELD FOR HUMANPlan-gate: exact match for file paths, and ambiguous actions are denied.
5edits a file whose exact path the plan namesALLOWEDPlan-gate: exact match for file paths.
6runs a command starting with an approved prefixALLOWEDPlan-gate: approved prefix for commands.
7anything else, or anything the demo can't parseHELD FOR HUMANPlan-gate: deny by default; the agent stops for a human.

In the described gate, HELD and BLOCKED are both denials. The demo separates them to show the difference between "outside the plan, a person could widen it" and "no plan can authorize this". The log line carries a timestamp, the decision, a class, the target, the previous line's hash and its own. The real log chains SHA-256 hashes; this simulation uses a short non-cryptographic hash so it fits on one line. The honest boundary from the field report applies: the chain makes edits and deletions inside the record detectable, but cutting off the last line goes unnoticed without an external anchor. Try "Delete the last line" to see it.