Skip to content

chore: shrink release binary + dedupe JSONC read helpers - #188

Merged
getappz merged 4 commits into
masterfrom
chore/shorten-handoff-prompt
Jul 15, 2026
Merged

chore: shrink release binary + dedupe JSONC read helpers#188
getappz merged 4 commits into
masterfrom
chore/shorten-handoff-prompt

Conversation

@getappz

@getappz getappz commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • Shrink the release binary ~31% (17.94 MiB -> 12.35 MiB) via panic="abort" and trimming unused zip codec features (default-features = false, features = ["deflate"])
  • Dedupe JSONC-read boilerplate flagged by CodeRabbit on fix(config): tolerate JSONC when reading agent config files #174: add shared skip_string helper in src/jsonc.rs and a shared read_jsonc(path, default) helper used across src/components.rs and src/init.rs

Test plan

  • cargo build (release) — binary size measured before/after
  • cargo test --workspace — 453 passed, 0 failed
  • cargo clippy -- -D warnings -A unsafe_code -A clippy::pedantic — clean
  • sanity-ran the built binary

Summary by CodeRabbit

  • Bug Fixes
    • Improved JSON/JSONC configuration loading with consistent fallback behavior when files are missing, unreadable, or invalid.
    • Enhanced JSONC parsing to reliably handle comments and trailing commas while preserving correct behavior inside quoted strings.
    • Updated configuration merge behavior to match the improved JSON/JSONC loading and parsing flow.
  • Reliability
    • Tightened the ZIP dependency configuration to use only the intended compression feature set, reducing unintended behavior.

getappz added 2 commits July 15, 2026 04:06
Drops shipped agentflare.exe from 17.94 MiB to 12.35 MiB (-31%).
panic=\abort\ strips unwind tables across the whole dependency graph
(no catch_unwind anywhere in the workspace, so no functional risk).
zip now only pulls the deflate codec it actually uses (src/update.rs
reads plain zip archives for self-update; bzip2/lzma/zstd/zopfli/aes
were unused default features).
Extract skip_string() out of strip_json_comments/strip_trailing_commas
(same byte-level string-skip loop was copy-pasted in both) and add
jsonc::read_jsonc(path, default) to replace the read -> parse_jsonc ->
fallback boilerplate repeated across json_at, merge_json,
merge_opencode_mcp (components.rs) and wire_opencode (init.rs).
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5abdc4a3-012d-41e0-841e-ace5cf9c722b

📥 Commits

Reviewing files that changed from the base of the PR and between 0650135 and 0676f5e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • Cargo.toml

📝 Walkthrough

Walkthrough

The change centralizes JSONC file loading and fallback handling across configuration paths, reuses string scanning logic, and restricts the zip dependency to its deflate feature.

Changes

JSONC loading consolidation

Layer / File(s) Summary
Shared JSONC reader and string scanning
src/jsonc.rs
Adds fallback-based JSONC reading and reuses escape-aware string scanning for comment and trailing-comma processing.
Configuration loading call sites
src/components.rs, src/init.rs
Updates configuration and merge paths to use shared JSONC loading with null or empty-object defaults.

Dependency configuration

Layer / File(s) Summary
Zip feature selection
Cargo.toml
Disables default zip features and enables only deflate.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • getappz/agentflare#174: Updates the same JSONC loading and merging paths with related JSONC utility changes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main changes: release-size reduction and shared JSONC read helpers.
Description check ✅ Passed It covers Summary and Test plan well; the Notes for reviewers section is the only missing template section.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/shorten-handoff-prompt

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: 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 `@src/jsonc.rs`:
- Around line 17-24: Preserve missing-file defaults without allowing failed
reads or parses to be rewritten: update src/jsonc.rs lines 17-24 and read_jsonc
to distinguish NotFound from existing-file I/O or parse errors, then make
merge_json at src/components.rs line 102, merge_opencode_mcp at
src/components.rs line 122, and wire_opencode at src/init.rs line 511 abort
without writing when those existing-file failures occur; missing files should
retain the current default behavior.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2068d7bd-aecd-49b2-8e29-5290e96e251c

📥 Commits

Reviewing files that changed from the base of the PR and between 1ca98ef and 80056dd.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml
  • src/components.rs
  • src/init.rs
  • src/jsonc.rs

Comment thread src/jsonc.rs
Comment on lines +17 to +24
/// Reads `path`, parses it as JSONC, and falls back to `default()` on any
/// failure (missing file, unreadable, or invalid JSON/JSONC) — the shared
/// read-then-fallback contract every agent-config call site needs.
pub fn read_jsonc(path: &std::path::Path, default: impl FnOnce() -> Value) -> Value {
std::fs::read_to_string(path)
.ok()
.and_then(|s| parse_jsonc(&s).ok())
.unwrap_or_else(default)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Preserve the distinction between missing and invalid configuration files.

The shared fallback contract is safe for read-only access but unsafe for callers that rewrite configuration: malformed or unreadable existing files can be replaced with a partial default object.

  • src/jsonc.rs#L17-L24: return a typed result or distinguish NotFound from parse/I/O errors.
  • src/components.rs#L102-L102: make merge_json abort without writing on existing-file read/parse failures.
  • src/components.rs#L122-L122: apply the same protection in merge_opencode_mcp.
  • src/init.rs#L511-L511: prevent wire_opencode from rewriting opencode.jsonc after a failed read or parse.
📍 Affects 3 files
  • src/jsonc.rs#L17-L24 (this comment)
  • src/components.rs#L102-L102
  • src/components.rs#L122-L122
  • src/init.rs#L511-L511
🤖 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/jsonc.rs` around lines 17 - 24, Preserve missing-file defaults without
allowing failed reads or parses to be rewritten: update src/jsonc.rs lines 17-24
and read_jsonc to distinguish NotFound from existing-file I/O or parse errors,
then make merge_json at src/components.rs line 102, merge_opencode_mcp at
src/components.rs line 122, and wire_opencode at src/init.rs line 511 abort
without writing when those existing-file failures occur; missing files should
retain the current default behavior.

@getappz

getappz commented Jul 15, 2026

Copy link
Copy Markdown
Owner Author

Reviewed. Binary-size numbers check out and the zip feature trim looks safe. One concern on panic = "abort" before merging:

agentflare serves MCP over stdio via rmcp, which spawns every incoming tool call as its own tokio::spawn task (spawn_service_task in rmcp 1.8.0's service.rs, called per JsonRpcRequest). Under the current default (panic = "unwind"), a panic inside a tool handler is caught at that task boundary — the request fails, the rest of the session (other in-flight calls, the connection itself) keeps running. With panic = "abort", any panic anywhere in the process calls abort() immediately, killing the whole agentflare process — every other in-flight tool call and the entire session go down with it, not just the request that panicked.

"Zero catch_unwind call sites in the workspace" doesn't cover this — the isolation being removed is tokio's implicit per-task panic containment, not anything this codebase opts into explicitly. It's also worth flagging that cargo test --workspace (dev profile) can't exercise this risk at all, since panic=abort only applies under [profile.release] — the test plan's green run doesn't actually cover the risky part of this change.

Not saying this is necessarily wrong to ship — an MCP server crashing a session on a genuine bug might be an acceptable/even preferable failure mode vs. silently swallowing panics. But it's a real behavior change (single-request failure → whole-session crash) that's worth an explicit call, not just the "no catch_unwind" check. Rest of the diff (zip feature trim, JSONC dedup) looks good.

rmcp spawns every MCP tool call as its own tokio task; panic=abort
removes that per-task isolation, turning a single panicking tool
call into a whole-session process abort instead of just a failed
request. The zip default-features trim is still safe and kept
(binary drops ~250KiB from that alone; the earlier 31%/5.6MiB
figure was mostly panic=abort, which this reverts).
@getappz

getappz commented Jul 15, 2026

Copy link
Copy Markdown
Owner Author

Pushed a fix for the panic=abort concern above: dropped `panic = "abort"` from `[profile.release]`, kept the zip feature trim. rmcp spawns every MCP tool call as its own tokio task and relies on unwind-based task isolation to survive a panicking handler — abort defeats that process-wide, which is a real regression for a long-running server binary, not just a theoretical one. There's no way to scope panic strategy to only the CLI-invocation code paths within a single `[[bin]]` target, so the safer call is to not take it here.

Re-measured: zip trim alone drops the binary ~250KiB (18,808,320 → 18,556,928 bytes) — the bulk of the originally-claimed 31%/5.6MiB was panic=abort, which is now reverted. Verified: `cargo build --release` clean, `cargo test --workspace` 453 passed, `cargo fmt --check` clean, binary sanity-run (`--version`/`--help`) OK.

Merging once CI is green on the new commit.

@getappz
getappz merged commit f65c582 into master Jul 15, 2026
15 checks passed
@getappz
getappz deleted the chore/shorten-handoff-prompt branch July 15, 2026 06:51
getappz added a commit that referenced this pull request Aug 25, 2026
…awl/entire) (#600)

* ## Status

**What I did:** Reviewed and finished work already in progress in this worktree for item #188 (session checkpoint linkage + `git explain`/`rewind`):

- `crates/flare-git-core/src/provenance.rs` — added an `Agentflare-Session` commit trailer (resolved from `AGENTFLARE_SESSION_ID` or `CLAUDE_CODE_SESSION_ID`) plus `parse_trailers()` to read trailers back off an existing commit message.
- `src/cli/git.rs` — new `agentflare git explain [<commit>]` (prints agent/branch/item/session provenance plus the originating prompt, read from the local Claude Code transcript at `~/.claude/projects/*/<session_id>.jsonl`) and `agentflare git rewind list|restore` (browse commits with provenance annotations; non-destructive working-tree restore with a pre-restore snapshot and a `--yes` confirmation gate). Includes a path-traversal guard (`is_safe_session_id`) since session ids come from self-reported, unattested trailer text.
- `src/paths.rs` / `src/cost.rs` — factored the existing ad-hoc `claude_projects_dir()` in `cost.rs` into a shared `paths::claude_projects_dir()`, reused by the new `explain` transcript lookup.
- `.githooks/prepare-commit-msg` + `docs-site/src/content/docs/cli.md` — updated doc comments/CLI docs for the new trailer and subcommands.
- Cleaned up one leftover double-blank-line in `cost.rs` left by that refactor.

**Tests run:**
- `cargo build` — clean (only pre-existing unrelated `unsafe-code` warnings).
- `cargo test -p flare-git-core provenance` — 9/9 pass.
- `cargo test cli::git` — 25/25 pass.
- Confirmed `cargo clippy -p flare-git-core -- -D warnings` failures are pre-existing in the unrelated `agent-registry` crate (verified by stashing this diff and re-running clippy on clean `HEAD` — same 9 errors).
- Manual smoke test against this repo's real history: `agentflare git explain HEAD` and `agentflare git rewind list --limit 5` both produce correct output (including graceful "(unknown)"/"(none)" fallback for pre-existing commits without trailers).

**Concerns:** None blocking. Two things worth knowing:
1. Session attribution only works when a commit is made directly by a live Claude Code session (env-inherited `CLAUDE_CODE_SESSION_ID`) — headless dispatch commits won't carry it unless the child process passes that env through, which `provenance.rs`'s doc comment already calls out explicitly rather than silently mis-attributing.
2. I did not commit — leaving the worktree as-is per this session's git policy (commits only on explicit request).

Agentflare-Branch: task/188-session-checkpoint-linkage-rewind-explai
Agentflare-Item: 188-session-checkpoint-linkage-rewind-explai

* fix: cargo fmt in src/cli/git.rs to unblock CI on PR #600

Agentflare-Agent: claude-code
Agentflare-Branch: task/188-session-checkpoint-linkage-rewind-explai
Agentflare-Item: 188

---------

Co-authored-by: shiva <shiva@gosysinfo.tech>
getappz added a commit that referenced this pull request Aug 25, 2026
…tch (#601)

execute_work chdir'd into an item's worktree via std::env::set_current_dir,
which mutates the whole process's cwd, not per-thread. The daemon dispatches
multiple in-process work-item jobs concurrently by design
(work_max_concurrency), so two jobs racing here could have one item's
pipeline run against a different item's checked-out worktree -- observed
live, twice, with two different item pairs (items #189/#70 and #189/#188).

Add run_in_worktree (src/cli/work_cwd_lock.rs), which serializes the
chdir -> run -> restore critical section behind a mutex, same mitigation
shape as flare_git_core::worktree::WORKTREE_ADD_LOCK. Only this section is
serialized -- claiming, agent resolution, and DB reads above it still run
concurrently. Split into a satellite file (and the new regression test into
another) to keep work.rs under the repo's LOC gate.

Regression test dispatches two items concurrently on separate threads and
asserts neither thread's cwd drifts into the other's worktree mid-run;
confirmed it reliably reproduces the race (3/3 runs) with the lock removed
and passes reliably (3/3) with it restored, both before and after factoring
the lock+chdir logic into run_in_worktree.

Agentflare-Agent: claude-code
Agentflare-Branch: fix/execute-work-cwd-race

Co-authored-by: shiva <shiva@gosysinfo.tech>
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