124
bug & gap findings
2
live criticals
29
issue drafts, ready to file
9
read-only sub-agents
Critical 2 High 28 Medium 38 Low 32 Verified-good 6

## Fix First

the load-bearing ones
F74 Critical · live now · verified Memory rollover is keeping 14 entries, not 15 — on every branch, right now

An off-by-one trims memory at the keep target instead of above it: the trigger fires at `len >= 15` and the extractor forces `max(excess, 1)`, so at exactly 15 it removes one it should keep. The proof is on disk — memory's own `local.json` holds exactly 14 sessions and 14 learnings, and the rollover log shows `(15/15 sessions)` firing 53 times. Every branch silently loses one extra memory per rollover. Standing hold on rollover fixes respected — documented, not filed.

F5b Critical · root cause corrected Medic error-notification has been switched off for 63 days

The medic log tells the whole story in three lines: at 2026-05-10 20:30:21 — the same minute a 25-second burst of test-fixture errors flooded in — medic was switched off ("Medic DISABLED — error dispatch suppressed") and never switched back on. Since then `config.medic_enabled = false` makes the dispatch path drop every detected error before anything else runs; 63 days later it's still suppressing live errors (1,667 "Medic OFF" log lines, zero "Circuit breaker OPEN"). A brief annoyance muted the entire error-notification system for two months. Honest note: my first pass blamed a stuck circuit breaker; a later sweep refuted it and I re-verified on disk. That breaker is a real but separate latent bug (F5c) that must be fixed before medic is switched back on, or it re-floods.

F1 High PR#696 red CI is one inherently racy test

Every red job fails on the same assertion: `test_mtime_cache_avoids_reread` passes only when two file writes share an mtime tick — a filesystem coin flip that lands green locally and red on GitHub runners. Two-line deterministic fix (`os.utime` to pin mtime equality). @prax owns.

F14–F17 High aipass doctor cries wolf on a healthy install

Our first-touch trust tool reports 7 errors on a clean repo — all false: it scans `.backup/snapshots/` as if they were live agents, compares registry names case-sensitively against 5 legitimately-uppercase entries, prints an unsubstituted `{{BRANCHNAME}}`, and shows ✓ marks whose text is a warning. A newcomer reads "my install is broken."

F30 High spawn repair advises a command that would delete the live @aipass agent

`spawn repair` flags `src/aipass/aipass/` as duplicate "pollution" and prints the remediation `--clean-pollution` (archive + remove). That directory is the living concierge agent. Following the tool's own advice archives a user-facing citizen. Needs a passport-awareness guard.

F52 High · verified in code Commons artifact gifting is broken by name-casing

Gift / trade / mint write an `UPPERCASE` owner (`trade_ops.py:58`) while every ownership check compares lowercase. Gift an artifact to `@seed` and it becomes invisible in their inventory and permanently un-tradeable (`"SEED" != "seed"`). The self-gift guard never trips. The registry-casing disease, database edition.

F6 · F43 High Tests write fixtures into production logs, poisoning the error registry

pytest fixtures ("disk full", "boom", `/tmp/pytest-of-patrick/…`) land in real branch `logs/`; the 24/7 log-watcher ingests them into the error registry (664+ occurrences of one fixture line alone). One cut fixes the class: route logging to tmp when `PYTEST_CURRENT_TEST` is set.

F22 · F23 High The human-facing concierge has the worst help in the fleet

`aipass --help` is a bare module dump — no "what is this," no first steps, internal modules exposed. `aipass help "how do I create a new branch"` answers with git-PR commands and never mentions @spawn. The one tool built for humans is the least helpful.

F46 High 14 feedback messages unread since April — including 4 external bug reports

Precise bug reports from an external project sat `NEW` for three months; we later rediscovered every one of them the hard way. The owner-to-owner channel works technically and fails operationally — no inbox check in startup, no aging alarm.

F53 · F54 High Commons: systemic DB connection leak + unlocked log that self-wipes

~14 handler files close their sqlite connection only on the success path (no `finally:`), 40+ sites — hottest runs on every post. The shared op-log does unlocked read-modify-write; a torn write is "healed" by silently resetting the log to `[]`. The correct pattern already exists in sibling files.

F59 High · verified · integrity The owner model is advisory: git-write trusts an unprotected passport name

`verify_git_access` grants owner-tier git if the `branch_name` in the caller's own `passport.json` reads "devpulse" — no registry cross-check, no signature, and no gate protects that file. The DPLAN-0231 owner-capability model was built to key on the sealed `registry_id`; the actual check reads the mutable name instead. Scope honestly: agents are same-user and cooperative, so this is "the model isn't enforced," not a remote exploit — but it undoes a guarantee you deliberately built.

F84 · F85 High · verified · destructive Two commands can destroy a branch or another branch's plan history

`spawn delete_branch` guards only three hardcoded names — no check for a live process or `owner:true` — so it will archive-and-remove any other running branch on request. And the flow central aggregator, when it reads a branch's registry during a transient unreadable moment, "heals" it by writing an empty registry back — one branch's routine aggregation can wipe another's entire plan history. Both traced in code.

F114 High · verified · adoption-blocking The contribution surface everyone would reach for first has no safety boundary

Running a skill executes its `handler.py` in-process with full privileges — no sandbox, no confirmation, no review (verified: the only relevant line is a bare `exec_module`). A built-in skill is also `shell=True`-injectable, and a skill dropped into `~/.aipass/skills/` can silently impersonate a trusted built-in by name. Skills are the natural first thing an outside contributor would build — so this is the one place the adoption plan and the security posture collide. A community-skills ecosystem needs a trust model (sandbox, review, or a first-run consent gate) before it can open.

## The Pattern Underneath

### The deepest root: the gauges are decorative, so nothing looks broken

Running the live system surfaced the mechanism behind everything else. The data is sound — the vector store passes an integrity check with 5,012 embeddings, the decision DB is clean, 11,000 tests collect without error, six suites run green. But the system's self-report is wrong almost everywhere it's checked: the dashboard claims 1,274 vectors when there are 5,012; dashboards labeled "live" are up to ten days stale; doctor invents seven errors on a healthy repo; the standards audit reports "100%" while silently ignoring any file it can't parse. When every gauge reads "fine" regardless of reality, a thing can break quietly and stay broken for months — which is exactly what medic, rollover, and the stuck breaker did. The highest-leverage fix isn't any single bug; it's making the instruments measured — real counts, real freshness, invariants that fail loud — so the system can finally see its own state.

### We build the write side and never the read side

The same shape recurs across F5 (errors detected, never triaged), F26 (presence records written, never cleaned), F40/F46 (mail delivered, never read), F49 (a health check pointed at a retired schema), F5b (a breaker that opens but can't close), F81 (a scheduler running with zero jobs). Detection, ingestion, and enforcement ship; the closing ritual — the thing that reads, ages, resolves, or recovers — is the half that's consistently missing. It's a culture fix as much as a code fix: every new pipeline needs its janitor shipped with it.

### One fix retires a dozen bugs

Across six branches the single most common defect is the same: shared state — registries, passports, inboxes, scheduler runstate, the logger's own data — written with a raw `open("w") + json.dump`, no temp-and-rename, no lock. A crash mid-write truncates the file; the paired loader "fails open" to empty and writes that empty back, turning a transient read hiccup into permanent data loss. The correct atomic-write helper already exists in every branch — it's just applied inconsistently. One shared primitive plus a seedgo checker that forbids the raw pattern closes roughly a dozen findings at once, including the two that can wipe another branch's plan registry or truncate a passport.

### The deepest gap: blindness to silent degradation

I dated the biggest findings by git blame: the rollover bug has been trimming memory since April 22, the seedgo audit has silently dropped crashing checkers since March 23 (its inception), medic has been off since May 10. They survived for months — not because they're hard to find, but because none of them produces a symptom. Rollover archives the entry instead of deleting it, so nothing looks lost. Medic being off just means silence. A dropped checker just makes a number rounder. The whole system is instrumented for visible failure — logs, errors, red CI — and has almost no way to notice when something quietly starts doing the wrong thing. The durable fix isn't per-bug; it's a handful of invariants that assert the invisible — rollover leaves exactly N, medic is on, every registered checker actually ran — and shout when they don't.

### The gates fail open, quietly

The security gates are well-built where they run — but they default to allow at four independent layers: a missing config file, a handler that crashes, malformed input, and any parser exception, each logged only as a line of text. And the standards audit does the same — a file that makes a checker throw is dropped from the score rather than failed, so "100%" quietly means "100% of the files we could parse." None of this is a remote exploit — these are cooperative same-user agents — but a guarantee that fails silently isn't a guarantee. The cheap half of the fix is to make every fail-open loud: surface it to the error registry, not just a log.

## The Contributor Funnel

DPLAN-0240
~600
unique humans / month
237
stars
1
external human, ever
0
retained / contributing

Attraction works; conversion is broken. GitHub topics are empty, the homepage field is blank, Discussions are dead, and the Commons — a genuinely rich agent-society sandbox with craftable artifacts, time capsules, and a hidden exploration game — has exactly one post.

### The April Precedent

This exact play was already run once. In April an external agent created three `good first issue` tasks and added the README "Need help?" line. Three weeks later our own issue-zero sweep batch-closed all three — same minute, zero comments — and the underlying work was never done (the seedgo `readme_currency` proof still fails today). We didn't just lose a contributor's momentum; our tidiness reflex deleted the on-ramp.

- Tier 0 Set GitHub topics, fill the homepage field, pin a "Start here" discussion, add a code of conduct — ~30 minutes, near-zero risk.
- Tier 1 An external-response reflex (<24h reply, via our own dispatch plumbing) and a protected shelf of `good first issue` tasks we deliberately don't self-clear.
- Tier 2 Fix the first-ten-minutes tools: doctor's false errors, the concierge's help, the two broken examples in `drone --help`.
- Tier 3 A docs front-door, and revive the Commons with automatic agent rituals — then expose a read-only public feed. "Watch AI agents run their own society" is a headline no competitor can match.

## Deliverables

✓docs/discovery/S304_discovery_mission.md — 58 findings + 6 adoption notes + 17 ready-to-file issue drafts, evidence inline
✓DPLAN-0240 — contributor funnel, four tiers, the April Precedent
✓todo 66 — CI red root-caused to F1; local.json updated
✓compass #94 / #95 — circuit-breaker lesson + April-Precedent decision recorded
✓5 read-only sub-agents — newcomer, logs, code sweeps (commons/backup/ai_mail/daemon), security gates