Skip to content

Establish the initial 0.1.0 release - #1

Merged
naoto256 merged 3 commits into
mainfrom
release/0.1.0
Aug 9, 2026
Merged

Establish the initial 0.1.0 release#1
naoto256 merged 3 commits into
mainfrom
release/0.1.0

Conversation

@naoto256

@naoto256 naoto256 commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • provide Rust-owned synthesis, recall, and read-only peek operations
  • integrate Claude and Codex hooks through a portable shell adapter
  • define the initial plugin, release, documentation, and regression-test contracts
  • publish all product metadata as version 0.1.0

Summary by CodeRabbit

  • New Features

    • Added Amnestic Trace for compact working-memory capture and restoration across AI coding sessions.
    • Added Claude Code and Codex integrations for automatic capture before compaction and recall afterward.
    • Added handoff, key, peek, and default-prompt commands for transferring, inspecting, and managing session memory.
    • Added configurable prompts, secure local storage, bounded snapshots, and fail-open hook behavior.
    • Added Linux and macOS release packages with checksums.
  • Documentation

    • Added installation, usage, security, troubleshooting, contribution, licensing, and changelog documentation.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@naoto256, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6b9e4b0a-97ae-4bce-9b4d-cb9bce5693e0

📥 Commits

Reviewing files that changed from the base of the PR and between abb249c and 2e30c18.

📒 Files selected for processing (1)
  • plugin/README.md
📝 Walkthrough

Walkthrough

Amnestic Trace adds a Rust runtime for journal-based working-memory capture, bounded extraction, snapshot storage, recall, handoff, and inspection. It also adds Claude Code and Codex plugins, shell adapters, CI and release workflows, supply-chain policy, licenses, and documentation.

Changes

Amnestic Trace runtime

Layer / File(s) Summary
Storage and journal contracts
src/store.rs, src/journal.rs
The filesystem store persists validated session snapshots and delivery markers with atomic writes and private permissions. Journal readers detect Claude and Codex formats, apply timestamp filters, and return bounded windows.
Synthesis and extraction workflow
src/synthesize.rs, src/extract.rs, src/detach.rs, src/default-prompt.md
Synthesis selects journals, manages debt markers, detaches workers, runs restricted extraction agents, validates handoffs, and publishes ready snapshots.
Recall, handoff, and inspection
src/recall.rs, src/main.rs, src/peek.rs
Recall processes hook events, claims ready snapshots exactly once, renders handoffs, supports keyed moves or clones, and provides human-readable or JSON inspection output.
Plugin and shell integration
.claude-plugin/*, plugin/.claude-plugin/*, plugin/.codex-plugin/*, plugin/hooks/*, plugin/skills/*, plugin/tools/*, tests/hook-regressions.sh
Claude Code and Codex manifests configure synthesis and recall hooks. The shell adapter fails open and has regression coverage across supported shells.
Build, release, and project policy
Cargo.toml, deny.toml, .github/workflows/*, README.md, plugin/README.md, CHANGELOG.md, CONTRIBUTING.md, LICENSE-*
The project adds package and dependency policies, CI checks, Linux and macOS release packaging, release notes and checksums, licenses, contribution rules, and usage documentation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Hook as Compaction or recall hook
  participant CLI as amtr CLI
  participant Journal as Journal reader
  participant Agent as Extraction agent
  participant Store as Session store
  Hook->>CLI: invoke synthesis or recall
  CLI->>Journal: read bounded journal window
  CLI->>Agent: run restricted extraction
  Agent-->>CLI: return validated handoff
  CLI->>Store: persist or claim snapshot
  Store-->>CLI: return restoration output
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the pull request's primary objective: establishing the initial 0.1.0 release baseline.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (6)
src/journal.rs (1)

452-505: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Gate the 128 MiB journal test behind an opt-in.

The test writes over 128 MiB to the system temp directory on every cargo test run. On a constrained CI runner this consumes wall time and disk. Keep the coverage, but mark it #[ignore] and run it in a dedicated CI step, or reduce the fixture to just above the boundary the test needs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/journal.rs` around lines 452 - 505, Mark
read_window_streams_a_journal_larger_than_would_fit_in_a_string with #[ignore]
so the over-128 MiB fixture is not created during normal cargo test runs, while
preserving the existing coverage for dedicated execution.
src/store.rs (2)

183-188: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Align find_by_key with rows() on a missing cortex directory.

rows() maps NotFound on read_dir to an empty result. find_by_key propagates the error. A store opened through open_existing() never creates CORTEX, so a base directory without the cortex subdirectory turns a plain "no such key" into an I/O error for any caller that resolves a key against such a store.

♻️ Proposed change
     pub fn find_by_key(&self, amtr_key: &str) -> io::Result<Option<Row>> {
-        for entry in fs::read_dir(self.base.join(CORTEX))?.flatten() {
+        let entries = match fs::read_dir(self.cortex()) {
+            Ok(entries) => entries,
+            Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(None),
+            Err(error) => return Err(error),
+        };
+        for entry in entries.flatten() {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/store.rs` around lines 183 - 188, Update find_by_key to handle a missing
CORTEX directory like rows(), converting read_dir’s NotFound error into an empty
search result while propagating other I/O errors. Preserve the existing JSON
filtering and key lookup behavior for an existing directory.

345-365: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Remove the temporary file when the write fails.

If write_all, sync_all, or open fails, the function returns early and leaves <name>.tmp.<pid> in the cortex directory. prepare_debt in src/synthesize.rs sweeps only .delivering., .expiring., and .publishing. candidates, so these .tmp. files stay forever. They are also skipped by rows() and find_by_key because of the extension filter, so the leak is silent.

♻️ Proposed change
-    {
-        let mut opts = fs::OpenOptions::new();
-        opts.write(true).create(true).truncate(true);
-        #[cfg(unix)]
-        {
-            use std::os::unix::fs::OpenOptionsExt;
-            opts.mode(0o600);
-        }
-        let mut f = opts.open(&tmp)?;
-        f.write_all(body)?;
-        f.sync_all()?;
-    }
-    fs::rename(&tmp, path)
+    let write = (|| -> io::Result<()> {
+        let mut opts = fs::OpenOptions::new();
+        opts.write(true).create(true).truncate(true);
+        #[cfg(unix)]
+        {
+            use std::os::unix::fs::OpenOptionsExt;
+            opts.mode(0o600);
+        }
+        let mut f = opts.open(&tmp)?;
+        f.write_all(body)?;
+        f.sync_all()
+    })();
+    if let Err(error) = write {
+        let _ = fs::remove_file(&tmp);
+        return Err(error);
+    }
+    if let Err(error) = fs::rename(&tmp, path) {
+        let _ = fs::remove_file(&tmp);
+        return Err(error);
+    }
+    Ok(())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/store.rs` around lines 345 - 365, Update write_atomic to remove the
generated temporary path when opening, writing, or syncing fails, while
preserving the original error and leaving successful rename behavior unchanged.
Ensure cleanup also covers failures within the temporary-file operation before
returning from the function.
src/synthesize.rs (1)

46-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Make the two-candidate selection explicit.

The chain applies .filter(|path| path.is_file()) twice. The second filter re-tests a transcript_path that the first filter already accepted. The result is correct, but a reader has to trace both arms to confirm that rollout_path is checked at all.

♻️ Proposed change
     fn journal(&self) -> Option<PathBuf> {
-        self.transcript_path
-            .clone()
-            .filter(|path| path.is_file())
-            .or_else(|| self.rollout_path.clone())
-            .filter(|path| path.is_file())
-            .or_else(|| find_codex_journal(&self.session_id))
+        [&self.transcript_path, &self.rollout_path]
+            .into_iter()
+            .flatten()
+            .find(|path| path.is_file())
+            .cloned()
+            .or_else(|| find_codex_journal(&self.session_id))
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/synthesize.rs` around lines 46 - 53, Make the candidate selection in
journal explicit: validate transcript_path once, then independently validate
rollout_path before falling back to find_codex_journal(&self.session_id). Avoid
chaining the second filter onto the already-filtered result, while preserving
the existing file checks and fallback order.
src/extract.rs (1)

265-270: 🩺 Stability & Availability | 🔵 Trivial | ⚖️ Poor tradeoff

Consider killing the whole agent process group on timeout.

The worker already runs in its own session after detach(). Put the agent in its own process group with pre_exec and setpgid, then send the signal to that group. This reaps descendants that the CLI spawned instead of orphaning them for the remaining lifetime of the machine.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/extract.rs` around lines 265 - 270, Update the child-process setup to use
pre_exec with setpgid, placing the extraction agent in its own process group
after detach(). In the timeout branch of the extraction flow, signal the entire
process group rather than only child, then wait as before so spawned descendants
are reaped.
plugin/skills/amtr/SKILL.md (1)

15-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a language to the two fenced code blocks.

markdownlint reports MD040 for both blocks. Use text to keep them unhighlighted.

♻️ Proposed fix
-```
+```text
 /amtr                     name this session's own key, to give to another session
-```
+```text
 /amtr <the key you just printed>

Also applies to: 109-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugin/skills/amtr/SKILL.md` around lines 15 - 19, Update the two fenced code
blocks in the amtr skill documentation to specify the text language, preserving
their contents and unhighlighted presentation.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 105-109: Update the cargo deny check step to pass the --locked
flag, ensuring it uses the existing Cargo.lock without modifying the dependency
graph. Keep the existing advisories, bans, sources, and licenses checks
unchanged.

In @.github/workflows/release.yml:
- Around line 70-95: Before the build steps in the release workflow, add
validation that compares the version derived from GITHUB_REF_NAME#v with the
package version in Cargo.toml and the versions in both plugin manifests. Fail
the workflow with a clear error if any value differs; otherwise allow the
existing archive and release-name flow to continue unchanged.

In `@plugin/README.md`:
- Around line 3-5: Update the introduction text around the plugin hook
description to accurately document all four hook events: PreCompact,
SessionStart, PreToolUse, and UserPromptSubmit. Replace “three hooks” with
either “one capture hook and three delivery hooks” or “four hook events,”
preserving the surrounding wording.
- Around line 176-183: Update the README’s default-prompt redirection example to
use the active data root returned by the prompt path resolution, such as the
path under the configured ~/.amtr store when selected, so it matches
prompt_path() and customizes the active prompt. Adjust the surrounding
persistence guidance only as needed to keep the documented upgrade behavior
accurate.
- Around line 104-106: Disable the automatic Codex extraction path by default in
the documented configuration and require explicit opt-in, preferably through an
isolated Codex home/configuration that disables MCP servers and hosted
network-capable tools. Update the extraction command accordingly, and add
regression coverage using the exact command to verify the journal cannot read a
local canary file or access a reachable remote URL.

In `@plugin/tools/amtr-hook.sh`:
- Around line 17-18: Update the PATH construction near the existing HOME guard
in amtr-hook.sh to safely handle an unset PATH under set -u, using the same
defaulting pattern already applied to HOME, while preserving the current
appended bin directories and export behavior.

In `@src/detach.rs`:
- Around line 34-98: Gate the detach module and its Unix-specific APIs behind
#[cfg(unix)] so symbols such as log_stderr_to and detach are not compiled on
unsupported platforms. Ensure the crate still builds on non-Unix targets by
providing the appropriate existing or minimal not(unix) fallback for any
required public interface.

In `@src/extract.rs`:
- Around line 260-272: Update stderr handling around the extraction timeout,
failed-status, and validation paths so joining the stderr reader cannot block
indefinitely when descendants retain the pipe. Bound the reader join with a
channel and deadline, degrading to an empty note and leaving the thread detached
if it does not finish; ensure all error paths, including the timeout branch in
the extraction loop, still return and allow marker cleanup.

In `@src/recall.rs`:
- Around line 397-403: Update report_key to call
store::validate_session_id(session_id)? before Store::open() and any row
loading, preserving the existing return behavior after validation.

In `@src/store.rs`:
- Around line 43-47: Add rust-version = "1.85.0" to Cargo.toml to explicitly
enforce the minimum compiler required by the edition 2024 let-chains in
src/journal.rs (lines 212-217) and std::env::home_dir() usage in src/store.rs
(lines 43-47); no direct code changes are needed in either Rust source site.

---

Nitpick comments:
In `@plugin/skills/amtr/SKILL.md`:
- Around line 15-19: Update the two fenced code blocks in the amtr skill
documentation to specify the text language, preserving their contents and
unhighlighted presentation.

In `@src/extract.rs`:
- Around line 265-270: Update the child-process setup to use pre_exec with
setpgid, placing the extraction agent in its own process group after detach().
In the timeout branch of the extraction flow, signal the entire process group
rather than only child, then wait as before so spawned descendants are reaped.

In `@src/journal.rs`:
- Around line 452-505: Mark
read_window_streams_a_journal_larger_than_would_fit_in_a_string with #[ignore]
so the over-128 MiB fixture is not created during normal cargo test runs, while
preserving the existing coverage for dedicated execution.

In `@src/store.rs`:
- Around line 183-188: Update find_by_key to handle a missing CORTEX directory
like rows(), converting read_dir’s NotFound error into an empty search result
while propagating other I/O errors. Preserve the existing JSON filtering and key
lookup behavior for an existing directory.
- Around line 345-365: Update write_atomic to remove the generated temporary
path when opening, writing, or syncing fails, while preserving the original
error and leaving successful rename behavior unchanged. Ensure cleanup also
covers failures within the temporary-file operation before returning from the
function.

In `@src/synthesize.rs`:
- Around line 46-53: Make the candidate selection in journal explicit: validate
transcript_path once, then independently validate rollout_path before falling
back to find_codex_journal(&self.session_id). Avoid chaining the second filter
onto the already-filtered result, while preserving the existing file checks and
fallback order.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b03f6a0-8f2b-44e9-a597-a850d521f5e5

📥 Commits

Reviewing files that changed from the base of the PR and between a65760f and e695e10.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (27)
  • .claude-plugin/marketplace.json
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • Cargo.toml
  • LICENSE-APACHE
  • LICENSE-MIT
  • README.md
  • deny.toml
  • plugin/.claude-plugin/plugin.json
  • plugin/.codex-plugin/plugin.json
  • plugin/README.md
  • plugin/hooks/claude.json
  • plugin/hooks/codex.json
  • plugin/skills/amtr/SKILL.md
  • plugin/tools/amtr-hook.sh
  • src/default-prompt.md
  • src/detach.rs
  • src/extract.rs
  • src/journal.rs
  • src/main.rs
  • src/peek.rs
  • src/recall.rs
  • src/store.rs
  • src/synthesize.rs
  • tests/hook-regressions.sh

Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/release.yml
Comment thread plugin/README.md Outdated
Comment thread plugin/README.md
Comment on lines +104 to +106
The agent's input is a session journal, which contains text this tool did not
author — fetched pages, dependency output, error messages. Text like that can
try to steer whatever reads it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -u

# Trace the Codex extraction command and isolation flags.
rg -n -C 10 --glob '*.rs' --glob '*.sh' \
  'Command::new|--sandbox|features\.shell_tool|mcp_servers|codex'

Repository: naoto256/amnestic-trace

Length of output: 161


🏁 Script executed:

#!/bin/bash
set -u

echo "== files =="
git ls-files | sed -n '1,120p'

echo "== plugin README relevant sections =="
if [ -f plugin/README.md ]; then
  nl -ba plugin/README.md | sed -n '90,155p'
fi

echo "== repo-wide search relevant terms =="
rg -n -C 3 --glob '!target/**' --glob '!dist/**' --glob '!build/**' \
  'codex|Codex|PreCompact|precompact|features\.shell_tool|shell_tool|commands|mcp_servers|--sandbox|-c |sandbox|network|exfil|file access' . || true

Repository: naoto256/amnestic-trace

Length of output: 34651


🌐 Web query:

openai/codex #16045 mcp_servers={} no-op configured servers

💡 Result:

The issue openai/codex #16045`` refers to a bug where using -c 'mcp_servers={}' at the command line does not clear configured MCP servers as intended [1][2]. Instead of overwriting the configuration, the empty TOML table `{}` performs a non-destructive merge with existing settings, leaving all previously configured servers enabled [1]. This behavior is problematic for users who want to run lightweight, isolated sessions without the overhead of MCP server discovery or tool loading [1]. Related issues confirm that empty `[mcp_servers]` tables in other configuration layers—such as `[profiles]` or agent role files—similarly fail to shadow or clear inherited global MCP server configurations [3][4][5]. As of August 2026, the following workarounds and context are relevant: Workarounds: - Per-server disabling: You must explicitly disable each server individually using command-line flags (e.g., `-c 'mcp_servers.SERVER_NAME.enabled=false'`) [1]. - Separate configuration files: For profiles or agent roles, a common workaround is to use an entirely separate configuration file that excludes the unwanted MCP server definitions [5]. Status: - The issue remains open as of early 2026 [1][4]. - Developers have suggested future fixes such as treating an empty `mcp_servers` table as a "replace" operation rather than a "merge" operation, or implementing a dedicated flag like `--no-mcp` [1]. - Future architectural changes to Codex profiles are expected to address limitations in how nested configuration sections (including `mcp_servers`) are inherited and overridden [6].

Citations:


Disable Codex extraction by default until hosted tools can be disabled.

The Codex extraction path runs journal text through codex exec with only features.shell_tool=false, --sandbox read-only, and -c mcp_servers={}. The shell tool is disabled, but mcp_servers={} does not clear configured MCP servers, and hosted tools can still receive the journal contents and send data off machine.

Since this compaction trigger runs automatically, make Codex extraction optional or require an opt-in isolated Codex home/configuration that disables MCP servers and hosted network-capable tools. Add regression coverage that checks a local canary file and a reachable remote URL under the exact extraction command.

🧰 Tools
🪛 LanguageTool

[grammar] ~106-~106: Ensure spelling is correct
Context: ...ssages. Text like that can try to steer whatever reads it. - Claude Code: launched ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugin/README.md` around lines 104 - 106, Disable the automatic Codex
extraction path by default in the documented configuration and require explicit
opt-in, preferably through an isolated Codex home/configuration that disables
MCP servers and hosted network-capable tools. Update the extraction command
accordingly, and add regression coverage using the exact command to verify the
journal cannot read a local canary file or access a reachable remote URL.

Comment thread plugin/README.md
Comment thread plugin/tools/amtr-hook.sh Outdated
Comment on lines +17 to +18
PATH="$PATH:$home/.local/bin:$home/.cargo/bin:/opt/homebrew/bin:/usr/local/bin"
export PATH

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard $PATH the same way as $HOME.

set -u is active. If the host does not export PATH, line 17 aborts the script with a non-zero status, and the host event sees a failed hook. Line 7 already applies this guard to HOME.

🛡️ Proposed fix
-PATH="$PATH:$home/.local/bin:$home/.cargo/bin:/opt/homebrew/bin:/usr/local/bin"
+PATH="${PATH:-/usr/bin:/bin}:$home/.local/bin:$home/.cargo/bin:/opt/homebrew/bin:/usr/local/bin"
 export PATH
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PATH="$PATH:$home/.local/bin:$home/.cargo/bin:/opt/homebrew/bin:/usr/local/bin"
export PATH
PATH="${PATH:-/usr/bin:/bin}:$home/.local/bin:$home/.cargo/bin:/opt/homebrew/bin:/usr/local/bin"
export PATH
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugin/tools/amtr-hook.sh` around lines 17 - 18, Update the PATH construction
near the existing HOME guard in amtr-hook.sh to safely handle an unset PATH
under set -u, using the same defaulting pattern already applied to HOME, while
preserving the current appended bin directories and export behavior.

Comment thread src/detach.rs
Comment on lines +34 to +98
pub fn log_stderr_to(dir: &Path) {
let _ = std::fs::create_dir_all(dir);
let log_path = dir.join("amtr.log");
if std::fs::metadata(&log_path).is_ok_and(|m| m.len() > MAX_LOG_BYTES) {
let _ = std::fs::remove_file(&log_path);
}

let mut buf = log_path.as_os_str().as_encoded_bytes().to_vec();
buf.push(0);
unsafe {
let fd = libc::open(
buf.as_ptr() as *const libc::c_char,
libc::O_WRONLY | libc::O_CREAT | libc::O_APPEND,
0o600 as libc::c_uint,
);
if fd >= 0 {
libc::dup2(fd, 2);
if fd > 2 {
libc::close(fd);
}
}
}
}

/// Detaches the worker from the host's process group. The caller returns
/// immediately in the original process, so the hook exits while extraction runs
/// in parallel with compaction itself.
///
/// # Assumes a single-threaded process
///
/// `fork` carries over only the calling thread. A lock held by any other thread
/// at that instant stays locked forever in the child, and the allocator's is
/// enough to hang it on the next allocation. Nothing before this point starts a
/// thread — the extraction subprocess's reader and writer come after — and
/// anything that changes must keep it that way or move the fork ahead of
/// itself.
pub fn detach() -> Role {
unsafe {
match libc::fork() {
-1 => return Role::CannotDetach,
0 => {}
_ => return Role::Caller, // original process: hook returns now
}
// New session: we are no longer in the host's process group, so a
// group-wide kill on hook timeout does not reach us.
libc::setsid();
match libc::fork() {
-1 => {}
0 => {}
_ => libc::_exit(0), // reparented to init, so nobody waits on us
}
// Close the hook's stdin and stdout; a host that reads them to EOF
// would otherwise block on a worker that outlives it. stderr is left
// alone: it already points at the log, opened before any of this.
let devnull = libc::open(c"/dev/null".as_ptr(), libc::O_RDWR);
if devnull >= 0 {
libc::dup2(devnull, 0);
libc::dup2(devnull, 1);
if devnull > 2 {
libc::close(devnull);
}
}
}
Role::Worker
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check declared targets, CI matrix, and cfg gating consistency.
fd -t f 'Cargo.toml' -H | xargs -r cat
fd -t f -e yml -e yaml . .github | xargs -r rg -n 'runs-on|target|matrix|windows' 
rg -n 'cfg\(unix\)|cfg\(not\(unix\)\)|libc::' src

Repository: naoto256/amnestic-trace

Length of output: 3108


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## repository files"
git ls-files | sed -n '1,120p'

echo "## Cargo manifests"
fd -t f '^Cargo\.toml$' -H -x sh -c 'echo "--- $1"; sed -n "1,120p" "$1"' sh {}

echo "## CI / release workflow snippets"
fd -t f -e yml -e yaml . .github | while read -r f; do
  echo "--- $f"
  nl -ba "$f" | sed -n '1,150p'
done

echo "## relevant source snippets"
for f in src/detach.rs src/store.rs src/synthesize.rs src/recall.rs; do
  if [ -f "$f" ]; then
    echo "--- $f line count"
    wc -l "$f"
    echo "--- $f snippets"
    nl -ba "$f" | sed -n '1,120p;260,425p;580,615p'
  fi
done

echo "## exact cfg/extern/use context"
rg -n '#\(cfg|extern crate|use .*libc|libc::open|libc::fork|cfg_attr' Cargo.toml Cargo.lock src

Repository: naoto256/amnestic-trace

Length of output: 1444


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## CI / release workflow snippets"
for f in .github/workflows/ci.yml .github/workflows/release.yml; do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f"
  fi
done

echo "## relevant source snippets"
for f in src/detach.rs src/store.rs src/synthesize.rs src/recall.rs; do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f"
  fi
done

echo "## exact cfg/extern/use context"
rg -n '#\[cfg|cfg_attr|use .*libc|libc::open|libc::fork|libc::setsid|libc::dup2|extern crate' Cargo.toml Cargo.lock src

Repository: naoto256/amnestic-trace

Length of output: 50380


Gate src/detach.rs to #[cfg(unix)].

The release matrix only targets aarch64-apple-darwin and x86_64-unknown-linux-gnu, but the crate does not declare Unix-only support and CI builds without --target. detach() uses fork/session/process-fd APIs and a /dev/null path that do not compile on Windows; add a unix-only gate for this module or make the fork paths platform-specific with a not(unix) fallback.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/detach.rs` around lines 34 - 98, Gate the detach module and its
Unix-specific APIs behind #[cfg(unix)] so symbols such as log_stderr_to and
detach are not compiled on unsupported platforms. Ensure the crate still builds
on non-Unix targets by providing the appropriate existing or minimal not(unix)
fallback for any required public interface.

Comment thread src/extract.rs Outdated
Comment thread src/recall.rs
Comment thread src/store.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugin/README.md`:
- Around line 179-185: Update the prompt generation commands after amtr_root
selection to write amtr default-prompt output to a temporary file, then move it
to prompt.md only when generation succeeds; preserve the existing prompt file if
generation fails or is interrupted, and clean up the temporary file as
appropriate.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 09d6cde3-b2de-4c2c-add1-c848871e5de4

📥 Commits

Reviewing files that changed from the base of the PR and between e695e10 and abb249c.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • Cargo.toml
  • plugin/README.md
  • plugin/skills/amtr/SKILL.md
  • plugin/tools/amtr-hook.sh
  • src/extract.rs
  • src/recall.rs
  • src/store.rs
  • src/synthesize.rs
  • tests/hook-regressions.sh
🚧 Files skipped from review as they are similar to previous changes (8)
  • Cargo.toml
  • plugin/skills/amtr/SKILL.md
  • src/synthesize.rs
  • plugin/tools/amtr-hook.sh
  • tests/hook-regressions.sh
  • src/store.rs
  • src/extract.rs
  • src/recall.rs

Comment thread plugin/README.md Outdated
@naoto256
naoto256 merged commit 63ab54a into main Aug 9, 2026
11 checks passed
@naoto256
naoto256 deleted the release/0.1.0 branch August 9, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant