diff --git a/.aipass/hooks.json b/.aipass/hooks.json index d4f049ee..0e84c6df 100644 --- a/.aipass/hooks.json +++ b/.aipass/hooks.json @@ -3,6 +3,11 @@ "hooks_enabled": true, "UserPromptSubmit": { + "presence_gate": { + "enabled": true, + "handler": "aipass.hooks.apps.handlers.security.presence_gate.handle", + "matcher": "" + }, "identity_injector": { "enabled": true, "handler": "aipass.hooks.apps.handlers.prompt.identity.handle", @@ -98,6 +103,11 @@ "handler": "aipass.hooks.apps.handlers.notification.telegram_response.handle", "matcher": "", "timeout": 30 + }, + "presence_release": { + "enabled": true, + "handler": "aipass.hooks.apps.handlers.security.presence_gate.handle_stop", + "matcher": "" } }, diff --git a/.aipass/tier1_navmap.md b/.aipass/tier1_navmap.md index ab898dd7..3da3426b 100644 --- a/.aipass/tier1_navmap.md +++ b/.aipass/tier1_navmap.md @@ -55,7 +55,7 @@ src/aipass// - @skills — capability framework. Discoverable, self-contained skill units any agent can run; consume AIPass services as opt-in imports (e.g. the Telegram skill). - @daemon — task scheduler. Cron-triggered firing; each branch owns its `.daemon/schedule.json`, the daemon discovers and fires. - @commons — the social space. Where branches post, comment, vote, and gather as a community. - - @backup — local-first backups. Project-owned snapshots and restore for any directory; no external service. + - @backup — local-first backups. Snapshots + versioning + restore for any directory; optional Google Drive sync (planned). `.backup/` is a shared runtime namespace — @memory rollover and @flow (plan archive) also write there. # Daily commands @@ -96,6 +96,7 @@ Your continuity across sessions. Save proactively — after milestones, decision - `local.json` — session log, key learnings, todos. - `observations.json` — what you learn about the user. - Overflow rolls to vectors automatically — never trim by hand. Two ChromaDB stores: your branch's `.chroma` (local) + a global one across all branches. `drone @memory search "query"` recalls them. Search before assuming you're cold. + - Entry caps are hook-enforced (over-limit edit = rejected whole). The live cap is rendered in each file's `*_meta` line — read it before writing, draft to ~80% of it; if rejected, rewrite hard in one pass. # House rules diff --git a/.backupignore b/.backupignore index f606661b..57595e6b 100644 --- a/.backupignore +++ b/.backupignore @@ -2,7 +2,6 @@ # Lines starting with # are comments. Blank lines are ignored. # Edit this file to customize. Source defaults: handlers/ignore/patterns.py -.backup_system/ .backup/ .git/ .svn/ @@ -27,4 +26,3 @@ dist/ *.log .ruff_cache/ .coverage -*logs \ No newline at end of file diff --git a/.claude/commands/prep.md b/.claude/commands/prep.md index c165fbdc..69a71810 100644 --- a/.claude/commands/prep.md +++ b/.claude/commands/prep.md @@ -25,7 +25,18 @@ Each memory file plays a distinct role. Update based on what actually changed th - **`date`** — ISO date/datetime. - Plus its text field + extras: key_learnings `{number, date, key, value}` · sessions `{number, date, summary, status, tags}` · todos `{number, date, task, priority, status}` · observations `{number, date, note, tags}`. -**When adding:** stamp `number` + `date`, then **prepend** (newest on top). **Don't hand-trim** — rollover archives the oldest *by number* to @memory automatically. +**When adding:** stamp `number` + `date`, then **prepend** (newest on top). **Don't hand-trim** sessions/key_learnings/observations — rollover archives the oldest *by number* to @memory automatically. **Todos are the exception** — rollover never touches them, so you prune done ones by hand (see Reconcile below). + +### Reconcile todos — verify against reality, don't trust the label + +Stored status drifts: a todo finished in a past session often never gets closed. Before writing the session entry, **audit every open todo against the actual system** — check the real state, not the stored `status`: + +- Does the file/dir still exist (or is it gone)? Is the code path in or out? Does the README/doc actually say what the todo claims? Does the audit pass? +- **Close what's verifiably done** → note it in the session entry, then **DELETE the todo from the array**. Rollover never trims todos (they're operational — only sessions/key_learnings/observations roll), so done items left as `status: done` pile up and go stale across chats. Fail honestly — remove only on evidence, never just to tidy the list. +- **Re-scope what's partially done** → record which sub-items landed, keep the rest open. +- **Leave deferred / pending-decision todos open** — but confirm they're still real. + +Quick checks beat assumptions: `ls`/`find` for files, `git ls-files`/`grep` for code/docs, `drone @seedgo audit` for standards. This step is the whole point of "close whats done." ## 2. Active Plans @@ -55,6 +66,7 @@ List everything updated. Format: ``` Prep complete: - local.json: [what was added] +- Todos: [reconciled vs reality — N done & removed, M re-scoped, K still open] - observations.json: [updated / skipped] - Plans: [which ones updated] - Git: [branch, uncommitted count, suggestion] diff --git a/.claude/templates/memo.md b/.claude/templates/memo.md index 37b06a61..6c9bc059 100644 --- a/.claude/templates/memo.md +++ b/.claude/templates/memo.md @@ -14,7 +14,7 @@ Purpose: Update branch memory files after completing work this session. Each memory file plays a distinct role. Update based on what actually changed this session. - **`.trinity/passport.json`** — IDENTITY. Who you are: role, capabilities, principles. Only update if identity genuinely evolved this session. Don't touch it just to touch it. -- **`.trinity/local.json`** — YOUR MEMORY. Session history, key_learnings, and todos[]. Add a session entry for significant work. Add key_learnings for facts you'd need next time. Update todos[] with open items. Trim oldest sessions if over 20. +- **`.trinity/local.json`** — YOUR MEMORY. Add a session entry for significant work; add key_learnings for facts you'd need next time. **Todos: add what you parked, and DELETE every todo you finished this session** — the proof goes in the session entry, not the todo. Rollover never trims todos (they're operational), so done ones you leave behind resurface as "open" next load and you waste time re-confirming them. (Sessions/key_learnings DO auto-roll by number — don't hand-trim those.) - **`.trinity/observations.json`** — YOUR MEMORY OF THE USER. Collaboration insights, preferences, friction points, flow states. Skip entirely if nothing new about the user this session. ## If Relevant diff --git a/.codex/skills/memo/SKILL.md b/.codex/skills/memo/SKILL.md index 95135647..250f122a 100644 --- a/.codex/skills/memo/SKILL.md +++ b/.codex/skills/memo/SKILL.md @@ -18,14 +18,14 @@ Purpose: Update branch memory files after completing work this session. ### Always -- **.trinity/local.json** — Add new session entry to `sessions` if significant work was done. Add new `key_learnings` for facts you'd need next time. +- **.trinity/local.json** — Add a session entry to `sessions` if significant work was done; add `key_learnings` for facts you'd need next time. **Todos: add what you parked, and DELETE every todo you finished this session** — the proof goes in the session entry, not the todo. Rollover never trims todos (they're operational), so done ones you leave behind resurface as "open" next load and you waste time re-confirming them. - **.trinity/observations.json** — Add notable collaboration insights: breakthrough moments, pattern corrections, flow states, friction points, preference discoveries. Skip if nothing notable this session. ### Entry shape — one rule for all four types `key_learnings`, `sessions`, `todos` (local.json) and `observations` (observations.json) all share ONE shape: a **list of objects, newest at the top (index 0)**. Every entry carries a **`number`** (monotonic int per type — highest = newest, never reused; new = current max + 1) and a **`date`** (ISO), plus its text field + extras: key_learnings `{number, date, key, value}` · sessions `{number, date, summary, status, tags}` · todos `{number, date, task, priority, status}` · observations `{number, date, note, tags}`. -**When adding:** stamp `number` + `date`, then **prepend** (newest on top). **Don't hand-trim** — rollover archives the oldest *by number* to @memory automatically. +**When adding:** stamp `number` + `date`, then **prepend** (newest on top). **Don't hand-trim** sessions/key_learnings/observations — rollover archives the oldest *by number* to @memory automatically. **Todos are the exception** — rollover never touches them, so you prune done ones by hand (delete finished todos, see above). ### If Relevant diff --git a/.codex/skills/prep/SKILL.md b/.codex/skills/prep/SKILL.md index d18832c4..a75955b4 100644 --- a/.codex/skills/prep/SKILL.md +++ b/.codex/skills/prep/SKILL.md @@ -18,7 +18,9 @@ Purpose: Button up everything at the end of a session — or before a /compact. - **.trinity/observations.json** — Add collaboration insights if anything notable happened. Skip if nothing new. - **.trinity/passport.json** — Only update if role/purpose/principles genuinely changed this session. -**Entry shape — one rule for all four types:** `key_learnings`, `sessions`, `todos` (local.json) and `observations` (observations.json) are all **lists, newest at top (index 0)**. Every entry carries a **`number`** (monotonic int per type — highest = newest, never reused; new = current max + 1) and a **`date`** (ISO), plus its text field + extras: key_learnings `{number, date, key, value}` · sessions `{number, date, summary, status, tags}` · todos `{number, date, task, priority, status}` · observations `{number, date, note, tags}`. Stamp `number` + `date` and **prepend**; **don't hand-trim** — rollover archives the oldest *by number* automatically. +**Entry shape — one rule for all four types:** `key_learnings`, `sessions`, `todos` (local.json) and `observations` (observations.json) are all **lists, newest at top (index 0)**. Every entry carries a **`number`** (monotonic int per type — highest = newest, never reused; new = current max + 1) and a **`date`** (ISO), plus its text field + extras: key_learnings `{number, date, key, value}` · sessions `{number, date, summary, status, tags}` · todos `{number, date, task, priority, status}` · observations `{number, date, note, tags}`. Stamp `number` + `date` and **prepend**; **don't hand-trim** sessions/key_learnings/observations — rollover archives the oldest *by number* automatically. **Todos are the exception** — rollover never touches them, so you prune done ones by hand (see Reconcile). + +**Reconcile todos — verify against reality, don't trust the label.** Stored status drifts (a todo finished a past session often never got closed). Audit every **open** todo against the actual system: file/dir still there? code path in or out? README says what it claims? audit passes? **Close what's verifiably done** → note it in the session entry, then **DELETE the todo from the array** (rollover never trims todos — they're operational — so done items left as `status: done` pile up and go stale across chats), **re-scope** partials, **leave** deferred/pending-decision ones open. Fail honestly — remove only on evidence, never to tidy the list. Use `ls`/`find`/`git ls-files`/`grep`/`drone @seedgo audit`, not assumptions. ## 2. Active Plans @@ -48,6 +50,7 @@ List everything updated. Format: ``` Prep complete: - local.json: [what was added] +- Todos: [reconciled vs reality — N done & removed, M re-scoped, K still open] - observations.json: [updated / skipped] - Plans: [which ones updated] - Git: [branch, uncommitted count, suggestion] diff --git a/.gitignore b/.gitignore index 0f2dca62..6035a54b 100644 --- a/.gitignore +++ b/.gitignore @@ -87,29 +87,29 @@ src/aipass/*/apps/integrations/** !src/aipass/*/apps/integrations/README.md # Spawn template exceptions (template files must be tracked for public repo) -!src/aipass/spawn/templates/builder/.trinity/ -!src/aipass/spawn/templates/builder/.trinity/** -!src/aipass/spawn/templates/builder/.ai_mail.local/ -!src/aipass/spawn/templates/builder/.ai_mail.local/** -!src/aipass/spawn/templates/builder/.archive/ -!src/aipass/spawn/templates/builder/.archive/** -!src/aipass/spawn/templates/builder/.spawn/ -!src/aipass/spawn/templates/builder/.spawn/** -!src/aipass/spawn/templates/builder/.claude/ -!src/aipass/spawn/templates/builder/.claude/** -!src/aipass/spawn/templates/builder/*_json/ -!src/aipass/spawn/templates/builder/*_json/** -!src/aipass/spawn/templates/builder/logs/ -!src/aipass/spawn/templates/builder/logs/** -!src/aipass/spawn/templates/builder/artifacts/ -!src/aipass/spawn/templates/builder/artifacts/** -!src/aipass/spawn/templates/builder/dropbox/ -!src/aipass/spawn/templates/builder/dropbox/** -!src/aipass/spawn/templates/builder/tools/ -!src/aipass/spawn/templates/builder/tools/** -!src/aipass/spawn/templates/builder/docs.local/ -!src/aipass/spawn/templates/builder/docs.local/** -!src/aipass/spawn/templates/builder/DASHBOARD.local.json +!src/aipass/spawn/templates/aipass_framework/.trinity/ +!src/aipass/spawn/templates/aipass_framework/.trinity/** +!src/aipass/spawn/templates/aipass_framework/.ai_mail.local/ +!src/aipass/spawn/templates/aipass_framework/.ai_mail.local/** +!src/aipass/spawn/templates/aipass_framework/.archive/ +!src/aipass/spawn/templates/aipass_framework/.archive/** +!src/aipass/spawn/templates/aipass_framework/.spawn/ +!src/aipass/spawn/templates/aipass_framework/.spawn/** +!src/aipass/spawn/templates/aipass_framework/.claude/ +!src/aipass/spawn/templates/aipass_framework/.claude/** +!src/aipass/spawn/templates/aipass_framework/*_json/ +!src/aipass/spawn/templates/aipass_framework/*_json/** +!src/aipass/spawn/templates/aipass_framework/logs/ +!src/aipass/spawn/templates/aipass_framework/logs/** +!src/aipass/spawn/templates/aipass_framework/artifacts/ +!src/aipass/spawn/templates/aipass_framework/artifacts/** +!src/aipass/spawn/templates/aipass_framework/dropbox/ +!src/aipass/spawn/templates/aipass_framework/dropbox/** +!src/aipass/spawn/templates/aipass_framework/tools/ +!src/aipass/spawn/templates/aipass_framework/tools/** +!src/aipass/spawn/templates/aipass_framework/docs.local/ +!src/aipass/spawn/templates/aipass_framework/docs.local/** +!src/aipass/spawn/templates/aipass_framework/DASHBOARD.local.json # Commons artifacts subsystem — real source code (craft/trade/capsule), NOT a # runtime dir. Collides with the blanket `artifacts/` ignore (line 49); *.py-only diff --git a/CHANGELOG.md b/CHANGELOG.md index f13c2d3e..469da464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,451 @@ PyPI version — not the changelog header. --- +## [2026-07-02] + +Released as **2.6.1**. Rolls up the DPLAN-0226 / FPLAN-0289 / TDPLAN-0010 / +FPLAN-0298 batch (unified Telegram↔Claude Code bridge, single-session presence +gate, live Telegram streaming, `aipass init` template selector + portability, +`@backup share`) — all documented under `[2026-07-01]` — plus the CI +stabilization below. + +### Fixed + +- **CI green — six regressions from the DPLAN-0226 / FPLAN-0289 / TDPLAN-0010 + batch (PR #646).** The dev branch had gone red across `seedgo-audit`, the + `test` matrix, and Windows; root-caused and fixed at source: + - **seedgo** — the new `template_check` advisory checker was gating CI. + `branch_audit.py` averaged *all* checker scores into the branch total, so + `template_check`'s `ADVISORY=True` was never honored and it dragged 7 + branches below the 100% floor on legitimate README brace-examples. Added a + `gating_scores` filter that excludes `ADVISORY is True` checkers before + computing the average (strict `is True` to avoid MagicMock false-positives) + and exposed `advisory_standards` in the audit output. Also refreshed the + provider hooks snapshot fixture to include the `presence_gate` + `UserPromptSubmit` hook (FPLAN-0289), fixing 4 `test_hooks_snapshot` tests. + - **hooks** — `cc_sessions.py` (added by the bridge, `f6cbe34`) was missing + its README entry and a seedgo `modules` bypass (it reads external + `~/.claude/sessions/*.json`, not branch data, so `json_handler` is the wrong + tool — same precedent as `presence.py`). Added both. + - **spawn** — retired the `passport(disabled).py` / `passport_ops(disabled).py` + pair to `.archive/`; the `(disabled)` suffix kept them visible to the type + checker, which flagged a broken cross-import between them. + - **ai_mail** — `test_child_inherits_broker_fd` gave its throwaway test branch + a real `.trinity/passport.json` so the broker's new `.trinity`-marker + resolution (`f914ab6`) can resolve it and permit the delete. + - **spawn** — the `builder→aipass_framework` template rename (`13463c0`) left + `.gitignore` exceptions pointing at the old `templates/builder/` path, so + `DASHBOARD.local.json` + ~10 other template files were silently untracked + since the rename — present on disk (dirty tree passed) but absent from clean + clones/CI, so `test_full_spawn` failed only in a clean checkout. Fixed all 23 + `.gitignore` exception paths and committed the now-visible template + scaffolding. + - **skills** — `test_streaming` asserted a `+1` newline byte, but `write_text` + text mode translates `\n`→`\r\n` on Windows (2 bytes), failing `windows-setup` + only. Switched the test's transcript writes to `write_bytes()` for + deterministic LF; production `_tail_transcript_bytes` was already CRLF-safe. + +## [2026-07-01] + +### Added + +- **`aipass init` is now a template selector (TDPLAN-0010)** — `init` presents a + chooser with **`empty project`** at the top, pre-selected as the default + (creates just the project folder, no scaffold), and **`aipass_framework`** + below it (the full AIPass agent framework — the old always-on behavior, now + opt-in). Flag and positional forms both work: `aipass init --list` (branches + before the `--` catch-all) and `aipass init