Session S304 · Autonomous Discovery Scan · Search-only
A full unsupervised walk of AIPass — all 18 agents' code, the logs, error registries, security gates, live processes, ~4,000 tests run, and the newcomer path. Zero system files changed. Every fix here is a proposal, evidence attached.
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.
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.
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.
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."
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.
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.
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.
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.
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.
~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.
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
good first issue tasks we deliberately don't self-clear.drone --help.