Files
AIPass/CHANGELOG.md
T
AIOSAIandClaude Opus 4.8 076110a2fb security(release): sign GitHub Release artifacts with Sigstore (keyless)
publish.yml github-release job now signs the wheel + sdist via
sigstore/gh-action-sigstore-python (pinned v3.3.0 / 04cffa1d), keyless OIDC,
and attaches the .sigstore.json bundles to the GitHub Release through the
existing dist/* glob. Added id-token: write to the job for OIDC.

PyPI uploads were already attested (Trusted Publishing); Scorecard's
Signed-Releases check inspects GitHub Releases, which only carried bare wheels
-> score 0. .sigstore.json is in Scorecard's recognized signatureExtensions.
Verified: action globs ./dist/*.whl ./dist/*.tar.gz (action.py:202), auto-attach
gated on release-event (we trigger on push:tags) so we upload via dist/* and set
release-signing-artifacts:false. First live proof = next v* tag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:19:51 -07:00

34 KiB
Raw Blame History

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.W24] - 2026-06-08

Security

  • Least-privilege token on the e2e-wheel workflow. e2e-wheel.yml was the one CI workflow missing a top-level permissions: block (it was added during the cross-OS work after PR #624 hardened the others), so it ran with the default broad GITHUB_TOKEN scopes — dropping the OpenSSF Scorecard Token-Permissions check to 0. Added permissions: 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 with sigstore/gh-action-sigstore-python (keyless OIDC — no signing key is generated, stored, or held by anyone) and attaches the resulting .sigstore.json bundles 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 next v* tag.

[2026.W23] - 2026-06-02

Fixed

  • aipass init scaffold correctness. A fresh aipass init now generates a project-specific AGENTS.md (new agents_md() generator) instead of falling back to copying AIPass's own repo-root AGENTS.md boilerplate — Codex users were getting the wrong file. Project README.md quick-start/structure paths now reflect the real src/<package>/<agent>/ layout.
  • First-agent default name my-agent → my_agent. aipass init seeded 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 to my_agent makes directory, module, @address and the README example all consistent.
  • Dead citizenship.registry_path removed from spawn templates. The field pointed at a non-existent .aipass/registry.json; it was never read anywhere (registry is located by find_registry() glob), so it's dropped from the builder and birthright passport templates.

Removed

  • The entire STATUS flow is decommissioned (TDPLAN-0007). The per-branch hand-maintained STATUS.local.md beacon 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 + /memo skill, the compact-recovery hook, the email footer, and aipass init / spawn scaffolding. Live branch state was already fully covered by DASHBOARD.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 operational todos[] section in .trinity/local.json (@memory-owned schema, capped, never vectorized by rollover), pushed to all 13 branches and surfaced as a todo_count on 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 — so drone @branch with no args renders consistent styled output everywhere.
  • CLI polish for human-facing output. drone @hooks --help rewritten (Rich, with hooksound on/off/status now surfaced); drone @spawn repair help clarified as distinct from update and showing the preview/--apply flow; 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-generated DASHBOARD backups across 10 branches). aipass.common.json_ops.backup_json gained an optional backup_dir parameter (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//DASHBOARD on 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 update calls spawn via subprocess (TDPLAN-0006 P3). init_flow.py previously 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-existing drone @spawn sync-registry --fix (same pattern as aipass init agent → drone @spawn create), preserving graceful degradation (a missing drone, 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.common shared library — dedup spawn/aipass scaffold machinery (TDPLAN-0006 P2). @spawn and @aipass each carried their own copy of the JSON merge/handler utilities and registry discovery. Extracted them into a new branch-free package src/aipass/common/ (json_ops = deep_merge + backup_json; json_handler.JsonHandler; registry_discovery.find_registry) that both branches now import. aipass.common imports 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's json_handler shrank 254 → 88 lines). The save_json contract is unified to raise ValueError 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. 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 --help rewritten to dynamically list registered types + templates and document the add-a-new-type workflow. Stale orphan plan registries removed; dead prefix_exists() dropped. (728 tests, seedgo 100%.)
  • drone @spawn update no 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), turned README into DASHBOARD, and deep-merged stale template into live .trinity/ memory — update <class> --all would 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.json and .seedgo/bypass.json are 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 update and drone @spawn repair preview by default and require an explicit --apply to write — forgetting a flag is now a safe no-op instead of irreversible damage (--dry-run kept as an alias). aipass doctor repair suggestions emit the matching --apply form.

Added

  • Introspection Rich-formatting standard (seedgo). New check_introspection_rich_formatting checker enforces that each branch's print_introspection() output uses Rich markup (delegation-aware — it walks _-prefixed helper functions), keeping no-arg drone @branch output styled and consistent. Documented in introspection.md; all 13 branches brought into compliance (see Changed).
  • Playbook plan type (PBPLAN) — reusable SOP checklists (flow). A new playbook_plans template family for throwaway, vectorize-on-close operational runbooks (first SOP: the Sunday merge). Drop a .md under 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: @memory gains an intake handler + pool module (processes then empties the pool, keep_recent=0), @hooks adds a lifecycle/auto_process handler (session-guarded via CLAUDE_CODE_SESSION_ID, since Claude Code has no SessionStart hook), and @trigger gains 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_gate read-verb allowlist — raw read-only git for every branch. The PreToolUse git_gate previously blocked all raw git (forcing drone @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 stay drone-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 scaffolding (T1), a hook actually firing via the bridge with an observable engine.jsonl record (T2a), and drone resolving + 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 init preflight + drone stdout 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 the rm -rf block. Deletes are confined to the project root and the system temp dirs (/tmp and $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_gate hook — block raw recursive rm, teach the safe path — a PreToolUse gate (mirroring git_gate) that blocks raw rm -r/-rf/-fr/ --recursive and redirects the agent to drone rm. Provider-agnostic (runs in the hook engine, not tied to Claude Code permission rules), conservative (unparseable targets are blocked, not allowed), and skips drone rm itself. This makes the safe-delete path discoverable at the moment of friction. (#630)
  • Hook engine logs agent_type / agent_id per fire — the engine now records which agent triggered each hook (e.g. agent=main vs agent=Explore) in both engine.jsonl and 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-Practices check 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/merge reset 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 rm deny from provider settings — setup.sh and aipass init no longer ship Bash(rm -rf*) / Bash(rm -r *) deny rules (they were mis-filed among git rules, blocked all /tmp cleanup, and gave a bare "permission denied" with no guidance). The rm_gate hook + drone rm now own this — cross-provider, path-aware, and they teach. aipass doctor detects the stale rules on existing installs and aipass doctor --fix removes them (idempotent, preserves all other rules). Claude Code still natively circuit-breaks rm -rf / and rm -rf ~. (#630)

Fixed

  • Windows Test / macOS Test are no longer path-filtered — they were stalling PRs as required checks. Both workflows only triggered when setup.sh/drone/cli.py/handlers/__init__.py/pyproject.toml changed, but branch protection lists windows-setup/macos-setup as 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-audit CI gate was red despite 100% local audits — four checkers validated the working tree instead of committed source. CI audits a clean git 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 HEAD audits to CI's 97%). Four checkers now measure what git actually ships: log_structure no longer fails when the gitignored logs/ dir is absent (it still enforces no-hardcoded-paths); readme cross-references .gitignore (via git check-ignore with a fallback list) and skips gitignored dirs/links in the directory-tree and dead-link checks; encapsulation infers the branch from the path when the gitignored AIPASS_REGISTRY.json is unavailable (and no longer collides on the aipass branch); architecture skips cleanly when the gitignored passport.json is absent. A follow-up refined readme's git check-ignore use: .gitignore dir-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% — readme flagged cli_json/logs/artifacts as "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, the seedgo-audit CI job now installs the memory extra (pip install -e ".[dev,memory]"): the diagnostics standard runs pyright over every branch, and memory's handlers import chromadb/numpy at 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 init scaffolding and real-branch drone routing 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 init crashed on Windows (surfaced as a misleading "Unknown command: init"). Init scaffolded the project correctly, then crashed printing its ✓ Project initialized banner — Rich wrote the ✓/box glyphs through a cp1252 stdout, raising UnicodeEncodeError ('charmap'); the error handler's ✗ message hit the same wall, bubbling up to the command router which mislabeled it. The aipass entry 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 @branch crashed on Windows with the same UnicodeEncodeError ('charmap'). drone resolved + subprocessed the branch correctly, then crashed printing the captured output through cp1252 stdout. The existing PYTHONUTF8 guard only affected child interpreters, not the live process streams — drone's entry point now also reconfigure()s stdout/stderr to UTF-8 in place.
    • CI unit lane no longer runs the e2e wheel tests. ci.yml's pytest --rootdir=. swept in tests/e2e/ (which build a wheel per the dedicated e2e-wheel.yml), failing the unit lane; it now --ignores them. (DPLAN-0194)
  • A release merge can no longer destroy the dev branch — drone @git merge passed --delete-branch to gh pr merge unconditionally, so merging a dev→main PR deleted the persistent dev branch on the remote and stranded the working tree on main (the next commit silently landing on main). Merge now looks up the PR's head ref and only deletes non-protected branches — dev and main are never deleted, and an undeterminable head ref fails safe (no delete). After a merge it returns the working tree to dev (loud warning if it can't). drone @git branches now runs fetch --prune before listing so it reflects the live remote instead of stale cached refs, and a new drone @git prune-temp cleans up merged temp PR branches. (#625)
  • drone @git status/diff show 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 any drone @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 the AIPASS_HOME fallback, 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 — aipass is a user-facing binary, so aipass 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 for drone @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_plans was reset to 0 by every drone @prax dashboard refresh, because PLANS.central.json only held Flow's own plans (location==FLOW_ROOT filter). 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. The Security Scan workflow's dependency-scan job 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 runs python -m pip install --upgrade pip before 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-vuln entries were removed — verified against a clean reproduction of the job's environment, which audits to "No known vulnerabilities found" with nothing ignored.
  • Pinned the requests floor to a non-vulnerable version — raised requests to >=2.34.2 in pyproject.toml and the API branch's requirements.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.test now pins ubuntu:24.04 to its registry digest (sha256:786a8b55…) so the test image is reproducible and tamper-evident, clearing the Scorecard containerImage not pinned by hash finding. (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.json by walking up from CWD. (DPLAN-0190 Phase B)
  • Hooks activate in every project — aipass init now 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 doctor now checks for the config's presence. Dead hook-script shipping (_ship_hooks) removed. (DPLAN-0190 Phase A)
  • README logo — centered logo image replaces plain # AIPass header. New assets/logo.png added to the repo.
  • OpenSSF Scorecard — .github/workflows/scorecard.yml runs the official OSSF Scorecard action on push to main and weekly. Publishes a public security health score at scorecard.dev with a README badge. Actions pinned by SHA.
  • GitHub Releases — publish.yml now cuts a GitHub Release on each v* 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 systems shows 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 any src/<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 systems alongside 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 importlib from hooks.json paths, never statically imported. (DPLAN-0191)

Release

  • Version 2.5.0 published to PyPI. Trusted publishing via GitHub Actions (publish.yml triggers on v* 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 from setup.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) provides speak() and play() with built-in mute support. Toggle with drone @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 update now 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.py imports from the new handler module; test_bootstrap.py no longer asserts that project initialization ships standalone hook scripts (it no longer does).

Fixed

  • Settings merge on project update — aipass init update was 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__.py entrypoint and cleaned up .gitignore entries 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 under src/aipass/hooks/apps/handlers/. The old files remain on disk for reference but are no longer executed.
  • drone hook-sounds plugin disabled. Sound control moved to hooks branch as drone @hooks hooksound on|off with full mute support for all 14 handlers (the old plugin only controlled 4).

Infrastructure

  • Provider manifest migrated to bridge pattern. provider_manifest.json now stores bridge commands ($AIPASS_HOME/...bridges/claude.py EventType) instead of standalone script names. doctor_wire.py auto-wires bridge entries directly — no longer copies scripts to ~/.claude/hooks/ or generates sys.executable paths. 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 run Step 11) — new default stays in the current terminal via os.execvp instead 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. Fixes drone @prax errors in new projects.
  • Project CLAUDE.md template — aipass init now generates a project-specific CLAUDE.md from .aipass/project_CLAUDE.md instead of copying the AIPass-internal one. Removes the startup protocol reference to drone @prax dashboard refresh which doesn't exist in external projects.
  • Gemini CLI removed from aipass init CLI choices and handoff options. GEMINI.md no longer created for new projects. Gemini CLI is being retired upstream.
  • Demo GIF added to assets/demo.gif and referenced in README.

This is the first CHANGELOG entry. Prior work is documented in the repository's commit history and branch session logs.