Releases: AIOSAI/AIPass
Release list
v2.7.3
[2026-07-18]
v2.7.3 — the onboarding chain: from git clone to a conversation with an
agent that remembers you. Install's three dead-ends are gone — the default
init path, headless runs, and aipass new all now end where they should:
install chains through the guided init and opens a live conversation with
the AIPass concierge, first prompt authored with the install report in its
context. The concierge's Welcome Mode (research-backed opener, one name-ask,
deferred setup triage, hooks-first health check via a real @hooks dispatch,
every suggestion with its exact command) was proven in a live multi-turn
door-test — including the second-session payoff: relaunch, and it picks up
mid-task where you left off. Plus aipass new and the front-door overhaul below.
Added (onboarding chain — TDPLAN-0014)
- Install→chat handoff: after init returns, install
launch_inlines the
concierge with an authored first prompt (fresh-install recognition + binary
report). TTY-only; headless returns cleanly. - Welcome Mode in the concierge branch prompt: capability opener with 3–5
concrete starters, single graceful name-ask, ~turn-5 setup push ("every
machine is different"), hooks-first verification incl. trust-registry
enrollment, setup plan seeded from the cross-OS checklist, Windows→WSL
recommendation, prax-monitor + hooksound tips, exact copy-paste command with
every suggestion. - Feedback pulse (@hooks): one ignorable line every ~10 turns with the repo
feedback link —aipass feedback on/off(alias fordrone @hooks feedback)
turns it off. Registered disabled for the AIPass host itself. 25 tests. - Dead-end kills: empty-template init now runs handoff + report stages
(default path ends in the conversation); non-interactive installs complete
with defaults and exit 0 (headless stage 9 prints the launch command instead
of spawning);aipass newauto-launches into the new project's manager agent
on a TTY with a printed fallback and Ctrl-C escape line. - Unified handoff prompt: one
INIT_PROMPTconstant (was two drifting
strings in init_flow vs handoff).
Fixed (onboarding chain)
- Non-TTY
aipass init runcrashed with EOFError at the first prompt (caught
in a live door-test after unit suites ran green — the prompt layer now
auto-detects non-TTY and takes defaults). aipass newoutside an AIPass environment now exits 1 instead of 0.- Empty-template handoff messaging no longer claims an agent exists
("Your project is ready", resolved absolute path instead ofcd .). - Stage numbering shows a skip notice instead of silently jumping 5→8.
v2.7.2
[2026-07-17]
v2.7.2 — everything merged since v2.7.1, headlined by the compass decision
engine v2: curation with supersedes links + write-time conflict advisories
(Track 1), and ambient recall — rated past decisions now surface verbatim into
live sessions on matching prompts, governed by session caps and spacing
(Track 2). Also in this release: the plan close pipeline completes itself
(auto-vectorization + crash-safe registry writes), drone's 3-layer subprocess
timeout policy with a collision-free --drone-timeout flag, plan-number memory
search that pins the exact plan, a fleet-wide seedgo 100% restoration, and
SSH-signed commits now verifying on GitHub. Details in the sections below
(2026-07-16 carries the full stories).
Changed
-
Release cadence ruling: every dev→main merge ships a PATCH bump + tag by
default. PyPI tracks main, always current; version numbers carry no
significance during beta — the big jump is reserved for beta exit. -
Merge playbook SOP refined from live run PPLAN-0010. The raw
git fetch origin main:mainstep (now blocked by the git gate) is replaced
withdrone @git syncin both places it appeared, and the template opens
with the exact create command (drone @flow create . "Merge summary" merge pplan— template name before type), closing the trap where the wrong arg
order silently stamps the default template.
v2.7.1
[2026-07-15]
Added
- Supply-chain hardening pass (DPLAN-0243): commit signing + hash-pinned CI
tooling + release provenance. All commits are now SSH-signed via a
dedicated repo-scoped signing key (first signed commit 9048666, verified
Good "git" signature). Every standalone pip tool install across the four
CI workflows now installs--require-hashesfrom lock files in
.github/requirements/(pip/ruff/build/pytest/pip-audit), generated with
full multi-platform hash coverage — including the Windowscoloramamarker
dependency that naive Linux-side pinning silently drops.publish.yml
gained a SHA-pinned build-provenance attestation step (activates on the
next release), and Dependabot now watches the new lock directory as a
groupedpipecosystem. Editable-e .installs untouched. Full 31-check
CI matrix green on the change. Driven by the OpenSSF Scorecard gaps
surfaced via hvtracker.net (HVTrust 82.0, #1 in Multi-Agent Systems);
detector-gap correction filed upstream as YugantM/hvtracker#186 (Claude
Code-native projects misread as "no Anthropic dependency").
Fixed
-
CI green pass on the runaway-log PR — every red was ours, every fix
verified. Morning-after triage of PR#696's failing checks: the test
matrices' only failure was the known parked flake, but lint and the seedgo
audit were genuinely red from the previous night's new code. Oneruff formaton trigger's runaway-handler tests fixed lint. The audit findings
went back to their owners by dispatch: @hooks built the branch's missing
json_handler and wired it intopersistent_alert/alert_dismiss, added the
introspection no-args gate, and flattened_menu_live()'s nesting
(1071 tests green); @prax refactoredrate_tracker.pyto dependency
injection — the module layer now injectslogs_dirandtrigger.firevia
configure(), so the handler carries no cross-handler or handler→module
imports (1028 tests green). Both branches re-audit at 100% across all 41
standards, independently verified. Detection re-proven live post-refactor
with a fresh planted log storm. Also trimmed the tier-1 navmap prompt
(9.3k → 7.9k chars, under its ~8k injection cap) with the comms doctrine
intact. -
Windows flake pinned:
test_is_pid_alive_deadescaped the ca09629
sweep. That commit's rule — tests mockingos.killmust pin
sys.platform="linux"because Windows takes the ctypes OpenProcess path and
never reaches the mock — was applied to every pid-liveness test except this
one. It only failed when PID 1234 happened to be alive on the runner
(environment lottery, first hit today). Pinned like its siblings. The
remaining Windows session_boot reds and the relay mtime-cache flake predate
this PR and stay parked. -
The parked reds, unparked — Patrick's ruling: red CI is never parked.
"If CI is red, it's because you or I left it red." Both remaining reds fixed
by their owners the same hour. @prax root-caused the relay mtime-cache flake:
the test only passed when two writes landed in the same mtime-granularity
window (true locally, false on CI runners) — fixed by pinning mtime with
os.utimeso the cache contract is tested deterministically, proven 50/50 +
20/20 loops. @hooks root-caused the four Windows session_boot reds: the boot
path's_tmux_session_exists()ran a realsubprocess.run(["tmux", ...])
that Windows runners can't satisfy (WinError 2) — mocked in all four tests
per the ca09629 convention, leavingexecvp(already mocked) as the only
terminal call. Ruling recorded in compass; the "forget CI" era is over. -
Burst-evasion closed: bursty runaways can no longer slip past the rate
tracker. Found live during the morning's chain verification: any single
below-threshold 10-second scan window zero-reset the sustain counter, so a
bursty writer (20 short lines every 6 seconds — 200 lines/min average, the
exact retry-loop-with-sleep shape of the TG relay incident) ran 4 minutes
undetected. @prax's fix (rate_tracker v1.2.0): severity now evaluates
max(instant_rate, 60s window average)— continuous writers behave exactly
as before (instant rate dominates), bursts sustain through their gap
windows, and subsidence still clears as zeros fill the window. Four new
burst tests; live-proven with the previously-evading storm pattern:
RUNAWAY WARNING: prax_burst_storm_test.log — 191 lines/min sustained 120s
in the tracker log, fired from the restarted running service. Detection
evidence now spans all three storm shapes: continuous fast (332/min),
continuous moderate (257/min), bursty (191/min).
Added
- TG streaming v2 polish (DPLAN-0229): the last two finalize paths now
honor the streaming flag. v1 shipped with a deliberate gap — when logs
were active mid-turn or the final response exceeded 4096 chars, the Stop
hook fell back to "Done." + a fresh message, orphaning the streamed bubble.
@hooks threadedstreamingthrough_deliver_chunks: logs-active now
reconcile-edits the streamed message with the final formatted response, and
multi-chunk edits chunk 1 in place then sends [2/N]+ as continuations.
Batch mode is verified zero-change (regression tests for both paths), plus
an edit-fail fallback. 6 new tests, 1077 green. Live streamed-turn proof
pending Patrick's next streaming session — honestly flagged, not faked.
v2.7.0
[2026-07-11]
Added
- Owner seating made permanent + self-healing for every project (DPLAN-0239,
fixes #693). The owner-capability guard was correct but the DATA was never
seeded: every project created before 2026-07-10 had its owner only in the
self-editable passport, never in the sealed registry (8/8 external projects
unseated; AIPass's own registry was missingmetadata.idwith 13 entries
sharing one stale id). Identity model settled: registrymetadata.id=
project credential (passports conform); branch-entryregistry_id=
set-once PER-CITIZEN UUID minted at entry creation; entryowner:true=
the authority gate (first agent), chosen by ONE shared heuristic
(pick_owner_branch: manager → passport owner → first-created).
New:drone @spawn sync-registry --check [--json](read-only, 7 health
flags, pinned JSON schema) and--fix [--dry-run](idempotent reconcile:
seat owner, majority-consensus restore ofmetadata.id, mint citizen UIDs,
align passports; dry-run fully read-only; never moves a seated owner).
aipass doctorrenders owner health per flag;doctor --fix,install,
andinit updatedelegate repair to spawn — existing/external projects
self-heal on next update (the missing DPLAN-0231 PART-4 trigger). The adopt
path now seats owners;placeholders.pyresolves the registry from the
target dir (was CWD) and fails loud. @hooksauto_watchdognow injects the
real Monitor-tool watchdog command with the actual @target (was a dead
one-liner +run_in_background, which cannot wake a session). Deployed
live: AIPass + 6 external projects reconciled and verified clean — VERA is
now seated owner of Vera Studio (is_owner('@vera') = True, was refused).
Owners built (spawn 343 / aipass 673 / hooks 961 tests green); devpulse
verified every diff, live-ran every stage, full-repo sweep 9364 passed
(1 pre-existing skills litter fail → #694).
Changed
- Fleet seedgo compliance sweep — every branch to 100% (issues #686, #661).
Overnight campaign bringing all branches to 100% on the seedgo standard pack.
#686 (Subcommand_Help, per the #685 contract): entry points intercept
<cmd> --helpbefore dispatch, so--helpshows help instead of executing.
#661 (Output_Routing): status/error console output routed through the shared
@clisuccess()/error()/warning()helpers instead of rawconsole.print
markup. Owners self-audited and self-fixed their own branches; devpulse verified
each diff + re-ran each audit and committed per wave. Landed so far: spawn,
drone, flow, daemon, prax, ai_mail, backup, seedgo, memory, trigger, api, cli,
aipass, commons — all 14 offenders now at 100%. Fleet: 17/17 branches at
100% seedgo compliance (hooks, skills, devpulse were already compliant).
Owners self-audited and self-fixed; devpulse verified every diff, re-ran each
branch's full test suite, and committed per wave. A full 17-branch test run
(~10,349 tests) surfaced one pre-existing flaky test in drone
(test_pr_no_branch_dir/test_pr_no_argslacked cwd isolation, so a real
checkout's findable passport made the auth path pass unexpectedly) — given
monkeypatch.chdir(tmp_path)isolation to match its sibling test, so the full
suite is now deterministically green.
Fixed
-
Watchdog Monitor wake no longer double-fires (#693 follow-on, reported by
VERA via the feedback channel). Thewatchdog agentreminder banner
("invoke via Monitor tool, not run_in_background") printed to STDOUT at arm
time, and the harness Monitor tool treats every stdout line as a wake event —
so every armed watchdog fired a spurious wake the instant it armed, then the
real wake at completion. Rerouted to stderr (err_console); stdout now
carries completion/stall events only, matching the contract the agent handler
already followed. Verified live: exactly one wake, on real exit. The devpulse
README watchdog/feedback sections were also rewritten to document the owner
gate, the 3-step Monitor wake mechanic, why no passive wake can exist, and
the 600 s default timeout. -
Watchdog agent tests thread-race flakes made deterministic (devpulse).
Four tests patched the GLOBALtime.sleepwith stateful/side-effecting
fakes; prax's logger spawns daemon threads on first log, which executed the
fakes concurrently with the test (advancing a fake clock, unlinking the
fixture lock early, or re-truncatinglast_bounce.jsonmid-read in
_classify_exit→exit_code=None). All fakes are now thread-scoped via a
caller-frame guard: only sleeps from the agent module trigger the test's
side effect; foreign threads get a real 1 ms sleep. -
seedgo-audit back to 100 % after the S300 commits (PR659). Two 99 %
regressions from that day's own work:aipassdoctor.py_fix_owner_seating
had two silent catches (now log via prax like the sibling check function),
and the devpulse README claimed 407 tests where the readme checker counts
test functions (corrected to 309). -
Two more non-hermetic ai_mail tests made deterministic (PR659). With the full
suite now running on varied CI runners,test_get_pid_cwd_darwin_failureand
test_is_zombie_linux_no_procintermittently failed: they called the reallsof
(viasubprocess.run) and realopen("/proc/…")for a fixed PID (999 / 99999),
so on a runner where that PID happened to exist they returned a non-Noneresult
instead of the expected failure. Mockedsubprocess.runandbuiltins.openso the
tests assert the failure contract without touching real process//procstate.
Test-only; deterministic across repeated runs. -
Windows CI cross-platform fixes —
windows-setupgreen (PR659). Fixing the
telegram collection errors unmasked 14 pre-existing Windows-only failures across
six branches. Two root causes. (1) pid-liveness tests (ai_mail, flow, hooks,
skills) mockedos.kill, but the production_is_pid_alivealready branches to a
ctypesOpenProcesspath on Windows and never reachesos.kill, so the mocks had
no effect and the real path ran instead — pinnedsys.platformtolinuxin those
tests (or patched_is_pid_alivedirectly) so they exercise the POSIX contract
deterministically on every platform. (2) POSIX path assumptions — prax's jsonl
test hardcoded/some/path(backslashes understr(Path)on Windows) now asserts
againststr(test_path); hooks' rollover test comparesrepr()(matches%r
logging); ai_mail's darwin lsof-parser test uses a fixed POSIX path; and seedgo's
is_bypassed()now normalizes the rule file viaPath(rule_file).as_posix()before
matching (the one production fix — Windows backslash rule paths never matched the
forward-slash file path). 10 files (9 test, 1 code); owners self-fixed, devpulse
verified every diff + Linux no-regression (525 changed-test assertions green). -
Flaky
test_deletes_old_system_logmade deterministic (@prax log-sweep tests).
The sweep integration test reachedlog_watchdog._get_system_logs_dirthrough a
_get_sweep()wrapper and patched it by string path; a sibling test
(test_logging_handlers.py)sys.modules.pops and reimportslog_watchdog,
creating a second module object — so the string patch could target a different
object than the function's__globals__, the sweep scanned the real (empty)
system_logs/, removed 0 files, andassert files_removed == 1failed
intermittently (the same commit passed in one CI run and failed in another).
Switched to a directimport log_watchdog as lw+patch.object(lw, …)(shared
module__dict__) and patchedjson_handlerto block real file I/O. Test-only
(1 file); prax suite 978 green, two full-repo runs 11,019 passed each, sweep tests
deterministic across repeated runs. -
Telegram skill tests made CI-safe — full-repo collection + hermeticity (issue #691).
The 16 test files underskills/lib/telegram/tests/imported handlers via bare
from apps.handlers…, which collided with other branches'appspackages during
full-repo CI collection (~16 ImportError collection errors → CI red on Linux +
Windows). Converted to fully-qualifiedaipass.skills.lib.telegram.apps.handlers.*
imports (and matchingmock.patchtargets). Verifying that fix surfaced a second
problem the imports had exposed: ~11 tests reached the live Telegram API
(base_bot.run → _set_command_menu → set_bot_commands → urlopen) — they had never
run in CI before because they failed at collection. Added a session-scoped autouse
_block_networkconftest fixture that patchesurlopenon the four network-using
telegram modules (both bare and fully-qualified import paths, each guarded) so any
test attempting a live HTTP call fails loud instead of hanging. A full-repo CI run
then exposed a third layer the isolated suites had hidden:handler.pyand its
routing tests still used barefrom apps.handlers.X import Y/mock.patch("apps. handlers.X…"), which resolve to the wrong branch'sappsin a whole-repo run
(AttributeError / ModuleNotFoundError at runtime — 17test_handler_routing
failures). Fully-qualified those toaipass.skills.lib.telegram.apps.handlers.*in
bothhandler.py(7 lazy imports, now house-rule compliant) and the tests; the
skill's runtime behaviour is unchanged (verified viadrone @skills run telegram).
Net: full-repo collection 0 errors and the whole 11k-test suite green; telegram
suite 663 passed / 0 failed / 0 hangs, fully hermetic; coverage intact (import and
patch-target rewiring only — zero assertion changes). -
aipass installfrom a throwaway path can no longer hijack the machine-wide
AIPASS_HOME(issue #688). A probe install run from a/tmpscratchpad had
rewritten~/.claude/settings.jsonenv.AIPASS_HOME, silently pointing every
Claude Code session on the machine at a dead temp tree (s...
v2.6.1
[2026-07-02]
Released as 2.6.1. Rolls up the DPLAN-0226 / FPLAN-0289 / TDPLAN-0010 /
FPLAN-0298 batch (unified Telegram↔Claude Code bridge, single-session presence
gate, live Telegram streaming, aipass init template selector + portability,
@backup share) — all documented under [2026-07-01] — plus the CI
stabilization below.
Fixed
- CI green — six regressions from the DPLAN-0226 / FPLAN-0289 / TDPLAN-0010
batch (PR #646). The dev branch had gone red acrossseedgo-audit, the
testmatrix, and Windows; root-caused and fixed at source:- seedgo — the new
template_checkadvisory checker was gating CI.
branch_audit.pyaveraged all checker scores into the branch total, so
template_check'sADVISORY=Truewas never honored and it dragged 7
branches below the 100% floor on legitimate README brace-examples. Added a
gating_scoresfilter that excludesADVISORY is Truecheckers before
computing the average (strictis Trueto avoid MagicMock false-positives)
and exposedadvisory_standardsin the audit output. Also refreshed the
provider hooks snapshot fixture to include thepresence_gate
UserPromptSubmithook (FPLAN-0289), fixing 4test_hooks_snapshottests. - hooks —
cc_sessions.py(added by the bridge,f6cbe34) was missing
its README entry and a seedgomodulesbypass (it reads external
~/.claude/sessions/*.json, not branch data, sojson_handleris the wrong
tool — same precedent aspresence.py). Added both. - spawn — retired the
passport(disabled).py/passport_ops(disabled).py
pair to.archive/; the(disabled)suffix kept them visible to the type
checker, which flagged a broken cross-import between them. - ai_mail —
test_child_inherits_broker_fdgave its throwaway test branch
a real.trinity/passport.jsonso the broker's new.trinity-marker
resolution (f914ab6) can resolve it and permit the delete. - spawn — the
builder→aipass_frameworktemplate rename (13463c0) left
.gitignoreexceptions pointing at the oldtemplates/builder/path, so
DASHBOARD.local.json+ ~10 other template files were silently untracked
since the rename — present on disk (dirty tree passed) but absent from clean
clones/CI, sotest_full_spawnfailed only in a clean checkout. Fixed all 23
.gitignoreexception paths and committed the now-visible template
scaffolding. - skills —
test_streamingasserted a+1newline byte, butwrite_text
text mode translates\n→\r\non Windows (2 bytes), failingwindows-setup
only. Switched the test's transcript writes towrite_bytes()for
deterministic LF; production_tail_transcript_byteswas already CRLF-safe.
- seedgo — the new
v2.6.0
[2026-06-23]
The 2.6.0 release — a large dev → main merge spanning several weeks (68 commits).
Headline changes below; the granular per-merge history is in the dated sections that follow.
Added
- Compass v2 — devpulse-owned SQLite/FTS5 rated-decision engine +
/compass
human-triggered capture (separate from @memory; DB gitignored). - Decentralized daemon scheduler — each branch owns
.daemon/schedule.json;
the daemon discovers and fires. - Telegram skill — the Dev-Pass bridge ported to a self-contained AIPass skill
that consumes services as opt-in imports. - Tiered prompt injection — Tier 0 kernel every turn + Tier 1 navmap by cadence,
replacing the single always-on global prompt. - seedgo
HARDCODED_PATHstandard (#37) — flags hardcoded home paths in source
and docstrings.
Changed
- @backup fully restored —
aipass.backup.*namespace, 9-stage Rich CLI,
versioned baseline + per-file diff engine, Google Drive sync +restore. - Memory subsystem unified — single-source config limits, char-limit edit-gate,
unified entry schema, rollover safety + the silent-rollover repair. - Legacy global prompt retired across every runtime — Claude (cadence) and Codex
(SessionStart) read the same tier files. - @daemon / @commons / @skills revived to working citizens.
- Public source genericized —
Patrick→user(private memories stay gitignored).
Fixed
- Secrets hardening — no secret value reaches stdout (cleared CodeQL #86-88,
py/clear-text-logging-sensitive-data). - Memory rollover was silently dead — the PreCompact hook now delegates to
drone @memory rollover; the v1 line-count / 600-line fallback removed entirely. - Hardcoded home paths removed (seedgo #37).
@memorysymbolic.pybuilds its
8 dash-encoded branch-path names at runtime (was a literal-home-patrick-);
@praxbranch_detector.pydocstrings genericized. Both back to 100%
Hardcoded_Path. - Green-CI fixes across Linux / Windows / macOS;
dispatch_monitorPID-429
substring bug; git post-merge friction (FF-only realign).
v2.5.3
[2026-06-11]
Fixed
- seedgo audit local↔CI parity (FPLAN-0261). The local
seedgoaudit could
silently diverge from CI, breaking the "pass locally first, then ship" gate.
Three independent causes, all closed without coupling any checker to git
(.gitignoreis git's concern, not the audit's): (1) usage-scanning checkers
(unused_function,dead_code, +4)rglob'd gitignored output dirs
(artifacts/,dropbox/), so a stray local file could mark a function "used"
that a clean checkout correctly flags — every per-checker skip list hoisted to
one sharedSOURCE_SKIP_DIRS(output dirs simply aren't source). (2) The
diagnosticsstandard shelled out to barepython3 -m pyright(system python,
no pyright) and, on the resulting JSON-parse failure, returned 0 errors = clean
— a silent false-green; now usessys.executableand fails loud. (3) pyright
resolved imports against PATH-python, so results flipped with.venvactivation
— pinned via--pythonpath sys.executable. The audit is now deterministic
local == CI (proven all-13-branches-100% in an unactivated shell). Also:drone
bypasses the test-only brokerstart_background(intentional API, not dead code). - windows-setup CI: guard Linux-only sandbox tests. The kernel-sandbox build
is Linux-only (bwrap,AF_UNIXsockets,openat2); the code already guards on
sys.platform, but four test surfaces ran unconditionally and failed on
windows-latest. Module-levelpytestmark = pytest.mark.skipif(sys.platform != "linux", …)ondrone/tests/test_broker.pyandhooks/tests/test_sandbox.py;
scoped guards on the remainingAF_UNIXbroker-socket tests —
ai_mail/.../test_dispatch_monitor.py::TestBrokerRealE2E(class) and
aipass/.../test_sandbox_check.py::TestCheckBrokerAlivesocket-connect tests
(method-level, so the graceful no-broker paths still run on Windows). All skip on
Windows and run unchanged on Linux. windows-setup was green pre-sandbox-merge
(00edd8b) and red since (0b4ba63); this closes it. - Broker
start_backgroundconnect-before-bind race.drone's out-of-sandbox
broker daemon started viastart_background(), which returned before the
AF_UNIXsocket was bound — callers then raced the bind, and on a slower machine
create_identified_connection()hitFileNotFoundError(socket not yet present).
Deterministic locally (test_delete_nested_file0/5), green in CI only by timing
luck — latent flakiness. Fixed with athreading.Eventset right afterlisten();
start_background(timeout=5.0)now blocks on it and raises if the socket never
binds, so callers never guess asleep. Removed the 4 blindtime.sleep(0.15)
waits from the broker tests. Verified 55/55 broker tests, formerly-failing test 10/10.
Added
-
aipass initdetects missing Claude Code. Stage 6 (CLI choice) now checks
shutil.which("claude")when the picked CLI is Claude Code. If absent: interactive
runs promptInstall now? [Y/n]and run the canonical installer on yes (native
claude.ai/install.sh, PowerShell on Windows,npmfallback, 300s timeout, loud on
failure); non-interactive runs warn and continue. The whole system routes through
Claude Code (hook bridge, dispatch, prompt injection), so init no longer silently
assumes the runtime is present. Only fires when the chosen CLI isclaude. -
Kernel filesystem boundary for agent containment (DPLAN-0202 / FPLAN-0250).
Every autonomous agent can now launch inside a kernel-enforced mount namespace
(@anthropic-ai/sandbox-runtime→ bwrap+seccomp) where reads stay fully open
(the shared live filesystem is preserved — a bind-mount, not isolation: own-tree
writes land live on the real FS instantly) but deletes/overwrites of protected
paths (.git, sibling branch trees) fail at the kernel no matter how the call is
phrased —rm,python os.remove,find -delete, Write tool all hit EROFS.
/tmpand the agent's own tree stay writable;.gitis RW for devpulse, RO for
builders. A per-role policy generator (@hooks build_policy) derives each branch's
writable/RO map from its passport. Privileged deletes route through an
out-of-sandbox drone-broker daemon: identity-scoped allowlist,openat2
RESOLVE_BENEATH path re-resolution (confused-deputy proof), HMAC identity handshake
over a pre-connected inherited fd, JSONL audit.aipass doctorgained a Sandbox
check group (bwrap present+functional, node, srt, rg, broker socket) that is LOUD
when the flag is on and a prereq is missing — never a silent unsandboxed launch.
Proven by a live 16-check red-team suite. Inert by default — gated behind
AIPASS_SANDBOX_ENABLED(off); flag-off is byte-identical to the old dispatch path. -
rm_gate demoted to guardrail. Now framed honestly as early-feedback that
catches the accidentalrm -rfand teachesdrone rm— belt-and-suspenders, with
the kernel sandbox as the actual filesystem boundary. -
Prompt-injection cadence — fire the big loaders every Nth turn. The global
and branch prompts are large and were re-injected on every turn even though a
prior copy stays in the conversation. They now fire together every 5th turn
(config-tunable viahooks_json/custom_config/cadence_config.json), with a
per-session turn counter that resets on a new session and after compaction so
context is always rebuilt when it's actually needed. Identity and the mail flag
stay every-turn (tiny, want freshness). Cuts recurring per-turn context cost. -
Hook fire/skip observability. Cadence emits a structured
[HOOKS] cadence fired|skipped loader= turn= period= offset=line; the prax
monitor renders hook events distinctly so the cadence is visible live. -
Slim global prompt — context-on-demand. The always-injected global prompt
was rewritten from a ~13.8KB encyclopedia into a ~7.8KB navigation map
(DPLAN-0201):dronepinned as the router, the framework tree, all 13 agents
as short bios, and one drilled reflex — rundrone @agent --helpbefore using
a branch. Detail now lives in each agent's--help, fetched on demand. This
also dissolves the harness ~10k-char truncation that was silently dropping the
old prompt's tail; the slim prompt injects whole. Backup retained alongside.
Changed
- Shared leaf library re-homed:
aipass.common→aipass.aipass.shared(FPLAN-0260).
src/aipass/common/was the only non-citizen directory in the agent namespace —
a shared lib (json_handler / json_ops / registry_discovery, extracted in
TDPLAN-0006 P2) parked as a sibling to the agents with no owner. Per @seedgo
design review it now lives inside its steward atsrc/aipass/aipass/shared/,
owned by @aipass; @Spawn imports across (same blessed shared-infra category as
aipass.prax/aipass.cli). Content byte-identical; ~9 import/doc sites updated
across aipass+spawn. A new subprocess guard test pins the bootstrap-safety
invariant: importingshared/loads zero branch dependencies, soaipass init
keeps working pre-drone on fresh machines. Note:aipass.commonshipped in the
v2.5.2 wheel; it was internal plumbing — no deprecation shim. - Action-gated hook sound. Piper now speaks only when a hook actually does
something — handlers return asoundkey the engine plays, instead of
announcing on every invocation. Skipped loaders are silent. Quieter and honest. - README: hardcoded metrics → live badges + qualitative. Version is now a
live PyPI badge, test/PR counts replaced with a codecov coverage badge (75%
minimum) and qualitative wording — no more stale numbers to hand-maintain.
Fixed
- Cadence counter separate-process race. Each
UserPromptSubmithook runs as
its own OS process, so a module-level turn cache double-incremented and the
loaders leapfrogged (firing erratically instead of together). Fixed with an
mtime debounce + transcript-size token +flockso the counter advances exactly
once per real turn, verified against the live execution model. auto_fixran no diagnostics. A leftoverspeak()call (its import removed
in the sound refactor) raisedNameErroron every edit, swallowed by the
handler's broadexcept— so auto-fix silently surfaced nothing on any
.py/.jsonedit. Removed the dead call; diagnostics run again.- Hook events never colored in the monitor. The prax log-watcher's
_HOOK_PATTERNrequired anaction=field that cadence never emits (it logs
the action as the bare second word,fired/skipped), so extraction failed
and events fell through to plain rendering instead of the styled
bold-green ⚡ / dim · treatment. Fixed the regex to capture the bare action
word and enriched the event detail (period, offset, short session id).
Security
- Least-privilege token on the
e2e-wheelworkflow.e2e-wheel.ymlwas the
one CI workflow missing a top-levelpermissions:block (it was added during
the cross-OS work after PR #624 hardened the others), so it ran with the
default broadGITHUB_TOKENscopes — dropping the OpenSSF Scorecard
Token-Permissions check to 0. Addedpermissions: contents: read; the
workflow only reads the repo to build and smoke-test the wheel. - Signed GitHub Releases via Sigstore (keyless). The release workflow now
signs the built wheel + sdist withsigstore/gh-action-sigstore-python
(keyless OIDC — no signing key is generated, stored, or held by anyone) and
attaches the resulting.sigstore.jsonbundles to the GitHub Release. PyPI
uploads were already attested via Trusted Publishing; this extends verifiable
provenance to artifacts pulled from GitHub Releases and satisfies the OpenSSF
Scorecard Signed-Releases check. First proof lands on the nextv*tag.
v2.5.2
[2026.W24] - 2026-06-08
Security
- Least-privilege token on the
e2e-wheelworkflow.e2e-wheel.ymlwas the
one CI workflow missing a top-levelpermissions:block (it was added during
the cross-OS work after PR #624 hardened the others), so it ran with the
default broadGITHUB_TOKENscopes — dropping the OpenSSF Scorecard
Token-Permissions check to 0. Addedpermissions: contents: read; the
workflow only reads the repo to build and smoke-test the wheel. - Signed GitHub Releases via Sigstore (keyless). The release workflow now
signs the built wheel + sdist withsigstore/gh-action-sigstore-python
(keyless OIDC — no signing key is generated, stored, or held by anyone) and
attaches the resulting.sigstore.jsonbundles to the GitHub Release. PyPI
uploads were already attested via Trusted Publishing; this extends verifiable
provenance to artifacts pulled from GitHub Releases and satisfies the OpenSSF
Scorecard Signed-Releases check. First proof lands on the nextv*tag.
v2.5.1
[2026.W23] - 2026-06-02
Fixed
aipass initscaffold correctness. A freshaipass initnow generates a
project-specificAGENTS.md(newagents_md()generator) instead of falling
back to copying AIPass's own repo-rootAGENTS.mdboilerplate — Codex users
were getting the wrong file. ProjectREADME.mdquick-start/structure paths
now reflect the realsrc/<package>/<agent>/layout.- First-agent default name
my-agent→my_agent.aipass initseeded its
default agent with a hyphen, the lone source of a long-standing dir-vs-module
mismatch (the directory kept the hyphen while the importable module,@address
and registry name all normalize to underscore). Defaulting tomy_agentmakes
directory, module,@addressand the README example all consistent. - Dead
citizenship.registry_pathremoved from spawn templates. The field
pointed at a non-existent.aipass/registry.json; it was never read anywhere
(registry is located byfind_registry()glob), so it's dropped from the
builderandbirthrightpassport templates.
Removed
- The entire STATUS flow is decommissioned (TDPLAN-0007). The per-branch
hand-maintainedSTATUS.local.mdbeacon and the auto-aggregated central
STATUS.md(853 lines / 70 KB nobody read) are gone — deleted from disk
across all 13 branches and scrubbed from every prompt, doc, startup protocol,
/prep+/memoskill, the compact-recovery hook, the email footer, and
aipass init/ spawn scaffolding. Live branch state was already fully covered
byDASHBOARD.local.json(prax) and history by.trinity/local.json. The
status-sync engine is kept intact but inert — made dormant by unwiring its
3-line trigger registration (trigger registry.py), so the code stays
revivable. The one thing STATUS uniquely gave us — a quick scratch todo — is
replaced by an operationaltodos[]section in.trinity/local.json
(@memory-owned schema, capped, never vectorized by rollover), pushed to all 13
branches and surfaced as atodo_counton the dashboard. Shipped as one
coordinated cross-branch change (memory, prax, trigger, aipass, spawn, hooks,
ai_mail, seedgo + devpulse).
Changed
- All 13 branches at seedgo 100% under the new introspection standard.
Wrappedprint_introspection()output in Rich markup across ai_mail, drone,
spawn, trigger, prax and devpulse (the rest were already compliant) —
presentation only, no logic change — sodrone @branchwith no args renders
consistent styled output everywhere. - CLI polish for human-facing output.
drone @hooks --helprewritten (Rich,
withhooksound on/off/statusnow surfaced);drone @spawnrepair help
clarified as distinct fromupdateand showing the preview/--applyflow;
drone restores Rich colour on human-facing routed output (--help,
introspection,status) via the inherit path. - Spawn backups land in one namespace
.spawn/.recovery/(TDPLAN-0006 P4).
Spawn's pre-merge JSON backups previously dropped a.recovery/directory at
each branch root (which had accumulated 242 stale auto-generatedDASHBOARD
backups across 10 branches).aipass.common.json_ops.backup_jsongained an
optionalbackup_dirparameter (default unchanged), and spawn's update engine
now directs backups to{branch}/.spawn/.recovery/— tucked under the
spawn-managed.spawn/dir instead of cluttering the branch root. Memory stays
in the safety net (the engine simply never touches.trinity//DASHBOARDon
update, so it never needs to back them up). Stale.recovery/backups cleaned
up. (315 tests, seedgo 100%.) - No more cross-branch engine imports —
aipass init updatecalls spawn via
subprocess (TDPLAN-0006 P3).init_flow.pypreviously did
from aipass.spawn.apps.modules.sync_registry import sync_registry— the one
place aipass reached directly into spawn's Python. Replaced with a subprocess
call to the already-existingdrone @spawn sync-registry --fix(same pattern as
aipass init agent→drone @spawn create), preserving graceful degradation
(a missingdrone, non-zero exit, or timeout is silently skipped — registry
sync never hard-fails an update). The aipass branch now has zero direct
imports of another branch's engine code; the remaining cross-branch imports are
shared service layers only (cli Rich UI, prax logging, trigger events). (438
tests, seedgo 100%.) aipass.commonshared library — dedup spawn/aipass scaffold machinery
(TDPLAN-0006 P2).@spawnand@aipasseach carried their own copy of the
JSON merge/handler utilities and registry discovery. Extracted them into a new
branch-free packagesrc/aipass/common/(json_ops=deep_merge+
backup_json;json_handler.JsonHandler;registry_discovery.find_registry)
that both branches now import.aipass.commonimports zero branch code, so
aipass/bootstrap.py(which runs before the drone runtime exists) can depend on
it without breaking the pre-infrastructure constraint. The duplicated copies are
deleted (spawn keeps a thin re-export shim; aipass'sjson_handlershrank
254 → 88 lines). Thesave_jsoncontract is unified to raiseValueError
on invalid structure across both branches. (313 spawn + 434 aipass tests, both
seedgo 100%.)
Fixed
- Flow plan-type self-serve UX — register override, help, orphan cleanup.
Explicitdrone @flow register <dir> <PREFIX>now overrides an auto-derived
prefix instead of silently failing (guarded — refuses if the auto-registered
type already holds plans), so custom prefixes are settable when adding a new
plan type.create/templates --helprewritten to dynamically list registered
types + templates and document the add-a-new-type workflow. Stale orphan plan
registries removed; deadprefix_exists()dropped. (728 tests, seedgo 100%.) drone @spawn updateno longer scrambles branches (#636, critical — TDPLAN-0006
P0+P1). The update engine compared a freshly-created branch against the class
template by content hash with rename-detection, and because the CREATE path
regenerated template-registry IDs in filesystem-walk order (≠ the master's
hand-crafted IDs), a branch created seconds earlier produced 30 proposed renames
that rotated identity/memory dirs into each other
(apps→.trinity→.seedgo→.claude→.archive→.aipass), turnedREADMEinto
DASHBOARD, and deep-merged stale template into live.trinity/memory —
update <class> --allwould have destroyed every citizen in one command. Rebuilt
update_ops.py(v2.0) on an explicit named-managed-files + path-based model:
.trinity/*,DASHBOARD.local.json,artifacts/birth_certificate.jsonand
.seedgo/bypass.jsonare delivered on create only and never touched on update;
the create==update invariant now yields 0 renames / 0 merges on a fresh branch.
The old ID-based engine (change_detection.py,reconcile.py) is deleted.- Destructive spawn ops are now dry-run by default (TDPLAN-0006 P0).
drone @spawn updateanddrone @spawn repairpreview by default and require an explicit
--applyto write — forgetting a flag is now a safe no-op instead of irreversible
damage (--dry-runkept as an alias).aipass doctorrepair suggestions emit the
matching--applyform.
Added
- Introspection Rich-formatting standard (seedgo). New
check_introspection_rich_formattingchecker enforces that each branch's
print_introspection()output uses Rich markup (delegation-aware — it walks
_-prefixed helper functions), keeping no-argdrone @branchoutput styled and
consistent. Documented inintrospection.md; all 13 branches brought into
compliance (see Changed). - Playbook plan type (
PBPLAN) — reusable SOP checklists (flow). A new
playbook_planstemplate family for throwaway, vectorize-on-close operational
runbooks (first SOP: the Sunday merge). Drop a.mdunder
templates/playbook_plans/, register once, then
drone @flow create . "subject" <sop>stamps a run to tick through and close. - Memory-pool auto-processing (TDPLAN-0005) — dropped files in
memory/memory_pool/are now vectorized and archived automatically on
session-start and pre-compact, instead of requiring a manual
drone @memory pool process. A 3-branch build:@memorygains an intake
handler +poolmodule (processes then empties the pool,keep_recent=0),
@hooksadds alifecycle/auto_processhandler (session-guarded via
CLAUDE_CODE_SESSION_ID, since Claude Code has no SessionStart hook), and
@triggergains event #15 (memory_pool_auto_processed) with a Medic error
path. Runtime pool dirs (memory_pool/,memory_pool_archive/) are now
gitignored. - HVTracker badge added to the README badge cluster, linking to the public
agent profile at hvtracker.net (closes #628). git_gateread-verb allowlist — raw read-only git for every branch. The
PreToolUsegit_gatepreviously blocked all raw git (forcingdrone @git
even for harmless reads), which left agents unable to inspect what git ships —
the exact forensics needed to diagnose the audit gap above. It now allows 22
read-only verbs raw (ls-files,ls-tree,show,cat-file,rev-parse,
rev-list,log,status,diff,blame,archive,grep, …) while
write operations staydrone-gated. Global options (-C,-c,--git-dir,
…) are skipped when extracting the verb, and chained commands are split on
&&/||/;/|so a read piped into a write still blocks the whole line.
(81 tests)- Cross-OS end-to-end WIRING test (
tests/e2e/,e2e-wheel.yml) — the first
CI gate that proves real AIPass wiring (not units-with-mocks) by building the
wheel, installing it into a clean venv, and asserting a 4-tier ladder: package
install + console scripts (T0),aipass init...
v2.5.0
[2026.W22] - 2026-05-30
Added
drone @hooks status— read-only viewer for a project's hook config:
master switch, every hook's enabled state per event group, matchers, and an
enabled/total summary. Resolves the project's.aipass/hooks.jsonby walking
up from CWD. (DPLAN-0190 Phase B)- Hooks activate in every project —
aipass initnow writes
.aipass/hooks.json, so new projects fire the hook engine out of the box
(previously: no config shipped, 0 hooks fired).aipass init update
union-merges the template, preserving any per-hook on/off choices the user
made.aipass doctornow checks for the config's presence. Dead hook-script
shipping (_ship_hooks) removed. (DPLAN-0190 Phase A) - README logo — centered logo image replaces plain
# AIPassheader.
Newassets/logo.pngadded to the repo. - OpenSSF Scorecard —
.github/workflows/scorecard.ymlruns the official
OSSF Scorecard action on push tomainand weekly. Publishes a public security
health score at scorecard.dev with a README badge. Actions pinned by SHA. - GitHub Releases —
publish.ymlnow cuts a GitHub Release on eachv*tag,
with notes pulled from the top CHANGELOG section and the built dist attached.
PyPI publish + GitHub Release now fire from the same tag. - Registry descriptions — all 13 branches now have one-liner descriptions
inAIPASS_REGISTRY.json.drone systemsshows what each agent does
instead of blank lines. Closes #607.
Changed
- Security gates fully project-aware — both the edit gate and the
subagent stop gate now derive the package name dynamically from CWD instead
of hardcodingsrc/aipass/. Cross-branch write protection and branch
detection work for anysrc/<package>/<branch>/project; previously the
subagent gate silently no-opped outside AIPass. 9 new external-project tests.
Closes #605. - Hooks branch promoted to service — registry profile changed from
"AIPass Workshop" to "library" so it appears indrone systemsalongside
the other 12 services. - Hooks branch hardened to 100% seedgo — the @hooks citizen took full
ownership of its branch: every handler verified wired + firing, README
rewritten (two-tier provider/project model, dynamic-dispatch design, event
table), 2 stale tests resolved (253 pass). Dead-code/unused-function flags
documented as architectural bypasses — the 15 handlers are invoked
dynamically viaimportlibfromhooks.jsonpaths, never statically
imported. (DPLAN-0191)
Release
- Version 2.5.0 published to PyPI. Trusted publishing via GitHub Actions
(publish.ymltriggers onv*tags — no manual twine upload needed). The
same tag now also cuts a GitHub Release with these notes attached.
Removed
- Gemini CLI full removal — deleted
.gemini/directory (5 files) and
GEMINI.md. Stripped all references fromsetup.sh(~50 lines),
README.md,bug-report.yml,aipass init(bootstrap/scaffold/test),
hooks (README/prompt/passport), and prax monitoring (~300 lines). 21 files
changed, -927 lines. Closes
#608.