Skip to content

feat: cover the shell layer in agentflare init (bashenv guard, opencode branch-guard, config split) - #324

Merged
getappz merged 2 commits into
masterfrom
task/255
Jul 25, 2026
Merged

feat: cover the shell layer in agentflare init (bashenv guard, opencode branch-guard, config split)#324
getappz merged 2 commits into
masterfrom
task/255

Conversation

@getappz

@getappz getappz commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

Closes gaps found in item #255's audit of agentflare init — a fresh machine wasn't fully configured by init alone:

  • New claude-code-bashenv-guard component: creates/patches ~/.bashenv's two marker-delimited blocks (lean-ctx function dispatcher + force-push/rm -rf DEBUG-trap guard) and wires BASH_ENV into ~/.claude/settings.json, never clobbering surrounding content or other env vars. Tool list is generated from shim_install's existing GENERIC_SHIM_TOOLS, not a second hand-maintained copy.
  • New opencode-branch-guard component: drops the branch-guard plugin (shells out to agentflare hook pre-tool-use) into opencode's auto-loaded ~/.config/opencode/plugin/ directory — opencode has no PreToolUse hook of its own, so this was previously 100% hand-installed.
  • opencode_config_merged(): idempotency checks now see a merged view of opencode.json + opencode.jsonc (matching opencode's own deep-merge), so a value already present in either file isn't re-added. Writes still only ever target opencode.jsonc, the file init owns — the hand-maintained sibling is never touched.

Test plan

  • cargo clippy --workspace --all-targets --all-features -- -D warnings -A unsafe_code -A clippy::pedantic (exact CI command) — clean
  • cargo fmt --all --check — clean
  • cargo test --workspace — green (two unrelated, pre-existing local flakes isolated and confirmed to pass standalone: a Windows link-step contention issue in agentflare-flare-code and a load-sensitive timing test in flare-git-core; neither touches any file in this diff)
  • New unit tests for bashenv.rs (upsert/patch idempotency, BASH_ENV wiring, preserves unrelated content) and the two new components (check/apply/host-scoping) and the config-merge helper

Summary by CodeRabbit

  • New Features
    • Added automatic Bash environment setup for supported Claude Code workflows.
    • Added safeguards against destructive commands and force-pushing in scoped projects.
    • Added an OpenCode branch protection plugin for tool-based file changes.
  • Enhancements
    • OpenCode setup now recognizes existing configuration and avoids duplicate rules.
    • OpenCode MCP detection now works across supported configuration files.
    • Installation preserves unrelated configuration and shell content.
  • Bug Fixes
    • Improved repeatability of setup operations so current installations are left unchanged.

…nfig split)

agentflare init audited itself as incomplete on a fresh machine (item #255):
the .bashenv DEBUG-trap guard + lean-ctx function dispatcher were entirely
hand-installed, opencode had no branch-guard plugin at all (no PreToolUse
hook to wire agentflare's own guard into), and init's opencode idempotency
checks only ever looked at opencode.jsonc, missing entries a user had in
the sibling opencode.json.

- New "claude-code-bashenv-guard" component: creates/patches ~/.bashenv's
  two marker-delimited blocks (shim dispatcher + guard trap) and wires
  BASH_ENV into ~/.claude/settings.json, never clobbering surrounding
  content. Tool list is generated from shim_install's own GENERIC_SHIM_TOOLS
  instead of a second hand-maintained copy.
- New "opencode-branch-guard" component: drops the same branch-guard.js
  plugin (calls `agentflare hook pre-tool-use`) into opencode's auto-loaded
  ~/.config/opencode/plugin/ directory.
- opencode_config_merged() gives idempotency checks a merged view of
  opencode.json + opencode.jsonc (matching opencode's own deep-merge), so a
  value already present in either file isn't re-written. Writes still only
  ever target opencode.jsonc, the file init owns.

Agentflare-Agent: claude-code_2-1-220_agent
Agentflare-Branch: task/255
Agentflare-Item: 255
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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

Review profile: CHILL

Plan: Pro Plus

Run ID: c5acd3f9-b19c-41fd-8ace-e1d9dff81752

📥 Commits

Reviewing files that changed from the base of the PR and between bd1842e and 9f2e8b9.

📒 Files selected for processing (1)
  • src/bashenv.rs
📝 Walkthrough

Walkthrough

Adds a marker-managed ~/.bashenv installer and Claude Code wiring, introduces an OpenCode branch-guard plugin, merges sibling OpenCode configuration for checks, and prevents duplicate rule wiring across opencode.json and opencode.jsonc.

Changes

Guard integration

Layer / File(s) Summary
Bash environment installation
src/bashenv.rs, src/main.rs, src/shim_install.rs
Generates and maintains Bash shim and safety-guard blocks, wires BASH_ENV into Claude settings, exposes installation status and installation entrypoints, and tests idempotent preservation behavior.
OpenCode branch guard component
src/paths.rs, src/rule_text.rs, src/components.rs
Adds OpenCode path helpers and a branch-guard plugin that invokes the pre-tool-use hook, with host-gated component checks, application, merged configuration detection, and tests.
Sibling OpenCode configuration wiring
src/init.rs
Treats matching instructions in sibling opencode.json as already wired and tests that duplicate opencode.jsonc output is avoided.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClaudeGuard as claude-code-bashenv-guard
  participant Installer as ensure_installed
  participant BashEnv as ~/.bashenv
  participant Settings as ~/.claude/settings.json
  ClaudeGuard->>Installer: apply installation
  Installer->>BashEnv: upsert shim and guard blocks
  Installer->>Settings: persist env.BASH_ENV
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title is concise and accurately highlights the main changes: bashenv guarding, opencode branch-guarding, and config splitting.
Description check ✅ Passed The Summary and Test plan sections are complete and detailed; only the Notes for reviewers section is missing.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task/255

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: 6

🧹 Nitpick comments (1)
src/bashenv.rs (1)

95-107: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Guard patterns miss common equivalent forms.

rm -fr /, rm -r -f /, rm --recursive --force / and force-push via refspec (git push origin +main) all slip through. The doc comment already labels these rules "static v0", so this is a coverage note rather than a defect — worth capturing before the arai match_hook migration.

🤖 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/bashenv.rs` around lines 95 - 107, Expand the static v0 command-match
patterns in the bash DEBUG trap to cover equivalent destructive removal forms
such as rm -fr, separated -r/-f, and long options targeting /, plus force-push
refspecs like git push origin +main. Preserve the existing scoped-repository
check for git push and the current return behavior.
🤖 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/bashenv.rs`:
- Around line 208-218: Update set_bash_env_setting and its caller so a failed
settings.json write is distinguishable from an already-wired configuration.
Return a tri-state or propagate the write_json_pretty error, then update the
match handling around env_wired to report the failure instead of claiming
settings are already up to date.
- Around line 168-172: Update the env handling in the settings initialization
flow to coerce an existing non-object “env” value, including null or a string,
into an empty JSON object before calling as_object_mut(). Preserve existing
object contents and ensure the unwrap cannot panic for any valid JSON value.
- Around line 118-131: Update upsert_block so it does not append a new block
when the start marker exists without a matching end marker. Detect this
truncated-marker case and bail out without modifying the content, while
preserving the existing replace and append behavior for intact marker pairs or
when start is absent.

In `@src/components.rs`:
- Around line 397-413: Update the branch-guard rule handling in the check/apply
closures to compare the existing file contents with the current rule text
instead of checking existence alone. Make check report stale files as
unsatisfied, and make apply refresh files matching a previously shipped version
while preserving the existing host guard and status messages; reuse the
established stale-rule comparison pattern such as init::is_stale_rule where
applicable.

In `@src/paths.rs`:
- Around line 79-84: Update opencode_plugin_dir to join the opencode directory
with the plural "plugins" component, ensuring generated plugin files are placed
in the directory OpenCode scans. Adjust the adjacent documentation to describe
the plural path and remove the incorrect singular-path guidance.

In `@src/rule_text.rs`:
- Line 58: Update GUARDED_TOOLS to include the shell tool identifier alongside
the existing write/edit/patch entries, ensuring both lowercase and uppercase
bash/Bash calls are covered by the branch guard as required by the tool-name
handling.

---

Nitpick comments:
In `@src/bashenv.rs`:
- Around line 95-107: Expand the static v0 command-match patterns in the bash
DEBUG trap to cover equivalent destructive removal forms such as rm -fr,
separated -r/-f, and long options targeting /, plus force-push refspecs like git
push origin +main. Preserve the existing scoped-repository check for git push
and the current return 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: 364985dd-7162-44f2-b46d-954d201e6331

📥 Commits

Reviewing files that changed from the base of the PR and between cd0b68a and bd1842e.

📒 Files selected for processing (7)
  • src/bashenv.rs
  • src/components.rs
  • src/init.rs
  • src/main.rs
  • src/paths.rs
  • src/rule_text.rs
  • src/shim_install.rs

Comment thread src/bashenv.rs
Comment thread src/bashenv.rs Outdated
Comment thread src/bashenv.rs Outdated
Comment thread src/components.rs
Comment on lines +397 to +413
check: {
let host = host_owned.clone();
Box::new(move || host != "opencode" || opencode_plugin_dir().join("branch-guard.js").exists())
},
apply: {
let host = host_owned.clone();
Box::new(move || {
if host != "opencode" {
return "not applicable for this host".to_string();
}
let path = opencode_plugin_dir().join("branch-guard.js");
if write_if_absent(&path, rule_text::OPENCODE_BRANCH_GUARD_JS) {
format!("{} written", path.display())
} else {
format!("{} exists, skipped", path.display())
}
})

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 | ⚡ Quick win

Stale branch-guard.js is never refreshed.

check is a bare exists() and apply uses write_if_absent, so once the file is on disk any future change to OPENCODE_BRANCH_GUARD_JS (new tool ids, bug fixes) never reaches existing installs and check still reports satisfied. bashenv.rs solves the same problem with a content comparison; consider comparing contents here too (and rewriting when it matches a previously shipped version, mirroring init::is_stale_rule).

🤖 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/components.rs` around lines 397 - 413, Update the branch-guard rule
handling in the check/apply closures to compare the existing file contents with
the current rule text instead of checking existence alone. Make check report
stale files as unsatisfied, and make apply refresh files matching a previously
shipped version while preserving the existing host guard and status messages;
reuse the established stale-rule comparison pattern such as init::is_stale_rule
where applicable.

Comment thread src/paths.rs
Comment on lines +79 to +84
/// `~/.config/opencode/plugin` — opencode auto-loads every plugin file
/// dropped directly in this directory (singular "plugin"; the similarly
/// named "plugins" is not an opencode convention and isn't scanned).
pub fn opencode_plugin_dir() -> PathBuf {
opencode_dir().join("plugin")
}

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 | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

opencode global plugin directory ~/.config/opencode/plugin auto-load and opencode.json vs opencode.jsonc merge

💡 Result:

In OpenCode, the global plugin directory is located at /.config/opencode/plugins/ [1][2][3]. JavaScript or TypeScript files placed in this directory (or the project-level.opencode/plugins/ directory) are automatically loaded at startup [1][2][3]. Regarding configuration files, OpenCode supports both.json and.jsonc (JSON with Comments) formats [4][5]. When both opencode.json and opencode.jsonc files are present in the same directory, OpenCode performs a silent merge of their contents [6][7]. During this merge: 1. Settings are combined rather than replaced [4][5]. 2. Non-conflicting settings from all configuration sources are preserved [4][5]. 3. For conflicting keys, later configuration sources override earlier ones based on the established precedence order [4][5]. The precedence order for configuration sources (from lowest to highest priority) is generally: 1. Remote config (.well-known/opencode) [4][5] 2. Global config (/.config/opencode/opencode.json/jsonc) [4][5] 3. Custom config (OPENCODE_CONFIG env var) [4][5] 4. Project config (opencode.json/jsonc in project) [4][5] 5..opencode directories [4][5] 6. Inline config (OPENCODE_CONFIG_CONTENT env var) [4][5] 7. Managed config files and system preferences [4][5] Because the merge is silent, it can sometimes lead to confusing behavior if both file types contain conflicting settings, as the system does not inherently warn you when one file overrides the other [6]. [1][4][6][5][3]

Citations:


🏁 Script executed:

sed -n '1,140p' src/paths.rs

Repository: getappz/agentflare

Length of output: 5950


🌐 Web query:

OpenCode plugin directory plugins vs plugin opencode docs config jsonc merge silent deep merge

💡 Result:

In OpenCode, the plugin system distinguishes between two primary ways of integrating extensions, each with distinct loading and configuration behaviors [1][2][3]. Plugin Directory vs. npm Plugins - Plugin Directory (Local Plugins): These are JavaScript or TypeScript files placed directly into designated directories:.opencode/plugins/ (project-level) or ~/.config/opencode/plugins/ (global) [1][4]. They are automatically loaded at startup and are intended for local, custom extensions [1][3]. - npm Plugins: These are external packages defined in your configuration file (e.g., opencode.json) [5][3]. OpenCode installs these automatically using Bun, caching dependencies in ~/.cache/opencode/node_modules/ [1][4]. Configuration Merging (JSONC) OpenCode configuration files (typically opencode.json or opencode.jsonc) are merged across multiple layers (from remote organizational defaults to local project-specific overrides) [5][3]. The merging logic follows these principles: - Deep Merge: Standard objects are deep-merged, where later configurations override earlier ones only for conflicting keys [3][6]. - Special Array Handling: Unlike standard deep-merge behavior where a source might replace a target array, OpenCode special-cases the plugin and instructions arrays [6]. These arrays are concatenated and then deduplicated based on canonical names (or exact strings), with the final (highest priority) entries taking precedence [7][6]. - JSONC Support: OpenCode supports JSONC (JSON with Comments), and certain internal utilities use tools like jsonc-parser to modify configurations while preserving existing comments during programmatic updates [8]. There is no native "silent merge" feature in the core OpenCode configuration system, though third-party plugins (e.g., techdivision/opencode-plugin-config) may implement custom deep-merge strategies that operate in-memory without writing to disk [9]. In standard OpenCode operation, project configurations take higher precedence than global and remote configurations, and managed macOS preferences (via MDM) hold the highest priority [5][3].

Citations:


🏁 Script executed:

rg -n "opencode_plugin_dir|opencode_json_path|opencode_config_path|opencode_rules_dir" src

Repository: getappz/agentflare

Length of output: 2523


Use plugins/ instead of plugin/ OpenCode auto-loads plugin files from ~/.config/opencode/plugins/, so the singular path here won’t be scanned and branch-guard.js won’t load.

🤖 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/paths.rs` around lines 79 - 84, Update opencode_plugin_dir to join the
opencode directory with the plural "plugins" component, ensuring generated
plugin files are placed in the directory OpenCode scans. Adjust the adjacent
documentation to describe the plural path and remove the incorrect singular-path
guidance.

Comment thread src/rule_text.rs
// flare_git_core::branch::is_protected_branch), consulted from every
// harness. Fail-open if the agentflare binary is missing/errors, matching
// this repo's other guards' fail-open philosophy.
const GUARDED_TOOLS = new Set(["write", "edit", "patch", "apply_patch", "multiedit"])

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 | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

opencode plugin tool.execute.before tool ids list write edit patch bash

💡 Result:

In OpenCode, the tool.execute.before hook is a plugin lifecycle event that intercepts tool calls before they are executed [1][2][3]. This hook receives an input object containing the tool ID (input.tool), session ID, and call ID, and an output object containing the tool arguments (output.args), which can be inspected or modified [2][3]. Regarding the specific tools mentioned: 1. Bash, Write, and Edit: These are standard tool IDs commonly used in the system [1][4]. When using this hook, you can identify these tools by checking if input.tool equals "bash", "write", or "edit" [1][5]. 2. Patching (apply_patch): The tool ID for patching is "apply_patch", not "patch" [6][4]. It is crucial to use "apply_patch" when checking the input.tool in your hook, as checking for "patch" will not correctly capture the execution of patch-related operations [6][7]. 3. Model-Conditional Behavior: It is important to note that OpenCode may substitute file-editing tools based on the model in use [5]. For many models (e.g., Claude, Gemini, GPT-4o), the "edit" and "write" tools are used [5]. However, for certain GPT-series models (e.g., GPT-5), these may be substituted by the "apply_patch" tool [5]. Consequently, a robust plugin implementation should account for these different tool IDs to ensure model-agnostic behavior [5]. 4. Implementation Note: When modifying arguments within a tool.execute.before hook, ensure your implementation correctly mutates the argument object passed to the tool. Some earlier implementations faced issues where mutations were not reflected because a fresh object was created; it is recommended to ensure the hook updates the actual arguments object intended for the execution [8].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and inspect the relevant section.
git ls-files 'src/rule_text.rs' 'src/**' | sed -n '1,120p'

echo
echo '--- src/rule_text.rs (around the referenced lines) ---'
sed -n '1,140p' src/rule_text.rs

echo
echo '--- Search for GUARDED_TOOLS and tool ids ---'
rg -n 'GUARDED_TOOLS|tool.execute.before|apply_patch|multiedit|bash|write|edit|patch' src . || true

Repository: getappz/agentflare

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- src/hook_redirect.rs (1-80) ---'
sed -n '1,80p' src/hook_redirect.rs

echo
echo '--- src/components.rs (388-410) ---'
sed -n '388,410p' src/components.rs

echo
echo '--- src/rule_text.rs (54-75) ---'
sed -n '54,75p' src/rule_text.rs

Repository: getappz/agentflare

Length of output: 5546


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- opencode/bash references ---'
rg -n 'opencode|bashenv|Bash|bash tool|shell guard|branch-guard|pre-tool-use|tool.execute.before' src/rule_text.rs src/components.rs src/hook_redirect.rs src/bashenv.rs src/cli src | sed -n '1,240p' || true

echo
echo '--- src/bashenv.rs (top) ---'
sed -n '1,220p' src/bashenv.rs

Repository: getappz/agentflare

Length of output: 29349


Add the shell tool to the branch guard. GUARDED_TOOLS only covers the edit/write/patch family, so a bash/Bash call can still write files or run git push on a protected branch. Include the shell tool here too so opencode gets the same deny surface.

🤖 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/rule_text.rs` at line 58, Update GUARDED_TOOLS to include the shell tool
identifier alongside the existing write/edit/patch entries, ensuring both
lowercase and uppercase bash/Bash calls are covered by the branch guard as
required by the tool-name handling.

@getappz getappz changed the title init: cover the shell layer (bashenv guard, opencode branch-guard, config split) feat: cover the shell layer in agentflare init (bashenv guard, opencode branch-guard, config split) Jul 25, 2026
…wiring

- upsert_block: leave a truncated marker (start present, no matching end)
  alone instead of appending a second copy after it.
- set_bash_env_setting: coerce a non-object "env" value (null, a stray
  string) instead of unwrap-panicking on as_object_mut(); return a
  tri-state outcome so a write failure is reported as a failure, not
  silently folded into "already up to date".

Agentflare-Agent: claude-code_2-1-220_agent
Agentflare-Branch: task/255
Agentflare-Item: 255
@getappz

getappz commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

Went through all 6 findings:

Fixed (pushed in 9f2e8b9):

  • bashenv.rs 118-131 — upsert_block now leaves a truncated marker (start present, no matching end) alone instead of appending a second copy after it.
  • bashenv.rs 168-172 — coerce a non-object env value (null, a stray string) instead of unwrap-panicking on as_object_mut().
  • bashenv.rs 208-218 — set_bash_env_setting now returns a tri-state outcome (AlreadySet / Wired / Failed) so a write failure surfaces as a failure message instead of silently reading as "already up to date".

Not applying:

  • paths.rs 79-84, "should be plugins (plural)" — this is backwards. Verified directly against opencode's docs (opencode.ai/docs/plugins/): "Local plugins are loaded directly from the plugin directory" — singular plugin/, auto-loaded, no config registration needed. plugins/ (plural) isn't an opencode convention at all and is never scanned. Applying this suggestion would silently break the whole opencode-branch-guard component (the file would sit in a directory opencode never reads). The doc comment on opencode_plugin_dir already states this explicitly.
  • rule_text.rs line 58, "add shell/Bash to GUARDED_TOOLS" — checked this against Claude Code's own reference guard (hook_redirect.rs's MUTATING_TOOLS), which the opencode plugin shells out to for the actual decision. That list also excludes Bash/shell — this is a consistent, existing design choice across the whole guard system (structured file-mutation tools only, not arbitrary shell execution), not something specific to this new file. Widening it here without doing the same to MUTATING_TOOLS would just make the two diverge. Worth a separate, deliberate discussion — out of scope for this PR.
  • components.rs 397-413, staleness detection for branch-guard.js reusing is_stale_rule — legitimate future improvement, but there's no historical "superseded" version yet (this is the first version shipped), so there's nothing to detect staleness against. The current write-if-absent behavior matches the existing "rules" component's default (never silently overwrite a file that might be hand-edited). Once there's an actual old version to compare against, this can be wired into the same confirm_rule_refresh flow the rule files use.
  • bashenv.rs 95-107 nitpick (expand rm -fr/refspec force-push patterns) — you tagged this Trivial/Low value yourself, and it's pre-existing content carried over verbatim from the already-validated, currently-running .bashenv guard (explicitly labeled "static v0" prototype in its own comment). Not blocking; can be widened in a follow-up to the guard itself.

@getappz
getappz merged commit fc34887 into master Jul 25, 2026
15 checks passed
@getappz
getappz deleted the task/255 branch July 25, 2026 06:14
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