From e5f0d4f1c484f4d9b83acb4a2baeea2caf1fc3b5 Mon Sep 17 00:00:00 2001 From: AIPass Date: Wed, 25 Mar 2026 01:10:22 -0700 Subject: [PATCH] S56: spawn template overhaul + system-wide README push + .gitkeep cleanup (#129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Spawn template system rebuilt: regenerate-registry command (3-pass ID matching), registry 26→41 files, generate_branch_meta fixed, Phase 0 snapshot added - System-wide push: 12/12 branches updated (227 additions, 0 errors) - READMEs added to all standard directories across 15 branches - .claude/settings.local.json tracked system-wide (deny rules) - 35 .gitkeep files removed (replaced by READMEs) - Bypass files updated across 13 branches - Bugs fixed: manager citizen_class crash, backup rglob performance Co-authored-by: Claude Opus 4.6 (1M context) --- .gitignore | 2 +- src/aipass/ai_mail/.aipass/README.md | 3 + src/aipass/ai_mail/.claude/README.md | 5 + .../ai_mail/.claude/settings.local.json | 28 ++ src/aipass/ai_mail/.seedgo/README.md | 5 + src/aipass/ai_mail/.seedgo/bypass.json | 6 +- src/aipass/ai_mail/apps/README.md | 8 + src/aipass/ai_mail/apps/handlers/README.md | 5 + src/aipass/ai_mail/apps/modules/README.md | 5 + src/aipass/ai_mail/apps/plugins/README.md | 5 + src/aipass/ai_mail/docs/README.md | 3 + src/aipass/ai_mail/templates/README.md | 5 + src/aipass/ai_mail/tests/README.md | 6 + src/aipass/api/.aipass/README.md | 3 + src/aipass/api/.claude/README.md | 5 + src/aipass/api/.claude/settings.local.json | 28 ++ src/aipass/api/.seedgo/README.md | 5 + src/aipass/api/.seedgo/bypass.json | 6 +- src/aipass/api/apps/README.md | 8 + src/aipass/api/apps/handlers/README.md | 5 + src/aipass/api/apps/modules/README.md | 5 + src/aipass/api/apps/plugins/README.md | 5 + src/aipass/api/templates/README.md | 5 + src/aipass/api/tests/README.md | 6 + src/aipass/backup/.aipass/README.md | 3 + src/aipass/backup/.claude/README.md | 5 + src/aipass/backup/.claude/settings.local.json | 28 ++ src/aipass/backup/.seedgo/README.md | 5 + src/aipass/backup/.seedgo/bypass.json | 9 +- src/aipass/backup/docs/.gitkeep | 0 src/aipass/backup/templates/README.md | 5 + src/aipass/backup/tests/README.md | 6 + src/aipass/cli/.aipass/README.md | 3 + src/aipass/cli/.claude/README.md | 5 + src/aipass/cli/.claude/settings.local.json | 28 ++ src/aipass/cli/.seedgo/README.md | 5 + src/aipass/cli/.seedgo/bypass.json | 6 +- src/aipass/cli/apps/README.md | 8 + src/aipass/cli/apps/handlers/README.md | 5 + src/aipass/cli/apps/modules/README.md | 5 + src/aipass/cli/apps/plugins/README.md | 5 + src/aipass/cli/cli_json/.gitkeep | 0 src/aipass/cli/docs/.gitkeep | 0 src/aipass/cli/templates/README.md | 5 + src/aipass/cli/tests/README.md | 6 + src/aipass/daemon/.aipass/README.md | 3 + src/aipass/daemon/.claude/README.md | 5 + src/aipass/daemon/.claude/settings.local.json | 28 ++ src/aipass/daemon/.seedgo/README.md | 5 + src/aipass/daemon/.seedgo/bypass.json | 6 +- src/aipass/daemon/apps/README.md | 8 + src/aipass/daemon/apps/handlers/README.md | 5 + src/aipass/daemon/apps/modules/README.md | 5 + src/aipass/daemon/apps/plugins/README.md | 5 + src/aipass/daemon/docs/.gitkeep | 0 src/aipass/daemon/docs/README.md | 3 + src/aipass/daemon/templates/README.md | 5 + src/aipass/daemon/tests/README.md | 6 + src/aipass/devpulse/.aipass/README.md | 3 + src/aipass/devpulse/.claude/README.md | 5 + .../devpulse/.claude/settings.local.json | 9 - src/aipass/devpulse/.seedgo/README.md | 5 + src/aipass/devpulse/.seedgo/bypass.json | 24 +- src/aipass/devpulse/apps/README.md | 8 + src/aipass/devpulse/apps/__init__.py | 1 + src/aipass/devpulse/apps/devpulse.py | 86 +++++ src/aipass/devpulse/apps/handlers/README.md | 5 + .../apps/handlers/__init__.py} | 0 src/aipass/devpulse/apps/modules/README.md | 5 + .../apps/modules/__init__.py} | 0 src/aipass/devpulse/apps/plugins/README.md | 5 + .../apps/plugins/__init__.py} | 0 src/aipass/devpulse/devpulse_json/.gitkeep | 0 src/aipass/devpulse/docs/.gitkeep | 0 src/aipass/devpulse/docs/README.md | 3 + src/aipass/devpulse/templates/README.md | 5 + src/aipass/devpulse/tests/README.md | 6 + src/aipass/drone/.aipass/README.md | 3 + src/aipass/drone/.claude/README.md | 5 + src/aipass/drone/.claude/settings.local.json | 25 ++ src/aipass/drone/.seedgo/README.md | 5 + src/aipass/drone/.seedgo/bypass.json | 18 +- src/aipass/drone/apps/README.md | 8 + src/aipass/drone/apps/handlers/README.md | 5 + src/aipass/drone/apps/modules/README.md | 5 + src/aipass/drone/apps/plugins/README.md | 5 + src/aipass/drone/docs/.gitkeep | 0 src/aipass/drone/docs/README.md | 3 + src/aipass/drone/drone_json/.gitkeep | 0 src/aipass/drone/templates/README.md | 5 + src/aipass/drone/tests/README.md | 6 + src/aipass/flow/.aipass/README.md | 3 + src/aipass/flow/.claude/README.md | 5 + src/aipass/flow/.claude/settings.local.json | 28 ++ src/aipass/flow/.seedgo/README.md | 5 + src/aipass/flow/.seedgo/bypass.json | 6 +- src/aipass/flow/apps/README.md | 8 + src/aipass/flow/apps/handlers/README.md | 5 + src/aipass/flow/apps/modules/README.md | 5 + src/aipass/flow/apps/plugins/README.md | 5 + src/aipass/flow/docs/README.md | 3 + src/aipass/flow/templates/README.md | 5 + src/aipass/flow/tests/README.md | 6 + src/aipass/memory/.aipass/README.md | 3 + src/aipass/memory/.claude/README.md | 5 + src/aipass/memory/.claude/settings.local.json | 28 ++ src/aipass/memory/.seedgo/README.md | 5 + src/aipass/memory/.seedgo/bypass.json | 24 +- src/aipass/memory/apps/README.md | 8 + src/aipass/memory/apps/handlers/README.md | 5 + src/aipass/memory/apps/modules/README.md | 5 + src/aipass/memory/apps/plugins/README.md | 5 + src/aipass/memory/docs/.gitkeep | 0 src/aipass/memory/docs/README.md | 3 + src/aipass/memory/templates/README.md | 5 + src/aipass/memory/tests/README.md | 6 + src/aipass/prax/.aipass/README.md | 3 + src/aipass/prax/.claude/README.md | 5 + src/aipass/prax/.claude/settings.local.json | 28 ++ src/aipass/prax/.seedgo/README.md | 5 + src/aipass/prax/.seedgo/bypass.json | 29 +- src/aipass/prax/apps/README.md | 8 + src/aipass/prax/apps/handlers/README.md | 5 + src/aipass/prax/apps/modules/README.md | 5 + src/aipass/prax/apps/plugins/README.md | 5 + src/aipass/prax/docs/.gitkeep | 0 src/aipass/prax/docs/README.md | 3 + src/aipass/prax/prax_json/.gitkeep | 0 src/aipass/prax/templates/README.md | 5 + src/aipass/prax/tests/README.md | 6 + src/aipass/seedgo/.aipass/README.md | 3 + src/aipass/seedgo/.claude/README.md | 5 + src/aipass/seedgo/.claude/settings.local.json | 28 ++ src/aipass/seedgo/.seedgo/README.md | 5 + src/aipass/seedgo/.seedgo/bypass.json | 22 +- src/aipass/seedgo/apps/README.md | 8 + src/aipass/seedgo/apps/handlers/README.md | 5 + src/aipass/seedgo/apps/modules/README.md | 5 + src/aipass/seedgo/apps/plugins/README.md | 5 + src/aipass/seedgo/seedgo_json/.gitkeep | 0 src/aipass/seedgo/templates/README.md | 5 + src/aipass/seedgo/tests/README.md | 6 + src/aipass/spawn/.claude/settings.local.json | 28 ++ src/aipass/spawn/.seedgo/bypass.json | 20 ++ .../spawn/apps/handlers/change_detection.py | 37 ++- src/aipass/spawn/apps/handlers/meta_ops.py | 132 +++++--- .../apps/handlers/regenerate_registry_ops.py | 291 +++++++++++++++++ src/aipass/spawn/apps/handlers/update_ops.py | 24 +- .../spawn/apps/modules/regenerate_registry.py | 195 ++++++++++++ src/aipass/spawn/apps/spawn.py | 14 +- src/aipass/spawn/docs/.gitkeep | 0 src/aipass/spawn/spawn_json/.gitkeep | 0 .../builder/.spawn/.template_registry.json | 299 +++++++++++++----- src/aipass/trigger/.aipass/README.md | 3 + src/aipass/trigger/.claude/README.md | 5 + .../trigger/.claude/settings.local.json | 28 ++ src/aipass/trigger/.seedgo/README.md | 5 + src/aipass/trigger/.seedgo/bypass.json | 98 ++++-- src/aipass/trigger/apps/README.md | 8 + src/aipass/trigger/apps/handlers/README.md | 5 + src/aipass/trigger/apps/modules/README.md | 5 + src/aipass/trigger/apps/plugins/README.md | 5 + src/aipass/trigger/docs/README.md | 3 + src/aipass/trigger/templates/README.md | 5 + src/aipass/trigger/tests/README.md | 6 + src/aipass/trigger/trigger_json/.gitkeep | 0 src/commons/.claude/settings.local.json | 28 ++ src/skills/.claude/settings.local.json | 28 ++ 168 files changed, 2067 insertions(+), 251 deletions(-) create mode 100644 src/aipass/ai_mail/.aipass/README.md create mode 100644 src/aipass/ai_mail/.claude/README.md create mode 100644 src/aipass/ai_mail/.claude/settings.local.json create mode 100644 src/aipass/ai_mail/.seedgo/README.md create mode 100644 src/aipass/ai_mail/apps/README.md create mode 100644 src/aipass/ai_mail/apps/handlers/README.md create mode 100644 src/aipass/ai_mail/apps/modules/README.md create mode 100644 src/aipass/ai_mail/apps/plugins/README.md create mode 100644 src/aipass/ai_mail/docs/README.md create mode 100644 src/aipass/ai_mail/templates/README.md create mode 100644 src/aipass/ai_mail/tests/README.md create mode 100644 src/aipass/api/.aipass/README.md create mode 100644 src/aipass/api/.claude/README.md create mode 100644 src/aipass/api/.claude/settings.local.json create mode 100644 src/aipass/api/.seedgo/README.md create mode 100644 src/aipass/api/apps/README.md create mode 100644 src/aipass/api/apps/handlers/README.md create mode 100644 src/aipass/api/apps/modules/README.md create mode 100644 src/aipass/api/apps/plugins/README.md create mode 100644 src/aipass/api/templates/README.md create mode 100644 src/aipass/api/tests/README.md create mode 100644 src/aipass/backup/.aipass/README.md create mode 100644 src/aipass/backup/.claude/README.md create mode 100644 src/aipass/backup/.claude/settings.local.json create mode 100644 src/aipass/backup/.seedgo/README.md delete mode 100644 src/aipass/backup/docs/.gitkeep create mode 100644 src/aipass/backup/templates/README.md create mode 100644 src/aipass/backup/tests/README.md create mode 100644 src/aipass/cli/.aipass/README.md create mode 100644 src/aipass/cli/.claude/README.md create mode 100644 src/aipass/cli/.claude/settings.local.json create mode 100644 src/aipass/cli/.seedgo/README.md create mode 100644 src/aipass/cli/apps/README.md create mode 100644 src/aipass/cli/apps/handlers/README.md create mode 100644 src/aipass/cli/apps/modules/README.md create mode 100644 src/aipass/cli/apps/plugins/README.md delete mode 100644 src/aipass/cli/cli_json/.gitkeep delete mode 100644 src/aipass/cli/docs/.gitkeep create mode 100644 src/aipass/cli/templates/README.md create mode 100644 src/aipass/cli/tests/README.md create mode 100644 src/aipass/daemon/.aipass/README.md create mode 100644 src/aipass/daemon/.claude/README.md create mode 100644 src/aipass/daemon/.claude/settings.local.json create mode 100644 src/aipass/daemon/.seedgo/README.md create mode 100644 src/aipass/daemon/apps/README.md create mode 100644 src/aipass/daemon/apps/handlers/README.md create mode 100644 src/aipass/daemon/apps/modules/README.md create mode 100644 src/aipass/daemon/apps/plugins/README.md delete mode 100644 src/aipass/daemon/docs/.gitkeep create mode 100644 src/aipass/daemon/docs/README.md create mode 100644 src/aipass/daemon/templates/README.md create mode 100644 src/aipass/daemon/tests/README.md create mode 100644 src/aipass/devpulse/.aipass/README.md create mode 100644 src/aipass/devpulse/.claude/README.md create mode 100644 src/aipass/devpulse/.seedgo/README.md create mode 100644 src/aipass/devpulse/apps/README.md create mode 100644 src/aipass/devpulse/apps/__init__.py create mode 100644 src/aipass/devpulse/apps/devpulse.py create mode 100644 src/aipass/devpulse/apps/handlers/README.md rename src/aipass/{ai_mail/ai_mail_json/.gitkeep => devpulse/apps/handlers/__init__.py} (100%) create mode 100644 src/aipass/devpulse/apps/modules/README.md rename src/aipass/{ai_mail/docs/.gitkeep => devpulse/apps/modules/__init__.py} (100%) create mode 100644 src/aipass/devpulse/apps/plugins/README.md rename src/aipass/{api/docs/.gitkeep => devpulse/apps/plugins/__init__.py} (100%) delete mode 100644 src/aipass/devpulse/devpulse_json/.gitkeep delete mode 100644 src/aipass/devpulse/docs/.gitkeep create mode 100644 src/aipass/devpulse/docs/README.md create mode 100644 src/aipass/devpulse/templates/README.md create mode 100644 src/aipass/devpulse/tests/README.md create mode 100644 src/aipass/drone/.aipass/README.md create mode 100644 src/aipass/drone/.claude/README.md create mode 100644 src/aipass/drone/.claude/settings.local.json create mode 100644 src/aipass/drone/.seedgo/README.md create mode 100644 src/aipass/drone/apps/README.md create mode 100644 src/aipass/drone/apps/handlers/README.md create mode 100644 src/aipass/drone/apps/modules/README.md create mode 100644 src/aipass/drone/apps/plugins/README.md delete mode 100644 src/aipass/drone/docs/.gitkeep create mode 100644 src/aipass/drone/docs/README.md delete mode 100644 src/aipass/drone/drone_json/.gitkeep create mode 100644 src/aipass/drone/templates/README.md create mode 100644 src/aipass/drone/tests/README.md create mode 100644 src/aipass/flow/.aipass/README.md create mode 100644 src/aipass/flow/.claude/README.md create mode 100644 src/aipass/flow/.claude/settings.local.json create mode 100644 src/aipass/flow/.seedgo/README.md create mode 100644 src/aipass/flow/apps/README.md create mode 100644 src/aipass/flow/apps/handlers/README.md create mode 100644 src/aipass/flow/apps/modules/README.md create mode 100644 src/aipass/flow/apps/plugins/README.md create mode 100644 src/aipass/flow/docs/README.md create mode 100644 src/aipass/flow/templates/README.md create mode 100644 src/aipass/flow/tests/README.md create mode 100644 src/aipass/memory/.aipass/README.md create mode 100644 src/aipass/memory/.claude/README.md create mode 100644 src/aipass/memory/.claude/settings.local.json create mode 100644 src/aipass/memory/.seedgo/README.md create mode 100644 src/aipass/memory/apps/README.md create mode 100644 src/aipass/memory/apps/handlers/README.md create mode 100644 src/aipass/memory/apps/modules/README.md create mode 100644 src/aipass/memory/apps/plugins/README.md delete mode 100644 src/aipass/memory/docs/.gitkeep create mode 100644 src/aipass/memory/docs/README.md create mode 100644 src/aipass/memory/templates/README.md create mode 100644 src/aipass/memory/tests/README.md create mode 100644 src/aipass/prax/.aipass/README.md create mode 100644 src/aipass/prax/.claude/README.md create mode 100644 src/aipass/prax/.claude/settings.local.json create mode 100644 src/aipass/prax/.seedgo/README.md create mode 100644 src/aipass/prax/apps/README.md create mode 100644 src/aipass/prax/apps/handlers/README.md create mode 100644 src/aipass/prax/apps/modules/README.md create mode 100644 src/aipass/prax/apps/plugins/README.md delete mode 100644 src/aipass/prax/docs/.gitkeep create mode 100644 src/aipass/prax/docs/README.md delete mode 100644 src/aipass/prax/prax_json/.gitkeep create mode 100644 src/aipass/prax/templates/README.md create mode 100644 src/aipass/prax/tests/README.md create mode 100644 src/aipass/seedgo/.aipass/README.md create mode 100644 src/aipass/seedgo/.claude/README.md create mode 100644 src/aipass/seedgo/.claude/settings.local.json create mode 100644 src/aipass/seedgo/.seedgo/README.md create mode 100644 src/aipass/seedgo/apps/README.md create mode 100644 src/aipass/seedgo/apps/handlers/README.md create mode 100644 src/aipass/seedgo/apps/modules/README.md create mode 100644 src/aipass/seedgo/apps/plugins/README.md delete mode 100644 src/aipass/seedgo/seedgo_json/.gitkeep create mode 100644 src/aipass/seedgo/templates/README.md create mode 100644 src/aipass/seedgo/tests/README.md create mode 100644 src/aipass/spawn/.claude/settings.local.json create mode 100644 src/aipass/spawn/apps/handlers/regenerate_registry_ops.py create mode 100644 src/aipass/spawn/apps/modules/regenerate_registry.py delete mode 100644 src/aipass/spawn/docs/.gitkeep delete mode 100644 src/aipass/spawn/spawn_json/.gitkeep create mode 100644 src/aipass/trigger/.aipass/README.md create mode 100644 src/aipass/trigger/.claude/README.md create mode 100644 src/aipass/trigger/.claude/settings.local.json create mode 100644 src/aipass/trigger/.seedgo/README.md create mode 100644 src/aipass/trigger/apps/README.md create mode 100644 src/aipass/trigger/apps/handlers/README.md create mode 100644 src/aipass/trigger/apps/modules/README.md create mode 100644 src/aipass/trigger/apps/plugins/README.md create mode 100644 src/aipass/trigger/docs/README.md create mode 100644 src/aipass/trigger/templates/README.md create mode 100644 src/aipass/trigger/tests/README.md delete mode 100644 src/aipass/trigger/trigger_json/.gitkeep create mode 100644 src/commons/.claude/settings.local.json create mode 100644 src/skills/.claude/settings.local.json diff --git a/.gitignore b/.gitignore index 258b2429..bb475e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,7 @@ docs.local/ # Claude Code local state .claude/hooks/__pycache__/ .claude/hooks/.last_diagnostics_file -**/.claude/settings.local.json +# **/.claude/settings.local.json — UNIGNORED: deny rules are system config that must travel with PRs # Disabled files (AIPass convention: rename with (disabled) instead of delete) *(disabled) diff --git a/src/aipass/ai_mail/.aipass/README.md b/src/aipass/ai_mail/.aipass/README.md new file mode 100644 index 00000000..345300f3 --- /dev/null +++ b/src/aipass/ai_mail/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `AI_MAIL`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/ai_mail/.claude/README.md b/src/aipass/ai_mail/.claude/README.md new file mode 100644 index 00000000..a99df140 --- /dev/null +++ b/src/aipass/ai_mail/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `AI_MAIL`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/ai_mail/.claude/settings.local.json b/src/aipass/ai_mail/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/ai_mail/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/ai_mail/.seedgo/README.md b/src/aipass/ai_mail/.seedgo/README.md new file mode 100644 index 00000000..ee64245a --- /dev/null +++ b/src/aipass/ai_mail/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `AI_MAIL`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/ai_mail/.seedgo/bypass.json b/src/aipass/ai_mail/.seedgo/bypass.json index c749d98b..f1c93755 100644 --- a/src/aipass/ai_mail/.seedgo/bypass.json +++ b/src/aipass/ai_mail/.seedgo/bypass.json @@ -231,12 +231,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -246,4 +246,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/ai_mail/apps/README.md b/src/aipass/ai_mail/apps/README.md new file mode 100644 index 00000000..6799e19d --- /dev/null +++ b/src/aipass/ai_mail/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `AI_MAIL`. + +- `ai_mail.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/ai_mail/apps/handlers/README.md b/src/aipass/ai_mail/apps/handlers/README.md new file mode 100644 index 00000000..1d2bc1fa --- /dev/null +++ b/src/aipass/ai_mail/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `AI_MAIL`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/ai_mail/apps/modules/README.md b/src/aipass/ai_mail/apps/modules/README.md new file mode 100644 index 00000000..c55ff124 --- /dev/null +++ b/src/aipass/ai_mail/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `AI_MAIL`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/ai_mail/apps/plugins/README.md b/src/aipass/ai_mail/apps/plugins/README.md new file mode 100644 index 00000000..169f2999 --- /dev/null +++ b/src/aipass/ai_mail/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `AI_MAIL`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/ai_mail/docs/README.md b/src/aipass/ai_mail/docs/README.md new file mode 100644 index 00000000..3123746f --- /dev/null +++ b/src/aipass/ai_mail/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `AI_MAIL` branch. diff --git a/src/aipass/ai_mail/templates/README.md b/src/aipass/ai_mail/templates/README.md new file mode 100644 index 00000000..581e7ce5 --- /dev/null +++ b/src/aipass/ai_mail/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `AI_MAIL`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/ai_mail/tests/README.md b/src/aipass/ai_mail/tests/README.md new file mode 100644 index 00000000..f2b39f59 --- /dev/null +++ b/src/aipass/ai_mail/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `AI_MAIL`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/api/.aipass/README.md b/src/aipass/api/.aipass/README.md new file mode 100644 index 00000000..db729ac8 --- /dev/null +++ b/src/aipass/api/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `API`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/api/.claude/README.md b/src/aipass/api/.claude/README.md new file mode 100644 index 00000000..dd9e96b4 --- /dev/null +++ b/src/aipass/api/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `API`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/api/.claude/settings.local.json b/src/aipass/api/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/api/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/api/.seedgo/README.md b/src/aipass/api/.seedgo/README.md new file mode 100644 index 00000000..59fdc4be --- /dev/null +++ b/src/aipass/api/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `API`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/api/.seedgo/bypass.json b/src/aipass/api/.seedgo/bypass.json index 29ddf307..855b826f 100644 --- a/src/aipass/api/.seedgo/bypass.json +++ b/src/aipass/api/.seedgo/bypass.json @@ -86,12 +86,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -101,4 +101,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/api/apps/README.md b/src/aipass/api/apps/README.md new file mode 100644 index 00000000..8d9316e1 --- /dev/null +++ b/src/aipass/api/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `API`. + +- `api.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/api/apps/handlers/README.md b/src/aipass/api/apps/handlers/README.md new file mode 100644 index 00000000..e2cbe0e5 --- /dev/null +++ b/src/aipass/api/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `API`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/api/apps/modules/README.md b/src/aipass/api/apps/modules/README.md new file mode 100644 index 00000000..b7be611c --- /dev/null +++ b/src/aipass/api/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `API`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/api/apps/plugins/README.md b/src/aipass/api/apps/plugins/README.md new file mode 100644 index 00000000..a1cbf5d4 --- /dev/null +++ b/src/aipass/api/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `API`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/api/templates/README.md b/src/aipass/api/templates/README.md new file mode 100644 index 00000000..bd5ca9f6 --- /dev/null +++ b/src/aipass/api/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `API`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/api/tests/README.md b/src/aipass/api/tests/README.md new file mode 100644 index 00000000..1f7e37e7 --- /dev/null +++ b/src/aipass/api/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `API`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/backup/.aipass/README.md b/src/aipass/backup/.aipass/README.md new file mode 100644 index 00000000..c3995906 --- /dev/null +++ b/src/aipass/backup/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `BACKUP`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/backup/.claude/README.md b/src/aipass/backup/.claude/README.md new file mode 100644 index 00000000..c7d18886 --- /dev/null +++ b/src/aipass/backup/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `BACKUP`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/backup/.claude/settings.local.json b/src/aipass/backup/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/backup/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/backup/.seedgo/README.md b/src/aipass/backup/.seedgo/README.md new file mode 100644 index 00000000..90da9178 --- /dev/null +++ b/src/aipass/backup/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `BACKUP`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/backup/.seedgo/bypass.json b/src/aipass/backup/.seedgo/bypass.json index 4f971286..9bb2c538 100644 --- a/src/aipass/backup/.seedgo/bypass.json +++ b/src/aipass/backup/.seedgo/bypass.json @@ -35,7 +35,6 @@ "standard": "deep_nesting", "reason": "SKIP — file is being rewritten. 6 functions flagged (depth 4-5)." }, - { "file": "apps/handlers/operations/file_operations.py", "standard": "architecture", @@ -81,7 +80,6 @@ "standard": "architecture", "reason": "utils/ contains cross-cutting utilities. backup_timestamps is used by both backup_core and google_drive_sync — belongs to no single domain." }, - { "file": "apps/handlers/json/statistics_handler.py", "standard": "handlers", @@ -122,7 +120,6 @@ "standard": "handlers", "reason": "Imports BackupResult model from models/ — report formatting needs the result data model. Models are the shared contract between handlers." }, - { "file": "apps/modules/google_drive_sync.py", "standard": "naming", @@ -154,12 +151,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -169,4 +166,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/backup/docs/.gitkeep b/src/aipass/backup/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/backup/templates/README.md b/src/aipass/backup/templates/README.md new file mode 100644 index 00000000..b4d52f82 --- /dev/null +++ b/src/aipass/backup/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `BACKUP`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/backup/tests/README.md b/src/aipass/backup/tests/README.md new file mode 100644 index 00000000..771c247f --- /dev/null +++ b/src/aipass/backup/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `BACKUP`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/cli/.aipass/README.md b/src/aipass/cli/.aipass/README.md new file mode 100644 index 00000000..ec10353e --- /dev/null +++ b/src/aipass/cli/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `CLI`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/cli/.claude/README.md b/src/aipass/cli/.claude/README.md new file mode 100644 index 00000000..f623cb96 --- /dev/null +++ b/src/aipass/cli/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `CLI`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/cli/.claude/settings.local.json b/src/aipass/cli/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/cli/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/cli/.seedgo/README.md b/src/aipass/cli/.seedgo/README.md new file mode 100644 index 00000000..b76fe7fe --- /dev/null +++ b/src/aipass/cli/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `CLI`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/cli/.seedgo/bypass.json b/src/aipass/cli/.seedgo/bypass.json index 469819b1..036dd4f9 100644 --- a/src/aipass/cli/.seedgo/bypass.json +++ b/src/aipass/cli/.seedgo/bypass.json @@ -73,12 +73,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -88,4 +88,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/cli/apps/README.md b/src/aipass/cli/apps/README.md new file mode 100644 index 00000000..65d95db2 --- /dev/null +++ b/src/aipass/cli/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `CLI`. + +- `cli.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/cli/apps/handlers/README.md b/src/aipass/cli/apps/handlers/README.md new file mode 100644 index 00000000..156dcbdc --- /dev/null +++ b/src/aipass/cli/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `CLI`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/cli/apps/modules/README.md b/src/aipass/cli/apps/modules/README.md new file mode 100644 index 00000000..4fe501b6 --- /dev/null +++ b/src/aipass/cli/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `CLI`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/cli/apps/plugins/README.md b/src/aipass/cli/apps/plugins/README.md new file mode 100644 index 00000000..1644fb9e --- /dev/null +++ b/src/aipass/cli/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `CLI`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/cli/cli_json/.gitkeep b/src/aipass/cli/cli_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/cli/docs/.gitkeep b/src/aipass/cli/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/cli/templates/README.md b/src/aipass/cli/templates/README.md new file mode 100644 index 00000000..b5591f95 --- /dev/null +++ b/src/aipass/cli/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `CLI`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/cli/tests/README.md b/src/aipass/cli/tests/README.md new file mode 100644 index 00000000..dbc28d44 --- /dev/null +++ b/src/aipass/cli/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `CLI`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/daemon/.aipass/README.md b/src/aipass/daemon/.aipass/README.md new file mode 100644 index 00000000..e14a536a --- /dev/null +++ b/src/aipass/daemon/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `DAEMON`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/daemon/.claude/README.md b/src/aipass/daemon/.claude/README.md new file mode 100644 index 00000000..23885aea --- /dev/null +++ b/src/aipass/daemon/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `DAEMON`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/daemon/.claude/settings.local.json b/src/aipass/daemon/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/daemon/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/daemon/.seedgo/README.md b/src/aipass/daemon/.seedgo/README.md new file mode 100644 index 00000000..f7a81aa1 --- /dev/null +++ b/src/aipass/daemon/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `DAEMON`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/daemon/.seedgo/bypass.json b/src/aipass/daemon/.seedgo/bypass.json index ceb0fb27..7a640a44 100644 --- a/src/aipass/daemon/.seedgo/bypass.json +++ b/src/aipass/daemon/.seedgo/bypass.json @@ -10,12 +10,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -25,4 +25,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/daemon/apps/README.md b/src/aipass/daemon/apps/README.md new file mode 100644 index 00000000..cdab7970 --- /dev/null +++ b/src/aipass/daemon/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `DAEMON`. + +- `daemon.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/daemon/apps/handlers/README.md b/src/aipass/daemon/apps/handlers/README.md new file mode 100644 index 00000000..dfb2ece9 --- /dev/null +++ b/src/aipass/daemon/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `DAEMON`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/daemon/apps/modules/README.md b/src/aipass/daemon/apps/modules/README.md new file mode 100644 index 00000000..d4617cb5 --- /dev/null +++ b/src/aipass/daemon/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `DAEMON`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/daemon/apps/plugins/README.md b/src/aipass/daemon/apps/plugins/README.md new file mode 100644 index 00000000..5168dc78 --- /dev/null +++ b/src/aipass/daemon/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `DAEMON`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/daemon/docs/.gitkeep b/src/aipass/daemon/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/daemon/docs/README.md b/src/aipass/daemon/docs/README.md new file mode 100644 index 00000000..bb09ba70 --- /dev/null +++ b/src/aipass/daemon/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `DAEMON` branch. diff --git a/src/aipass/daemon/templates/README.md b/src/aipass/daemon/templates/README.md new file mode 100644 index 00000000..dc4f4f38 --- /dev/null +++ b/src/aipass/daemon/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `DAEMON`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/daemon/tests/README.md b/src/aipass/daemon/tests/README.md new file mode 100644 index 00000000..e8a48ea8 --- /dev/null +++ b/src/aipass/daemon/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `DAEMON`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/devpulse/.aipass/README.md b/src/aipass/devpulse/.aipass/README.md new file mode 100644 index 00000000..dd30ac10 --- /dev/null +++ b/src/aipass/devpulse/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `DEVPULSE`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/devpulse/.claude/README.md b/src/aipass/devpulse/.claude/README.md new file mode 100644 index 00000000..c2127cf7 --- /dev/null +++ b/src/aipass/devpulse/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `DEVPULSE`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/devpulse/.claude/settings.local.json b/src/aipass/devpulse/.claude/settings.local.json index 8af63165..e6c73a43 100644 --- a/src/aipass/devpulse/.claude/settings.local.json +++ b/src/aipass/devpulse/.claude/settings.local.json @@ -2,16 +2,8 @@ "permissions": { "allow": [], "deny": [ - "Bash(git reset*)", - "Bash(git rebase*)", - "Bash(git merge*)", - "Bash(git config*)", "Bash(git push --force*)", "Bash(git push -f *)", - "Bash(git checkout -- *)", - "Bash(git checkout .*)", - "Bash(git restore --staged*)", - "Bash(git restore .*)", "Bash(git clean*)", "Bash(git branch -D*)", "Bash(git stash drop*)", @@ -21,7 +13,6 @@ "Bash(git checkout -b*)", "Bash(git commit*)", "Bash(git push*)", - "Bash(git add*)", "Bash(gh pr create*)", "Bash(gh pr close*)" ], diff --git a/src/aipass/devpulse/.seedgo/README.md b/src/aipass/devpulse/.seedgo/README.md new file mode 100644 index 00000000..6362bee0 --- /dev/null +++ b/src/aipass/devpulse/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `DEVPULSE`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/devpulse/.seedgo/bypass.json b/src/aipass/devpulse/.seedgo/bypass.json index 0967ef42..5fa3a8c6 100644 --- a/src/aipass/devpulse/.seedgo/bypass.json +++ b/src/aipass/devpulse/.seedgo/bypass.json @@ -1 +1,23 @@ -{} +{ + "metadata": { + "version": "1.0.0", + "created": "2026-03-25", + "description": "Standards bypass configuration for this branch" + }, + "bypass": [], + "notes": { + "usage": "Add entries to bypass specific seedgo standard violations", + "example": { + "file": "apps/example.py", + "standard": "imports", + "reason": "Legacy import required for compatibility" + }, + "fields": { + "file": "Relative path to the file", + "standard": "Which standard to bypass (imports, cli, naming, etc.)", + "lines": "Optional array of line numbers", + "pattern": "Optional regex pattern to match", + "reason": "Why this bypass exists" + } + } +} diff --git a/src/aipass/devpulse/apps/README.md b/src/aipass/devpulse/apps/README.md new file mode 100644 index 00000000..539a82d8 --- /dev/null +++ b/src/aipass/devpulse/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `DEVPULSE`. + +- `devpulse.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/devpulse/apps/__init__.py b/src/aipass/devpulse/apps/__init__.py new file mode 100644 index 00000000..e78baf1e --- /dev/null +++ b/src/aipass/devpulse/apps/__init__.py @@ -0,0 +1 @@ +# DEVPULSE apps package diff --git a/src/aipass/devpulse/apps/devpulse.py b/src/aipass/devpulse/apps/devpulse.py new file mode 100644 index 00000000..7d6debc9 --- /dev/null +++ b/src/aipass/devpulse/apps/devpulse.py @@ -0,0 +1,86 @@ +""" +DEVPULSE Branch - Main Orchestrator + +Auto-discovery architecture: +- Scans modules/ directory for .py files with handle_command() +- Routes commands to discovered modules automatically +- No manual imports or routing needed +""" + +import sys +import importlib +from pathlib import Path +from typing import List, Any + +from aipass.prax import logger + +# ============================================================================= +# MODULE DISCOVERY +# ============================================================================= + +MODULES_DIR = Path(__file__).parent / "modules" + + +def discover_modules() -> List[Any]: + """Auto-discover modules in modules/ directory.""" + modules = [] + + if not MODULES_DIR.exists(): + return modules + + for file_path in MODULES_DIR.glob("*.py"): + if file_path.name.startswith("_"): + continue + + module_name = f"apps.modules.{file_path.stem}" + + try: + module = importlib.import_module(module_name) + if hasattr(module, "handle_command"): + modules.append(module) + except Exception as e: + logger.error(f"[DEVPULSE] Failed to load module {module_name}: {e}") + + return modules + + +def route_command(command: str, args: List[str], modules: List[Any]) -> bool: + """Route command to appropriate module.""" + for module in modules: + try: + if module.handle_command(command, args): + return True + except Exception as e: + logger.error(f"[DEVPULSE] Module {module.__name__} error: {e}") + return False + + +# ============================================================================= +# MAIN ENTRY POINT +# ============================================================================= + +def main(): + """Main entry point - routes commands or shows help.""" + modules = discover_modules() + args = sys.argv[1:] + + if len(args) == 0 or args[0] in ["--help", "-h", "help"]: + print(f"DEVPULSE - {len(modules)} modules discovered") + for module in modules: + name = module.__name__.split(".")[-1] + desc = (module.__doc__ or "").strip().split("\n")[0] if module.__doc__ else "No description" + print(f" {name:20} {desc}") + return 0 + + command = args[0] + remaining = args[1:] if len(args) > 1 else [] + + if route_command(command, remaining, modules): + return 0 + + print(f"Unknown command: {command}") + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/aipass/devpulse/apps/handlers/README.md b/src/aipass/devpulse/apps/handlers/README.md new file mode 100644 index 00000000..92efb469 --- /dev/null +++ b/src/aipass/devpulse/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `DEVPULSE`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/ai_mail/ai_mail_json/.gitkeep b/src/aipass/devpulse/apps/handlers/__init__.py similarity index 100% rename from src/aipass/ai_mail/ai_mail_json/.gitkeep rename to src/aipass/devpulse/apps/handlers/__init__.py diff --git a/src/aipass/devpulse/apps/modules/README.md b/src/aipass/devpulse/apps/modules/README.md new file mode 100644 index 00000000..2c79ce71 --- /dev/null +++ b/src/aipass/devpulse/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `DEVPULSE`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/ai_mail/docs/.gitkeep b/src/aipass/devpulse/apps/modules/__init__.py similarity index 100% rename from src/aipass/ai_mail/docs/.gitkeep rename to src/aipass/devpulse/apps/modules/__init__.py diff --git a/src/aipass/devpulse/apps/plugins/README.md b/src/aipass/devpulse/apps/plugins/README.md new file mode 100644 index 00000000..79bf3c5e --- /dev/null +++ b/src/aipass/devpulse/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `DEVPULSE`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/api/docs/.gitkeep b/src/aipass/devpulse/apps/plugins/__init__.py similarity index 100% rename from src/aipass/api/docs/.gitkeep rename to src/aipass/devpulse/apps/plugins/__init__.py diff --git a/src/aipass/devpulse/devpulse_json/.gitkeep b/src/aipass/devpulse/devpulse_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/devpulse/docs/.gitkeep b/src/aipass/devpulse/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/devpulse/docs/README.md b/src/aipass/devpulse/docs/README.md new file mode 100644 index 00000000..d1eaca24 --- /dev/null +++ b/src/aipass/devpulse/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `DEVPULSE` branch. diff --git a/src/aipass/devpulse/templates/README.md b/src/aipass/devpulse/templates/README.md new file mode 100644 index 00000000..558f964c --- /dev/null +++ b/src/aipass/devpulse/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `DEVPULSE`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/devpulse/tests/README.md b/src/aipass/devpulse/tests/README.md new file mode 100644 index 00000000..fb723b8f --- /dev/null +++ b/src/aipass/devpulse/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `DEVPULSE`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/drone/.aipass/README.md b/src/aipass/drone/.aipass/README.md new file mode 100644 index 00000000..584dc253 --- /dev/null +++ b/src/aipass/drone/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `DRONE`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/drone/.claude/README.md b/src/aipass/drone/.claude/README.md new file mode 100644 index 00000000..775b743d --- /dev/null +++ b/src/aipass/drone/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `DRONE`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/drone/.claude/settings.local.json b/src/aipass/drone/.claude/settings.local.json new file mode 100644 index 00000000..b93ab209 --- /dev/null +++ b/src/aipass/drone/.claude/settings.local.json @@ -0,0 +1,25 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/drone/.seedgo/README.md b/src/aipass/drone/.seedgo/README.md new file mode 100644 index 00000000..ca603b1b --- /dev/null +++ b/src/aipass/drone/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `DRONE`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/drone/.seedgo/bypass.json b/src/aipass/drone/.seedgo/bypass.json index 89ae473a..e0cd655c 100644 --- a/src/aipass/drone/.seedgo/bypass.json +++ b/src/aipass/drone/.seedgo/bypass.json @@ -8,7 +8,10 @@ { "file": "apps/drone.py", "standard": "cli", - "lines": [166, 168], + "lines": [ + 166, + 168 + ], "reason": "Raw passthrough of module subprocess stdout/stderr — console.print() breaks routed output" }, { @@ -29,13 +32,17 @@ { "file": "apps/handlers/discovery_handler.py", "standard": "handlers", - "lines": [190], + "lines": [ + 190 + ], "reason": "Discovery handler needs registry_handler.load_registry() to resolve branch paths for help lookups. Justified cross-handler dependency — discovery is the only consumer." }, { "file": "apps/handlers/scanning/scanner.py", "standard": "handlers", - "lines": [29], + "lines": [ + 29 + ], "reason": "Scanner needs discovery_handler's get_entry_point() and parse_help_for_commands() to discover commands from branch help output. Justified — scanner's core function depends on discovery's parsing." }, { @@ -120,6 +127,11 @@ ], "notes": { "usage": "Add entries to 'bypass' list to exclude specific violations", + "example": { + "file": "apps/example.py", + "standard": "imports", + "reason": "Legacy import required for compatibility" + }, "fields": { "file": "Relative path from branch root (required)", "standard": "Standard name: cli, imports, naming, etc. (required)", diff --git a/src/aipass/drone/apps/README.md b/src/aipass/drone/apps/README.md new file mode 100644 index 00000000..32d47234 --- /dev/null +++ b/src/aipass/drone/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `DRONE`. + +- `drone.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/drone/apps/handlers/README.md b/src/aipass/drone/apps/handlers/README.md new file mode 100644 index 00000000..903ad938 --- /dev/null +++ b/src/aipass/drone/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `DRONE`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/drone/apps/modules/README.md b/src/aipass/drone/apps/modules/README.md new file mode 100644 index 00000000..6ce5eee4 --- /dev/null +++ b/src/aipass/drone/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `DRONE`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/drone/apps/plugins/README.md b/src/aipass/drone/apps/plugins/README.md new file mode 100644 index 00000000..9261df51 --- /dev/null +++ b/src/aipass/drone/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `DRONE`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/drone/docs/.gitkeep b/src/aipass/drone/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/drone/docs/README.md b/src/aipass/drone/docs/README.md new file mode 100644 index 00000000..4665bd6f --- /dev/null +++ b/src/aipass/drone/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `DRONE` branch. diff --git a/src/aipass/drone/drone_json/.gitkeep b/src/aipass/drone/drone_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/drone/templates/README.md b/src/aipass/drone/templates/README.md new file mode 100644 index 00000000..4c37ff3a --- /dev/null +++ b/src/aipass/drone/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `DRONE`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/drone/tests/README.md b/src/aipass/drone/tests/README.md new file mode 100644 index 00000000..e36180ea --- /dev/null +++ b/src/aipass/drone/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `DRONE`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/flow/.aipass/README.md b/src/aipass/flow/.aipass/README.md new file mode 100644 index 00000000..7770fcb4 --- /dev/null +++ b/src/aipass/flow/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `FLOW`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/flow/.claude/README.md b/src/aipass/flow/.claude/README.md new file mode 100644 index 00000000..b44d79c0 --- /dev/null +++ b/src/aipass/flow/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `FLOW`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/flow/.claude/settings.local.json b/src/aipass/flow/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/flow/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/flow/.seedgo/README.md b/src/aipass/flow/.seedgo/README.md new file mode 100644 index 00000000..0f36e0d6 --- /dev/null +++ b/src/aipass/flow/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `FLOW`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/flow/.seedgo/bypass.json b/src/aipass/flow/.seedgo/bypass.json index d03a2da5..92f1dadc 100644 --- a/src/aipass/flow/.seedgo/bypass.json +++ b/src/aipass/flow/.seedgo/bypass.json @@ -413,12 +413,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -428,4 +428,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/flow/apps/README.md b/src/aipass/flow/apps/README.md new file mode 100644 index 00000000..eab2eb02 --- /dev/null +++ b/src/aipass/flow/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `FLOW`. + +- `flow.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/flow/apps/handlers/README.md b/src/aipass/flow/apps/handlers/README.md new file mode 100644 index 00000000..532f33be --- /dev/null +++ b/src/aipass/flow/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `FLOW`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/flow/apps/modules/README.md b/src/aipass/flow/apps/modules/README.md new file mode 100644 index 00000000..d62e582b --- /dev/null +++ b/src/aipass/flow/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `FLOW`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/flow/apps/plugins/README.md b/src/aipass/flow/apps/plugins/README.md new file mode 100644 index 00000000..357aa056 --- /dev/null +++ b/src/aipass/flow/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `FLOW`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/flow/docs/README.md b/src/aipass/flow/docs/README.md new file mode 100644 index 00000000..914d034c --- /dev/null +++ b/src/aipass/flow/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `FLOW` branch. diff --git a/src/aipass/flow/templates/README.md b/src/aipass/flow/templates/README.md new file mode 100644 index 00000000..8b964a44 --- /dev/null +++ b/src/aipass/flow/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `FLOW`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/flow/tests/README.md b/src/aipass/flow/tests/README.md new file mode 100644 index 00000000..e7e4632a --- /dev/null +++ b/src/aipass/flow/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `FLOW`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/memory/.aipass/README.md b/src/aipass/memory/.aipass/README.md new file mode 100644 index 00000000..30092b22 --- /dev/null +++ b/src/aipass/memory/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `MEMORY`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/memory/.claude/README.md b/src/aipass/memory/.claude/README.md new file mode 100644 index 00000000..5cafe890 --- /dev/null +++ b/src/aipass/memory/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `MEMORY`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/memory/.claude/settings.local.json b/src/aipass/memory/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/memory/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/memory/.seedgo/README.md b/src/aipass/memory/.seedgo/README.md new file mode 100644 index 00000000..cd24dde9 --- /dev/null +++ b/src/aipass/memory/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `MEMORY`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/memory/.seedgo/bypass.json b/src/aipass/memory/.seedgo/bypass.json index 51e33536..0e469d0a 100644 --- a/src/aipass/memory/.seedgo/bypass.json +++ b/src/aipass/memory/.seedgo/bypass.json @@ -2,8 +2,8 @@ "metadata": { "version": "1.0.0", "created": "2026-03-07T23:23:54.979418", - "last_updated": "2026-03-24", - "description": "Standards bypass configuration for this branch" + "description": "Standards bypass configuration for this branch", + "last_updated": "2026-03-24" }, "bypass": [ { @@ -71,7 +71,6 @@ "standard": "modules", "reason": "process_plans_command is a thin CLI wrapper that delegates to plans_processor handler. Orchestration, not implementation." }, - { "file": "apps/handlers/templates/pusher.py", "standard": "handlers", @@ -122,19 +121,16 @@ "standard": "handlers", "reason": "Architectural: imports storage.chroma for ChromaDB client access during vector search." }, - { "file": "apps/handlers/monitor/memory_watcher.py", "standard": "error_handling", "reason": "stdlib logging.getLogger() used at import-time before prax is available. Immediately replaced by get_system_logger() 3 lines below." }, - { "file": "apps/handlers/dashboard_push.py", "standard": "debug_print", "reason": "print(ok) is inside a subprocess script string — IPC output to stdout, not debug output." }, - { "file": "apps/handlers/learnings/manager.py", "standard": "dead_code", @@ -150,7 +146,6 @@ "standard": "dead_code", "reason": "Legacy search handler — query_executor.py is the active path. Retained for direct-import fallback." }, - { "file": "apps/modules/symbolic.py", "standard": "naming", @@ -226,7 +221,6 @@ "standard": "naming", "reason": "Module-level variables (SESSION_STATE, DEFAULT_CONFIG) are mutable state and config dicts." }, - { "file": "apps/modules/symbolic.py", "standard": "documentation", @@ -277,7 +271,6 @@ "standard": "documentation", "reason": "Multiline function signatures cause false-positive missing docstring detection." }, - { "file": "apps/modules/symbolic.py", "standard": "architecture", @@ -298,7 +291,6 @@ "standard": "architecture", "reason": "724 lines — symbolic storage with ChromaDB operations. Splitting would fragment cohesive vector storage logic." }, - { "file": "apps/handlers/rollover/extractor.py", "standard": "naming", @@ -364,13 +356,11 @@ "standard": "naming", "reason": "Module-level mutable state, not constants." }, - { "file": "apps/handlers/templates/spawn_pusher.py", "standard": "architecture", "reason": "Memory doesn't use all builder templates — branch has custom structure." }, - { "file": "handlers/learnings/manager.py", "standard": "dead_code", @@ -386,7 +376,6 @@ "standard": "dead_code", "reason": "Legacy search handler — query_executor.py is the active path. Retained for direct-import fallback." }, - { "file": "apps/handlers/learnings/manager.py", "standard": "architecture", @@ -402,7 +391,6 @@ "standard": "architecture", "reason": "Legacy search handler — query_executor.py is active path. Retained for fallback." }, - { "file": "apps/handlers/intake/pool_processor.py", "standard": "unused_function", @@ -438,7 +426,6 @@ "standard": "unused_function", "reason": "is_plan_vectorized is a public API function for external callers." }, - { "file": "apps/modules/templates.py", "standard": "deep_nesting", @@ -532,6 +519,11 @@ ], "notes": { "usage": "Add entries to 'bypass' list to exclude specific violations", + "example": { + "file": "apps/example.py", + "standard": "imports", + "reason": "Legacy import required for compatibility" + }, "fields": { "file": "Relative path from branch root (required)", "standard": "Standard name: cli, imports, naming, etc. (required)", @@ -540,4 +532,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/memory/apps/README.md b/src/aipass/memory/apps/README.md new file mode 100644 index 00000000..60833edf --- /dev/null +++ b/src/aipass/memory/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `MEMORY`. + +- `memory.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/memory/apps/handlers/README.md b/src/aipass/memory/apps/handlers/README.md new file mode 100644 index 00000000..83778352 --- /dev/null +++ b/src/aipass/memory/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `MEMORY`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/memory/apps/modules/README.md b/src/aipass/memory/apps/modules/README.md new file mode 100644 index 00000000..f0b0aa52 --- /dev/null +++ b/src/aipass/memory/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `MEMORY`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/memory/apps/plugins/README.md b/src/aipass/memory/apps/plugins/README.md new file mode 100644 index 00000000..e675f6dd --- /dev/null +++ b/src/aipass/memory/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `MEMORY`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/memory/docs/.gitkeep b/src/aipass/memory/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/memory/docs/README.md b/src/aipass/memory/docs/README.md new file mode 100644 index 00000000..d6850512 --- /dev/null +++ b/src/aipass/memory/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `MEMORY` branch. diff --git a/src/aipass/memory/templates/README.md b/src/aipass/memory/templates/README.md new file mode 100644 index 00000000..21840bfc --- /dev/null +++ b/src/aipass/memory/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `MEMORY`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/memory/tests/README.md b/src/aipass/memory/tests/README.md new file mode 100644 index 00000000..359efda1 --- /dev/null +++ b/src/aipass/memory/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `MEMORY`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/prax/.aipass/README.md b/src/aipass/prax/.aipass/README.md new file mode 100644 index 00000000..0fb67688 --- /dev/null +++ b/src/aipass/prax/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `PRAX`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/prax/.claude/README.md b/src/aipass/prax/.claude/README.md new file mode 100644 index 00000000..dc79f752 --- /dev/null +++ b/src/aipass/prax/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `PRAX`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/prax/.claude/settings.local.json b/src/aipass/prax/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/prax/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/prax/.seedgo/README.md b/src/aipass/prax/.seedgo/README.md new file mode 100644 index 00000000..0cd56155 --- /dev/null +++ b/src/aipass/prax/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `PRAX`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/prax/.seedgo/bypass.json b/src/aipass/prax/.seedgo/bypass.json index 94ecf587..b4be0b1b 100644 --- a/src/aipass/prax/.seedgo/bypass.json +++ b/src/aipass/prax/.seedgo/bypass.json @@ -2,14 +2,21 @@ "metadata": { "version": "2.0.0", "created": "2026-03-07T22:43:24.315842", - "last_updated": "2026-03-24", - "description": "Standards bypass configuration for prax branch" + "description": "Standards bypass configuration for prax branch", + "last_updated": "2026-03-24" }, "bypass": [ { "file": "apps/modules/logger.py", "standard": "cli", - "lines": [149, 180, 190, 199, 210, 231], + "lines": [ + 149, + 180, + 190, + 199, + 210, + 231 + ], "pattern": "print(", "reason": "Bootstrap/lifecycle logging - print() is used before the logging system is initialized and during shutdown. Logger cannot use itself for initialization messages (circular dependency)." }, @@ -25,7 +32,6 @@ "pattern": "console.print(", "reason": "Display handler for file change reporting. reporter.py formats and renders file change events to terminal using Rich markup. console.print() is its designated purpose." }, - { "file": "apps/handlers/logging/log_watchdog.py", "standard": "error_handling", @@ -92,7 +98,6 @@ "pattern": "logging.getLogger(", "reason": "Prax import chain — imported by discovery/watcher.py which is in logger.py's dependency graph. Cannot import from aipass.prax.apps.modules.logger (circular dependency)." }, - { "file": "apps/handlers/config/load.py", "standard": "log_visibility", @@ -135,7 +140,6 @@ "pattern": "logging.getLogger(", "reason": "Prax import chain — imported via discovery/watcher.py. Cannot import from aipass.prax.apps.modules.logger (circular dependency)." }, - { "file": "apps/handlers/discovery/scanner.py", "standard": "handlers", @@ -252,26 +256,22 @@ "standard": "handlers", "reason": "Architectural — imports PRAX_JSON_DIR from config.load (shared infrastructure). Uses module_name parameter for explicit filter context from callers." }, - { "file": "apps/handlers/json/json_handler.py", "standard": "json_structure", "reason": "json_handler.py IS the JSON template management system for prax. load_template() and json_templates/ are its core functionality, not a violation of the template-free standard. This file provides the template infrastructure that other files consume." }, - { "file": "apps/modules/monitor.py", "standard": "modules", "reason": "Monitor is a 3-thread architecture (display, file watcher, log watcher) that is tightly coupled by design. The threads share state (queues, positions dict, stop events) making splitting impractical without introducing complex inter-module synchronization. Direct JSON read of registry at line 344 is a one-time startup operation for branch discovery — routing through json_handler would add unnecessary dependency for a simple registry read." }, - { "file": "apps/handlers/dashboard/agent_status_writer.py", "standard": "debug_print", "pattern": "print(ok)", "reason": "False positive — print(ok) is inside a subprocess script string passed to python -c, not a bare print() call in this module's execution context." }, - { "file": "apps/modules/logger.py", "standard": "imports", @@ -287,7 +287,6 @@ "standard": "imports", "reason": "False positive — stdlib imports (lines 49-55) are correctly before aipass imports (lines 58+). Checker misidentifies docstring content as import lines." }, - { "file": "apps/modules/dashboard.py", "standard": "documentation", @@ -313,7 +312,6 @@ "standard": "documentation", "reason": "False positive — multiline function signature causes docstring checker to miss existing docstring." }, - { "file": "apps/modules/dashboard.py", "standard": "naming", @@ -364,7 +362,6 @@ "standard": "naming", "reason": "False positive — _terminal_output_enabled and _terminal_module_available are mutable flags set conditionally, not constants." }, - { "file": "apps/handlers/discovery/watcher.py", "standard": "unused_function", @@ -390,7 +387,6 @@ "standard": "unused_function", "reason": "format() is a logging.Formatter.format() override — called by the Python logging framework when formatting log records, not by name in branch code." }, - { "file": "apps/", "standard": "architecture", @@ -399,6 +395,11 @@ ], "notes": { "usage": "Add entries to 'bypass' list to exclude specific violations", + "example": { + "file": "apps/example.py", + "standard": "imports", + "reason": "Legacy import required for compatibility" + }, "fields": { "file": "Relative path from branch root (required)", "standard": "Standard name: cli, error_handling, log_visibility, handlers, etc. (required)", diff --git a/src/aipass/prax/apps/README.md b/src/aipass/prax/apps/README.md new file mode 100644 index 00000000..621670c7 --- /dev/null +++ b/src/aipass/prax/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `PRAX`. + +- `prax.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/prax/apps/handlers/README.md b/src/aipass/prax/apps/handlers/README.md new file mode 100644 index 00000000..0e2f5281 --- /dev/null +++ b/src/aipass/prax/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `PRAX`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/prax/apps/modules/README.md b/src/aipass/prax/apps/modules/README.md new file mode 100644 index 00000000..d4018ca6 --- /dev/null +++ b/src/aipass/prax/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `PRAX`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/prax/apps/plugins/README.md b/src/aipass/prax/apps/plugins/README.md new file mode 100644 index 00000000..fe39b916 --- /dev/null +++ b/src/aipass/prax/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `PRAX`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/prax/docs/.gitkeep b/src/aipass/prax/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/prax/docs/README.md b/src/aipass/prax/docs/README.md new file mode 100644 index 00000000..9e6ecf9f --- /dev/null +++ b/src/aipass/prax/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `PRAX` branch. diff --git a/src/aipass/prax/prax_json/.gitkeep b/src/aipass/prax/prax_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/prax/templates/README.md b/src/aipass/prax/templates/README.md new file mode 100644 index 00000000..77f57313 --- /dev/null +++ b/src/aipass/prax/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `PRAX`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/prax/tests/README.md b/src/aipass/prax/tests/README.md new file mode 100644 index 00000000..42a2bf12 --- /dev/null +++ b/src/aipass/prax/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `PRAX`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/seedgo/.aipass/README.md b/src/aipass/seedgo/.aipass/README.md new file mode 100644 index 00000000..2966a513 --- /dev/null +++ b/src/aipass/seedgo/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `SEEDGO`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/seedgo/.claude/README.md b/src/aipass/seedgo/.claude/README.md new file mode 100644 index 00000000..2a34dcc0 --- /dev/null +++ b/src/aipass/seedgo/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `SEEDGO`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/seedgo/.claude/settings.local.json b/src/aipass/seedgo/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/seedgo/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/seedgo/.seedgo/README.md b/src/aipass/seedgo/.seedgo/README.md new file mode 100644 index 00000000..dd56a69b --- /dev/null +++ b/src/aipass/seedgo/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `SEEDGO`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/seedgo/.seedgo/bypass.json b/src/aipass/seedgo/.seedgo/bypass.json index bc592ca0..cd67e3e5 100644 --- a/src/aipass/seedgo/.seedgo/bypass.json +++ b/src/aipass/seedgo/.seedgo/bypass.json @@ -37,25 +37,33 @@ { "file": "apps/handlers/__init__.py", "standard": "handlers", - "lines": [101], + "lines": [ + 101 + ], "reason": "Line 101 is inside an f-string error message showing the correct import pattern to users. Not an actual module import. False positive from text-matching checker." }, { "file": "apps/handlers/audit/branch_audit.py", "standard": "handlers", - "lines": [14], + "lines": [ + 14 + ], "reason": "Same-branch cross-handler import (allowed per architecture standard). Audit handler imports bypass/ignore_handler for file filtering during audits." }, { "file": "apps/handlers/aipass_standards/architecture_check.py", "standard": "handlers", - "lines": [22], + "lines": [ + 22 + ], "reason": "Same-branch cross-handler import (allowed per architecture standard). Architecture checker imports bypass/ignore_handler for template ignore patterns." }, { "file": "apps/handlers/diagnostics/diagnostics_check.py", "standard": "handlers", - "lines": [32], + "lines": [ + 32 + ], "reason": "Same-branch cross-handler import (allowed per architecture standard). Diagnostics handler imports bypass/ignore_handler for audit ignore patterns." }, { @@ -203,12 +211,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -218,4 +226,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/seedgo/apps/README.md b/src/aipass/seedgo/apps/README.md new file mode 100644 index 00000000..7f9250d5 --- /dev/null +++ b/src/aipass/seedgo/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `SEEDGO`. + +- `seedgo.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/seedgo/apps/handlers/README.md b/src/aipass/seedgo/apps/handlers/README.md new file mode 100644 index 00000000..9e1d98b1 --- /dev/null +++ b/src/aipass/seedgo/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `SEEDGO`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/seedgo/apps/modules/README.md b/src/aipass/seedgo/apps/modules/README.md new file mode 100644 index 00000000..acfa3804 --- /dev/null +++ b/src/aipass/seedgo/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `SEEDGO`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/seedgo/apps/plugins/README.md b/src/aipass/seedgo/apps/plugins/README.md new file mode 100644 index 00000000..fd74c2a2 --- /dev/null +++ b/src/aipass/seedgo/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `SEEDGO`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/seedgo/seedgo_json/.gitkeep b/src/aipass/seedgo/seedgo_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/seedgo/templates/README.md b/src/aipass/seedgo/templates/README.md new file mode 100644 index 00000000..d1b56f92 --- /dev/null +++ b/src/aipass/seedgo/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `SEEDGO`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/seedgo/tests/README.md b/src/aipass/seedgo/tests/README.md new file mode 100644 index 00000000..ec1299bb --- /dev/null +++ b/src/aipass/seedgo/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `SEEDGO`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/spawn/.claude/settings.local.json b/src/aipass/spawn/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/spawn/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/spawn/.seedgo/bypass.json b/src/aipass/spawn/.seedgo/bypass.json index 6092225c..4176bc18 100644 --- a/src/aipass/spawn/.seedgo/bypass.json +++ b/src/aipass/spawn/.seedgo/bypass.json @@ -159,6 +159,26 @@ "file": "apps/handlers/passport_ops.py", "standard": "documentation", "reason": "grant_passport() has a docstring at line 47 — checker doesn't recognize it due to multi-line function signature spanning lines 42-46." + }, + { + "file": "apps/handlers/regenerate_registry_ops.py", + "standard": "json_structure", + "reason": "Pure registry generation — walks template, hashes files, builds registry. Uses meta_ops.compute_file_hash and json.dumps directly. Not an operational handler." + }, + { + "file": "apps/handlers/regenerate_registry_ops.py", + "standard": "handlers", + "reason": "Imports meta_ops.compute_file_hash and load_template_registry — registry regeneration needs hash computation and existing registry loading. meta_ops is a shared data handler." + }, + { + "file": "apps/handlers/regenerate_registry_ops.py", + "standard": "deep_nesting", + "reason": "_scan_template_directory() — three-pass ID assignment (hash match, path match, new ID) with nested loops. Algorithm requires this structure for correct ID preservation." + }, + { + "file": "apps/handlers/regenerate_registry_ops.py", + "standard": "documentation", + "reason": "_scan_template_directory() has docstring — multi-line function signature confuses checker." } ], "notes": { diff --git a/src/aipass/spawn/apps/handlers/change_detection.py b/src/aipass/spawn/apps/handlers/change_detection.py index 8cd659e6..654a5705 100644 --- a/src/aipass/spawn/apps/handlers/change_detection.py +++ b/src/aipass/spawn/apps/handlers/change_detection.py @@ -25,6 +25,7 @@ def detect_changes( template_registry: dict, branch_meta: dict, branch_dir: Path, + old_branch_tracking: dict | None = None, ) -> dict: """Detect changes between template registry and branch metadata. @@ -37,6 +38,9 @@ def detect_changes( template_registry: Template registry dict (from .template_registry.json). branch_meta: Branch metadata dict (from .branch_meta.json). branch_dir: Path to the branch directory (for existence checks). + old_branch_tracking: Snapshot of file_tracking from BEFORE metadata + regeneration (Phase 0 pattern). Used for accurate rename detection. + When None, falls back to current branch_meta tracking. Returns: Dict with change categories:: @@ -125,16 +129,29 @@ def detect_changes( branch_path = b_info.get("current_path", "") # Check for RENAME: same ID but path changed in template - # Compare the template-side path against the template_name stored in branch meta - branch_template_name = b_info.get("template_name", "") - if branch_template_name and template_path != branch_template_name: - renames.append({ - "file_id": file_id, - "template_path": template_path, - "branch_path": branch_path, - "old_name": branch_template_name, - "new_name": template_path, - }) + # Use old tracking snapshot for comparison if available (Phase 0 pattern) + if old_branch_tracking and file_id in old_branch_tracking: + old_info = old_branch_tracking[file_id] + old_template_name = old_info.get("template_name", "") + if old_template_name and template_path != old_template_name: + renames.append({ + "file_id": file_id, + "template_path": template_path, + "branch_path": branch_path, + "old_name": old_template_name, + "new_name": template_path, + }) + else: + # Fallback: compare against current branch meta + branch_template_name = b_info.get("template_name", "") + if branch_template_name and template_path != branch_template_name: + renames.append({ + "file_id": file_id, + "template_path": template_path, + "branch_path": branch_path, + "old_name": branch_template_name, + "new_name": template_path, + }) # Check for UPDATE: same ID, same location, content hash changed # Only applies to files (directories don't have content hashes) diff --git a/src/aipass/spawn/apps/handlers/meta_ops.py b/src/aipass/spawn/apps/handlers/meta_ops.py index 9452fd16..b23164d9 100644 --- a/src/aipass/spawn/apps/handlers/meta_ops.py +++ b/src/aipass/spawn/apps/handlers/meta_ops.py @@ -188,6 +188,7 @@ def generate_branch_meta(branch_dir: Path, template_registry: dict) -> dict: """ branch_dir = Path(branch_dir) branch_name = branch_dir.name + branch_lower = branch_name.lower().replace("-", "_") # Build reverse lookups from template registry # path -> (file_id, file_info) for matching by path @@ -199,6 +200,11 @@ def generate_branch_meta(branch_dir: Path, template_registry: dict) -> dict: path = file_info.get("path", file_info.get("current_name", "")) template_path_to_id[path] = (file_id, file_info) + # Also index the placeholder-resolved path so branch files match + if "{{BRANCH}}" in path: + resolved_path = path.replace("{{BRANCH}}", branch_lower) + template_path_to_id[resolved_path] = (file_id, file_info) + content_hash = file_info.get("content_hash", "") # Don't index empty-file hashes (too many collisions) if content_hash and content_hash != "e3b0c44298fc": @@ -210,59 +216,103 @@ def generate_branch_meta(branch_dir: Path, template_registry: dict) -> dict: path = dir_info.get("path", dir_info.get("current_name", "")) template_dir_path_to_id[path] = (dir_id, dir_info) + # Also index the placeholder-resolved path + if "{{BRANCH}}" in path: + resolved_path = path.replace("{{BRANCH}}", branch_lower) + template_dir_path_to_id[resolved_path] = (dir_id, dir_info) + # Scan the branch filesystem and build tracking + # Two-pass approach: path matching first (pass 1), then hash matching (pass 2). + # This prevents hash collisions from stealing IDs that should be path-matched. file_tracking: dict[str, dict[str, Any]] = {} directory_tracking: dict[str, dict[str, str]] = {} matched_file_ids: set[str] = set() matched_dir_ids: set[str] = set() - for item in sorted(branch_dir.rglob("*")): - rel = str(item.relative_to(branch_dir)) + # Collect branch items using targeted scan (only template-known paths) + # instead of rglob("*") which is catastrophically slow on large branches + # like backup (22k+ files, 388GB). + branch_files: list[tuple[Path, str]] = [] # (item, rel_path) + branch_dirs: list[tuple[Path, str]] = [] - # Skip .spawn internals and __pycache__ - if _BRANCH_META_DIR in Path(rel).parts or "__pycache__" in Path(rel).parts: + # Build set of directories to scan from template registry + _scan_dirs: set[str] = {""} # "" = root directory + for _dir_info in template_registry.get("directories", {}).values(): + _d_path = _dir_info.get("path", _dir_info.get("current_name", "")) + if _d_path: + resolved = _d_path.replace("{{BRANCH}}", branch_lower) + _scan_dirs.add(resolved) + + # Also add parent dirs of all template files + for _file_info in template_registry.get("files", {}).values(): + _f_path = _file_info.get("path", _file_info.get("current_name", "")) + if _f_path: + resolved = _f_path.replace("{{BRANCH}}", branch_lower) + parent = str(Path(resolved).parent) + if parent != ".": + _scan_dirs.add(parent) + + # Scan only template-relevant directories (shallow iterdir, not rglob) + for scan_rel in sorted(_scan_dirs): + scan_path = branch_dir / scan_rel if scan_rel else branch_dir + if not scan_path.is_dir(): continue - if item.is_dir(): - # Try to match directory by path - if rel in template_dir_path_to_id: - dir_id, dir_info = template_dir_path_to_id[rel] - if dir_id not in matched_dir_ids: - directory_tracking[dir_id] = { - "template_name": dir_info.get("path", dir_info.get("current_name", "")), - "current_name": item.name, - "current_path": rel, - } - matched_dir_ids.add(dir_id) + for item in sorted(scan_path.iterdir()): + rel = str(item.relative_to(branch_dir)) - elif item.is_file(): - content_hash = compute_file_hash(item) + # Skip .spawn internals and __pycache__ + if _BRANCH_META_DIR in Path(rel).parts or "__pycache__" in Path(rel).parts: + continue - # Try to match by path first - matched = False - if rel in template_path_to_id: - file_id, file_info = template_path_to_id[rel] - if file_id not in matched_file_ids: - file_tracking[file_id] = { - "template_name": file_info.get("path", file_info.get("current_name", "")), - "current_name": item.name, - "current_path": rel, - "content_hash": content_hash, - } - matched_file_ids.add(file_id) - matched = True + if item.is_dir(): + branch_dirs.append((item, rel)) + elif item.is_file(): + branch_files.append((item, rel)) - # Fall back to hash matching if path didn't match - if not matched and content_hash and content_hash in template_hash_to_id: - file_id, file_info = template_hash_to_id[content_hash] - if file_id not in matched_file_ids: - file_tracking[file_id] = { - "template_name": file_info.get("path", file_info.get("current_name", "")), - "current_name": item.name, - "current_path": rel, - "content_hash": content_hash, - } - matched_file_ids.add(file_id) + # --- Pass 1: PATH MATCHING (directories) --- + for item, rel in branch_dirs: + if rel in template_dir_path_to_id: + dir_id, dir_info = template_dir_path_to_id[rel] + if dir_id not in matched_dir_ids: + directory_tracking[dir_id] = { + "template_name": dir_info.get("path", dir_info.get("current_name", "")), + "current_name": item.name, + "current_path": rel, + } + matched_dir_ids.add(dir_id) + + # --- Pass 1: PATH MATCHING (files) --- + for item, rel in branch_files: + if rel in template_path_to_id: + file_id, file_info = template_path_to_id[rel] + if file_id not in matched_file_ids: + content_hash = compute_file_hash(item) + file_tracking[file_id] = { + "template_name": file_info.get("path", file_info.get("current_name", "")), + "current_name": item.name, + "current_path": rel, + "content_hash": content_hash, + } + matched_file_ids.add(file_id) + + # --- Pass 2: HASH MATCHING (files not matched by path) --- + for item, rel in branch_files: + # Skip if already matched in pass 1 + if any(ft.get("current_path") == rel for ft in file_tracking.values()): + continue + + content_hash = compute_file_hash(item) + if content_hash and content_hash in template_hash_to_id: + file_id, file_info = template_hash_to_id[content_hash] + if file_id not in matched_file_ids: + file_tracking[file_id] = { + "template_name": file_info.get("path", file_info.get("current_name", "")), + "current_name": item.name, + "current_path": rel, + "content_hash": content_hash, + } + matched_file_ids.add(file_id) # Build the metadata structure template_version = template_registry.get("metadata", {}).get("version", "1.0.0") diff --git a/src/aipass/spawn/apps/handlers/regenerate_registry_ops.py b/src/aipass/spawn/apps/handlers/regenerate_registry_ops.py new file mode 100644 index 00000000..11d073b0 --- /dev/null +++ b/src/aipass/spawn/apps/handlers/regenerate_registry_ops.py @@ -0,0 +1,291 @@ +# =================== AIPass ==================== +# Name: regenerate_registry_ops.py +# Description: Regenerate .template_registry.json for spawn template directories +# Version: 1.0.0 +# Created: 2026-03-25 +# Modified: 2026-03-25 +# ============================================= + +"""Regenerate template registry — walk template directory, hash files, build registry. + +Scans a template directory, computes content hashes for all tracked files, +and builds a fresh .template_registry.json while preserving existing IDs +where possible (by content hash match first, then by path match). +""" + +import json +from datetime import datetime +from pathlib import Path + +from aipass.prax.apps.modules.logger import system_logger as logger +from aipass.spawn.apps.handlers.meta_ops import compute_file_hash, load_template_registry + +# ============================================================================= +# CONSTANTS +# ============================================================================= + +_SPAWN_DIR = ".spawn" +_TEMPLATE_REGISTRY_FILE = ".template_registry.json" + +# Directories to skip entirely during scan +_SKIP_DIRS = {"__pycache__", ".git", ".spawn"} + +# Placeholder patterns to detect in filenames +_BRANCH_PLACEHOLDERS = ("{{BRANCH}}", "{{BRANCHNAME}}") + + +# ============================================================================= +# PUBLIC API +# ============================================================================= + +def regenerate_template_registry(template_dir: Path) -> dict: + """Walk a template directory, hash files, and build a fresh registry. + + Preserves existing file/directory IDs where possible by matching + on content hash first, then path, before assigning new IDs. + + Args: + template_dir: Absolute path to the template directory (e.g. builder/). + + Returns: + dict with keys: metadata, files, directories, stats. + The stats key is extra (not written to JSON) — used for CLI output. + """ + template_dir = Path(template_dir) + + if not template_dir.is_dir(): + logger.error(f"Template directory does not exist: {template_dir}") + return {"error": f"Template directory does not exist: {template_dir}"} + + # Load existing registry for ID preservation + existing_registry = load_template_registry(template_dir) + + # Scan and build new registry entries + files, directories = _scan_template_directory(template_dir, existing_registry) + + today = datetime.now().strftime("%Y-%m-%d") + + registry = { + "metadata": { + "version": "1.0.0", + "last_updated": today, + "description": "Template file tracking registry for ID-based updates", + }, + "files": files, + "directories": directories, + } + + # Write the registry + spawn_dir = template_dir / _SPAWN_DIR + spawn_dir.mkdir(parents=True, exist_ok=True) + registry_path = spawn_dir / _TEMPLATE_REGISTRY_FILE + + try: + tmp_path = registry_path.with_suffix(".tmp") + tmp_path.write_text( + json.dumps(registry, indent=2, ensure_ascii=False) + "\n", + encoding="utf-8", + ) + tmp_path.rename(registry_path) + except (IOError, OSError) as exc: + logger.error(f"Failed to write template registry: {exc}") + return {"error": f"Failed to write registry: {exc}"} + + # Build stats for CLI output (not part of the persisted registry) + existing_file_count = len(existing_registry.get("files", {})) if existing_registry else 0 + existing_dir_count = len(existing_registry.get("directories", {})) if existing_registry else 0 + + stats = { + "files_tracked": len(files), + "directories_tracked": len(directories), + "previous_files": existing_file_count, + "previous_directories": existing_dir_count, + "registry_path": str(registry_path), + "template_dir": str(template_dir), + "template_name": template_dir.name, + } + + logger.info( + f"Regenerated template registry for {template_dir.name}: " + f"{len(files)} files, {len(directories)} directories" + ) + + return {**registry, "stats": stats} + + +# ============================================================================= +# INTERNAL — SCANNING +# ============================================================================= + +def _scan_template_directory( + template_dir: Path, + existing_registry: dict | None, +) -> tuple[dict, dict]: + """Walk template directory and build files and directories dicts. + + ID preservation strategy: + Files: + Priority 1 — content hash match in existing registry -> keep ID + Priority 2 — path match in existing registry -> keep ID + Priority 3 — new file -> assign next available ID (f001, f002, ...) + + Directories: + Priority 1 — path match in existing registry -> keep ID + Priority 2 — name match in existing registry -> keep ID + Priority 3 — new dir -> assign next available ID (d001, d002, ...) + + Args: + template_dir: Absolute path to template root. + existing_registry: Previously loaded registry dict, or None. + + Returns: + Tuple of (files_dict, directories_dict). + """ + # Build reverse lookups from existing registry + existing_files = existing_registry.get("files", {}) if existing_registry else {} + existing_dirs = existing_registry.get("directories", {}) if existing_registry else {} + + # File lookups: hash -> id, path -> id + # Index both the full hash AND the 12-char prefix to handle old registries + # that used 16-char hashes (file_ops.py) vs current 12-char (compute_file_hash) + hash_to_id: dict[str, str] = {} + path_to_file_id: dict[str, str] = {} + for fid, finfo in existing_files.items(): + path_to_file_id[finfo.get("path", "")] = fid + content_hash = finfo.get("content_hash", "") + if content_hash and content_hash != "placeholder": + hash_to_id[content_hash] = fid + # Also index the 12-char prefix for cross-format matching + if len(content_hash) > 12: + hash_to_id[content_hash[:12]] = fid + + # Directory lookups: path -> id, name -> id + path_to_dir_id: dict[str, str] = {} + name_to_dir_id: dict[str, str] = {} + for did, dinfo in existing_dirs.items(): + path_to_dir_id[dinfo.get("path", "")] = did + name_to_dir_id[dinfo.get("name", "")] = did + + # Track which IDs have been claimed + claimed_file_ids: set[str] = set() + claimed_dir_ids: set[str] = set() + + # Collect raw entries before assigning IDs + raw_files: list[dict] = [] + raw_dirs: list[dict] = [] + + for item in sorted(template_dir.rglob("*")): + rel = item.relative_to(template_dir) + rel_str = str(rel) + + # Skip excluded directories and their contents + if any(part in _SKIP_DIRS for part in rel.parts): + continue + + if item.is_dir(): + has_placeholder = any(p in item.name for p in _BRANCH_PLACEHOLDERS) + raw_dirs.append({ + "path": rel_str, + "name": item.name, + "has_branch_placeholder": has_placeholder, + }) + + elif item.is_file(): + content_hash = compute_file_hash(item) + has_placeholder = any(p in item.name for p in _BRANCH_PLACEHOLDERS) + raw_files.append({ + "path": rel_str, + "name": item.name, + "content_hash": content_hash, + "has_branch_placeholder": has_placeholder, + }) + + # Assign IDs to files with three-pass global matching. + # This prevents new files from stealing IDs that existing files should claim. + files: dict[str, dict] = {} + unmatched_files: list[dict] = [] + + # Pass 1: hash matching for all files + for entry in raw_files: + content_hash = entry.get("content_hash", "") + if content_hash and content_hash in hash_to_id: + candidate = hash_to_id[content_hash] + if candidate not in claimed_file_ids: + claimed_file_ids.add(candidate) + files[candidate] = entry + continue + unmatched_files.append(entry) + + # Pass 2: path matching for remaining files + still_unmatched: list[dict] = [] + for entry in unmatched_files: + path = entry.get("path", "") + if path and path in path_to_file_id: + candidate = path_to_file_id[path] + if candidate not in claimed_file_ids: + claimed_file_ids.add(candidate) + files[candidate] = entry + continue + still_unmatched.append(entry) + + # Pass 3: new IDs for truly new files + for entry in still_unmatched: + fid = _next_id("f", claimed_file_ids) + claimed_file_ids.add(fid) + files[fid] = entry + + # Assign IDs to directories with two-pass matching + directories: dict[str, dict] = {} + unmatched_dirs: list[dict] = [] + + # Pass 1: path matching + for entry in raw_dirs: + path = entry.get("path", "") + if path and path in path_to_dir_id: + candidate = path_to_dir_id[path] + if candidate not in claimed_dir_ids: + claimed_dir_ids.add(candidate) + directories[candidate] = entry + continue + unmatched_dirs.append(entry) + + # Pass 2: name matching for remaining dirs + still_unmatched_dirs: list[dict] = [] + for entry in unmatched_dirs: + name = entry.get("name", "") + if name and name in name_to_dir_id: + candidate = name_to_dir_id[name] + if candidate not in claimed_dir_ids: + claimed_dir_ids.add(candidate) + directories[candidate] = entry + continue + still_unmatched_dirs.append(entry) + + # Pass 3: new IDs for truly new dirs + for entry in still_unmatched_dirs: + did = _next_id("d", claimed_dir_ids) + claimed_dir_ids.add(did) + directories[did] = entry + + return files, directories + + +def _next_id(prefix: str, claimed: set[str]) -> str: + """Generate the next sequential ID with the given prefix. + + Scans f001..f999 or d001..d999 to find the first unclaimed slot. + + Args: + prefix: "f" for files, "d" for directories. + claimed: Set of already-claimed IDs. + + Returns: + Next available ID string (e.g. "f027"). + """ + for i in range(1, 1000): + candidate = f"{prefix}{i:03d}" + if candidate not in claimed: + return candidate + # Fallback — should never happen with < 1000 items + logger.warning(f"ID space exhausted for prefix '{prefix}'") + return f"{prefix}999" diff --git a/src/aipass/spawn/apps/handlers/update_ops.py b/src/aipass/spawn/apps/handlers/update_ops.py index deb77dd2..a68e3ea0 100644 --- a/src/aipass/spawn/apps/handlers/update_ops.py +++ b/src/aipass/spawn/apps/handlers/update_ops.py @@ -13,6 +13,7 @@ additions, JSON updates, pruned file archival, and coordinating the full update workflow for single and all-branch modes. """ +import copy import json import shutil from datetime import datetime @@ -109,6 +110,12 @@ def update_branch(branch_name: str, dry_run: bool = False, trace: bool = False) branch_meta = load_branch_meta(branch_dir) first_time = branch_meta is None + # Phase 0: Snapshot old tracking BEFORE any metadata generation/sync + # This preserves the old template_name values for rename detection + old_branch_tracking: dict | None = None + if branch_meta is not None: + old_branch_tracking = copy.deepcopy(branch_meta.get("file_tracking", {})) + if first_time: if trace: logger.info(f"[update] No branch_meta found — generating initial metadata (adoption)") @@ -133,7 +140,7 @@ def update_branch(branch_name: str, dry_run: bool = False, trace: bool = False) # ------------------------------------------------------------------ # 5. Change detection # ------------------------------------------------------------------ - changes = detect_changes(template_registry, branch_meta, branch_dir) + changes = detect_changes(template_registry, branch_meta, branch_dir, old_branch_tracking=old_branch_tracking) additions = changes.get("additions", []) updates_list = changes.get("updates", []) @@ -313,15 +320,24 @@ def update_all(dry_run: bool = False, trace: bool = False, citizen_class: str | def _read_citizen_class(branch_dir: Path) -> str: """Read citizen_class from a branch's passport.json. - Falls back to "builder" if passport doesn't exist or doesn't have - the citizen_class field (backward compatibility for pre-class branches). + Falls back to "builder" if passport doesn't exist, doesn't have + the citizen_class field, or has an unknown class (e.g. "manager"). """ + from aipass.spawn.apps.handlers.class_registry import validate_class + passport_path = branch_dir / ".trinity" / "passport.json" if not passport_path.exists(): return "builder" try: data = json.loads(passport_path.read_text(encoding="utf-8")) - return data.get("identity", {}).get("citizen_class", "builder") + citizen_class = data.get("identity", {}).get("citizen_class", "builder") + if not validate_class(citizen_class): + logger.warning( + f"[update] Unknown citizen_class '{citizen_class}' in {passport_path}, " + "falling back to 'builder'" + ) + return "builder" + return citizen_class except (json.JSONDecodeError, IOError) as e: logger.warning(f"[update] Failed to read citizen_class from passport {passport_path}: {e}") return "builder" diff --git a/src/aipass/spawn/apps/modules/regenerate_registry.py b/src/aipass/spawn/apps/modules/regenerate_registry.py new file mode 100644 index 00000000..ee565be4 --- /dev/null +++ b/src/aipass/spawn/apps/modules/regenerate_registry.py @@ -0,0 +1,195 @@ +# =================== AIPass ==================== +# Name: regenerate_registry.py +# Description: CLI module for regenerating template registries +# Version: 1.0.0 +# Created: 2026-03-25 +# Modified: 2026-03-25 +# ============================================= + +"""Regenerate template registry — thin CLI layer. + +Parses arguments and delegates to regenerate_registry_ops handler. +All implementation logic lives in apps/handlers/regenerate_registry_ops.py. +""" + +from aipass.prax import logger +from aipass.cli.apps.modules import console, error, warning + +from aipass.spawn.apps.handlers.regenerate_registry_ops import regenerate_template_registry +from aipass.spawn.apps.handlers.class_registry import get_template_dir, get_available_classes + + +def print_introspection(): + """Display module introspection info.""" + console.print() + console.print("regenerate_registry Module") + console.print("Regenerate .template_registry.json for spawn template directories") + console.print() + console.print("Connected Handlers:") + console.print(" handlers/") + console.print(" - regenerate_registry_ops.py (regenerate_template_registry — walk template, hash files, build registry)") + console.print() + + +# ============================================================================= +# DRONE ROUTING +# ============================================================================= + +def handle_command(command: str, args: list) -> bool: + """Handle commands routed by the entry point. + + Args: + command: The command string (e.g. "regenerate-registry") + args: List of arguments for the command + + Returns: + True if command was handled, False otherwise. + """ + if command != "regenerate-registry": + return False + + # No args → introspection + if not args: + print_introspection() + return True + + if "--help" in args: + print_introspection() + return True + + return handle_regenerate_registry(args) == 0 + + +# ============================================================================= +# PUBLIC API +# ============================================================================= + +def handle_regenerate_registry(args: list[str]) -> int: + """Parse args and execute template registry regeneration. + + Args patterns: + [] -> regenerate builder (default) + ["builder"] -> regenerate builder template + ["birthright"] -> regenerate birthright template + ["--all"] -> regenerate all template registries + ["--help"] -> show help + + Returns exit code (0=success, 1=failure). + """ + if args and args[0] in ["--help", "-h"]: + _print_help() + return 0 + + regen_all = "--all" in args + + if regen_all: + # Regenerate all known template classes + classes = get_available_classes() + all_results: list[dict] = [] + had_error = False + + for class_name in classes: + try: + template_dir = get_template_dir(class_name) + result = regenerate_template_registry(template_dir) + if "error" in result: + error(f"[{class_name}] {result['error']}") + had_error = True + else: + all_results.append(result) + except Exception as exc: + logger.error(f"[regenerate-registry] Error for {class_name}: {exc}") + error(f"[{class_name}] {exc}") + had_error = True + + for result in all_results: + _print_summary(result) + + return 1 if had_error else 0 + + # Single class — default to builder + clean_args = [a for a in args if not a.startswith("--")] + class_name = clean_args[0] if clean_args else "builder" + + available = get_available_classes() + if class_name not in available: + error( + f"Unknown template class '{class_name}'", + suggestion=f"Available: {', '.join(available)}", + ) + return 1 + + try: + template_dir = get_template_dir(class_name) + result = regenerate_template_registry(template_dir) + except Exception as exc: + logger.error(f"[regenerate-registry] Unexpected error: {exc}") + error(str(exc)) + return 1 + + if "error" in result: + error(result["error"]) + return 1 + + _print_summary(result) + return 0 + + +# ============================================================================= +# OUTPUT HELPERS +# ============================================================================= + +def _print_help() -> None: + """Print usage help for regenerate-registry command.""" + warning("Usage: drone @spawn regenerate-registry [class_name | --all]") + console.print() + console.print(" [green](no args)[/green] Regenerate builder template registry (default)") + console.print(" [green][/green] Regenerate registry for a specific template class") + console.print(" [green]--all[/green] Regenerate registries for all template classes") + console.print() + console.print("[dim]Available classes:[/dim]") + for cls in get_available_classes(): + console.print(f" [green]{cls}[/green]") + console.print() + + +def _print_summary(result: dict) -> None: + """Print a rich summary of the registry regeneration.""" + stats = result.get("stats", {}) + name = stats.get("template_name", "unknown") + files_tracked = stats.get("files_tracked", 0) + dirs_tracked = stats.get("directories_tracked", 0) + prev_files = stats.get("previous_files", 0) + prev_dirs = stats.get("previous_directories", 0) + registry_path = stats.get("registry_path", "") + + console.print() + console.print(f"[bold]Registry Regenerated: {name}[/bold]") + console.print() + console.print(f" Files tracked: {files_tracked} [dim](was {prev_files})[/dim]") + console.print(f" Directories tracked: {dirs_tracked} [dim](was {prev_dirs})[/dim]") + console.print(f" Registry path: [dim]{registry_path}[/dim]") + + # Show file list + files = result.get("files", {}) + if files: + console.print() + console.print(" [bold cyan]Files:[/bold cyan]") + for fid in sorted(files.keys()): + finfo = files[fid] + path = finfo.get("path", "") + placeholder = " [yellow](placeholder)[/yellow]" if finfo.get("has_branch_placeholder") else "" + console.print(f" {fid}: {path}{placeholder}") + + # Show directory list + directories = result.get("directories", {}) + if directories: + console.print() + console.print(" [bold cyan]Directories:[/bold cyan]") + for did in sorted(directories.keys()): + dinfo = directories[did] + path = dinfo.get("path", "") + placeholder = " [yellow](placeholder)[/yellow]" if dinfo.get("has_branch_placeholder") else "" + console.print(f" {did}: {path}{placeholder}") + + console.print() diff --git a/src/aipass/spawn/apps/spawn.py b/src/aipass/spawn/apps/spawn.py index 2f28f839..13c8b9a7 100644 --- a/src/aipass/spawn/apps/spawn.py +++ b/src/aipass/spawn/apps/spawn.py @@ -43,7 +43,7 @@ def print_help(): console.print(" [green]delete[/green] <@branch> Archive and deregister branch") console.print(" [green]sync-registry[/green] Repair registry against filesystem") console.print(" [green]sync-templates[/green] Pull managed files from source") - console.print(" [dim]regenerate-registry[/dim] Regenerate template registry hashes [dim][not yet implemented][/dim]") + console.print(" [green]regenerate-registry[/green] Regenerate template registry hashes") console.print() console.print("[bold cyan]CITIZEN CLASSES:[/bold cyan]") console.print() @@ -130,6 +130,7 @@ def print_introspection(): console.print(" - delete.py (handle_delete — archive and deregister branch)") console.print(" - sync_registry.py (handle_sync_registry — registry repair)") console.print(" - sync_templates.py (handle_sync_templates — template synchronization)") + console.print(" - regenerate_registry.py (handle_regenerate_registry — regenerate template registry)") console.print(" - passport.py (handle_passport — grant birthright citizenship)") console.print() @@ -176,14 +177,9 @@ def main(): from aipass.spawn.apps.modules.passport import handle_passport return handle_passport(remaining) - # Stub commands — planned but not yet implemented - stub_commands = { - "regenerate-registry": "Regenerate template registry hashes", - } - - if command in stub_commands: - warning(f"'{command}' is not yet implemented.", details=f"Planned: {stub_commands[command]}") - return 1 + if command == "regenerate-registry": + from aipass.spawn.apps.modules.regenerate_registry import handle_regenerate_registry + return handle_regenerate_registry(remaining) error(f"Unknown command: {command}", suggestion="Run 'drone @spawn --help' for available commands") return 1 diff --git a/src/aipass/spawn/docs/.gitkeep b/src/aipass/spawn/docs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/spawn/spawn_json/.gitkeep b/src/aipass/spawn/spawn_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/spawn/templates/builder/.spawn/.template_registry.json b/src/aipass/spawn/templates/builder/.spawn/.template_registry.json index 207cb125..5aa9147b 100644 --- a/src/aipass/spawn/templates/builder/.spawn/.template_registry.json +++ b/src/aipass/spawn/templates/builder/.spawn/.template_registry.json @@ -1,238 +1,367 @@ { "metadata": { - "description": "Template registry for tracking files", - "generated": true + "version": "1.0.0", + "last_updated": "2026-03-25", + "description": "Template file tracking registry for ID-based updates" }, "files": { + "f002": { + "path": ".ai_mail.local/README.md", + "name": "README.md", + "content_hash": "49299c242a01", + "has_branch_placeholder": false + }, "f001": { "path": ".ai_mail.local/inbox.json", "name": "inbox.json", - "content_hash": "c9702fe2cc21b748", + "content_hash": "c9702fe2cc21", "has_branch_placeholder": false }, - "f002": { - "path": ".ai_mail.local/sent/README.md", - "name": "README.md", - "content_hash": "49299c242a018d73", - "has_branch_placeholder": true - }, "f003": { "path": ".aipass/aipass_local_prompt.md", "name": "aipass_local_prompt.md", - "content_hash": "5f8e2a3859a99906", - "has_branch_placeholder": true + "content_hash": "5f8e2a3859a9", + "has_branch_placeholder": false }, "f004": { "path": ".archive/README.md", "name": "README.md", - "content_hash": "93d3fcb74f234b1d", - "has_branch_placeholder": true + "content_hash": "93d3fcb74f23", + "has_branch_placeholder": false }, "f005": { "path": ".claude/settings.local.json", "name": "settings.local.json", - "content_hash": "eacf065629cd9c03", + "content_hash": "eacf065629cd", "has_branch_placeholder": false }, "f006": { "path": ".gitignore", "name": ".gitignore", - "content_hash": "841dedb922da7ddb", + "content_hash": "841dedb922da", "has_branch_placeholder": false }, "f007": { "path": ".seedgo/bypass.json", "name": "bypass.json", - "content_hash": "0ac90a35515b35c2", - "has_branch_placeholder": true + "content_hash": "0ac90a35515b", + "has_branch_placeholder": false }, "f008": { "path": ".trinity/local.json", "name": "local.json", - "content_hash": "f4e62d2d12bada2e", - "has_branch_placeholder": true + "content_hash": "f4e62d2d12ba", + "has_branch_placeholder": false }, "f009": { "path": ".trinity/observations.json", "name": "observations.json", - "content_hash": "25b957960a5939a3", - "has_branch_placeholder": true + "content_hash": "25b957960a59", + "has_branch_placeholder": false }, "f010": { "path": ".trinity/passport.json", "name": "passport.json", - "content_hash": "04c2ead2a4284027", - "has_branch_placeholder": true + "content_hash": "04c2ead2a428", + "has_branch_placeholder": false }, "f011": { "path": "DASHBOARD.local.json", "name": "DASHBOARD.local.json", - "content_hash": "88360d943d4bacb6", - "has_branch_placeholder": true + "content_hash": "88360d943d4b", + "has_branch_placeholder": false }, "f012": { "path": "README.md", "name": "README.md", - "content_hash": "ad99517a50f96ba7", - "has_branch_placeholder": true + "content_hash": "ad99517a50f9", + "has_branch_placeholder": false }, "f013": { "path": "STATUS.local.md", "name": "STATUS.local.md", - "content_hash": "059295ad4d4e62eb", - "has_branch_placeholder": true + "content_hash": "059295ad4d4e", + "has_branch_placeholder": false }, "f014": { "path": "apps/__init__.py", "name": "__init__.py", - "content_hash": "41b011f487af14dc", - "has_branch_placeholder": true - }, - "f015": { - "path": "apps/handlers/__init__.py", - "name": "__init__.py", - "content_hash": "e3b0c44298fc1c14", - "has_branch_placeholder": false - }, - "f016": { - "path": "apps/modules/__init__.py", - "name": "__init__.py", - "content_hash": "e3b0c44298fc1c14", + "content_hash": "41b011f487af", "has_branch_placeholder": false }, "f017": { - "path": "apps/plugins/__init__.py", + "path": "apps/handlers/__init__.py", "name": "__init__.py", - "content_hash": "e3b0c44298fc1c14", + "content_hash": "e3b0c44298fc", "has_branch_placeholder": false }, "f018": { "path": "apps/{{BRANCH}}.py", "name": "{{BRANCH}}.py", - "content_hash": "fc71b424c10bb172", + "content_hash": "fc71b424c10b", "has_branch_placeholder": true }, "f019": { "path": "artifacts/birth_certificate.json", "name": "birth_certificate.json", - "content_hash": "1ec401f4e397eec7", - "has_branch_placeholder": true + "content_hash": "1ec401f4e397", + "has_branch_placeholder": false }, "f020": { "path": "docs/README.md", "name": "README.md", - "content_hash": "2434da568727499d", - "has_branch_placeholder": true + "content_hash": "2434da568727", + "has_branch_placeholder": false }, "f021": { "path": "dropbox/README.md", "name": "README.md", - "content_hash": "9e1e9b71f93b4cde", - "has_branch_placeholder": true + "content_hash": "9e1e9b71f93b", + "has_branch_placeholder": false }, "f022": { "path": "pytest.ini", "name": "pytest.ini", - "content_hash": "7b39ba7bca4025c5", + "content_hash": "7b39ba7bca40", "has_branch_placeholder": false }, "f023": { "path": "tests/__init__.py", "name": "__init__.py", - "content_hash": "881f06bb6574d2f7", - "has_branch_placeholder": true - }, - "f024": { - "path": "tests/conftest.py", - "name": "conftest.py", - "content_hash": "df147b2015e4b789", - "has_branch_placeholder": false - }, - "f025": { - "path": "tools/verify_branch.py", - "name": "verify_branch.py", - "content_hash": "3a7aa5d9b479fe92", + "content_hash": "881f06bb6574", "has_branch_placeholder": false }, "f026": { "path": "{{BRANCH}}_json/README.md", "name": "README.md", - "content_hash": "e64fa555e7b8e20f", - "has_branch_placeholder": true + "content_hash": "e64fa555e7b8", + "has_branch_placeholder": false + }, + "f016": { + "path": "apps/modules/__init__.py", + "name": "__init__.py", + "content_hash": "e3b0c44298fc", + "has_branch_placeholder": false + }, + "f024": { + "path": "tests/conftest.py", + "name": "conftest.py", + "content_hash": "5d98b049957b", + "has_branch_placeholder": false + }, + "f015": { + "path": ".aipass/README.md", + "name": "README.md", + "content_hash": "f42d87684fdf", + "has_branch_placeholder": false + }, + "f025": { + "path": ".claude/README.md", + "name": "README.md", + "content_hash": "adb0ce8c53c1", + "has_branch_placeholder": false + }, + "f027": { + "path": ".seedgo/README.md", + "name": "README.md", + "content_hash": "ea03468bbf16", + "has_branch_placeholder": false + }, + "f028": { + "path": ".trinity/README.md", + "name": "README.md", + "content_hash": "f461c9b16fc5", + "has_branch_placeholder": false + }, + "f029": { + "path": "apps/README.md", + "name": "README.md", + "content_hash": "92a956009e0e", + "has_branch_placeholder": false + }, + "f030": { + "path": "apps/handlers/README.md", + "name": "README.md", + "content_hash": "2e4f4a0c1b47", + "has_branch_placeholder": false + }, + "f031": { + "path": "apps/modules/README.md", + "name": "README.md", + "content_hash": "a4cf0a8e3b4f", + "has_branch_placeholder": false + }, + "f032": { + "path": "apps/plugins/README.md", + "name": "README.md", + "content_hash": "d1e4e2b98c38", + "has_branch_placeholder": false + }, + "f033": { + "path": "apps/plugins/__init__.py", + "name": "__init__.py", + "content_hash": "e3b0c44298fc", + "has_branch_placeholder": false + }, + "f034": { + "path": "artifacts/README.md", + "name": "README.md", + "content_hash": "de20d11e5cfd", + "has_branch_placeholder": false + }, + "f035": { + "path": "docs.local/README.md", + "name": "README.md", + "content_hash": "c19d8872ea2c", + "has_branch_placeholder": false + }, + "f036": { + "path": "docs.local/sub_agent_drops/README.md", + "name": "README.md", + "content_hash": "e3e5a6b9c9c5", + "has_branch_placeholder": false + }, + "f037": { + "path": "logs/README.md", + "name": "README.md", + "content_hash": "4ca207af6bd3", + "has_branch_placeholder": false + }, + "f038": { + "path": "templates/README.md", + "name": "README.md", + "content_hash": "73b020b003f9", + "has_branch_placeholder": false + }, + "f039": { + "path": "tests/README.md", + "name": "README.md", + "content_hash": "c157895c9b27", + "has_branch_placeholder": false + }, + "f040": { + "path": "tools/README.md", + "name": "README.md", + "content_hash": "3c7eaedb16ac", + "has_branch_placeholder": false + }, + "f041": { + "path": "{{BRANCH}}_json/custom_config/README.md", + "name": "README.md", + "content_hash": "28e9ae373563", + "has_branch_placeholder": false } }, "directories": { "d001": { "path": ".ai_mail.local", - "name": ".ai_mail.local" + "name": ".ai_mail.local", + "has_branch_placeholder": false }, "d002": { "path": ".ai_mail.local/sent", - "name": "sent" + "name": "sent", + "has_branch_placeholder": false }, "d003": { "path": ".aipass", - "name": ".aipass" + "name": ".aipass", + "has_branch_placeholder": false }, "d004": { "path": ".archive", - "name": ".archive" + "name": ".archive", + "has_branch_placeholder": false }, "d005": { "path": ".claude", - "name": ".claude" + "name": ".claude", + "has_branch_placeholder": false }, "d006": { "path": ".seedgo", - "name": ".seedgo" + "name": ".seedgo", + "has_branch_placeholder": false }, "d007": { "path": ".trinity", - "name": ".trinity" + "name": ".trinity", + "has_branch_placeholder": false }, "d008": { "path": "apps", - "name": "apps" + "name": "apps", + "has_branch_placeholder": false }, "d009": { "path": "apps/handlers", - "name": "handlers" + "name": "handlers", + "has_branch_placeholder": false }, "d010": { "path": "apps/modules", - "name": "modules" + "name": "modules", + "has_branch_placeholder": false }, "d011": { "path": "apps/plugins", - "name": "plugins" + "name": "plugins", + "has_branch_placeholder": false }, "d012": { "path": "artifacts", - "name": "artifacts" + "name": "artifacts", + "has_branch_placeholder": false }, "d013": { "path": "docs", - "name": "docs" + "name": "docs", + "has_branch_placeholder": false }, "d014": { "path": "dropbox", - "name": "dropbox" + "name": "dropbox", + "has_branch_placeholder": false }, "d015": { "path": "templates", - "name": "templates" + "name": "templates", + "has_branch_placeholder": false }, "d016": { "path": "tests", - "name": "tests" + "name": "tests", + "has_branch_placeholder": false }, "d017": { "path": "tools", - "name": "tools" + "name": "tools", + "has_branch_placeholder": false }, "d018": { "path": "{{BRANCH}}_json", - "name": "{{BRANCH}}_json" + "name": "{{BRANCH}}_json", + "has_branch_placeholder": true + }, + "d019": { + "path": "docs.local", + "name": "docs.local", + "has_branch_placeholder": false + }, + "d020": { + "path": "docs.local/sub_agent_drops", + "name": "sub_agent_drops", + "has_branch_placeholder": false + }, + "d021": { + "path": "logs", + "name": "logs", + "has_branch_placeholder": false + }, + "d022": { + "path": "{{BRANCH}}_json/custom_config", + "name": "custom_config", + "has_branch_placeholder": false } } } diff --git a/src/aipass/trigger/.aipass/README.md b/src/aipass/trigger/.aipass/README.md new file mode 100644 index 00000000..7015908d --- /dev/null +++ b/src/aipass/trigger/.aipass/README.md @@ -0,0 +1,3 @@ +# Branch Prompt + +AI context for `TRIGGER`. The `aipass_local_prompt.md` file is injected every turn, telling the AI who you are and how to work in your branch. diff --git a/src/aipass/trigger/.claude/README.md b/src/aipass/trigger/.claude/README.md new file mode 100644 index 00000000..0de81a78 --- /dev/null +++ b/src/aipass/trigger/.claude/README.md @@ -0,0 +1,5 @@ +# Claude Code Settings + +Claude Code configuration for `TRIGGER`. + +Contains `settings.local.json` with permission rules. Most branches are denied raw git commands and must use `drone @git` instead. diff --git a/src/aipass/trigger/.claude/settings.local.json b/src/aipass/trigger/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/aipass/trigger/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/aipass/trigger/.seedgo/README.md b/src/aipass/trigger/.seedgo/README.md new file mode 100644 index 00000000..b16a384f --- /dev/null +++ b/src/aipass/trigger/.seedgo/README.md @@ -0,0 +1,5 @@ +# Standards Bypass + +Seedgo audit bypass config for `TRIGGER`. + +When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified. diff --git a/src/aipass/trigger/.seedgo/bypass.json b/src/aipass/trigger/.seedgo/bypass.json index a95cd474..2392bb9c 100644 --- a/src/aipass/trigger/.seedgo/bypass.json +++ b/src/aipass/trigger/.seedgo/bypass.json @@ -14,7 +14,9 @@ { "file": "apps/modules/core.py", "standard": "silent_catch", - "lines": [160], + "lines": [ + 160 + ], "pattern": "except Exception: pass", "reason": "Intentional: handler callback runs inside event bus fire(). Logging here would cause infinite recursion (logger fires events via trigger)." }, @@ -75,105 +77,134 @@ { "file": "apps/handlers/log_watcher.py", "standard": "handlers", - "lines": [75], + "lines": [ + 75 + ], "reason": "log_watcher imports error_registry.report() for Medic v2 dedup. This is a deliberate handler-to-handler dependency — the registry IS the dedup backend." }, { "file": "apps/handlers/error_reporter.py", "standard": "handlers", - "lines": [25, 45], + "lines": [ + 25, + 45 + ], "reason": "error_reporter imports error_registry for tracking and ai_mail for email delivery. These are its core dependencies — it's the dispatch endpoint of the error pipeline." }, { "file": "apps/handlers/watchers/log_watcher.py", "standard": "handlers", - "lines": [242], + "lines": [ + 242 + ], "reason": "Watcher imports trigger module to fire events. Handler→module import needed because watcher operates as standalone watchdog callback." }, { "file": "apps/handlers/events/error_detected.py", "standard": "handlers", - "lines": [76], + "lines": [ + 76 + ], "reason": "error_detected handler imports error_registry to query error details during dispatch. Core integration point for the error pipeline." }, { "file": "apps/handlers/events/startup.py", "standard": "handlers", - "lines": [371], + "lines": [ + 371 + ], "reason": "Startup handler imports memory rollover module to trigger memory checks on startup events. Cross-branch integration via modules layer public API." }, - { "file": "apps/config.py", "standard": "testing", - "lines": [31], + "lines": [ + 31 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/modules/core.py", "standard": "testing", - "lines": [160], + "lines": [ + 160 + ], "pattern": "except Exception: pass", "reason": "Deferred event queue handler execution — logging would cause infinite recursion (logger fires events via trigger). Same as silent_catch bypass." }, { "file": "apps/handlers/json/json_handler.py", "standard": "testing", - "lines": [24], + "lines": [ + 24 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/plan_file.py", "standard": "testing", - "lines": [58], + "lines": [ + 58 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_error() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/memory_threshold_exceeded.py", "standard": "testing", - "lines": [46], + "lines": [ + 46 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/error_logged.py", "standard": "testing", - "lines": [48], + "lines": [ + 48 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/bulletin_created.py", "standard": "testing", - "lines": [55], + "lines": [ + 55 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/error_detected.py", "standard": "testing", - "lines": [54], + "lines": [ + 54 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/startup.py", "standard": "testing", - "lines": [51], + "lines": [ + 51 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, { "file": "apps/handlers/events/registry.py", "standard": "testing", - "lines": [28], + "lines": [ + 28 + ], "pattern": "except Exception: pass", "reason": "Meta-logging helper _log_warning() — cannot log a failure to log. Same pattern as silent_catch bypass." }, - { "file": "apps/handlers/error_registry.py", "standard": "architecture", @@ -189,32 +220,40 @@ { "file": "apps/handlers/error_reporter.py", "standard": "architecture", - "lines": [153], + "lines": [ + 153 + ], "pattern": "handler importing from parent module", "reason": "error_reporter imports trigger bus to fire error_detected events after reporting. Handler must access event bus to complete the error pipeline." }, { "file": "apps/handlers/watchers/log_watcher.py", "standard": "architecture", - "lines": [244], + "lines": [ + 244 + ], "pattern": "handler importing from parent module", "reason": "Log watcher imports trigger bus to fire error_logged/warning_logged events. Watchdog callback must access event bus to bridge file monitoring to event system." }, { "file": "apps/handlers/events/error_detected.py", "standard": "architecture", - "lines": [153, 243], + "lines": [ + 153, + 243 + ], "pattern": "handler importing from parent module", "reason": "error_detected imports error_registry (line 76) and medic_state — core pipeline dependencies for dispatch gating. Already bypassed under handlers standard." }, { "file": "apps/handlers/events/registry.py", "standard": "architecture", - "lines": [34], + "lines": [ + 34 + ], "pattern": "handler importing from parent module", "reason": "Registry handler imports trigger module to wire event handlers via trigger.on(). The wiring function must reference the event bus." }, - { "file": "apps/handlers/events/warning_logged.py", "standard": "handlers", @@ -230,11 +269,12 @@ { "file": "apps/handlers/events/registry.py", "standard": "handlers", - "lines": [34], + "lines": [ + 34 + ], "pattern": "handler imports modules", "reason": "Registry wiring function imports trigger module to call trigger.on(). Must access the event bus to register handlers — this IS its purpose." }, - { "file": "apps/handlers/error_registry.py", "standard": "naming", @@ -271,14 +311,12 @@ "pattern": "local variable naming", "reason": "Local variables inside startup handler functions, not module-level constants. Checker false positive on function-scoped assignments." }, - { "file": "apps/config.py", "standard": "imports", "pattern": "prax logger import", "reason": "config.py cannot import prax logger — circular dependency. Uses _log_warning() file-based pattern instead. Comment on line 26 documents this." }, - { "file": "apps/handlers/json/json_handler.py", "standard": "unused_function", @@ -291,12 +329,12 @@ "example": { "file": "apps/modules/logger.py", "standard": "cli", + "reason": "Circular dependency - logger cannot import CLI", "lines": [ 146, 177 ], - "pattern": "if __name__ == '__main__'", - "reason": "Circular dependency - logger cannot import CLI" + "pattern": "if __name__ == '__main__'" }, "fields": { "file": "Relative path from branch root (required)", @@ -306,4 +344,4 @@ "reason": "Required - why this bypass exists" } } -} \ No newline at end of file +} diff --git a/src/aipass/trigger/apps/README.md b/src/aipass/trigger/apps/README.md new file mode 100644 index 00000000..c4154eba --- /dev/null +++ b/src/aipass/trigger/apps/README.md @@ -0,0 +1,8 @@ +# Apps + +Application layer for `TRIGGER`. + +- `trigger.py` — Entry point. Auto-discovers and routes commands to modules. +- `modules/` — Business logic and orchestration. One module per command. +- `handlers/` — Implementation details. Called by modules, never by CLI directly. +- `plugins/` — Scheduled tasks and extensions. diff --git a/src/aipass/trigger/apps/handlers/README.md b/src/aipass/trigger/apps/handlers/README.md new file mode 100644 index 00000000..10180eb7 --- /dev/null +++ b/src/aipass/trigger/apps/handlers/README.md @@ -0,0 +1,5 @@ +# Handlers + +Implementation details for `TRIGGER`. + +Handlers do the actual work. They are called by modules, never directly by the CLI. Keep business logic in modules, implementation in handlers. diff --git a/src/aipass/trigger/apps/modules/README.md b/src/aipass/trigger/apps/modules/README.md new file mode 100644 index 00000000..5e3a128c --- /dev/null +++ b/src/aipass/trigger/apps/modules/README.md @@ -0,0 +1,5 @@ +# Modules + +Business logic for `TRIGGER`. One module per command. + +Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here. diff --git a/src/aipass/trigger/apps/plugins/README.md b/src/aipass/trigger/apps/plugins/README.md new file mode 100644 index 00000000..8658743d --- /dev/null +++ b/src/aipass/trigger/apps/plugins/README.md @@ -0,0 +1,5 @@ +# Plugins + +Scheduled tasks and extensions for `TRIGGER`. + +Plugins are standalone units of work that can be scheduled via the daemon. Each plugin handles one specific recurring task. diff --git a/src/aipass/trigger/docs/README.md b/src/aipass/trigger/docs/README.md new file mode 100644 index 00000000..dc33f82d --- /dev/null +++ b/src/aipass/trigger/docs/README.md @@ -0,0 +1,3 @@ +# Docs + +Documentation files for the `TRIGGER` branch. diff --git a/src/aipass/trigger/templates/README.md b/src/aipass/trigger/templates/README.md new file mode 100644 index 00000000..60e994ae --- /dev/null +++ b/src/aipass/trigger/templates/README.md @@ -0,0 +1,5 @@ +# Templates + +Branch-specific templates for `TRIGGER`. + +Any templates this branch provides to the system or uses internally. Examples: plan templates (flow), trinity templates (memory), test templates (seedgo). diff --git a/src/aipass/trigger/tests/README.md b/src/aipass/trigger/tests/README.md new file mode 100644 index 00000000..db30c87b --- /dev/null +++ b/src/aipass/trigger/tests/README.md @@ -0,0 +1,6 @@ +# Tests + +Pytest unit tests for `TRIGGER`. + +- `conftest.py` — Shared fixtures (temp dirs, mocks, sample data). +- `test_*.py` — Test files. Standard tests cover JSON handler, CLI routing, and error resilience. Custom tests cover branch-specific domain logic. diff --git a/src/aipass/trigger/trigger_json/.gitkeep b/src/aipass/trigger/trigger_json/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/commons/.claude/settings.local.json b/src/commons/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/commons/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +} diff --git a/src/skills/.claude/settings.local.json b/src/skills/.claude/settings.local.json new file mode 100644 index 00000000..376527bc --- /dev/null +++ b/src/skills/.claude/settings.local.json @@ -0,0 +1,28 @@ +{ + "permissions": { + "allow": [], + "deny": [ + "Bash(git reset*)", + "Bash(git rebase*)", + "Bash(git merge*)", + "Bash(git config*)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git checkout -- *)", + "Bash(git checkout .*)", + "Bash(git restore --staged*)", + "Bash(git restore .*)", + "Bash(git clean*)", + "Bash(git branch -D*)", + "Bash(git stash drop*)", + "Bash(git stash clear*)", + "Bash(rm -rf*)", + "Bash(rm -r *)", + "Bash(git checkout -b*)", + "Bash(git commit*)", + "Bash(git push*)" + ], + "ask": [] + }, + "enabledMcpjsonServers": [] +}