Skip to content

feat(sidecar,shell): HGW runtime stack #80–#84 (project write policy, project_create, 24-step turns, auto-approve, git safety) - #84

Merged
SaulBuilds merged 19 commits into
mainfrom
hgw/w1-git-safety
Oct 16, 2026
Merged

SaulBuilds merged 19 commits into
mainfrom
hgw/w1-git-safety

Conversation

@SaulBuilds

@SaulBuilds SaulBuilds commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Lands the whole HGW runtime stack in one squash (owner decision 2026-10-15): #80 project write policy + git in the sandbox (HGW-W2), #81 project_create (HGW-W3), #82 24-step turns + failure output (HGW-W5/W6), #83 auto-approve list + build e2e (HGW-W11), and this PR's git cleanup + member commit identity. Each was reviewed and approved on its own PR; #80–#83 close as landed here. Retargeted to main after #79; the merge of main changes no files relative to the approved head.

Follow-up to the HGW-W2 stack (#79 → #83), carrying the owner's runtime decisions of 2026-10-15 on #79–#83 (recorded in the HUP owner-decisions log).

1. Risky git state a run adds is reverted (was: reported)

After every shell_run (and every runner) run, citrate-agent-shell reverts what the run added that would make git start a program outside the sandbox later, and reports each revert in RunReport.git_warnings (the shell_run summary says the changes were undone):

  • config entries: core.hooksPath, core.fsmonitor, core.sshCommand, core.pager/editor/askPass/gitProxy, alias.*, filter.*, diff/merge drivers, credential.*, include.path/includeIf.*.path, non-https url.*.insteadOf, protocol.*.allow=always, gpg.program, tool cmd/path, upload/receive-pack hooks; plus trailer.*, commit.cleanup, core.commentChar/commentString (they could drop the Hermes trailer);
  • new hook files (not *.sample); a hooks folder or .git/config swapped for a symbolic link is put back.

Normal config (user.*, remote.*, branch.*, core.autocrlf, https mirrors) stays. What was there before the run is never touched. A .git the run turned into a pointer (gitdir: file or symlink) is reported with the risky state where it points, not changed (it may be the member's own folder).

2. Commit identity + Co-authored-by: Hermes trailer

New agent-sidecar/src/git_identity.rs:

  • Author/committer = the identity the app passes (CITRATE_HERMES_GIT_USER_NAME + CITRATE_HERMES_GIT_USER_EMAIL, both set and valid; this is the input core will wire), else the member's own global git config (user.name/user.email, read once at startup with the real git, empty env but HOME), else Hermes <hermes@citrate.invalid>. Passed as GIT_AUTHOR_*/GIT_COMMITTER_*, which outrank every config file.
  • git commit gets --trailer "Co-authored-by: Hermes <hermes@citrate.invalid>" after the subcommand. Command-scope config (outranks the repo's) forces trailer.ifmissing=add, ifexists=addIfDifferent (global and for co-authored-by) and core.commentChar=#, next to the existing hooks/fsmonitor-off pair ([v0.5.1 HGW-W11] Auto-approve safe-command list (amended D-16) #77).
  • Refused before the member is asked, saying why (so it can't be dropped silently): -c/--config-env for user.*, author.*, committer.*, trailer.*, include*, core.commentChar/commentString, commit.cleanup; in git commit, --author, --cleanup, -C/-c/--reuse-message/--reedit-message (git's unique-prefix abbreviations included; option values such as -m "--author=x" are not mistaken for options); git commit-tree.

The approval card still shows the model's exact argv; the trailer is added by the runtime.

Scope limits: commits from merge/cherry-pick/revert/am carry the member identity but no trailer. A non-git program (e.g. a member-approved sh -c "git commit") gets neither. A repo config from before the run that aliases another trailer token to Co-authored-by with its own ifMissing could still suppress the trailer.

Tests (red first)

  • agent-shell: a_git_pointer_made_by_the_run_is_reported_not_followed_into_changes (new); the revert tests in tests/sandbox.rs (incl. real git under Seatbelt); git_state unit tests for the trailer keys.
  • agent-sidecar: git_runs_carry_the_commit_identity_and_other_programs_do_not, the_commit_identity_resolves_app_then_member_git_config_then_hermes, the_app_sets_the_commit_identity_through_the_environment, the_members_global_git_config_is_read_for_the_identity, a_commit_carries_the_member_identity_and_the_hermes_trailer (real git; the repo's trailer.ifmissing=doNothing + commentChar=C do not drop it), a_commit_that_would_change_the_author_or_drop_the_trailer_is_refused_before_asking; 4 unit tests in git_identity.
  • Local: cargo test --workspace 2317 passed / 0 failed (macOS). clippy has no findings in agent-sidecar/agent-shell, and fmt is clean for both. The audit check fails on main as well, from new upstream advisories; a separate PR fixes it.

Core follow-up: pass the member's identity via the two env vars when spawning the sidecar (core wiring lane, identity passthrough).

🤖 Generated with Claude Code

https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe

SaulBuilds and others added 11 commits October 15, 2026 11:34
Owner decision 2026-10-15 (HGW (2)). Before this change any shell_run
output, even an approved `node -v`, tainted the session, and every later
command and sidecar-hosted write was declined for the rest of the
conversation ("which this tool's host cannot ask for"), with no way to
clear it.

Now, in a session opened with hicAware: true:
- a tainted effectful sidecar call (fs_*, file_write, sheet_write,
  toolchain tools, capsules) waits on a new per-session action card
  (GET /sessions/:id/actions/pending, POST .../actions/decide
  {id, allow, subject}); the card shows the tool, the exact canonical
  arguments, a summary, the hicReason and every taint source;
- shell_run keeps its own card and still asks after taint; the card
  now carries hicReason and taintSources;
- an approval releases that one call; the session stays tainted, so
  the next action asks again (never global, never automatic);
- decisions are recorded (kind sidecar.tool_call, write-ahead).

Without hicAware (headless, scheduled) nobody can be asked: the call is
declined with citrate_agent_loop::cannot_ask_reason, which names the
taint source and says why.

Tests: agent-loop taint_tests (+1), action_approvals unit (+3),
action_approvals_tests session/route tests (+6), shell_run_tests (+2,
one rewritten), files_tests taint case rewritten to the card flow.
Workspace: 2241 -> 2253 passed, 0 failed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…t-retry (HGW-1)

Aligns the HGW-1 interface with the HGW-W1 issue (#74):
- routes are GET /sessions/:id/approvals/pending and
  POST /sessions/:id/approvals/:aid/decide {allow, subject};
- POST /sessions/:id/taint/clear {note}: the member clears the taint
  from an explicit card (TaintState::clear_by_member). Recorded
  write-ahead (kind taint.clear); with no records log, or when the
  record cannot be written, nothing is cleared (503). Scheduled
  (unattended) runs are never cleared (409); empty note 400; not
  tainted 409. Approving one action still never clears the taint;
- a declined card tells the model to ask the member instead of
  retrying (shell_run and approval cards).
Test support opens one undo store per manager (a store is locked while
open).

Tests: action_approvals_tests (+2). Workspace: 2253 -> 2255 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…(HGW-2)

Owner decision 2026-10-15 (HGW). Hermes could not set up a project: the
file tools refused package.json, foundry.toml, remappings.txt and the
rest of the build configuration everywhere, and the macOS sandbox denied
every write to .git/config and .git/hooks, so `git init` failed even
offline.

Project roots (agent-sidecar):
- POST /sessions takes `projectRoots` (absolute, existing folders under
  live read+write subtree folder grants; needs `grants`). SessionGrants
  keeps them; project_create (next PR) adds the projects it makes.
- Inside a project root the file tools (fs_*, file_write, sheet_write)
  may create and change build configuration. Outside, refused as before
  (the message now points at projects). A marker file alone never makes
  a folder a project.
- Env files stay the member's everywhere. The file tools never write
  inside a .git folder (git does, through the sandboxed shell_run).
- The toolchain's own config check (ffi, fs_permissions, ...) is
  unchanged: forge still refuses risky config whoever wrote it.

Sandbox (agent-shell):
- Seatbelt: .git/ is writable inside write roots (git init/config/commit
  work); a hook file other than git's *.sample files is still denied, as
  are removing or moving .git/hooks and symlinking a new one in.
- bwrap: .git/config is no longer masked (parity); existing .git/hooks
  stays read-only.
- RunReport.git_warnings: risky git state a run leaves behind that would
  run a program outside the sandbox later (hooks, core.hooksPath,
  core.fsmonitor, `!` aliases, filters, includes, ...), new since before
  the run. shell_run puts it in the run facts and the summary.
- Linux bwrap run tests (skip unless bwrap works; CITRATE_REQUIRE_BWRAP=1
  makes them fail instead, for the Linux CI lane).

Tests: project_policy_tests (+6), agent-shell sandbox (+3 macOS real
Seatbelt incl. git init/commit and hooks closed; +3 Linux), git_state
unit (+2), shell_run git warning (+1). Workspace: 2253 -> 2265 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
Hermes had no way to start a project: there was no default folder and
no tool to make one, and template rendering was a panel action only.

project_create {name, template?, params?} (sidecar-hosted, offered to
sessions with folder grants when CITRATE_HERMES_PROJECTS=1):
- name is one plain folder name (no separators, no `..`, no leading
  `.`/`-`/`~`, at most 64 chars); refused before anything is asked;
- the projects root (CITRATE_HERMES_PROJECTS_ROOT, passed by core;
  default ~/Citrate/Projects) must exist and be under live read+write
  subtree folder grants; <root>/<name> must not exist (never reused);
- always waits on an action card (HGW-1 queue) showing the exact folder
  and template; no HIC-aware app = nothing created; a tainted session
  shows one card carrying the taint reason;
- after approval (grants re-checked): creates the folder, renders the
  template if asked, writes .citrate/project.json, and makes the folder
  a session project root (HGW-2 build-config writes apply); a failed
  render removes the new folder and says why; returns the path.

Template rendering stays core's: the TemplateRenderer trait is the seam,
and CliTemplateRenderer runs core's `citrate-templates render --root
<templates> --template <id> --tier <T> --out <dest> [--param k=v]...`
(CITRATE_HERMES_TEMPLATE_RENDERER + CITRATE_HERMES_TEMPLATES_ROOT,
CITRATE_HERMES_TEMPLATE_TIER) through the shell runner, in the OS
sandbox when there is one, writing only the new folder.

Tests: projects unit (+4), projects_tests session/route (+10, incl. the
CLI renderer under real Seatbelt). Workspace: 2265 -> 2279 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…x (HGW-2, #75)

Per the HGW-W2 issue (#75): the Seatbelt `.env*` deny and the bwrap
`.env*` masks exempt the templates' `.env.example` and `.env.sample`
(not secrets; agent-guard exempts them the same way). `.env` and
`.env.local` stay neither readable nor writable.

Tests: sandbox env_files unit extended; real-Seatbelt test (+1).
Workspace: 2267 -> 2268 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
… (HGW-5)

Owner decision 2026-10-15 (HGW (3), D-16 as amended): sandboxed,
offline, project-scoped read and build commands run without a card.

- The list is data: agent-sidecar/policy/auto_approve.toml (compiled
  in; CITRATE_HERMES_AUTO_APPROVE=0 turns it off, an absolute path
  replaces it). Rules are argv templates (program, subcommands, flags,
  value flags with kinds, required flags, operand kind and count). The
  shipped list: ls, pwd, cat, head, tail, wc, node <file>, npm run
  <script>, npm test, npx tsc, forge build/test, cargo build/test/check
  --offline, git init/status/diff/add/commit -m.
- shell_run releases a match without a card only when the session is
  untainted, the OS sandbox is enforced, and the folder is inside a
  project root; that run may write only the project (not the wider
  grant). Network-capable or unlisted commands, or anything outside a
  project, still ask. After taint every command asks (HGW-1).
- Each auto run is recorded write-ahead (kind shell.run.auto, actor
  agent, HIC-2); if it cannot be recorded it asks instead. Its result
  says so (run.approval = {mode: auto, rule, project}); member-approved
  runs say {mode: member}.
- agent-loop: ToolOutcome::Vouched. An auto run's output derives from
  the project's own files (no network, project-only writes, untainted
  session), like a folder-grant file read, so it does not taint; the
  worker wire maps it to Ok (fail closed across the process boundary).
- git through shell_run commits as "Hermes <hermes@citrate.invalid>"
  (the scratch HOME has no identity; git refused to commit).
- shell_run's description now states the approval semantics and says
  to ask, not retry, after a decline.

End to end (real Seatbelt, scratch home, scripted model): create the
project (one card) -> write package.json, build.js and a buggy source ->
git init/add/commit -> npm run build fails -> the model reads
"ReferenceError: greeet is not defined" from the tool result, fixes it
with fs_edit -> build passes -> commit; then untrusted output makes the
next listed command ask, with the taint reason on its card. Negative
checks in the same run: no write outside the project, no network, no
risky git state. Linux (bwrap) runs the same tests; they skip without
a working bwrap unless CITRATE_REQUIRE_BWRAP=1 (the CI lane).

Tests: auto_approve unit (+4), auto_approve_tests (+7), e2e (+1),
taint_tests vouched (+1), shell_run git identity (+1). Workspace:
2285 -> 2299 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…t on (HGW-4)

A build needs more than 8 model calls, and a failing step has to show
the model why it failed.

- Turns: default maxSteps 8 -> 24 (sessions::DEFAULT_MAX_STEPS), cap
  stays 32. A session's maxSteps still wins; the sidecar-wide default
  is configurable with CITRATE_HERMES_MAX_STEPS (clamped 1..=32).
- Capture (agent-shell): a capped stream now keeps its first half-cap
  and its last half-cap (first error and final cause), with the
  truncation marker between them, instead of only the head.
- shell_run: a non-zero exit puts the exit status and the end of stderr
  (or stdout when stderr is empty), at most FAILURE_TAIL_BYTES = 2048,
  in the summary the model reads first, and as stderr_tail/stdout_tail
  in the run facts. Successful runs are unchanged.
- Toolchain: a run with no parseable report now states the exit code.
  Recognized compiler errors stay sanitized and trusted (the S6.3
  guarantee: injected text in sources never reaches trusted output).
  When no cause is recognized, the end of stderr is handed over raw,
  bounded, and the result is Untrusted, so it taints the session (and,
  with HGW-1, later actions go to HIC cards).

Tests: agent-shell runner (+1, two capture assertions extended),
loop_capability_tests (+3), shell_run failure tail (+1), toolchain
unparsed stderr (+1). Workspace: 2279 -> 2285 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
)

Aligns HGW-5 with the HGW-W11 issue (#77):
- npm run is auto-approved only for the script names build, test,
  lint and typecheck (new rule field operand_values); any other script
  asks;
- every git run through shell_run gets command-scope config
  core.hooksPath=/dev/null and core.fsmonitor=false (outranks the
  repository's own config), so Hermes's git never runs hooks;
- GET /shell/auto-approve returns the list in effect (enabled,
  conditions, rules) for the app's Settings, behind the bearer.

Tests: matrix extended; route test (+1); git hooks/fsmonitor off (+1).
Workspace: 2302 -> 2304 passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…er decision 2026-10-15)

After every run the runner reverts what the run added that would make git
start a program outside the sandbox later: risky config entries (hooksPath,
fsmonitor, sshCommand, pager/editor, aliases, filters, diff/merge drivers,
credential helpers, includes, non-https insteadOf, protocol allow=always,
gpg.program, ...), new hook files, and a hooks folder or config swapped for
a symbolic link. Normal config (user.*, remote.*, branch.*) stays; what was
there before the run is never touched. Each revert is a line in
RunReport.git_warnings and the shell_run summary says the changes were
undone.

A .git the run turned into a pointer (gitdir: file or symlink) is reported
with the risky state where it points, not changed: that folder may be the
member's own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…W, owner decision 2026-10-15)

Author and committer of commits made through shell_run are the member's:
the identity the app passes (CITRATE_HERMES_GIT_USER_NAME/_EMAIL, both
set and valid), else the member's own global git config (read once with
the real git outside the sandbox, empty env but HOME), else
"Hermes <hermes@citrate.invalid>". They reach git as GIT_AUTHOR_*/
GIT_COMMITTER_*, which outrank every config file.

`git commit` gets --trailer "Co-authored-by: Hermes <hermes@citrate.invalid>",
and command-scope config keeps git adding it (trailer.ifmissing=add,
ifexists=addIfDifferent, commentChar #) over the repository's own.

Not the model's to change, so refused before the member is asked:
-c/--config-env for user.*, author.*, committer.*, trailer.*, include*,
core.commentChar/String, commit.cleanup; commit --author, --cleanup,
-C/-c/--reuse-message/--reedit-message (abbreviations included); and
git commit-tree. Trailer/cleanup/comment-char config a run writes into
the repository is reverted after it with the other risky git state.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
@SaulBuilds
SaulBuilds requested a review from a team as a code owner October 15, 2026 20:23
@SaulBuilds

Copy link
Copy Markdown
Contributor Author

📡 DGX team: Linux bwrap run proof for the HGW stack (#79 → #84)

The owner asked DGX to run the Linux sandbox tests, since they can't run on macOS. This branch (hgw/w1-git-safety, top of the stack) contains all of #79–#84. On a Linux box with bubblewrap installed (Ubuntu: sudo apt-get install -y bubblewrap; unprivileged user namespaces must be enabled):

git clone https://github.com/CitrateNetwork/citrate-agent-runtime.git && cd citrate-agent-runtime
git checkout hgw/w1-git-safety && git rev-parse HEAD
bwrap --version
# Fail instead of skip when bwrap is missing or broken:
CITRATE_REQUIRE_BWRAP=1 cargo test -p agent-shell --test sandbox -- --nocapture 2>&1 | tee bwrap-sandbox.log
CITRATE_REQUIRE_BWRAP=1 cargo test -p agent-sidecar 2>&1 | tee bwrap-sidecar.log

Please reply here with:

  1. the commit sha, distro + kernel (uname -r), and bwrap --version;
  2. pass/fail lines for writes_outside_the_grant_are_denied_under_bwrap, git_init_add_and_commit_work_inside_the_grant_under_bwrap, network_is_unshared_under_bwrap;
  3. the test result: summary lines from both logs, and the full output of any failure.

If a test skips with "bwrap is unusable here", check sysctl kernel.unprivileged_userns_clone and (Ubuntu 24.04+) kernel.apparmor_restrict_unprivileged_userns. Report what you found before changing any setting on a fleet node.

@BerryManifold BerryManifold left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The new cleanup does not yet enforce the recorded owner requirement across every affected repository. A focused real-Seatbelt regression check confirmed that a command can leave executable git configuration outside the cleanup coverage. Holding approval until that boundary is enforced and covered by a regression test. Detailed reproduction is retained privately under the organization security policy; no exploit details are posted here.

SaulBuilds and others added 7 commits October 15, 2026 15:45
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…dependency updates, #85)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…udit dependency updates, #85)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…dependency updates, #85)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…pendency updates, #85)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
…ncy updates, #85)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
The post-run git cleanup (HGW-2, owner decision 2026-10-15) now finds
repositories by walking every write root, before and after the run,
instead of checking only the run's folder, its parents and its direct
children:

- `.git` folders at any depth, bare repositories, linked worktrees
  (`.git/worktrees/*`) and submodule git folders (`.git/modules/**`);
- `config.worktree` is checked alongside `config`, and `hooks/` in each;
- repositories the run creates are reverted against an empty baseline;
- `.git` files/links and `commondir` are followed when they point at a
  git folder inside the write roots; ones pointing outside are reported
  and left unchanged;
- more keys that run a program or move the worktree are treated as risky
  (core.worktree, core.alternateRefsCommand, submodule.*.update = !...,
  hook.*, interactive.diffFilter, sendemail commands,
  gpg.ssh.defaultKeyCommand, tar.*.command, guitool.*.cmd).

The walk is bounded (300,000 entries, 48 levels). When it stops early
the report says so, and a repository the before-run walk did not reach
is reported rather than changed. Tests cover each case through the
runner, under Seatbelt on macOS and under bubblewrap on Linux.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
@SaulBuilds

Copy link
Copy Markdown
Contributor Author

@BerryManifold thanks. d312bd5 widens the post-run git cleanup so it is enforced across every repository the run could write:

  • Discovery: each write root is walked before and after the run (symbolic links are not followed). It finds .git folders at any depth, bare repositories, linked worktrees (.git/worktrees/*) and submodule git folders (.git/modules/**). Repositories the run creates are reverted against an empty baseline.
  • Files checked per git folder: config, config.worktree and hooks/.
  • Pointers: a .git file or link, and commondir, are followed into a git folder inside the write roots and cleaned there. One that points outside them is reported and not changed.
  • More risky keys: core.worktree, core.alternateRefsCommand, submodule.*.update = !…, hook.*, interactive.diffFilter, the sendemail commands, gpg.ssh.defaultKeyCommand, tar.*.command, guitool.*.cmd.
  • Bounds: 300,000 entries and 48 levels per walk. If a walk stops early the report says so, and a repository the before-run walk didn't reach is reported, not changed.

New tests:

  • through the runner: repositories_anywhere_in_the_write_roots_are_cleaned, worktree_config_and_submodule_git_folders_are_cleaned, a_git_pointer_outside_the_write_roots_is_reported_and_one_inside_is_cleaned;
  • real Seatbelt: macos::git_state_anywhere_in_the_grant_is_cleaned_under_seatbelt and macos::a_hook_written_through_a_differently_cased_git_folder_does_not_survive;
  • bubblewrap: linux::git_state_anywhere_in_the_grant_is_cleaned_under_bwrap, which the DGX run above will now include;
  • units in git_state: walk coverage, walk bounds, nested write roots, new keys, and a pointer at a folder that isn't a repository (nothing there is changed).

Local cargo test --workspace: 2325 passed, 0 failed. If your private reproduction covers a case this misses, I'll add it.

BerryManifold
BerryManifold previously approved these changes Oct 16, 2026

@BerryManifold BerryManifold left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approval submitted at the owner’s explicit direction. This does not retract or resolve the previously reported git-state cleanup finding; no new verification of a fix is claimed.

Matr0xshka
Matr0xshka previously approved these changes Oct 16, 2026

@Matr0xshka Matr0xshka 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.

Approval submitted at the owner’s explicit direction. This does not retract or resolve the previously reported git-state cleanup finding; no new verification of a fix is claimed.

main is the squash of #79, identical to hgw/w1-taint-hic@00264e5, which this branch already contains; the resolution keeps this branch's tree. Lands #80-#84 as one squash (owner decision 2026-10-15).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018wWZZ8GRVU9USh3kKQHsFe
@SaulBuilds
SaulBuilds changed the base branch from hgw/w1-auto-approve to main October 16, 2026 04:05
@SaulBuilds
SaulBuilds dismissed stale reviews from Matr0xshka and BerryManifold October 16, 2026 04:05

The base branch was changed.

@SaulBuilds SaulBuilds changed the title feat(shell,sidecar): revert risky git config after runs; member commit identity (v0.5.1 HGW-W2 follow-up) feat(sidecar,shell): HGW runtime stack #80–#84 (project write policy, project_create, 24-step turns, auto-approve, git safety) Oct 16, 2026

@BerryManifold BerryManifold left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reapproval submitted at the owner’s explicit direction. No new code review or verification of the previously reported finding is claimed.

@Matr0xshka Matr0xshka 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.

Reapproval submitted at the owner’s explicit direction. No new code review or verification of the previously reported finding is claimed.

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.

3 participants