Commit Graph
648 Commits
Author SHA1 Message Date
AIOSAI 83e65b3374 chore: gitignore PPLAN-*.md for plan-type consistency + spawn builder template registry id refresh 2026-06-11 13:53:40 -07:00
AIOSAI 2af856d81d chore(release): v2.5.3 — date-based CHANGELOG headers + rename sunday_merge playbook to merge (drop weekly cadence) 2026-06-11 12:49:07 -07:00
AIOSAI 54d55abebc feat(aipass): init detects missing Claude Code, offers install (yes/no) 2026-06-11 00:12:32 -07:00
AIOSAI ed17630b76 fix(drone): broker start_background blocks until listening — kill connect-before-bind race 2026-06-10 23:23:56 -07:00
AIOSAI 707f54a6f2 fix(ci): guard remaining AF_UNIX broker tests for Windows — ai_mail + aipass 2026-06-10 23:04:52 -07:00
AIOSAIandClaude Opus 4.8 e33cf2bfbe fix(ci): guard Linux-only sandbox tests for Windows — skipif(sys.platform != linux)
test_broker.py (AF_UNIX sockets + openat2) and test_sandbox.py (bwrap) are
Linux-only; module-level pytestmark skips them on windows-latest while leaving
Linux runs unchanged. Unblocks the windows-setup CI check (red since the
sandbox build 0b4ba63).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 22:50:44 -07:00
AIOSAIandClaude Opus 4.8 53340ab169 fix(seedgo): audit local==CI parity — output-dir skips + diagnostics fail-honesty + pyright determinism (FPLAN-0261)
Hoist per-checker SKIP_DIRS to shared SOURCE_SKIP_DIRS (artifacts/dropbox are
output dirs, not source; no git coupling). Diagnostics: python3->sys.executable,
parse/run failures now fail loud instead of silent 0-errors-clean, and pin
pyright resolution with --pythonpath sys.executable. drone bypasses test-only
broker start_background. Proven all-13-branches-100% deterministic in an
unactivated shell (local==CI).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 22:09:01 -07:00
AIOSAI 17863ac4c5 refactor(shared): re-home aipass.common into its steward — src/aipass/aipass/shared (FPLAN-0260)
src/aipass/common was the only non-citizen directory in the agent namespace.
Per @seedgo design review: moved into @aipass (owner) as aipass.aipass.shared,
content byte-identical. @spawn imports across (blessed shared-infra category,
same as aipass.prax/cli). New subprocess guard test pins the bootstrap-safety
invariant (shared/ loads zero branch deps — aipass init stays pre-drone-safe).
9 import/doc sites updated, 9 documented seedgo bypasses (pre-infra leaf,
stdlib-only by design). aipass 480 + spawn 315 tests green, both audits 100%,
repo-wide zero refs to the old path.
2026-06-10 18:26:26 -07:00
AIOSAIandClaude Opus 4.8 0b4ba63fae feat(sandbox): kernel filesystem boundary for agent containment (DPLAN-0202/FPLAN-0250)
Every autonomous agent can launch inside a kernel-enforced mount namespace
(srt -> bwrap+seccomp): reads stay open (shared live FS preserved, bind-mount not
isolation; own-tree writes land live), but rm/python/find/Write on .git or sibling
trees hit EROFS. /tmp + own tree writable; .git RW devpulse, RO builders. Inert by
default behind AIPASS_SANDBOX_ENABLED (off); flag-off path byte-identical to old.

hooks: srt wrapper + per-role build_policy + broker_secret mask; rm_gate demoted.
drone: out-of-sandbox broker (identity allowlist, openat2 RESOLVE_BENEATH, HMAC
handshake over inherited fd, audit); drone rm via broker when sandboxed.
ai_mail: dispatch gate + broker-fd wiring (fail-loud exit -4, never silent).
aipass: doctor Sandbox group + setup.sh prereqs (LOUD on missing).

Proven by a live 16-check red-team suite. seedgo 100% + 2859 tests green across
all 5 touched branches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 13:16:22 -07:00
AIOSAIandClaude Opus 4.8 0c6e8ac425 fix(hooks): auto_watchdog sound-migration (FPLAN-0249 tail)
Same action-gated pattern as the notification handlers — speak() -> 'sound'
return-key. Missed in b26bd7c. Hooks suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 13:10:27 -07:00
AIOSAIandClaude Opus 4.8 b26bd7c853 fix(hooks): cadence sound-migration tail — action-gated sound via return-key (FPLAN-0249)
Notification handlers (announce, email, stop_sound, tool_sound) return a
'sound' key the engine plays on action instead of calling speak() on every
invocation — quieter and honest (skipped loaders stay silent). Slim
cadence_investigation.md. Tests updated to assert the return-key form. 472/472
hooks green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 13:09:32 -07:00
AIOSAIandClaude Fable 5 00edd8b3a0 fix(hooks): auto_fix ruff legs were silently dead — invoke via venv interpreter
Three ruff call sites called bare `ruff`, absent from the hook subprocess
PATH (ruff lives only in .venv) — logged 'ruff not found' 177x over ~a month,
silently skipping lint+format on every edit. Also `--output-format=text` was
removed from modern ruff. Fixed all three sites to `sys.executable -m ruff`
(the pattern the working pyright leg already uses) + concise format + honest
rc>=2 error logging. Tests now pin the invocation (argv == sys.executable -m
ruff) so a regression fails loud — the subprocess-mock is how this hid.
438/438 hooks tests green; live-verified through the real hook pipeline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 22:34:38 -07:00
AIOSAIandClaude Fable 5 73aedef20f fix(prax): hook events render styled in monitor — regex required phantom action= field (td-007)
Root cause: _HOOK_PATTERN required an action= key that cadence never
emits — it logs the action as the bare second word (fired/skipped).
Extraction failed, so events never reached the styled print_hook_event
renderer (bold-green lightning / dim dot). Pipeline was already correct.

- _HOOK_PATTERN -> bare-word capture: r'\[HOOKS\]\s+(\w+)\s+(\w+)'
- enriched hook event detail (period, offset, short session id)
- corrected docstring that documented the phantom action= format
- tests updated to real production format + real-pipeline test added
- type:ignore on watchdog imports (repo convention)

Verified: 914/914 prax suite green (90 log_watcher). @prax dispatched
for full-pipeline trace; stale monitor process explained the no-show.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 20:16:16 -07:00
AIOSAIandClaude Fable 5 fc4b263504 fix(hooks): cadence separate-process race + action-gated sound + auto_fix diagnostics regression (DPLAN-0200, FPLAN-0249)
Cadence redo — verified against the live execution model, not unit tests:
- Counter now advances exactly once per real turn (mtime debounce +
  transcript-size token + flock). Fixes the separate-process leapfrog where
  global/branch loaders double-incremented and fired erratically.
- Structured [HOOKS] cadence fired|skipped logging; prax monitor renders
  hook events distinctly for live visibility.
- Action-gated sound: handlers return a 'sound' key the engine plays only on
  real action — skipped loaders are silent (no more false piper every turn).
- Fixed auto_fix.py: leftover speak() NameError (swallowed by broad except)
  meant diagnostics silently never ran on any edit. Removed; sound moved to
  the error path.
- Tests rewritten to model separate-process execution (leapfrog regression
  test added); sound assertions across all refactored handlers. 438 pass.

prax: hook fire/skip event rendering in the live monitor. 913 pass.

README: hardcoded metrics (version/tests/PRs/standards) -> live PyPI+codecov
badges and qualitative wording; killed the 33-vs-36 drift. CHANGELOG W24.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 16:28:26 -07:00
AIOSAI 2bccf0311e feat(hooks): prompt injection cadence — fire loaders every Nth turn, config-tunable (DPLAN-0200, FPLAN-0249)
Stop re-injecting the global + branch prompts every turn (~3k tokens/turn).
They now fire together every 5th turn; the prior injection persists in context
between fires. Identity + email stay every-turn.

- apps/modules/cadence.py: per-session turn counter (/tmp/aipass-cadence-
  {session_id}.json), should_fire(loader)/reset_counter(), DEFAULTS + deep-merge
  config (api provider.py pattern). 'drone @hooks cadence' introspection.
- global_loader.py + branch_loader.py: cadence guard via importlib (crash-
  isolated); non-fire turn returns empty.
- compact.py: PreCompact resets counter to -1 -> next turn = 0 = all fire
  (rebuild context after compaction). New session = fresh counter = all fire.
- hooks_json/custom_config/cadence_config.json: tunable knob (period/offsets/
  enabled), one file, no code edits. Data lives in the json home, not the code
  dir. Missing file = code DEFAULTS = safe.
- .seedgo/bypass: documented stdlib-json config read (json_handler N/A for a
  dispatch engine).

435 tests pass (26 new), seedgo 100%, pyright 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 23:07:36 -07:00
AIOSAI d24887b7f5 feat(memory): template-conformance normalize + auto-heal on triggers (DPLAN-0200)
Memory files now reconcile to template, not just clean known fields:
- normalize.py: rewrote from field-targeted cleanup to template-conformance —
  strips ANY key not in the template at every level (root/metadata/limits/status).
  Kills legacy orphans (old 'st' blocks, active_tasks, current_lines, max_lines)
  that field-targeted cleanup was blind to. Fixed _MEMORY_ROOT path (parents[3])
  that silently skipped template loading in production.
- memory_watcher.py: wired normalize_memory_file into both scan paths
  (check_and_rollover + on_modified) with a write-loop guard — drift now
  self-heals on every trigger, no manual run needed.
- line_counter.py: stop writing current_lines (entry-count is the only metric).
- LOCAL/OBSERVATIONS templates: removed line-count fields.

Entry-count is the sole rollover metric, both files, all branches.
873 tests pass, seedgo 100%.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 23:07:24 -07:00
AIOSAI a53ea93b17 fix(ai_mail): preserve multi-line reply/send bodies — join args[1:]
Reply and send silently truncated multi-line bodies to the first CLI arg.
handle_reply(args[1]) and parse_send_args(rest[1]) dropped args[2:]/rest[2:]
when a body word-split into multiple args. Now join all remaining args.
Backwards-compatible; single-arg messages unchanged. +6 tests (718 total).

Found via @hooks replies arriving as first-line-only (60/48 chars).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 21:27:23 -07:00
AIOSAI ff9cc3f3b5 docs(playbook): strengthen — never move HEAD lightly (Patrick's rule) 2026-06-08 11:29:48 -07:00
AIOSAI e97130ffbc docs(playbook)+memory: git law — local=truth, never checkout main / move heads lightly; squash vs ff realign corrected 2026-06-08 11:28:33 -07:00
AIOSAIandClaude Opus 4.8 2e96ddc302 chore(release): bump version 2.5.1 -> 2.5.2 (security patch)
Mid-week patch release for the CI/release security hardening:
least-privilege e2e-wheel token + Sigstore-signed GitHub Releases.
Bumps both pyproject.toml and src/aipass/__init__.py __version__.

Versioning scheme: patch (2.5.x) = small mid-week fixes, minor (2.x.0)
= Sunday main-merge batches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:28:48 -07:00
AIOSAI c7055de5e2 docs(playbook): sunday_merge — bump BOTH version files, pre-flight version check, clearer manual tag step (from this run's friction) 2026-06-08 10:09:00 -07:00
AIOSAI 91b3f437fe chore(release): bump __version__ 2.5.0->2.5.1 to match pyproject + v2.5.1 release tag 2026-06-08 00:08:33 -07:00
AIOSAI 1e00119d9b fix(init): correct aipass init scaffold — project-specific AGENTS.md, README paths, my-agent->my_agent default, drop dead registry_path 2026-06-07 23:58:41 -07:00
AIOSAIandClaude Opus 4.8 9a64db9093 fix(spawn): seed todos[] into builder template .trinity/local.json (TDPLAN-0007 follow-up)
Verification audit caught a gap: spawn create copies templates/builder/ tree
directly (DEFAULT_TEMPLATE), but builder/.trinity/local.json lacked the todos[]
schema — so freshly spawned branches would not inherit it. Seeded todos[] +
max_todos:10 + todo_text_max_chars:200 + operational note to match @memory's
LOCAL.template.json. Now both spawn-create and template-push paths produce
todos[].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:30:35 -07:00
AIOSAIandClaude Opus 4.8 626ab81a46 refactor(status): decommission entire STATUS flow — STATUS.local.md + central STATUS.md retired, replaced by local.json todos[] + dashboard count (TDPLAN-0007)
Cross-branch coordinated change. Per-branch STATUS.local.md (13) + central
STATUS.md deleted; all prompts/docs/skills/hooks/footer/scaffolding scrubbed.
Status-sync engine kept intact-but-inert (trigger registry unwired, 3 lines).
Replacement: operational todos[] in .trinity/local.json (@memory schema, capped,
rollover-exempt), pushed to all 13 branches + surfaced as dashboard todo_count.

Owners: memory (schema+global push+template), prax (dashboard todo_section +
engine dormant), trigger (unwire), aipass (init scaffolding), spawn (template
delete + todos[] seed), hooks (compact recovery), ai_mail (footer), seedgo
(_RUNTIME_ARTIFACTS cleanup), devpulse (scrub+delete+assemble).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:53:24 -07:00
AIOSAI f4b203a74e feat(standards): enforce Rich introspection formatting + 13 branches to seedgo 100%
- seedgo: new check_introspection_rich_formatting (delegation-aware) + introspection.md richness section + tests
- 13 branches: wrap print_introspection in Rich markup -> all at seedgo 100%
- S202 CLI polish: @hooks --help rewrite (hooksound on/off/status surfaced), spawn repair help clarity, drone Rich colour restore for --help/introspection/status
- flow: playbook plan-type (PPLAN) self-serve templates (default.md, sunday_merge.md SOP) + register-overrides-auto fix + --help rewrite
- hooks: setup.sh installs auto_process bridges + seedgo snapshot fixture learns them (TDPLAN-0005 followup, clears commit-gate blocker)
- remove orphaned devpulse/SETUP.md (vectorized to @memory)
- CHANGELOG [2026.W23]
2026-06-07 18:51:21 -07:00
AIOSAIandClaude Opus 4.8 e80e524dfe refactor(spawn): backups to single .spawn/.recovery namespace (TDPLAN-0006 P4)
Spawn's pre-merge JSON backups dropped a .recovery/ dir at each branch root,
which had accumulated 242 stale auto-gen DASHBOARD backups across 10 branches
(the original .recovery report that started this whole investigation).

- aipass.common.json_ops.backup_json gained optional backup_dir param
  (default unchanged = file_path.parent/.recovery, backward-compatible).
- spawn update engine (update_ops.py _merge_json) now passes
  branch_dir/.spawn/.recovery as the backup dest -> backups land under the
  spawn-managed .spawn/ dir, one namespace, not cluttering branch roots.
- Memory stays in the safety net: no memory-exclusion added; the engine just
  never touches .trinity/DASHBOARD on update so it never backs them up.
- 2 new tests (unit: custom backup_dir; integration: backup lands in
  .spawn/.recovery). 315 spawn + 438 aipass tests green; seedgo 100% both.

Stale .recovery backups swept separately (untracked/gitignored, local hygiene).
.recovery/ gitignore pattern already covers .spawn/.recovery/.

TDPLAN-0006 P4 — final phase. Closes the spawn update-safety + consolidation
work (P0 dry-run-default, P1 #636 engine, P2 shared lib, P3 import kill, P4
backup relocate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:24:31 -07:00
AIOSAIandClaude Opus 4.8 59a6fcee13 refactor(aipass): subprocess to drone @spawn sync-registry — kill last cross-branch engine import (TDPLAN-0006 P3)
init_flow.py:896 was the one place aipass imported spawn's Python directly:
  from aipass.spawn.apps.modules.sync_registry import sync_registry
Replaced with subprocess.run(['drone','@spawn','sync-registry','--fix']) — the
command spawn already exposes — matching the aipass init agent -> drone @spawn
create pattern. Graceful degradation preserved: FileNotFoundError (no drone),
non-zero exit, and timeout are all silently skipped so a registry-sync hiccup
never hard-fails an init update. Safe because init update runs on an existing
project where drone is installed (NOT the pre-drone fresh-init path).

aipass branch now has ZERO direct imports of another branch's ENGINE code.
Remaining cross-branch imports are shared SERVICE layers only (cli Rich UI,
prax logger used in 347 files, trigger events) — infrastructure, not duplication.

Verified: zero aipass.spawn imports in .py code; fresh aipass init still
scaffolds (bootstrap pre-drone intact, 69 tests); 438 tests green (4 new for
the subprocess path: success/failure/missing-drone/timeout); seedgo 100%.

TDPLAN-0006 P3. P4 (.recovery relocate) is the last phase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:14:28 -07:00
AIOSAIandClaude Opus 4.8 14e134b8e6 refactor(common): extract aipass.common shared lib — dedup spawn/aipass (TDPLAN-0006 P2)
@spawn and @aipass each maintained their own copy of the JSON merge/handler
utilities and registry discovery. Collapsed into ONE branch-free package both
import: src/aipass/common/ (json_ops: deep_merge + backup_json ;
json_handler.JsonHandler ; registry_discovery.find_registry).

- aipass.common imports ZERO branch code → aipass/bootstrap.py (runs pre-drone)
  can depend on it without breaking the pre-infrastructure constraint. Verified:
  bootstrap zero-import intact, real aipass init still scaffolds a fresh project.
- Duplicate copies deleted: spawn keeps a thin re-export shim; aipass json_handler
  shrank 254 -> 88 lines; aipass find_registry dedup'd across structure_scanner,
  doctor, doctor_fix.
- save_json contract UNIFIED: raises ValueError on invalid structure (was
  return-False in aipass). All call sites + tests updated to the raise contract.
- find_registry dedup scoped to spawn<->aipass only; seedgo/drone copies flagged
  as follow-up.

Verified: 313 spawn + 434 aipass tests green; seedgo 100% both; aipass.common
branch-free; aipass init scaffolds post-refactor.

TDPLAN-0006 P2. P3 (move project-update into spawn, kill init_flow import) +
P4 (.recovery relocate) to follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:03:15 -07:00
AIOSAIandClaude Opus 4.8 ccc8d6a97b fix(spawn): dry-run-default + path-based update engine — kill #636 branch-scrambler (TDPLAN-0006 P0+P1)
#636: drone @spawn update would scramble every branch's identity/memory in
one command. On a branch created seconds earlier, --dry-run proposed 30 renames
rotating identity dirs (apps->.trinity->.seedgo->.claude->.archive->.aipass),
README->DASHBOARD, and deep-merged stale template into live .trinity/. Root
cause: the CREATE path regenerated template-registry IDs in filesystem-walk
order (!= the master's hand-crafted IDs), so content-hash + rename-detection
saw a mismatch on a pristine branch. update --all would have destroyed all 13
citizens at once.

P0 — safety by default:
- update + repair are now dry-run by default; --apply required to write.
  Forgotten flag = safe preview-only no-op. --dry-run kept as alias.
- doctor_fix.py repair suggestions emit the matching --apply form
  (+ aipass test_doctor_fix updated to the new contract).

P1 — engine rebuild (update_ops.py v2.0):
- Path-based named-managed-files model replaces whole-tree hash-diff +
  rename-detection. ID divergence is moot — IDs are no longer used.
- .trinity/*, DASHBOARD.local.json, artifacts/birth_certificate.json,
  .seedgo/bypass.json = delivered on CREATE only, NEVER touched on update.
- Old ID engine (change_detection.py, reconcile.py) + orphaned tests deleted.

Verified on fresh sandbox: update --dry-run = 0 renames / 0 updates / 0
additions (create==update invariant); no-flag run = dry-run preview, filesystem
byte-identical; 313 spawn tests green; seedgo 100% (all 36 standards).

Closes #636. P2/P3/P4 (shared lib, seam, .recovery relocate) to follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:54:09 -07:00
AIOSAI 1ef1e2e89c feat(memory): auto-process memory pool + rollover on session-start/pre-compact (TDPLAN-0005) 2026-06-06 20:28:19 -07:00
AIOSAIandClaude Opus 4.8 8efb204486 fix(seedgo): de-git readme_check — audit reads local files only (DPLAN-0198)
Drops git check-ignore + git log from readme_check. Runtime dirs tolerated via
static list (_is_runtime_artifact); freshness checks date-presence only, no
history comparison. Local-CI parity proven 13/13 both ways (working tree +
git archive clean checkout). Invariant: a checker never consults git or
.gitignore; only bypass.json excludes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:31:38 -07:00
AIOSAIandClaude Opus 4.8 4c7e14a255 fix(seedgo): readme check-ignore must match dir-only patterns on clean checkout (DPLAN-0195)
The last 1%: 7 branches scored 99% in CI while 100% locally. Root cause proven
by reproducing CI's exact path (tracked-only tree + real .git): .gitignore
dir-only patterns (trailing slash — logs/, **/*_json/, .trinity/) do NOT match
via 'git check-ignore <bare-path>' when the path is absent from disk (clean
checkout), because git cannot infer 'directory' to apply a dir-only pattern.
The working tree has those dirs on disk, so it matched there — the exact
working-tree-vs-clean-checkout divergence.

_is_gitignored now also tests the trailing-slash form; all 7 readme failures
(cli_json/logs/artifacts/.trinity/ etc flagged 'missing on disk') clear.
Regression test builds a real git repo with dir-only patterns + non-existent
paths. CI gate also now prints failing standards + check messages (says WHY).

Verified: clean tree w/ real .git 13/13 100%; working tree 13/13 100%; seedgo
1053 tests green; pyright 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 00:19:38 -07:00
AIOSAIandClaude Opus 4.8 24065f11b3 fix(seedgo): audit committed source not working tree — seedgo-audit CI gate green (DPLAN-0195)
Four standards checkers validated the working tree, so CI (clean checkout =
tracked files only) scored ~97% while local audits passed at 100%. Fix each
to measure what git actually ships:

- log_structure: skip absent gitignored logs/ dir (keeps hardcoded-path checks)
- readme: cross-ref .gitignore (git check-ignore + fallback), skip ignored
  dirs/links in tree + dead-link checks
- encapsulation: infer branch from path when gitignored REGISTRY absent; fix
  aipass-branch collision
- architecture: skip cleanly when gitignored passport.json absent

Clean-tree AND working-tree audits both 13/13 = 100%. seedgo 1052 tests green,
pyright 0.

Also: git_gate read-verb allowlist (22 read verbs raw, write stays drone-gated);
update devpulse test_git_gate contract to match; devpulse local-prompt git
breadcrumb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 23:58:53 -07:00
AIOSAI 176f68439c ci(standards): full-history checkout for audit + honest aipass README refresh 2026-06-05 22:29:19 -07:00
AIOSAI c58fd263ab ci(standards): all 13 branches to genuine 100% — file-size advisory + readme-freshness git-history 2026-06-05 21:56:46 -07:00
AIOSAI cc8f809a50 refactor(seedgo): archive pre-DPLAN-0184 hook cruft (FPLAN-0241)
Archive orphaned hook bridge/probe/manifest modules + their tests to
.archive/ — their only callers were the .claude/hooks scripts disabled
by DPLAN-0184. Seedgo audits hooks via standards; the hooks branch owns
the engine/bridge/handlers. README + bypass.json + prompts updated to
match. 1045 tests green, pyright clean.
2026-06-05 19:44:35 -07:00
AIOSAIandClaude Opus 4.8 8bd270287d chore(release): bump 2.5.0 -> 2.5.1
- pyproject: patch bump (cross-OS e2e wiring harness + Windows portability
  fixes landed this week; CHANGELOG [2026.W23] documents the work)
- tests/CROSS_OS_TESTING.md: add manual layer-3 cross-OS acceptance checklist
  (living draft; refined as real Win/Mac VM runs surface gaps)
- prax dashboard: drop commons_mentions from quick-status calc

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:52:23 -07:00
AIOSAIandClaude Opus 4.8 668841417f fix(portability): aipass init UTF-8 stdout on Windows + CI e2e lane (DPLAN-0194)
The real T1 Windows bug (diagnosed via the now-reverted error-surfacing
probe): aipass init scaffolds fine, then crashes printing its success
banner — Rich writes the success glyphs through a cp1252 stdout
(UnicodeEncodeError 'charmap'). Same class as the drone fix. The aipass
entry point now reconfigure()s stdout/stderr to UTF-8 in place on Windows.

Also: ci.yml's broad 'pytest --rootdir=.' swept in tests/e2e (which build
a wheel via the dedicated e2e-wheel.yml), failing the unit lane since the
harness landed; now --ignore=tests/e2e in both pytest jobs.

route_command error-surfacing probe reverted to honor 'no function change'
(the masked-error mislabel is noted as a separate @aipass recommendation).

Local: e2e 14/14 green, aipass units 24/24, ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 01:17:56 -07:00
AIOSAIandClaude Opus 4.8 89fa2c1db2 fix(aipass): surface module errors instead of masking as 'Unknown command'
route_command swallowed any handle_command exception and let main() print
a misleading 'Unknown command', hiding real failures (e.g. the Windows
aipass-init error the e2e harness hit). It now also prints the failing
module + traceback to stderr. Bool contract unchanged; 24/24 aipass unit
tests pass. This makes the masked Windows init failure diagnosable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 01:06:36 -07:00
AIOSAIandClaude Opus 4.8 f3b3ebad9b fix(portability): Windows aipass init + drone stdout (DPLAN-0194)
Two latent Windows portability bugs caught by the new e2e wiring harness:

- aipass init: _preflight_check ancestor walk crashed on OSError from
  un-enumerable Windows drive-root entries (pagefile.sys), swallowed by
  route_command as 'Unknown command: init'. Walk now skips unreadable
  entries (logged).
- drone @branch: crashed with UnicodeEncodeError ('charmap') printing a
  routed branch's captured output via Rich on cp1252 stdout. PYTHONUTF8
  only affects child interpreters; entry point now reconfigure()s the live
  stdout/stderr to UTF-8.

Pure portability — Linux/macOS behaviour unchanged. e2e suite 14/14 green
locally on Linux. Lets the 3-OS CI verify Windows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 01:00:01 -07:00
AIOSAIandClaude Opus 4.8 cd1af34be8 test(e2e): cross-OS wiring harness + 3-OS CI, red-first (FPLAN-0239)
Build-wheel -> install-clean -> assert 4-tier wiring ladder (install/init/
hooks-fire/drone-route). Validated green on Linux; Windows red-first by design
(symlink/venv-path/tmp gaps = DPLAN-0194 P3 fix-list).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 00:03:37 -07:00
AIOSAI ee78c39e80 security(deps): pin requests>=2.34.2 to clear 6 OSV advisories (DPLAN-0193 step 1) 2026-06-03 11:34:02 -07:00
AIOSAI 87d131218e feat(hooks): log agent_type/agent_id per hook fire for visibility (#606) 2026-06-02 22:02:22 -07:00
AIOSAI e63a4e9945 feat(#630): retire blanket rm deny + aipass doctor migration
Phase 2 of #630. The rm_gate hook + drone rm now own destructive-delete
protection (cross-provider, path-aware, teaching), so the Claude-only blanket
deny is redundant AND harmful (it short-circuits before the hook, suppressing
the teaching message).

- setup.sh: removed Bash(rm -rf*) + Bash(rm -r *) from git_deny (new installs)
- bootstrap.py: removed Bash(rm -rf *) shipped via aipass init (project settings)
- doctor_wire.reconcile_stale_deny(): aipass doctor WARNs on stale rules;
  --fix removes them (idempotent, preserves all else) — migration for existing
  installs (the 'aipass update should be trusted' goal)
- .aipass/project_hooks.json template: added rm_gate (new projects get it)

Tests: 8 reconcile + 432 aipass total, seedgo 99%. CHANGELOG W23.
2026-06-02 20:24:21 -07:00
AIOSAI 2f5ce5ac87 feat(#630): drone rm safe-delete + rm_gate block-and-teach hook
Provider-agnostic temp/scratch cleanup that doesn't trip the rm -rf block.

- drone rm <path>: contained recursive delete (project root + /tmp + $TMPDIR),
  refuses outside roots and hard-carves .git/.trinity/.aipass/.codex/.agents +
  sibling-branch worktrees. Mirrors Codex's OS-sandbox boundary in software so
  behavior is consistent across CLIs. Pure-python, red-team tested.
- rm_gate (PreToolUse hook): blocks raw recursive rm, teaches 'drone rm',
  cross-provider, conservative-block on unparseable targets. Mirrors git_gate.
- Wired rm_gate into .aipass/hooks.json; CHANGELOG W23.

Tests: 56 drone rm + 56 rm_gate, seedgo 99% both. Phase 2 (remove the now-
redundant rm deny from setup.sh + aipass doctor migration) tracked separately.
2026-06-02 20:05:16 -07:00
AIOSAIandClaude Opus 4.8 895b8f04fd fix(drone): protect dev on merge + live-remote branches + scope footer (#625, #623)
#625 (HIGH): drone @git merge passed --delete-branch to gh pr merge
unconditionally, so merging a dev->main PR DELETED the persistent dev branch
on the remote and left the tree on main (next commit silently on main). Now:
- merge looks up the PR head ref and only appends --delete-branch for
  non-protected branches; dev/main are never deleted. Unknown head ref fails
  SAFE (no delete) — devpulse hardening on top of @drone's protected-branch set.
- after merge, return the working tree to dev (loud warning if it can't).
- branches_handler runs git fetch --prune before git branch -r (no more
  'cached lies' reporting deleted branches as live).
- new drone @git prune-temp cleans merged temp PR branches (citizen/*).

#623: status/diff append a '(showing <branch> scope — use --all for full repo)'
footer when scoped, so an empty scoped view isn't mistaken for a clean repo.
Blank-output sub-item not reproducible — documented.

@drone built fixes 1-5 (FPLAN-0236); devpulse added the unknown-head-ref
fail-safe + test and verified independently. drone suite 716 pass, seedgo 99%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 17:39:01 -07:00
AIOSAIandClaude Opus 4.8 bedf58e7b5 fix(drone): external projects can resolve AIPass branches (#618)
resolve_branch() validated branch path containment against the primary
registry root even when the branch was found via the AIPASS_HOME fallback,
so external projects (Vera, Daemon) were blocked from calling @api and any
other AIPass branch with 'path escapes project root'.

Add get_branch_with_registry() (non-breaking sibling to get_branch_by_name)
that returns the branch plus the registry it was found in. resolve_branch()
now validates containment against that registry's root. Security preserved:
each branch stays contained within its own declaring registry; genuine
escapes still blocked. 4 new cross-project resolver tests, 58 resolver
tests pass, drone suite 702 pass, seedgo @drone 99%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 16:25:46 -07:00
AIOSAIandClaude Opus 4.8 da46dde7ce chore(aipass): purge stale placeholder bypass entries + refresh metadata
Removed 5 stale Phase-0/Phase-4 bypasses (verified seedgo passes without them
now that aipass is fully built). Restored 3 aipass.py entries (cli/debug_print/
introspection) with accurate current reasons — thin command router, not a
module. Metadata description updated to current operational state. 58→53 entries.
424 tests pass, seedgo 99%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:46:26 -07:00
AIOSAIandClaude Opus 4.8 f7d7f78c63 fix(aipass): bare 'aipass <command>' runs the command, not an introspection banner
aipass is a user-facing binary — 'aipass doctor' must run the health check,
not describe itself. All 7 modules (doctor, doctor_fix, doctor_wire, handoff,
help_chat, init_flow, profile) hit a no-args→introspection gate (a standard
meant for 'drone @branch <module>' discovery). Bare invocation now runs the
command or shows usage; introspection moved to --info. seedgo introspection
standard bypassed for these binary-invoked modules (documented). 424 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:22:22 -07:00