feat: Sunday release prep — hooks.json tracked, CHANGELOG.md, prax fix, gitignore cleanup
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
*
|
||||
!aipass_global_prompt.md
|
||||
!hooks.json
|
||||
!.gitignore
|
||||
#Do not add other exceptions here without careful consideration. Developer permissions0ns needed.
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"_comment": "Per-project hook configuration for the AIPass hook engine (DPLAN-0184)",
|
||||
"hooks_enabled": true,
|
||||
|
||||
"UserPromptSubmit": {
|
||||
"identity_injector": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.prompt.identity.handle",
|
||||
"matcher": ""
|
||||
},
|
||||
"email_notification": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.notification.email.handle",
|
||||
"matcher": ""
|
||||
},
|
||||
"branch_prompt": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.prompt.branch_loader.handle",
|
||||
"matcher": ""
|
||||
},
|
||||
"global_prompt": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.prompt.global_loader.handle",
|
||||
"matcher": ""
|
||||
}
|
||||
},
|
||||
|
||||
"PreToolUse": {
|
||||
"tool_use_sound": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.notification.tool_sound.handle",
|
||||
"matcher": "Bash|Edit|MultiEdit|Write|Read|Grep|Glob|WebSearch|WebFetch|Task"
|
||||
},
|
||||
"pre_edit_gate": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.security.edit_gate.handle",
|
||||
"matcher": "Edit|MultiEdit|Write|NotebookEdit"
|
||||
},
|
||||
"git_gate": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.security.git_gate.handle",
|
||||
"matcher": "Bash|Edit|MultiEdit|Write|NotebookEdit"
|
||||
},
|
||||
"engine_test_sound": {
|
||||
"enabled": false,
|
||||
"command": "python3 $AIPASS_HOME/.claude/hooks/engine_test_sound.py",
|
||||
"matcher": "WebSearch"
|
||||
}
|
||||
},
|
||||
|
||||
"PostToolUse": {
|
||||
"auto_fix_diagnostics": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.lifecycle.auto_fix.handle",
|
||||
"matcher": "Edit|MultiEdit|Write|NotebookEdit",
|
||||
"timeout": 45
|
||||
},
|
||||
"auto_watchdog": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.lifecycle.auto_watchdog.handle",
|
||||
"matcher": "Bash"
|
||||
}
|
||||
},
|
||||
|
||||
"SubagentStop": {
|
||||
"subagent_stop_gate": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.security.subagent_gate.handle",
|
||||
"matcher": "",
|
||||
"timeout": 60
|
||||
}
|
||||
},
|
||||
|
||||
"Stop": {
|
||||
"stop_sound": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.notification.stop_sound.handle",
|
||||
"matcher": ""
|
||||
}
|
||||
},
|
||||
|
||||
"Notification": {
|
||||
"notification_sound": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.notification.announce.handle",
|
||||
"matcher": ""
|
||||
}
|
||||
},
|
||||
|
||||
"PreCompact": {
|
||||
"pre_compact": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.lifecycle.compact.handle",
|
||||
"matcher": "",
|
||||
"timeout": 60
|
||||
},
|
||||
"pre_compact_rollover": {
|
||||
"enabled": true,
|
||||
"handler": "aipass.hooks.apps.handlers.lifecycle.rollover.handle",
|
||||
"matcher": "",
|
||||
"timeout": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,9 @@ src/aipass/*/apps/integrations/**
|
||||
!src/aipass/spawn/templates/builder/DASHBOARD.local.json
|
||||
!src/aipass/spawn/templates/builder/STATUS.local.md
|
||||
|
||||
# CI artifacts
|
||||
windows-pytest-results/
|
||||
|
||||
# Parked / one-off
|
||||
HERALD.md
|
||||
backup_data/
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to AIPass will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project uses [Calendar Versioning](https://calver.org/) in the format
|
||||
`YYYY.WNN` (year and ISO week number).
|
||||
|
||||
---
|
||||
|
||||
## [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. Tool usage, response
|
||||
completion, notifications, email alerts, and sub-agent activity each
|
||||
produce distinct spoken audio cues so operators can monitor sessions
|
||||
without watching the terminal.
|
||||
- **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.
|
||||
|
||||
---
|
||||
|
||||
*This is the first CHANGELOG entry. Prior work is documented in the
|
||||
repository's commit history and branch session logs.*
|
||||
@@ -203,16 +203,21 @@ def _calculate_quick_status_standalone(sections: Dict) -> Dict:
|
||||
"""
|
||||
ai_mail = sections.get("ai_mail", {})
|
||||
flow = sections.get("flow", {})
|
||||
commons = sections.get("commons_activity", {})
|
||||
|
||||
new_mail_raw = ai_mail.get("new", ai_mail.get("unread", 0))
|
||||
opened_raw = ai_mail.get("opened", 0)
|
||||
active_plans_raw = flow.get("active_plans", 0)
|
||||
commons_mentions_raw = commons.get("mentions", 0)
|
||||
|
||||
new_mail = len(new_mail_raw) if isinstance(new_mail_raw, list) else int(new_mail_raw or 0)
|
||||
opened_mail = len(opened_raw) if isinstance(opened_raw, list) else int(opened_raw or 0)
|
||||
active_plans = len(active_plans_raw) if isinstance(active_plans_raw, list) else int(active_plans_raw or 0)
|
||||
commons_mentions = (
|
||||
len(commons_mentions_raw) if isinstance(commons_mentions_raw, list) else int(commons_mentions_raw or 0)
|
||||
)
|
||||
|
||||
action_required = new_mail > 0 or active_plans > 0
|
||||
action_required = new_mail > 0 or active_plans > 0 or commons_mentions > 0
|
||||
|
||||
parts = []
|
||||
if new_mail > 0:
|
||||
@@ -221,11 +226,14 @@ def _calculate_quick_status_standalone(sections: Dict) -> Dict:
|
||||
parts.append(f"{opened_mail} opened")
|
||||
if active_plans > 0:
|
||||
parts.append(f"{active_plans} active plans")
|
||||
if commons_mentions > 0:
|
||||
parts.append(f"{commons_mentions} mentions")
|
||||
|
||||
return {
|
||||
"new_mail": new_mail,
|
||||
"opened_mail": opened_mail,
|
||||
"active_plans": active_plans,
|
||||
"commons_mentions": commons_mentions,
|
||||
"action_required": action_required,
|
||||
"summary": ", ".join(parts) if parts else "All clear",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user