33 KiB
Changelog
All notable changes to AIPass will be documented in this file.
The format is based on Keep a Changelog,
and this project uses Calendar Versioning in the format
YYYY.WNN (year and ISO week number).
[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,@addressand 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 thebuilderandbirthrightpassport templates.
Removed
- The entire STATUS flow is decommissioned (TDPLAN-0007). The per-branch
hand-maintained
STATUS.local.mdbeacon and the auto-aggregated centralSTATUS.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, andaipass 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.
Wrapped
print_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-generatedDASHBOARDbackups 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 didfrom 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 asaipass 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, soaipass/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 raiseValueErroron 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.
Explicit
drone @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), turnedREADMEintoDASHBOARD, and deep-merged stale template into live.trinity/memory —update <class> --allwould have destroyed every citizen in one command. Rebuiltupdate_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'sprint_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 newplaybook_planstemplate family for throwaway, vectorize-on-close operational runbooks (first SOP: the Sunday merge). Drop a.mdundertemplates/playbook_plans/, register once, thendrone @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 manualdrone @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 viaCLAUDE_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 @giteven 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 initscaffolding (T1), a hook actually firing via the bridge with an observableengine.jsonlrecord (T2a), anddroneresolving + subprocess-executing a real branch (T3). Runs on a 3-OS matrix (ubuntu/windows/macos,fail-fast: false). Ran red-first on Windows by design and immediately earned its keep — it caught two real, previously uncovered Windows wiring bugs (aipass initpreflight +dronestdout encoding, both fixed below). Notably the layers we most feared — clean-wheel install (T0) and hook firing (T2a) — passed on Windows. (DPLAN-0194 / FPLAN-0239) drone rm— provider-agnostic safe delete — a contained recursive delete that lets agents clean up scratch dirs without tripping therm -rfblock. Deletes are confined to the project root and the system temp dirs (/tmpand$TMPDIR), refusing anything outside (home,/etc,/, etc.). Even inside those roots it hard-refuses protected internals —.git,.trinity/,.aipass/,.codex/,.agents/, and sibling-branch worktrees — mirroring the filesystem boundary an OS-sandboxed agent (e.g. Codex) enforces, so behavior is consistent across CLIs. Pure-Python (shutil.rmtree), with a red-team test suite for containment escapes (symlinks, traversal, sibling branches). (#630)rm_gatehook — block raw recursiverm, teach the safe path — a PreToolUse gate (mirroringgit_gate) that blocks rawrm -r/-rf/-fr/--recursiveand redirects the agent todrone rm. Provider-agnostic (runs in the hook engine, not tied to Claude Code permission rules), conservative (unparseable targets are blocked, not allowed), and skipsdrone rmitself. This makes the safe-delete path discoverable at the moment of friction. (#630)- Hook engine logs
agent_type/agent_idper fire — the engine now records which agent triggered each hook (e.g.agent=mainvsagent=Explore) in bothengine.jsonland the prax monitor stream. Previously the payload flowed into handlers but was never logged, leaving no way to tell an internal main-turn fire from a real sub-agent fire. Pure visibility; no behavior change. Groundwork for #606. (#606) - OpenSSF Best Practices passing badge — AIPass earned the OpenSSF Best
Practices (CII) passing badge (100% of criteria), added to the README badge
cluster. Self-certified across all six categories — basics, change control,
reporting, quality, security, and analysis. Complements the existing OpenSSF
Scorecard, lifting the
CII-Best-Practicescheck from 0. (DPLAN-0193)
Changed
-
Standards floor raised to genuine 100% across all 13 branches — completed the campaign that lifted the seedgo gate threshold from 80 to 100. Rather than bypass failing files, two check flaws were fixed at the root: (1) the file-size / architecture check is now advisory (warn-only for 700–1500 line files with no docstring nudge, hard-fail only above 1500) — large files are a smell, not a defect; (2) readme-freshness now compares against git history, not file mtime —
git checkout/mergereset mtimes without any semantic change, so the old check false-positived (flow + prax shared an identical mtime from one git event, not real edits). It now diffs the README's "Last Updated" against the last commit that touched.py. Genuine content fixes where warranted (aipass requirements template + handler routing; honest README content refreshes on flow, prax, devpulse). The readme-freshness failure message now teaches the right fix ("update README content, then set the date — don't just bump it"). Also optimized the devpulse watchdog poll cadence (2s → 5s; the loop is cheap, so the tighter interval was wasted CPU). (#631) -
Retired the blanket
rmdeny from provider settings —setup.shandaipass initno longer shipBash(rm -rf*)/Bash(rm -r *)deny rules (they were mis-filed among git rules, blocked all/tmpcleanup, and gave a bare "permission denied" with no guidance). Therm_gatehook +drone rmnow own this — cross-provider, path-aware, and they teach.aipass doctordetects the stale rules on existing installs andaipass doctor --fixremoves them (idempotent, preserves all other rules). Claude Code still natively circuit-breaksrm -rf /andrm -rf ~. (#630)
Fixed
Windows Test/macOS Testare no longer path-filtered — they were stalling PRs as required checks. Both workflows only triggered whensetup.sh/drone/cli.py/handlers/__init__.py/pyproject.tomlchanged, but branch protection listswindows-setup/macos-setupas required. On any PR that didn't touch those paths the workflows never ran, so GitHub parked the required checks as "Expected — waiting for status" indefinitely, blocking the merge (the tests themselves were green — they simply didn't fire). They now run on every push/PR to main/dev, like the other required lanes. (A required check must never be path-filtered.)seedgo-auditCI gate was red despite 100% local audits — four checkers validated the working tree instead of committed source. CI audits a cleangit checkout(tracked files only — git ships no empty or gitignored dirs), but the working tree carries runtime dirs (logs/,*_json/,artifacts/,.trinity/,passport.json), so every branch scored ~97% in CI while passing at 100% locally. Reproduced exactly with a tracked-only tree (git archive HEADaudits to CI's 97%). Four checkers now measure what git actually ships:log_structureno longer fails when the gitignoredlogs/dir is absent (it still enforces no-hardcoded-paths);readmecross-references.gitignore(viagit check-ignorewith a fallback list) and skips gitignored dirs/links in the directory-tree and dead-link checks;encapsulationinfers the branch from the path when the gitignoredAIPASS_REGISTRY.jsonis unavailable (and no longer collides on theaipassbranch);architectureskips cleanly when the gitignoredpassport.jsonis absent. A follow-up refinedreadme'sgit check-ignoreuse:.gitignoredir-only patterns (trailing slash —logs/,**/*_json/,.trinity/) don't match a clean checkout's non-existent paths unless directory intent is signalled, so the check now also tests the trailing-slash form (this was the last 1% —readmeflaggedcli_json/logs/artifactsas "missing on disk" in CI only). The CI gate (.github/scripts/seedgo_audit.py) now also prints the failing standards and their check messages, so a sub-100 result says why, not just the percentage. Finally, theseedgo-auditCI job now installs thememoryextra (pip install -e ".[dev,memory]"): thediagnosticsstandard runs pyright over every branch, and memory's handlers importchromadb/numpyat module level — without those declared deps installed, pyright reported them as unresolved (reportMissingImports=error) and memory scored 55%, a false failure from a missing CI dep rather than a code defect. Clean-tree and working-tree audits both report 13/13 = 100%. (DPLAN-0195)- Two latent Windows portability bugs caught by the new e2e harness — both
were always present in the code; they only surfaced now because this is the
first CI to run
aipass initscaffolding and real-branchdronerouting on Windows (the old Windows CI ran an editable install,aipass-less, and only routed to in-process modules, so both paths had zero Windows coverage). Pure portability fixes — Linux/macOS behaviour is unchanged.aipass initcrashed on Windows (surfaced as a misleading "Unknown command: init"). Init scaffolded the project correctly, then crashed printing its✓ Project initializedbanner — Rich wrote the ✓/box glyphs through a cp1252 stdout, raisingUnicodeEncodeError ('charmap'); the error handler's✗message hit the same wall, bubbling up to the command router which mislabeled it. Theaipassentry point now reconfigures stdout/stderr to UTF-8 in place on Windows. (The init preflight ancestor-walk was also hardened to skip un-enumerable Windows drive-root entries — defensive, not the trigger.)drone @branchcrashed on Windows with the sameUnicodeEncodeError ('charmap').droneresolved + subprocessed the branch correctly, then crashed printing the captured output through cp1252 stdout. The existingPYTHONUTF8guard only affected child interpreters, not the live process streams —drone's entry point now alsoreconfigure()s stdout/stderr to UTF-8 in place.- CI unit lane no longer runs the e2e wheel tests.
ci.yml'spytest --rootdir=.swept intests/e2e/(which build a wheel per the dedicatede2e-wheel.yml), failing the unit lane; it now--ignores them. (DPLAN-0194)
- A release merge can no longer destroy the
devbranch —drone @git mergepassed--delete-branchtogh pr mergeunconditionally, so merging adev→mainPR deleted the persistentdevbranch on the remote and stranded the working tree onmain(the next commit silently landing on main). Merge now looks up the PR's head ref and only deletes non-protected branches —devandmainare never deleted, and an undeterminable head ref fails safe (no delete). After a merge it returns the working tree todev(loud warning if it can't).drone @git branchesnow runsfetch --prunebefore listing so it reflects the live remote instead of stale cached refs, and a newdrone @git prune-tempcleans up merged temp PR branches. (#625) drone @git status/diffshow their scope — when scoped to a branch (no--all), output now appends "(showing scope — use --all for full repo)", so an empty scoped view is no longer mistaken for a clean repo. (#623)- External projects can call AIPass branches via drone —
drone @api ...(and anydrone @X) now resolves from a non-AIPass project CWD instead of being blocked with "path escapes project root." The resolver was validating a branch's path against the primary registry root even when the branch was found via theAIPASS_HOMEfallback, so any external project (Vera Studio, Daemon) hit a false security block.resolve_branch()now validates containment against the registry the branch was actually found in. Security is unchanged — each branch is still contained within its own declaring registry's root; genuine path escapes remain blocked. (#618) aipass <command>runs instead of printing an introspection banner —aipassis a user-facing binary, soaipass doctor(and every other command) must execute, not describe itself. All 7 modules (doctor,doctor_fix,doctor_wire,handoff,help_chat,init_flow,profile) previously hit a no-args→introspection gate (a standard meant fordrone @branch <module>discovery) and showed a banner on bare invocation. Now bare invocation runs the command or shows usage; the introspection banner moved to--info. The seedgo introspection standard is bypassed for these binary-invoked modules (documented).- Dashboard plan counts no longer zeroed on refresh — a branch's
active_planswas reset to0by everydrone @prax dashboard refresh, becausePLANS.central.jsononly held Flow's own plans (location==FLOW_ROOTfilter). The central file is now comprehensive: all plans grouped per-branch, so refresh reports each branch's real count (e.g. devpulse now shows its 12 open plans instead of 0).
Security
dependency-scan(pip-audit) green again — upgrade pip, drop stale ignores. TheSecurity Scanworkflow'sdependency-scanjob had gone red: pip-audit scans the whole environment, and the runner's bundled pip (26.1.1) carries advisory PYSEC-2026-196 (fixed in 26.1.2). The job now runspython -m pip install --upgrade pipbefore auditing (it was the only CI job not upgrading pip), removing the vulnerable version outright rather than suppressing it. 26.1.2 also resolves CVE-2026-3219 and CVE-2026-6357, so the two now-stale--ignore-vulnentries were removed — verified against a clean reproduction of the job's environment, which audits to "No known vulnerabilities found" with nothing ignored.- Pinned the
requestsfloor to a non-vulnerable version — raisedrequeststo>=2.34.2inpyproject.tomland the API branch'srequirements.project.txt(which previously listed it unconstrained). This clears six OSV advisories the OpenSSF Scorecard flagged against the dependency (PYSEC-2014-13, PYSEC-2014-14, PYSEC-2018-28, GHSA-9wx4-h78v-vm56, GHSA-9hjg-9r4m-mvj7, GHSA-gc5v-m9x4-r6x2) — the oldest surfaced only because the dependency was declared without a version bound. No runtime change (the AIPass venv already ran a fixed release). (DPLAN-0193) - Pinned the test container base image by digest —
Dockerfile.testnow pinsubuntu:24.04to its registry digest (sha256:786a8b55…) so the test image is reproducible and tamper-evident, clearing the ScorecardcontainerImage not pinned by hashfinding. (DPLAN-0193)
[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 updateunion-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
in
AIPASS_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 hardcoding
src/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 in
drone 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 via
importlibfromhooks.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) andGEMINI.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.
[2026.W21] - 2026-05-25
First weekly release. AIPass now follows a Sunday release cadence: changes
accumulate on dev throughout the week and merge to main as a single
versioned release with notes.
Added
- Hook engine — a new centralized dispatch system for all hook execution. A thin bridge receives events from the AI provider (Claude, Codex, etc.) and routes them through a single Python engine that reads per-project configuration, executes the appropriate handlers, and logs every invocation. Replaces 14 standalone shell/Python scripts with native handler modules organized by domain: prompt injection, security enforcement, lifecycle management, and notifications.
- Per-project hook configuration via
.aipass/hooks.json. Each project can enable, disable, or customize individual hooks without touching provider-level settings. Previously hooks fired globally with no per-project control. - Audio feedback on hook events using Piper TTS. All 14 handlers
produce distinct spoken audio cues so operators can monitor sessions
without watching the terminal. A shared sound module
(
hooks/apps/sound.py) providesspeak()andplay()with built-in mute support. Toggle withdrone @hooks hooksound on|off— muting silences all 14 handlers without skipping their functional logic. - Hooks agent — the 13th citizen in the AIPass registry, owning all hook infrastructure: the engine, bridge, handlers, and configuration schema.
- Dashboard plugin for devpulse — aggregates git status, session history, and dispatch state into a single startup view. Wired into the session startup protocol so branch managers see current state immediately.
- External log routing — prax now accepts structured log entries from any branch, not just its own modules. Hook executions, dispatches, and agent activity all flow into the central monitoring log.
Changed
- Provider settings fully migrated to bridge pattern. All hook entries in the Claude provider configuration now call the bridge dispatcher instead of individual scripts. Each hook produces its own system-reminder to the model, preserving prompt injection fidelity (a single merged bridge was found to break prompt delivery due to Claude Code's output persistence threshold).
- setup.sh rewritten to install hooks via the bridge pattern. The old version hardcoded 14 script paths; the new version writes a single bridge call per event type and validates that the bridge module exists.
- Documentation sweep across
.claude/README.md,SECURITY.md, the global prompt, and branch-level docs to reflect the new hook architecture. References to legacy.claude/hooks/scripts replaced with the native handler locations. aipass init updatenow correctly preserves user-customized hook settings during project updates instead of overwriting them.- Seedgo snapshot tests rebuilt — the provider hooks snapshot fixture and extraction logic were structurally broken (silently passing with zero results). Both the fixture format and the test assertions have been corrected.
- Test suite updated for hook migration —
test_git_gate.pyimports from the new handler module;test_bootstrap.pyno longer asserts that project initialization ships standalone hook scripts (it no longer does).
Fixed
- Settings merge on project update —
aipass init updatewas clobbering user hook configurations. The merge logic now layers AIPass defaults under existing user settings. - Python 3.10 test collision — a module/function name collision caused mock patch targets to fail on Python 3.10. Test targets corrected.
- Dead code removal — removed an unused CLI
__main__.pyentrypoint and cleaned up.gitignoreentries that were masking tracked files. - Codecov patch threshold lowered to 50% to reflect the project's current coverage baseline and stop false-negative CI failures.
Removed
- 18 standalone hook scripts in
.claude/hooks/disabled (renamed with(disabled)suffix). Their logic now lives in native handler modules undersrc/aipass/hooks/apps/handlers/. The old files remain on disk for reference but are no longer executed. drone hook-soundsplugin disabled. Sound control moved to hooks branch asdrone @hooks hooksound on|offwith full mute support for all 14 handlers (the old plugin only controlled 4).
Infrastructure
- Provider manifest migrated to bridge pattern.
provider_manifest.jsonnow stores bridge commands ($AIPASS_HOME/...bridges/claude.py EventType) instead of standalone script names.doctor_wire.pyauto-wires bridge entries directly — no longer copies scripts to~/.claude/hooks/or generatessys.executablepaths. Doctor checks validate commands exist in provider settings instead of checking for script files on disk. - README v3 — rewritten for external users. Tighter problem/solution framing, collapsible agent details, Gemini CLI removed (untested), user-project perspective throughout.
- Inline handoff (
aipass init runStep 11) — new default stays in the current terminal viaos.execvpinstead of opening a new window. Users choose "stay here" or "new window." Enables single-terminal demo recordings. Closes #610. - Project-aware global prompt — the global prompt loader now detects
whether CWD is inside AIPass or an external project. External projects
receive their own lighter prompt (from
.aipass/aipass_global_prompt.md) instead of the full AIPass-internal playbook. Fixesdrone @praxerrors in new projects. - Project CLAUDE.md template —
aipass initnow generates a project-specific CLAUDE.md from.aipass/project_CLAUDE.mdinstead of copying the AIPass-internal one. Removes the startup protocol reference todrone @prax dashboard refreshwhich doesn't exist in external projects. - Gemini CLI removed from
aipass initCLI choices and handoff options. GEMINI.md no longer created for new projects. Gemini CLI is being retired upstream. - Demo GIF added to
assets/demo.gifand referenced in README.
This is the first CHANGELOG entry. Prior work is documented in the repository's commit history and branch session logs.