feat: add Claude Code hooks integration#13
Open
nandanugg wants to merge 6 commits intocortexkit:mainfrom
Open
Conversation
Add install/uninstall scripts that set up AFT hooks for Claude Code: - Tool interception for Read, Grep, Glob via PreToolUse hooks - CLI wrapper for semantic commands (outline, zoom, call_tree, callers, etc.) - Global AFT.md instructions so Claude learns to use AFT for context savings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add MANDATORY section emphasizing AFT-first approach - Add Decision Tree for quick command selection - Rename "Best Practices" to "Rules (NOT suggestions)" - Add Context Protection section to prevent context exhaustion - Clarify that AFT applies to all file types, not just code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add prominent "AFT applies to ALL file types" note in MANDATORY section - Change "Before ANY code exploration" to "Before reading ANY files" - Add docs/config example to decision tree - Add new row for docs/configs in "When to Use What" table - Add rule cortexkit#6: "ALWAYS outline before sampling" Addresses feedback that code-centric language caused AFT to be skipped for markdown/documentation files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Read from hooked tools list (conflicts with Edit validation) - Add guidance to use `aft read` via Bash for indexed reads - Add warning: use native Read tool when editing is needed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Subagents don't follow ordering guarantees, so leaving "outline first" as a mid-step instruction doesn't work. Run outline yourself and include the output in the subagent prompt. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5 tasks
ualtinok
added a commit
that referenced
this pull request
Apr 25, 2026
…llowups Second full-codebase audit found 38 items; 32 confirmed real after triple- verification, plus a third pass after Oracle review caught one introduced SSRF bypass. Security: - aft-cli: createGitHubIssue uses spawnSync with argv to prevent shell injection through repo/title (#6). - opencode + pi: restrict_to_project_root defaults to true for plugin contexts; the Rust CLI default stays false for direct/scripted use (#1). - opencode: per-server random RPC token (32B hex) stored in JSON port file; every request requires the token; legacy integer port files still parsed for backward compatibility (#23). - opencode: url-fetch SSRF guard with manual redirect handling (max 5 hops), full IPv6 expansion, and IPv4-mapped/compatible bypass detection (::ffff:127.0.0.1, ::127.0.0.1, [::]); allowPrivate escape hatch (#32 + Oracle followup). - Rust: handle_git_conflicts now validates each conflicted file path through ctx.validate_path() (#20). Cross-plugin parity: - pi-plugin pool keys bridges by realpathSync canonicalization, mirroring opencode (#5). - pi-plugin zoom multi-symbol fan-out routes through callBridge so each parallel request carries Pi's session_id (#16 — regression from v0.15.3). - pi-plugin tool-surface ALL_ONLY constants align with opencode (#9). - both bridges enforce 64MB MAX_STDOUT_BUFFER and treat overflow as crash (#10). - pi-plugin aft_transform validates per-op required parameters (#17). - both bridges' compareSemver implements semver pre-release ordering (#29). Rust correctness: - glob edit_match wraps multi-file writes in checkpoint snapshot with rollback on failure (#3). - LSP client kills+waits child on shutdown timeout and via Drop impl (#4). - type-checker working_dir uses config.project_root, not path.parent() (#7). - ast_search/grep return invalid_pattern errors instead of empty matches on malformed regex/AST patterns (#11). - zoom ambiguous suggestions output 1-based start-end line ranges (#12). - zoom line-range response uses clamped end_line (#13). - configure.validate_on_edit accepts booleans (#18). - checkpoint restore creates parent directories (#19). - lsp_hints paths_match uses canonical comparison + separator-bounded suffix matching (#22). - format.resolve_tool --version probe has 2s timeout (#24). - backup.canonicalize_key fallback logs at debug (#25). - read.handle_directory caps at 1000 entries with truncation note (#34). - read uses saturating_add/sub for end_line math (#36). - lsp_rename + lsp_find_references use consistent 1-based character (#37). - ast_search/replace comments now reference panic=unwind (#27). Workflow + docs: - release.yml has top-level concurrency control (#35). - test job runs bun build before publish-crates (#8). - release.yml uses sha256sum on Ubuntu (#29). - version-sync.mjs comment reflects 9 packages (#28). Verification: 726 Rust tests pass / 1 ignored (was 718, +8 new tests), 383 TS tests pass (was 362, +21 new tests covering RPC auth, SSRF guard, pool canonicalization, semver pre-release, structure validation, edit_match atomicity, IPv4-mapped IPv6 bypass detection). Typecheck + lint clean.
ualtinok
pushed a commit
that referenced
this pull request
Apr 30, 2026
Audit findings #12 and #13 from the v0.18 council (verified solo findings from MiniMax 2.7). * BUG-18 — transaction only called the lightweight `lsp_notify_file_changed`, unlike write_match / batch / write which call `lsp_post_write` and surface diagnostics inline. Multi-file transactions silently skipped diagnostic collection. Now calls `lsp_post_write` per successful write, threads multi_file_write_paths through for the workspace/didChangeWatchedFiles flow, merges per-file outcomes (diagnostics, pending_servers, exited_servers), and surfaces `lsp_diagnostics`, `lsp_complete`, `lsp_pending_servers`, `lsp_exited_servers` on the response — matching every other write path. * BUG-19 — `compute_new_content` silently picked fuzzy_matches[0] when multiple matches existed, while dry-run correctly errored with `ambiguous_match`. So dry-run says "this is ambiguous" but apply silently rewrites the FIRST match — could be the wrong one. Both paths now share the same `find_single_fuzzy_match` helper that errors on ambiguity. * Match-not-found stayed `transaction_failed` (not `invalid_request`): the request itself is well-formed, only the data didn't match. The transaction-rolls-back-on-failure e2e test asserts this contract.
ualtinok
added a commit
that referenced
this pull request
Apr 30, 2026
…al (#19, #13) Background bash tasks now survive aft restart. Spawned children are detached from the aft process via setsid() and write their output directly to disk; task metadata is persisted to <storage>/bash-tasks/<session_hash>/<task_id>.json so a fresh aft on startup can rehydrate Running tasks and redeliver pending completions. Architecture (Oracle-reviewed): - Pre-spawn metadata write (status=Starting) BEFORE Command::spawn() so a crash in the spawn window leaves a recoverable record on disk instead of an orphaned child with no trace. Replay marks Starting tasks as Failed. - Detached spawn via libc::setsid() in pre_exec, replacing process_group(0) on the bg path. Foreground bash unchanged. - stdin: null. stdout/stderr redirected directly to disk files via Stdio::from(File::create(...)) — child writes the file, aft never reads pipes, no Rust reader thread to keep alive. - Shell wrapper writes exit code via temp+rename (atomic) so readers never observe partial .exit content. User command is passed via argv ($1), NEVER interpolated into the wrapper body — string injection safe. - Terminal-state monotonic: once .json is Killed/Failed/Completed/TimedOut, no later observation can flip it. Late .exit appearance after a kill doesn't change status. - Completion durability: completion_delivered: bool field in .json. On startup replay, terminal-state tasks with completion_delivered=false re-enqueue into the in-memory queue. Plugin-side bash_drain_completions marks delivered=true after successful drain. - Kill semantics: idempotent. bash_kill checks for .exit existence — if present (shell wrapper got out before kill), leave the file alone; if absent, write 'killed' marker. Either way, .json transitions to Killed. - Single watchdog thread polls .exit files every 500ms for completion signaling and enforces timeouts (default 30 min, configurable per call). - main.rs detach() on stdin EOF replaces shutdown() — children survive graceful aft exit; only explicit cleanup kills. - Output reads tail directly from .stdout/.stderr files; 100MB cap enforced ONLY post-terminal (truncating live files would create sparse holes). - Windows path returns 'background bash is not yet supported on Windows' pending Job Objects + DETACHED_PROCESS implementation. New status variants: Starting, Killing, TimedOut. Files: - NEW: bash_background/persistence.rs (210 lines) — atomic JSON I/O, exit-file parsing, terminal-state guard, session-scoped paths. - NEW: bash_background/watchdog.rs (45 lines) — polling thread. - NEW: tests/integration/bash_background_persistence_test.rs (364 lines) — covers spawn detached, replay across restart, exit-file atomicity, terminal-state monotonicity, completion durability, kill idempotency, disk-tail reads without truncating live files, watchdog deadline, session isolation, stale-Running cleanup. - REWRITTEN: bash_background/registry.rs (838 lines, was 612) — detached spawn, in-memory state derived from disk on startup, idempotent terminal transitions, completion_delivered tracking, detach() vs shutdown() split. - REWRITTEN: bash_background/buffer.rs (146 lines, was ~400) — disk-only reads, post-terminal cap. - backup.rs: hash_session helper exposed pub(crate) for shared use. - bash_background/mod.rs, process.rs: re-exports + new variants. - commands/configure.rs: replay invocation. - main.rs: detach() on stdin EOF. Existing timeout test in bash_background_test.rs updated to match new TimedOut terminal status (was previously Failed). Test count: 937 → 955 Rust tests (+18 passing, 0 failing, 1 ignored). Plugin counts unchanged (no plugin layer changes). Closes council findings #19, #13. Foreground bash unchanged. Plugin protocol unchanged — drain_completions transparently sees disk-rehydrated completions. Implements v0.18 detached bash architecture per design Oracle-reviewed in this session.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Installation
Test plan
🤖 Generated with Claude Code