NAI OS · as-built inventory · 2026-10-15
Every measure in this repository that narrows what an agent may do: from the connector that exists at all, down to the sentence in the prompt. Nine layers, catalogued with the file each one lives in.
The cohort's own vocabulary calls Claude Code the harness: "the operating system/foundation"
an agent runs in (Resources/Sessions/Session 1.md). Harnessing, in that reading, is everything
that constrains the model inside it. In NAI OS those constraints are layered on purpose, and the repo states
the principle behind the layering in its own loop write-up:
"A guardrail written as prose can be argued with; a tool that isn't in the grant cannot be called.
When a loop's quality gate matters, put the separation in tools:."
Read the layers outside-in. A request passes the human-only line first, then the provider scope, the harness permission file, the agent's tool grant, the prompt boundary, the orchestrator's gates, the verification shape, and finally the data and publication guards and the code-level checks in the scripts. Every row below cites the file it was read from; nothing is inferred.
tools: allowlist.claude/settings.json.gitignore files plus one per-machine Stop hookAmber marks the one layer that is not a mechanism but a design decision: what the harness is never asked to do.
The pre-course deliverable fixed which tasks are agent candidates and which stay human. Every system's command description repeats its own version of that line, and two whole folders are kept agent-free.
| Measure | Lives in | What stays human | Evidence |
|---|---|---|---|
| Reserved task class | 01 Preparation/tasks-eating-time.md |
Final trade-off decisions, stakeholder negotiation and communication. | "Final trade-off decisions | Needs human judgment, context, and accountability." |
| Prepare-and-stop contract | Every command's description: |
Tax: human files via ELSTER and pays. Option study: human decides. Review: human delivers. Spec: human adopts. Newsletter and briefing: human sends. | nai-tax-theo.md: "You NEVER file, pay, or move money"; nai-option-study.md: "you NEVER decide"; nai-review.md: "the human delivers it". |
| Agent-free folder: decision gates | 13 Decision Pack/ |
Client gate conversations, answers verbatim, verdicts against pre-written criteria. | README: "Human-only by design — no agent in NAI OS writes or updates files here." |
| Agent-free workflow: LinkedIn | 14 LinkedIn/ |
Publishing under Udo's name. A copy script formats; a person pastes. | README: "There is deliberately no agent, no scheduler, and no LinkedIn API involved". |
| Judgement boundary in tax | loan-interest-vga, vat-worksheet |
Whether a loan is fremdüblich, which rate applies, whether a vGA exists: the Steuerberater's call. Ambiguous VAT lines go to "Unclassified — needs review", never to a guessed Kennziffer. | loan-interest-vga.md: "You FLAG risks; you NEVER decide". |
| Census never submits | /nai-cohort-census |
Posting to the cohort space. Also: names and counts only, never file contents or prompt text. | "You measure and draft; you NEVER submit". |
Before any permission rule or prompt applies, the server decides which tools exist. The repo's stated pattern
is "broad OAuth scopes at the server, narrow enforcement at the subagent tools: whitelist"
(docs/superpowers/mcp-google-setup.md), and it records the cost of that choice rather than hiding it.
| Measure | Lives in | What it narrows | Evidence |
|---|---|---|---|
| google-workspace tool list | Local server registration, user-scoped | Server runs with --tools gmail calendar chat contacts; nothing else is loaded. Chat and Contacts are exposed but granted to no agent (see gaps). |
docs/machine-setup.md Step 3; docs/architecture/concept-tools.html. |
| Qonto off by default | claude.ai connector toggle | Enabled only for the quarterly close, then disabled: no banking surface while editing prompts. The deny list (L2) stays on regardless. | docs/machine-setup.md: "treat Qonto as off by default, on for the quarterly close"; "the deny list is the guard that's always on." |
| nai-onto bearer token, scoped by role | .mcp.json |
Token scope read for queries, write only where runs are recorded. Never written into a file in the repo. |
docs/machine-setup.md: "Never write the token into a file in this repo." |
| Proxy-injected credentials in the cloud | Environment API credential | NAI_ONTO_TOKEN=proxy-injected; the agent proxy attaches the real token outside the VM, so it never enters the session. |
scripts/onto-sync/README.md: "the script then sends no Authorization header". |
| Service-account key outside the repo | GDRIVE_SA_JSON env var; scripts/paper-upload/.gitignore |
Key JSON lives outside the repo; the folder's .gitignore catches any *.json dropped there by mistake (only package.json is tracked). |
"A service-account key must never land in the repo." |
| Cloud-only SessionStart hook | .claude/hooks/session-start-gdrive.sh, wired in settings.json |
No-ops unless CLAUDE_CODE_REMOTE=true and the key is set; writes the rclone config with umask 077 and chmod 600, then self-checks the config references the file it wrote. |
The script's header comment and its grep -qF self-check. |
| Research library over API only | paper-ingester, scripts/paper-upload/drive.mjs |
Never the local H:\ mount, on any machine; one helper is the only way in. |
"This library is Drive-API-only, on every machine." |
The tracked .claude/settings.json is applied by Claude Code before any agent is dispatched. It is the
layer that holds even when a prompt is wrong, and the layer that keeps a connected Qonto session read-only.
| Measure | Rules | What it refuses | Evidence |
|---|---|---|---|
| Qonto deny list | 53 deny 9 allow | Every tool that creates, changes, sends or approves (transfers, cards, invoices, quotes, clients, memberships, attachments), plus the read tools the pipeline does not use. Applies in main and subagent sessions alike. | 06 Tax Agent/README.md: "deny-lists every other Qonto tool ... so the harness refuses them in any session — main or subagent." |
| Bash narrowed per purpose | 6 allow patterns | Allowed shapes only: curl -sSL -o "06 Tax Agent/* (receipts into the tax folder), git log/add/commit, gh repo *, one sort form. |
.claude/settings.json permissions.allow. |
| Wiki write denied at the shell | 3 deny | mv, cp and curl whose arguments reference library-wiki…wiki: a structural backstop under the paper-ingester's prose rule. |
paper-ingester.md: "a second, structural backstop under this instruction, not a replacement for following it." |
| Per-machine file kept out of git | .claude/settings.local.json* |
Holds the Stop hook and a live Google OAuth client secret; gitignored with a wildcard so editor backups are swept too; transferred out of band only. | Root .gitignore; docs/machine-setup.md Step 2. |
| Hook events | 1 tracked, 1 per machine | SessionStart (tracked, cloud setup). Stop (per machine): auto-commit and push, holding back guarded paths (L7). |
.claude/settings.json hooks; docs/machine-setup.md. |
All 25 subagents declare a tools: allowlist. The convention is exact: "Grant exactly what the body
uses. Not one tool more", and "A grant that contradicts a boundary is worse than a missing grant. A missing grant
fails loudly" (docs/agent-conventions.md). Only four agents hold a remote mcp__ tool at all.
| Measure | Agents | What the absence makes impossible | Evidence |
|---|---|---|---|
| No send tool in the mailbox agent | email-triage |
Holds search, read and draft. The server does expose send_gmail_message and label modification; neither is granted, so sending is impossible, not forbidden. |
docs/architecture/concept-boundary.html. |
| No write tool in the calendar agent | calendar-briefing |
Two Calendar read tools plus web lookups; no Write, no event mutation. |
Frontmatter: list_calendars, get_events, WebSearch, WebFetch. |
| Nine Qonto reads, no money tools | qonto-collector, loan-interest-vga |
List and get only; the loan agent holds list_transactions alone. No create, approve or transfer tool is in either grant. |
Frontmatter of both agents. |
| No web tools by design | option-recommender, finding-drafter, spec-rule-drafter, all three scopers, newsletter-writer, vat-worksheet, all four doc-* agents |
A drafter cannot cite what it cannot reach; evidence enters only through the verifier, the dropped files, or a vetted research file. | loop-pattern.md §1: "The critic is independent — enforced by tools, not prose". |
| Checkers get Grep, not Glob | finding-checker, spec-rule-checker, doc-checker |
Read, Write, Grep: enough to hunt for a quoted string, nothing to author with. |
Frontmatter of the three checkers. |
| Bash scoped to named purposes | qonto-collector, paper-ingester |
Collector: one purpose, curl receipts. Ingester: four purposes, curl the PDF, run render.mjs for a web-source candidate, run the Drive helper, delete the temp file. WebFetch in the ingester: one purpose, find the PDF link on a landing page. |
paper-ingester.md: "Bash is granted for exactly four purposes". |
| Grant audit before every commit | All agents | For each tool in tools:, find where the body uses it; if you cannot, remove it. onto-sync --check extracts the grants into the ontology and exits 1 on drift. |
docs/agent-conventions.md; scripts/onto-sync/README.md. |
Every agent prompt is self-contained on purpose: a shared include could move or be renamed and silently drop a
guardrail, and "for email-triage, whose boundary is 'never send', a silently-dropped guardrail is the
one failure mode that is unacceptable." The fix for drift between the copies was canonical wording, not indirection.
| Measure | Lives in | What it guarantees | Evidence |
|---|---|---|---|
| Four access classes, one verbatim sentence each | ## Boundary of every agent |
A observe only, no files (1 agent) · B read remote, write local (22) · C read remote, stage remote: drafts only (1) · D read remote, file remote: add new files only (1) | docs/agent-conventions.md, "The four access classes". |
| Mandatory heading and order | All agents | ## Boundary, never "Guardrails" or "HARD SAFETY BOUNDARY"; then Input, Missing input, Process, Output, Return. One structure, so a missing section is visible. |
"Canonical phrasings" table. |
| Missing-data contract | All agents; JSON status field |
ok / missing / unconfigured. Never fabricate to fill a gap; an empty array is not missing; never compute from partial data; every agent has a ## Missing input section. |
"vat-worksheet shipped without one and was the agent most likely to need it." |
| Entity from config, never hardcoded | 06 Tax Agent/inputs/config.yaml |
Agents read organization.name; nothing an agent writes may hardcode the GmbH. The example YAML is the fallback. |
CLAUDE.md; "Canonical phrasings". |
| Full repo-root-relative paths | All agents | A subagent has no "current period folder"; the period is a parameter, so every path is written in full. | "Verbosity wins." |
| No phase numbers in descriptions | All agents | Agents describe what they do, not when they run; the orchestrator's wave model is the truth. | "No phase numbers". |
| View, never a calculator | cockpit-writer, doc-renderer |
Every figure, date and sentence rendered appears verbatim in the source markdown; no sums, rounding or rewording. A cockpit that computes would be a second source of truth. | cockpit-writer.md rule 1; doc-renderer.md: "You never author, edit, shorten, expand, correct, or reorder the author's prose." |
| Verdict only, default UNSUPPORTED | The three checkers, option-verifier |
Never edit, add or drop what is being checked; a quote that cannot be located is UNSUPPORTED, never benefit of the doubt; never fabricate a source. | finding-checker.md rules 1 to 3; option-verifier.md rule 3. |
| No evidence, no finding | finding-drafter, spec-rule-drafter |
A concern without a verbatim quote from a dropped file becomes an open question for the human, never a finding or a rule. | "The evidence rule is absolute: no verbatim quote from a dropped file, no finding." |
| Gaps stated, never filled from memory | ea-context-reviewer, review-scoper, spec-context-scoper |
General knowledge may frame a brief; it never substitutes for absent evidence. | Boundary of each scoper. |
| Never claim "proven" | option-recommender |
Without web tools it may not call an option battle-tested or invent a citation; it may say what evidence would support it. Previous rounds are never modified. | option-recommender.md Boundary. |
| Hand-edited files never regenerated | voice-profiler, newsletter-writer |
The voice profile is written only if absent, then edited by hand; the writer reads exactly two files and nothing else in the repo. | voice-profiler.md: "if it exists, STOP". |
| Documenters never touch what they document | All four doc-* agents |
Never write into docs/, never edit an agent or command file, never author prose. |
doc-scoper.md, doc-surveyor.md Boundary. |
| Public information only | company-research, tech-radar, option-verifier, voice-profiler |
No scraping behind logins, no pretexting. | Boundary sentence shared by the web-reading agents. |
The command files hold the control flow. Their gates are of six kinds; each kind appears in several systems.
| Gate kind | Where | Rule | Evidence |
|---|---|---|---|
| STOP on missing input | option-study, review, spec-drafter, newsletter, paper-ingest, document | No slug, no request file, no instances, no voice profile, no paper link, no matching target: stop and say so. Never run on a guess. | nai-review.md: "Never run without a subject"; nai-newsletter.md: "do not draft an issue with no voice profile". |
| STOP before overwrite | option-study, review, spec-drafter, newsletter | An existing non-empty output folder may carry hand annotations: ask before overwriting, never silently. | "They may have annotated the study. Never silently overwrite." |
| STOP on a blocked or error return | All systems | A subagent's blocked: or missing: line, or a script's ERROR: line, is relayed verbatim and ends the run. Never continue on a partial source list. |
nai-document.md Step 3; nai-issue-to-agent.md step 1. |
| Confirm before the irreversible | issue-to-agent | A comment on a client issue cannot be edited or removed through the app, so the orchestrator stops for explicit confirmation. Silence, a vague reply or an assumed yes do not count. | "Do not proceed on silence, a vague reply, or an assumed 'yes'." |
| One remote write, nothing else | paper-ingest, issue-to-agent, issue-check | Paper ingest posts one summary comment and never closes, labels or edits the issue; an environment problem is relayed in chat, not posted. Issue check sends one push notification and never quotes a comment body. | nai-paper-ingest.md step 4; nai-issue-check.md step 2. |
| Hard round bound | option-study | At most three recommend-verify rounds. Only FAIL iterates; THIN exits as a finding; at the bound FAILed options are flagged, never dropped. | "You never run a fourth round. The bound is absolute — it does not stretch for 'one more try'". |
| Wave order, never same-message | option-study, review, spec-drafter, document | Verify only after the drafter has returned; dispatch the next wave in a new message so the critic never sees unfinished work. | "Only after Wave 1 returns — never in the same message". |
| Files are the interface | option-study | The critique travels as a file the next round reads from disk; the orchestrator passes paths and a round number, never the critique text. Earlier rounds are never edited. | loop-pattern.md §2: "The critique travels by file, not by context". |
| Orchestrator re-derives nothing | option-study, review, spec-drafter | Verdicts, counts and quotes are copied verbatim from the working files, never recounted or reworded; empty sections say "None", never omitted. | nai-review.md: "figure copied from the working files' own header lines, never recounted". |
| Stage, then promote by the orchestrator only | document | Generators write to 12 Documentation/runs/<target>/proposed/, never under docs/. Promotion happens only if mode is create, every verdict is CONFIRMED and every guard line is ✓; an existing page is always staged, never overwritten. |
nai-document.md Steps 4 and 7; "Never claim a page is published when it was only staged." |
| Exact target lists, no pattern fallback | document | The blog denylist (blog-ideas) and the editorial list are closed enumerations; an ambiguous target stops and asks. |
"Exactly these targets, and no pattern fallback". |
| Confidence-tiered autonomy | issue-route | TypeSafe confidence ≥ 0.85 dispatches, ≥ 0.60 asks, below that or readiness < 0.50 lists for the human; a model failure routes to human. Thresholds are tracked and hand-tuned; the README's first-week setting is 1.0, so nothing dispatches without a yes. | scripts/issue-router/thresholds.json; README "Calibrating the thresholds". |
| Unattended runs never ask | newsletter routine | On a schedule, the STOP gates become one-line exits: an existing folder or a quiet month ends the run; the draft goes to a branch and a pull request, nothing is sent. | 07 Newsletter/README.md: "An unattended run never asks". |
| Run ledger last, never blocking | Every system command | Recording the run in the ontology prints one line and always exits 0; UNCONFIGURED skips silently, ERROR is reported once and never retried, and it may never change the report above it. |
Section "Run ledger (last, never blocking)" in each command. |
Rigor is matched to what a wrong answer costs, not to what the system could afford. The map is
docs/verification-patterns.md; the design line is that for the cheap, disposable systems "the guardrail
is in tools:, not in a second agent's judgment."
| Shape | Systems | Who checks | Iterates |
|---|---|---|---|
| 1 Bounded generator/critic loop | option-study | option-verifier, web-grounded | ≤ 3 rounds, only on FAIL |
| 2 Single adversarial pass | review, spec-drafter, document | finding-checker, spec-rule-checker, doc-checker | No. The verdict is terminal; an UNSUPPORTED item goes to the human, never back to the drafter. |
| 3 Orchestrator-computed tie-out | tax-theo, document (publish guard) | The orchestrator, no subagent | No. Deltas are ✓ or flagged; the three guard checks are lookups, not judgement. |
| 4 No cross-check, by design | chief-of-staff, newsletter, paper-ingest, payroll-theodora | None; the human reads every line | n/a. Safety sits in the tool grant, and for paper-ingest in a tool-layer check (curl -f plus a %PDF magic-byte test). |
Why no loop in shapes 2 and 3. "Iterating would let the drafter rewrite findings until they slip
past the checker" (nai-review.md). The checker still runs on zero findings and records the zero, so its
absence is never silent.
Two guards per risk, each independent of the other. Git ignores real data; the Stop hook refuses to stage it even when forced. Vercel serves only an allowlist; a staged page sits outside that allowlist by construction.
| Measure | Lives in | What it holds back | Evidence |
|---|---|---|---|
Root .gitignore | .gitignore |
.claude/settings.local.json* (wildcard, live OAuth secret), 05 Briefings/* except README and the redacted sample, local worktrees. |
"Only the redacted sample is tracked." |
Per-system .gitignore with example carve-out | 08 Option Studies/, 09 Review Packs/, 10 Spec Drafts/ |
inputs/* and the output folder, re-including only the synthetic example slug as the visible trace. |
Each file's header comment names the Stop hook as the second layer. |
| Tax data, no synthetic example | 06 Tax Agent/.gitignore |
config.yaml, loan.yaml, payslips, every YYYY-MM/ and YYYY-Qn/ pack. Real GmbH figures are not faked; only *.example.yaml templates are tracked. |
CLAUDE.md, Privacy guards. |
| Script secrets and logs | scripts/issue-bridge, issue-router, onto-sync, paper-upload |
.env (Supabase service role, TypeSafe key, nai-onto token), routing-log.jsonl and .last-run.json (issue titles), the notification cursor, any stray key JSON. |
The four folders' .gitignore files. |
| Stop hook DENY pattern | .claude/settings.local.json, per machine |
Holds back the same confidential paths from staging on every auto-commit, with PCRE negative lookaheads carving out the examples; requires LC_ALL=C.UTF-8 or grep -P silently disables the guard. A canary test with git add -f is prescribed after rebuilding it. |
docs/machine-setup.md Step 2: "Without it, .gitignore is your only guard". |
| Deploy allowlist | .vercelignore (repo root, the only one) |
Excludes every top-level entry, re-includes exact files and folders under docs/. Introduced after a root-directory build published the whole repo. |
Header: "Misconfigured root builds once published the whole repo (2026-07-19)". |
| Staged pages inert by construction | 12 Documentation/runs/*/proposed/ |
Outside docs/, so never served however often the Stop hook pushes it; that inertness is what the publish gate is built on. |
12 Documentation/README.md. |
| Publish guard, three lookups | /nai-document Step 6 |
Serve path re-included in .vercelignore; new page reachable from a collecting page; every relative href and src resolves against the final path. |
"Check one is the one that would have caught the features.html 404 in 1d912a49." |
| Documented exceptions | 07 Newsletter/, 12 Documentation/, 06 Tax Agent/ |
Two folders have no .gitignore because every input and output is public already; the tax folder has no tracked example because real figures are not worth faking. Each exception is written down with its reason. |
CLAUDE.md: "Three folders deliberately don't follow that pattern". |
| Census leaks nothing | scripts/cohort-census/census.py |
Counts and names only; "never include file contents, prompt text, or any data an agent has touched". | nai-cohort-census.md §1. |
Where a boundary can be enforced in plain Node, it is. These refusals do not depend on the model reading its prompt.
| Measure | Script | What the code refuses | Evidence |
|---|---|---|---|
| Folder allowlist in the Drive helper | scripts/paper-upload/drive.mjs |
Lists or writes only direct children of work/; refuses work/ itself, library-wiki/, wiki/ and any nested folder; only adds new files, never overwrites, moves or deletes. |
paper-ingester.md: "The helper enforces the boundary in code as well". |
| Magic-byte check on downloads | paper-ingester Bash step |
curl -f plus a %PDF test, so a paywall or error page is never filed as if it were the paper. |
docs/verification-patterns.md §4. |
| Single-issue scope, insert only | scripts/issue-bridge/fetch-issue.mjs, post-comment.mjs |
Touch only the one issue id passed; the only write is one insert into issue_comments; never update or delete, never change content or status. |
README "Safety". |
| Read-only activity scan | scripts/issue-bridge/check-activity.mjs |
Select across all issues, writes only its own cursor file; a missing cursor defaults to now, so a first run never dumps history. Skips the owner's own activity. | README "Activity check". |
| Read-only router | scripts/issue-router/route.mjs |
gh issue list is the only subcommand; the script never comments, labels, closes or edits. Client issues from nai-analysis are deliberately not a source. Tests run fully offline. |
README "Safety"; design decision 3, 2026-09-25. |
| One-line status protocol | All bridge, router, onto-sync and Drive scripts | Print exactly one line, always exit 0: OK, MISSING, UNCONFIGURED or ERROR: …. Control flow reads the line, never the exit code, so a crash cannot be mistaken for success. |
scripts/issue-bridge/README.md; scripts/onto-sync/README.md. |
| New subagent needs a human role entry | scripts/onto-sync/sync.mjs, overrides.json |
The sync refuses an agent without a role in the overrides: the judgement-shaped part of the inventory stays a human call. --check exits 1 on any drift between agent files and the ontology. |
README: "that is the human's call, on purpose." |
| Clipboard formatter, no API | scripts/linkedin-copy/copy-post.ts |
Formats one post as plain text for pasting; the LinkedIn API is never called. | 14 LinkedIn/README.md. |
The ten systems and the three commands that are not systems, read across the layers.
| Command | Reaches outside the repo | Remote writes | Gates | Verification | Privacy guard | Stays human |
|---|---|---|---|---|---|---|
| /nai-chief-of-staff | Gmail read, Calendar read, web | Gmail drafts only | Drafts await review | None, by design | 05 Briefings gitignore + Stop hook | Sending mail, changing events |
| /nai-tax-theo | Qonto, 9 read tools | None | Entity from config; direction read, never assumed | Computed tie-out | 06 Tax Agent gitignore + Stop hook; Qonto deny list | Filing via ELSTER, paying |
| /nai-payroll-theodora | None (dropped payslip only) | None | Missing payslip flagged, never guessed | None, by design | 06 Tax Agent gitignore + Stop hook | Filing, paying |
| /nai-newsletter | Web, via tech-radar | None | STOP on existing folder, no voice profile, quiet month | None, by design | None needed (public output) | Pasting and sending |
| /nai-option-study | Web, verifier only | None | STOP on missing input / overwrite; 3-round bound; wave order | Bounded loop | 08 gitignore + Stop hook | The trade-off decision |
| /nai-review | None, no web anywhere | None | STOP on missing subject / overwrite; wave order | Single adversarial pass | 09 gitignore + Stop hook | Delivering the review |
| /nai-issue-to-agent | nai-analysis Supabase, one issue | One comment, after explicit confirmation | STOP on MISSING / ERROR / blocked; confirm before posting | Inherits the dispatched system's | .env gitignored + Stop hook | Confirming the undeletable post |
| /nai-spec-drafter | None, no web anywhere | None | STOP on missing instances / overwrite; create vs update never guessed | Single adversarial pass | 10 gitignore + Stop hook | Adopting the spec |
| /nai-paper-ingest | GitHub issue read, landing pages, Drive API | One PDF added, one issue comment | STOP on no link; never close, label or edit | None; tool-layer PDF check | Key outside repo; wiki denied at shell and in code | Wiki ingestion, topic correction |
| /nai-document | None, no web anywhere | None | STOP on unknown target; stage, promote only create + CONFIRMED + guard ✓ | Adversarial pass + computed guard | None needed; proposed/ inert | Promoting an updated page |
| /nai-cohort-census | None | None | Names and counts only | n/a | n/a | Submitting |
| /nai-issue-check | nai-analysis Supabase, read | One push notification | Quiet result sends nothing; never quotes bodies | n/a | Cursor file gitignored | Acting on the activity |
| /nai-issue-route | GitHub read, TypeSafe | None (dispatches paper-ingest) | auto ≥ 0.85, review ≥ 0.60, else human | n/a | Log and key gitignored + Stop hook | Review-tier and human-tier issues |
Twenty-five subagents. Class and tools are copied from each file's frontmatter and Boundary; the last column is the one rule specific to that agent beyond its class sentence.
| Agent | Class | tools: | Specific never |
|---|---|---|---|
| calendar-briefing | A | list_calendars, get_events, WebSearch, WebFetch | Never create, modify, move or delete events; writes no files. |
| email-triage | C | search_gmail_messages, get_gmail_message_content, draft_gmail_message | Never send, reply-send, delete, trash or archive; refuses if asked to send. |
| tech-radar | B | WebSearch, WebFetch, Read, Write | Scan mode writes nothing; public information only. |
| company-research | B | WebSearch, WebFetch, Read, Write | No scraping behind logins, no pretexting. |
| cockpit-writer | B | Read, Write, Glob | A view, never a calculator; never invents or drops a decision item; never edits the markdown it reads. |
| qonto-collector | B | 9 Qonto read tools, Read, Write, Bash | Never moves money; Bash for one purpose, curl receipts. |
| loan-interest-vga | B | Read, Write, list_transactions | Flags; never decides fremdüblich, rate or vGA; never invents contract terms. |
| vat-worksheet | B | Read, Write | Never fabricates a figure; ambiguous lines go to Unclassified, not a guessed Kennziffer. |
| payroll-lohnsteuer | B | Read, Write, Glob | Never invents a figure; missing payslip is flagged and the run stops. |
| newsletter-writer | B | Read, Write | Reads exactly two files; never sends, publishes or pushes. |
| voice-profiler | B | WebFetch, Read, Write, Glob | Writes the profile only if absent; STOPs if it exists. |
| ea-context-reviewer | B | Read, Write, Glob | No web tools; gaps stated as gaps, never filled from memory. |
| option-recommender | B | Read, Write | No web by design; never claims an option is proven; never modifies a previous round. |
| option-verifier | B | WebSearch, WebFetch, Read, Write | Never rewrites, adds or drops an option; never fabricates a source. |
| review-scoper | B | Read, Write, Glob | No web tools; gaps stated, never filled from memory. |
| finding-drafter | B | Read, Write, Glob | No verbatim quote, no finding; concerns become open questions. |
| finding-checker | B | Read, Write, Grep | Verdicts only; checks the citation, not the architecture; default UNSUPPORTED. |
| spec-context-scoper | B | Read, Write, Glob | No web tools; gaps stated, never filled from memory. |
| spec-rule-drafter | B | Read, Write, Glob | No verbatim quote, no rule; patterns become open questions. |
| spec-rule-checker | B | Read, Write, Grep | Verdicts only; checks the citation, not the grammar; default UNSUPPORTED. |
| doc-scoper | B | Read, Write, Glob, Grep | Never writes docs/; never edits an agent or command; never authors prose. |
| doc-surveyor | B | Read, Write, Glob | Stages only; no web; never writes prose it cannot cite. |
| doc-renderer | B | Read, Write | Never authors, edits, shortens or reorders the author's prose; never writes docs/. |
| doc-checker | B | Read, Write, Grep | Verdict is terminal; never sends a claim back; never writes docs/. |
| paper-ingester | D | Bash, Read, WebFetch | Adds new files to work/<Topic>/ only; Bash for four purposes; never touches wiki/. |
The repo records why most of these exist. The reasons are measures too: they are what keeps the next edit from undoing them.
| Date | What happened | Measure it produced | Recorded in |
|---|---|---|---|
| 2026-07-19 | A git-connected Vercel build from the repo root published every tracked file. | Repo-root .vercelignore as an exclude-all, re-include-exact allowlist. | docs/deploying-the-architecture-site.md |
| 2026-07-26 | A duplicate project and a root vercel.json shadowed docs/vercel.json; both deployments 404'd. | One project, one .vercelignore; the root vercel.json and docs/.vercelignore deleted. | Same document |
| commit 1d912a49 | features.html went live as a 404 because it was not re-included. | Publish guard check 1, serve path, in /nai-document. | docs/verification-patterns.md |
| before agent-conventions | Read, Write, Glob, Grep had been pasted as a default suffix onto 6 of 10 agents; two grants contradicted the agent's own boundary. | "Grant exactly what the body uses"; the pre-commit grant audit. | docs/agent-conventions.md |
| before agent-conventions | Five phrasings of read-only, four incompatible missing-data contracts, three house structures. | Four canonical class sentences, one contract, one structure. | Same document |
| before agent-conventions | vat-worksheet shipped without a Missing input section. | "Every agent has a ## Missing input section. No exceptions." | Same document |
| 2026-08-08 | Tech-radar brief on LifeOS: its installer mutates settings.json and would collide with the Stop-hook privacy guard. | Not installed. "Read three files, steal two ideas, install nothing." | 03 Research/tech-radar/lifeos-agent-harness-layer-2026-08-08.md |
| 2026-09-23 | paper-ingester needed to add files to a remote system, which no existing class allowed. | Access class D, read remote and file remote, add-only. | Commit "Add access class D (read remote, file remote) for paper-ingester" |
| 2026-09-25 | Issue router design: client issues are confidential; titles are sent to a third-party judgment API. | Only this repo's own issues are a source; nai-analysis deliberately excluded. | scripts/issue-router/README.md, decision 3 |
Stated in the repo's own words, not found by this inventory. They are where the next measure would go.
06 Tax Agent/README.md)gh CLI from Bash: no server scope, no mcp__ prefix, no tools: line, and the one gh allow entry matches neither call made. (docs/architecture/concept-tools.html)settings.json carries no mcp__google-workspace__ rule either way; the Gmail send tool is kept out only by L3. Chat write scopes and the whole Contacts service are exposed at the server and granted to nobody. (same page; docs/superpowers/mcp-google-setup.md).gitignore as its only guard until Step 2 of docs/machine-setup.md is done. The hook also auto-pushes to origin main after every turn, which the same document flags as a conflict risk on two machines.03 Research/tech-radar/lifeos-agent-harness-layer-2026-08-08.md)08/09/10 gitignore pattern. (13 Decision Pack/README.md)scripts/issue-router/README.md)OWNER_USER_ID. New-issue detection is skipped and comment detection falls back to a per-issue owner comparison that can wrongly skip a non-owner. The script warns rather than errors. (scripts/issue-bridge/README.md)