Skip to content

Dev - #2587

Closed
namastex888 wants to merge 28 commits into
mainfrom
dev
Closed

Dev#2587
namastex888 wants to merge 28 commits into
mainfrom
dev

Conversation

@namastex888

@namastex888 namastex888 commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • genie update improves delivery reliability for pinned Claude role-agent models, including when the related plugin is disabled.
    • genie doctor adds deeper Claude role-agent health checks with structured --json output and duplicate-surface warnings when applicable.
    • genie uninstall enhances agent cleanup, preserving modified and user-authored agent files.
    • Release workflows add stronger safety guards for protected-tag dispatch and stable production environment gating.
  • Bug Fixes

    • Release verification/publishing more strictly validates signature and provenance sidecars with fail-closed behavior.
  • Chores

    • Updated package/plugin versions to 5.260715.1; CI now uses deterministic installs (bun install --frozen-lockfile) and pinned actions.

namastex888 and others added 11 commits July 14, 2026 12:25
…ck uninstall

Group A (agents-fanout) of routing-delivery-fix, attempt 4 — architecture-first
repair replacing per-file staging/relinquish machinery with one transaction core
(capture -> validate -> publish -> manifest CAS -> finalize/rollback) and one
lock held across the complete uninstall including canonical-source deletion.
Closes the six terminal transaction-boundary defects from attempts 1-3; 7 new
invariant tests pin them. Independent execution review: SHIP (2026-07-12).

106 focused tests pass; bun run check 967 pass / 1 skip / 0 fail.
…arning

Group B (doctor-duplicate-guard) of routing-delivery-fix. Per-file classifier
over source-union-manifest names inside checkClaudeSync (genie-managed-current /
genie-managed-stale / present-unmanaged / missing-from-target; user-authored
agents never reported), enabledPlugins duplicate-surface warning, and a stable
machine-readable roleAgents payload on doctor --json for the dashboard.
Reuses Group A's enumeration + fail-closed manifest inspection (additive
exports only). Independent execution review: SHIP (2026-07-12).

43 doctor tests pass; bun run check 976 pass / 1 skip / 0 fail.
…-fix

feat(agent-sync): deliver pinned role agents through managed fan-out
…es + least-privilege CI

Close inherited findings F16/F17/F18 and the channel-scoped environment
deliverable of the stable-release-security-gate wish, entirely in repo code.

F16/F17 — every dispatchable entry point (release.yml, build-tarballs.yml,
sign-attest.yml, release-publish.yml) now gates on scripts/release-guard.sh:
a manual workflow_dispatch must target a protected v<version> tag, and a
break-glass run_id is bound to a SUCCESSFUL upstream run on the same repo,
workflow, tag ref, and head SHA before anything is signed or published. The
guard is extracted into a shell helper with colocated bun:test fixtures
(scripts/release-guard.test.ts, 18 cases) because CI has no workflow
simulator. HARD INVARIANT preserved: the dev release path dispatches
release.yml on the freshly-pushed tag, so it always satisfies the tag guard;
orchestrated workflow_call sub-runs pass no run_id and inherit the tag ref.

Deliverable 6 — release-publish.yml's publish job declares
`environment: production` ONLY when channel == 'stable'; dev/homolog resolve
to an empty environment string, so dev keeps publishing with no approval
gate. release-publish.yml's standalone dispatch channel default flips from
stable to dev (defensive).

F18 — SHA-pin all third-party actions (setup-bun, cosign-installer,
slsa-verifier installer, ggshield-action, attest-build-provenance); freeze
the last unfrozen `bun install`s in ci.yml + version.yml; add a
least-privilege top-level `permissions: contents: read` to ci.yml; and drop
blanket `secrets: inherit` from release.yml (called workflows use only the
auto-provided GITHUB_TOKEN). The SLSA generator reusable stays pinned to its
`@v2.1.0` semver tag with a documented exception — slsa-verifier derives the
trusted builder identity from that tag and the build fails if it is pinned to
a commit SHA.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gression guard

Close F31a in repo code. install.sh's extract_and_link no longer untars
directly over the live tree. It extracts to a same-filesystem staging dir,
verifies the staged binary runs and reports the expected version (rejecting a
corrupt or wrong-version artifact), moves sidecars into place, backs the live
binary up to bin/.previous, then commits with a single rename-over-live of the
`genie` binary — the old executable is runnable up to that instant, the new one
immediately after, and a crash mid-rename can never yield a partial file. A
failed post-swap verification rolls back to the backup.

The durable .steal lifecycle-lock recovery protocol (F42/F45–F47/F50) is left
byte-for-byte unchanged; scripts/install-swap.test.ts pins the SHA-256 of the
seven protected functions as a regression guard and exercises the swap against
destructive-failure fixtures: happy path, first install, corrupt artifact
(no binary), corrupt tarball, version mismatch, kill mid-swap (old binary stays
runnable), and failed provenance (download_and_verify refuses). update.ts's
atomic swap is already transactional; a corrupt-tarball fixture is added to
extractTarball to complete its destructive-failure coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Close F31b. Releases ship per-platform `genie-<v>-<platform>.tar.gz` plus a
cosign sigstore `*.tar.gz.bundle` and a per-tarball SLSA `*.tar.gz.intoto.jsonl`
(sign-attest.yml / release-publish.yml). The verifier previously expected the
non-existent `*.tgz` + detached `.sig`/`.cert` + a single
`provenance.intoto.jsonl`, so it could not verify any real release.

It now downloads `*.tar.gz{,.bundle,.intoto.jsonl}`, verifies each tarball with
`cosign verify-blob --bundle` (identity + issuer pinned, matching install.sh)
and `slsa-verifier verify-artifact` against the per-tarball provenance, and adds
a best-effort GitHub-native `gh attestation verify` cross-check. The canonical
signing-identity pin block (witnessed by check-fingerprint-pinning.sh) is
preserved verbatim. scripts/verify-release.test.ts covers the exit-code
contract (verified / cosign-fail / slsa-fail / missing-material / misuse).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, G2 settings evidence

Plan review FIX-FIRST→SHIP and adversarial execution review SHIP recorded in
WISH.md; Group 2 external state (production environment with independent
required reviewers + prevent-self-review + no admin bypass, v-tags-immutable
ruleset) captured as qa/github-settings-evidence-20260714.json; INDEX entry
moved to Poured.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex P1 on PR #2585: release-publish.yml's guard job requests actions:read
but the orchestrated caller granted only contents:write/id-token:write — a
called workflow cannot elevate past its caller, so every release.yml-driven
release (dev included) would fail at workflow initialization. Grant the
permission on the caller.

Also: validate RUN_ID grammar before probing for gh (fail-closed exit 3 even
without the CLI installed) and clean the provenance temp file via EXIT trap
(${tmp:-} because the trap outlives the function local under set -u).
Bot-comment triage recorded in WISH.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ity-gate

feat(release): stable release security gate — protected publication chain (F16–F18, F31)
@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds guarded release workflows, transactional installation and artifact verification, and manifest-backed Claude role-agent synchronization. It also extends doctor and uninstall flows, adds failure and concurrency tests, updates release metadata, and records security-gate planning evidence.

Changes

Release security and artifact handling

Layer / File(s) Summary
Protected release workflow and artifact verification
.github/workflows/*, scripts/release-guard.sh, scripts/verify-release.sh, scripts/*test.ts
Release dispatches and provenance are validated, workflow actions are pinned, installs are frozen, permissions are restricted, and bundle/provenance verification is enforced.
Transactional binary installation
install.sh, scripts/install-swap.test.ts
Downloaded binaries are staged, validated, atomically promoted, post-verified, and rolled back on failure.
Manifest-backed role-agent synchronization
src/lib/agent-sync.ts, src/lib/agent-sync.test.ts, .genie/wishes/routing-delivery-fix/WISH.md
Claude role agents use per-file manifests, digest checks, atomic transactions, backups, and generation-safe locks.
Role-agent diagnosis and uninstall lifecycle
src/genie-commands/doctor.ts, src/genie-commands/uninstall.ts, src/genie-commands/*test.ts
Doctor reports per-file delivery states, while uninstall removes managed agents transactionally and preserves modified or durable state.
Release metadata and supporting validation
package.json, plugins/*, .claude-plugin/marketplace.json, .genie/*
Release versions are updated consistently, planning status is recorded, and corrupt tarball extraction is covered by regression testing.

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

Possibly related PRs

  • automagik-dev/genie#2542: Overlaps the agent-sync implementation and its doctor, update, install, and uninstall integration points.
  • automagik-dev/genie#2583: Contains the same flat-agent synchronization, doctor classification, and uninstall transaction areas.
  • automagik-dev/genie#2584: Overlaps the release guard, transactional installer, and release verification changes.

Suggested reviewers: automagik-genie, github-actions[bot]

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague to describe the major changes in this PR. Rename it to reflect the main change, such as release security gating, agent sync changes, or install/verification hardening.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 dev

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.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request implements robust security gates for stable releases and a routing delivery fix for Claude role agents. Key enhancements include transactional binary promotion and rollback in the installer, workflow dispatch validation guards, and flat-agent file synchronization with a directory-level manifest. Additionally, the uninstallation and diagnostic commands have been extended to support flat agents under a shared sync lock. Feedback on the changes highlights a potential temporary file leak in the release guard script due to late evaluation of a local variable in an EXIT trap, as well as a Windows compatibility issue in the uninstallation script caused by colons in the backup folder timestamp.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/release-guard.sh
Comment on lines +135 to +136
# ${tmp:-} because the EXIT trap outlives this function's local under set -u.
trap 'rm -f "${tmp:-}"' EXIT

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.

medium

In Bash, an EXIT trap defined inside a function with single quotes evaluates its variables at script exit time (when the function has already returned and its local variables are out of scope). Because tmp is declared as local, it will be empty when the trap runs, causing the temporary file to leak. Using double quotes ensures the path is expanded and captured immediately when the trap is defined.

Suggested change
# ${tmp:-} because the EXIT trap outlives this function's local under set -u.
trap 'rm -f "${tmp:-}"' EXIT
# Evaluate the trap command immediately to capture the temp file path before the local variable goes out of scope.
trap "rm -f '${tmp}'" EXIT

/** Lazily allocate one exclusive backup generation and persist the exact validated bytes. */
function createAgentFileBackup(targets: AgentSyncRemovalTargets): (name: string, bytes: Buffer) => string {
const genieHome = targets.genieHome ?? resolveGenieHome();
const stamp = (targets.now ?? (() => new Date()))().toISOString();

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.

medium

The ISO string returned by toISOString() contains colons (:), which are invalid characters in folder and file names on Windows. This will cause allocateExclusiveBackupRoot to fail when running on Windows. Sanitize the timestamp by replacing colons and dots with hyphens, similar to how it is handled in agent-sync.ts.

Suggested change
const stamp = (targets.now ?? (() => new Date()))().toISOString();
const stamp = (targets.now ?? (() => new Date()))().toISOString().replace(/[:.]/g, '-');

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b5242d444

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread install.sh Outdated
Comment on lines +526 to +528
rm -rf "${bin:?}/${base}"
mv "$entry" "${bin}/${base}"
done < <(find "$staging" -mindepth 1 -maxdepth 1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep sidecars staged until binary promotion commits

This loop replaces VERSION, plugins, skills, etc. before the atomic genie rename. If the installer is interrupted or the promotion fails after these moves but before the binary rename, the old executable remains live with the new sidecars; because the compiled binary reads VERSION beside process.execPath, genie --version and runtime plugin/skill loading can reflect a partially promoted release even though the binary was not swapped. Sidecars need to be committed/rolled back with the binary rather than updated in this pre-commit window.

Useful? React with 👍 / 👎.

Comment thread src/genie-commands/doctor.ts Outdated
if (present) return inSource ? 'present-unmanaged' : null;
return inSource ? 'missing-from-target' : null;
}
if (!present) return inSource ? 'missing-from-target' : null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Report absent manifest-owned agents as stale

When a .genie-sync.json entry names an agent that is no longer in the source set and the target file is absent, this returns null; classifyRoleAgents then drops the manifest entry, and roleAgentSummary can report pass/"no genie role agents detected" even though stale manifest ownership still exists and sync/uninstall has cleanup work. Manifest-owned missing orphans should be surfaced as stale instead of hidden.

Useful? React with 👍 / 👎.

…side it

unlinkExactOwnedLockFile created its owner-capture quarantine as a child of
the lock directory (mkdtempSync(join(lockPath, '.owner-quarantine-'))). Under
simultaneous stale-lock steals, a losing stealer's transient quarantine subdir
made the winner's removeEmptyLockGeneration(lockPath) rmdir fail ENOTEMPTY, so
stealStaleAgentLock returned 'contended', acquireAgentMutationLock returned
null, and the rightful winner skipped — leaving an orphaned lock directory and
sometimes zero winners (regression introduced by 2315671). The same child
placement was a latent liveness edge: a crash between the rename and cleanup
left a .owner-quarantine-* child that made inspectLockObject classify the lock
'foreign' (readdirSync length check), a permanent un-stealable skip.

Relocate the quarantine to a sibling of the lock dir (${lockPath}.owner-
quarantine-), mirroring the existing `.stage-` sibling. Concurrent stealers can
never make the lock dir non-empty, so rmdir(lockPath) and inspectLockObject are
unaffected. Cleanup is unchanged: removeEmptyDirSafe(quarantineDir) already runs
on every exit path (success, mismatch, rename-ENOENT/throw) independent of
lockPath removal, so the sibling is swept the same way. ENOENT handling for the
owner-already-gone case is preserved.

Gate: 20/20 consecutive isolated "simultaneous stale-lock steals" runs, full
agent-sync.test.ts (216), full src/lib (756), typecheck, and biome all pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/agent-sync.ts (1)

551-679: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Flat-agent manifest digest is never validated as sha256-hex, unlike the workflow manifest and skill/workflow identities. readWorkflowManifest rejects a manifest whose digest fails /^[a-f0-9]{64}$/ as corrupt, but parseAgentFilesManifest only checks typeof entry.digest === 'string'. The uninstall batch's identity schema mirrors this gap instead of tightening it.

  • src/lib/agent-sync.ts#L551-L679: add !/^[a-f0-9]{64}$/.test(entry.digest) to the rejection condition in parseAgentFilesManifest so a malformed digest is treated as an unsafe/foreign manifest, not silently accepted as managed.
  • src/genie-commands/uninstall.ts#L95-L137: once the manifest enforces the format, change agentOwnedDigestSchema to reuse digestSchema instead of z.string().min(1).max(256), matching the skill/workflow identity variants in agentAssetIdentitySchema.
🤖 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/lib/agent-sync.ts` around lines 551 - 679, The flat-agent manifest
accepts malformed digests and the uninstall schema uses a weaker format. In
src/lib/agent-sync.ts lines 551-679, update parseAgentFilesManifest to reject
entry.digest unless it matches the 64-character lowercase SHA-256 hex format; in
src/genie-commands/uninstall.ts lines 95-137, change agentOwnedDigestSchema to
reuse digestSchema, matching the skill and workflow identity variants.
🤖 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/release.yml:
- Line 75: Update the actions/checkout@v5 step in the release workflow to set
persist-credentials to false, while leaving the accepted tag-pinning
configuration unchanged.

In @.github/workflows/sign-attest.yml:
- Line 83: Update the actions/checkout step in the sign-attest workflow to
reference the immutable commit 93cb6efe18208431cddfb8368fd83d5badbf9bfd instead
of the mutable v5 tag.

In `@install.sh`:
- Around line 485-547: Update promote_staged_install and rollback_binary to
preserve and restore the complete live sidecar tree, not only the genie
executable. Before moving staged entries, back up existing sidecars in a
dedicated rollback location; on any promotion or verification failure, restore
that tree alongside the previous binary, including entries already moved before
the failure. Ensure failed sidecar operations do not leave a mixed-version
installation.

In `@scripts/verify-release.sh`:
- Around line 116-118: Replace the GNU-only readlink -f usage in the local
tarball path handling with a portable absolute-path resolution method that works
on macOS and other supported platforms. Preserve the existing file-existence
check and exit behavior for the resolved path.

In `@src/genie-commands/doctor.ts`:
- Line 896: Update the status logic around the `present` check in `doctor.ts` so
an entry absent from both source and target is reported as `stale` rather than
`null`, preventing a false pass. Add a fixture covering an orphaned manifest
entry with neither source nor target file.

---

Outside diff comments:
In `@src/lib/agent-sync.ts`:
- Around line 551-679: The flat-agent manifest accepts malformed digests and the
uninstall schema uses a weaker format. In src/lib/agent-sync.ts lines 551-679,
update parseAgentFilesManifest to reject entry.digest unless it matches the
64-character lowercase SHA-256 hex format; in src/genie-commands/uninstall.ts
lines 95-137, change agentOwnedDigestSchema to reuse digestSchema, matching the
skill and workflow identity variants.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 3a4e56c5-189d-4a93-bab1-538ba647d79c

📥 Commits

Reviewing files that changed from the base of the PR and between b362e9c and 1b5242d.

📒 Files selected for processing (30)
  • .claude-plugin/marketplace.json
  • .genie/INDEX.md
  • .genie/brainstorms/stable-release-security-gate/DRAFT.md
  • .genie/wishes/routing-delivery-fix/WISH.md
  • .genie/wishes/stable-release-security-gate/WISH.md
  • .genie/wishes/stable-release-security-gate/qa/github-settings-evidence-20260714.json
  • .github/workflows/build-tarballs.yml
  • .github/workflows/ci.yml
  • .github/workflows/release-publish.yml
  • .github/workflows/release.yml
  • .github/workflows/sign-attest.yml
  • .github/workflows/version.yml
  • install.sh
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/.codex-plugin/plugin.json
  • plugins/genie/package.json
  • plugins/hermes-genie/plugin.yaml
  • scripts/install-swap.test.ts
  • scripts/release-guard.sh
  • scripts/release-guard.test.ts
  • scripts/verify-release.sh
  • scripts/verify-release.test.ts
  • src/genie-commands/__tests__/update.test.ts
  • src/genie-commands/doctor.test.ts
  • src/genie-commands/doctor.ts
  • src/genie-commands/uninstall.test.ts
  • src/genie-commands/uninstall.ts
  • src/lib/agent-sync.test.ts
  • src/lib/agent-sync.ts

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/sign-attest.yml Outdated
Comment thread install.sh Outdated
Comment thread scripts/verify-release.sh
Comment thread src/genie-commands/doctor.ts Outdated
namastex888 and others added 3 commits July 14, 2026 14:39
…ew-followups

fix(agent-sync): preserve no-replace delivery boundaries
…antine

fix(agent-sync): quarantine owner capture beside the lock dir, not inside it

@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: 13

🤖 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 @.genie/wishes/routing-delivery-fix/WISH.md:
- Around line 61-63: Update the recovery instructions in WISH.md, including the
referenced occurrences, to identify ~/.genie-recovery/ as the location for
sync-adoption backups. Keep ~/.genie/state-backups/ reserved for uninstall
backups and preserve the existing adoption and managed-stamp requirements.

In @.github/workflows/build-tarballs.yml:
- Line 94: Update the actions/checkout steps in
.github/workflows/build-tarballs.yml:94-94,
.github/workflows/release-publish.yml:113-113, and
.github/workflows/release.yml:75-75 to pin each action to an approved commit SHA
and configure with.persist-credentials as false.

In @.github/workflows/sign-attest.yml:
- Around line 82-83: Update both checkout steps in the workflow to pin
actions/checkout to an immutable commit SHA instead of the mutable v5 tag, and
set persist-credentials to false for each step.

In @.github/workflows/version.yml:
- Around line 158-161: Update the bun-version value in the version workflow’s
setup-bun step from 1.3.10 to 1.3.11, keeping the pinned Bun version consistent
with the other workflows.

In `@install.sh`:
- Around line 504-547: The promote_staged_install flow must roll back sidecars
together with the binary when promotion is interrupted or verification fails.
Snapshot the complete bin installation before the sidecar loop, restore that
snapshot on the before-promote fault and any post-swap verification failure, and
update rollback handling/messages so the entire installation is reverted
consistently rather than only ${bin}/genie.

In `@src/genie-commands/doctor.ts`:
- Around line 848-858: Update sourceAgentDigests to preserve read failures
instead of swallowing them, and ensure missing or unreadable canonical agent
files are represented in the doctor result. Adjust the empty-set handling near
the doctor health check so an empty canonical role-agent set emits a warning and
cannot be reported as healthy, while retaining normal digest behavior for
readable files.
- Line 896: Update the missing-entry handling in the manifest comparison logic
around the present check so an entry absent from both source and target is
reported as stale rather than returning null. Preserve the existing
missing-from-target result for source-present entries and ensure every managed
RoleAgentDelivery.files entry receives a status.

In `@src/genie-commands/uninstall.ts`:
- Around line 927-929: Update collectManagedAgentFiles to use
readAgentFilesManifestState instead of readAgentFilesManifest, distinguish
absent and foreign manifests from unsafe ones, and propagate an unsafe state as
a preflight/removal failure rather than treating it as no assets. Ensure full
uninstall cannot report success or remove Genie’s source when manifest-owned
Claude agents may remain loaded.
- Around line 1791-1797: Replace the direct console.log calls in
reportFlatAgentRemoval and the additionally referenced output sections with the
repository’s CLI output abstraction or process.stdout.write wrapper. Preserve
the existing messages, formatting, and output order while ensuring no
console.log usage remains in these source paths.

In `@src/lib/agent-sync.test.ts`:
- Around line 2249-2255: Update the legacy lock fixture in the test “a stale
legacy regular-file lock is captured safely and upgraded” so the written owner
record matches the format accepted by parseLockOwner(), while remaining stale
for the liveness check. Keep the test focused on upgrading a valid legacy lock
rather than malformed lock debris.

In `@src/lib/agent-sync.ts`:
- Around line 3546-3548: Update the state.published assignment in the stage
commit flow to build the snapshot from stage.bytes and the staged inode
identity, rather than rereading targetPath via captureAgentPathSnapshot.
Preserve the existing state.delta update while ensuring post-link in-place edits
conflict with op.entry.digest during verification.
- Around line 3969-3984: Update the agent synchronization flow around
runFlatAgentTransaction so the foreign-manifest backup uses the transaction’s
authoritative base snapshot rather than the earlier inspectAgentFilesManifest
result. Ensure any foreign manifest present when the transaction captures its
base is backed up exactly before a successful commit can replace it, and avoid
consuming a manifest that was not backed up.
- Around line 666-676: Update the manifest parsing logic around the files-entry
validation in the agent-sync flow to reject malformed ownership entries rather
than normalize them. Require digest, version, and syncedAt to be present strings
with valid values, returning null when any field is missing or invalid; only
construct AgentFileManifestEntry after all validation succeeds.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 3a4e56c5-189d-4a93-bab1-538ba647d79c

📥 Commits

Reviewing files that changed from the base of the PR and between b362e9c and 1b5242d.

📒 Files selected for processing (30)
  • .claude-plugin/marketplace.json
  • .genie/INDEX.md
  • .genie/brainstorms/stable-release-security-gate/DRAFT.md
  • .genie/wishes/routing-delivery-fix/WISH.md
  • .genie/wishes/stable-release-security-gate/WISH.md
  • .genie/wishes/stable-release-security-gate/qa/github-settings-evidence-20260714.json
  • .github/workflows/build-tarballs.yml
  • .github/workflows/ci.yml
  • .github/workflows/release-publish.yml
  • .github/workflows/release.yml
  • .github/workflows/sign-attest.yml
  • .github/workflows/version.yml
  • install.sh
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/.codex-plugin/plugin.json
  • plugins/genie/package.json
  • plugins/hermes-genie/plugin.yaml
  • scripts/install-swap.test.ts
  • scripts/release-guard.sh
  • scripts/release-guard.test.ts
  • scripts/verify-release.sh
  • scripts/verify-release.test.ts
  • src/genie-commands/__tests__/update.test.ts
  • src/genie-commands/doctor.test.ts
  • src/genie-commands/doctor.ts
  • src/genie-commands/uninstall.test.ts
  • src/genie-commands/uninstall.ts
  • src/lib/agent-sync.test.ts
  • src/lib/agent-sync.ts

Comment thread .genie/wishes/routing-delivery-fix/WISH.md Outdated
Comment thread .github/workflows/build-tarballs.yml Outdated
Comment thread .github/workflows/sign-attest.yml Outdated
Comment thread .github/workflows/version.yml Outdated
Comment on lines 158 to 161
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.10"

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

Update bun-version to "1.3.11".

This workflow pins Bun to 1.3.10, while ci.yml and build-tarballs.yml have been updated to 1.3.11. Keep the version consistent across all workflows to prevent lockfile discrepancies and behavior drift.

♻️ Proposed fix
-      - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
+      - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
         with:
-          bun-version: "1.3.10"
+          bun-version: "1.3.11"
📝 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
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.10"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.11"
🤖 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 @.github/workflows/version.yml around lines 158 - 161, Update the bun-version
value in the version workflow’s setup-bun step from 1.3.10 to 1.3.11, keeping
the pinned Bun version consistent with the other workflows.

Comment thread install.sh Outdated
Comment on lines +1791 to +1797
function reportFlatAgentRemoval(removal: AgentSyncRemovalResult): void {
for (const path of removal.removed) {
console.log(` \x1b[32m+\x1b[0m Removed managed flat agent: ${contractPath(path)}`);
}
for (const path of removal.kept.filter((path) => !removal.identityMismatch.includes(path))) {
console.log(` \x1b[33m!\x1b[0m Preserved modified flat agent at ${contractPath(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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Route new output through the CLI output abstraction.

Replace these direct console.log calls with the repository’s output sink or process.stdout.write wrapper.

As per coding guidelines, src/**/*.ts: Do not use console.log in source code.

Also applies to: 2304-2310, 2397-2411

🤖 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/genie-commands/uninstall.ts` around lines 1791 - 1797, Replace the direct
console.log calls in reportFlatAgentRemoval and the additionally referenced
output sections with the repository’s CLI output abstraction or
process.stdout.write wrapper. Preserve the existing messages, formatting, and
output order while ensuring no console.log usage remains in these source paths.

Source: Coding guidelines

Comment thread src/lib/agent-sync.test.ts
Comment thread src/lib/agent-sync.ts Outdated
Comment thread src/lib/agent-sync.ts Outdated
Comment thread src/lib/agent-sync.ts

@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/lib/agent-sync.ts`:
- Around line 2215-2232: Update atomicRenameRegularFileNoClobber to reuse a
module-scoped Darwin renamex_np symbol initialized once via dlopen, rather than
opening and closing libSystem.B.dylib on every publish. Preserve the existing
invocation, result handling, and cleanup behavior while removing the per-call
dlopen/close path.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 17530077-3637-4969-939d-9805149ff9b0

📥 Commits

Reviewing files that changed from the base of the PR and between 1b5242d and e594af9.

📒 Files selected for processing (9)
  • .claude-plugin/marketplace.json
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/.codex-plugin/plugin.json
  • plugins/genie/package.json
  • plugins/hermes-genie/plugin.yaml
  • src/genie-commands/uninstall.test.ts
  • src/lib/agent-sync.test.ts
  • src/lib/agent-sync.ts

Comment thread src/lib/agent-sync.ts Outdated

@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/genie-commands/uninstall.test.ts`:
- Around line 1109-1134: Update performUninstall’s genieDir removal branch to
revalidate the current directory identity immediately before deleting it, rather
than relying only on the earlier hasRemovableGenieDir decision. Ensure a foreign
replacement swapped in while the lock is held is preserved, and extend the
uninstall test to exercise the hasGenieDir = true path while retaining the
existing identity and lock assertions.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 133074ec-57dd-4cea-a767-f6873cb9f539

📥 Commits

Reviewing files that changed from the base of the PR and between e594af9 and 1eb1955.

📒 Files selected for processing (10)
  • .claude-plugin/marketplace.json
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/.codex-plugin/plugin.json
  • plugins/genie/package.json
  • plugins/hermes-genie/plugin.yaml
  • src/genie-commands/uninstall.test.ts
  • src/genie-commands/uninstall.ts
  • src/lib/agent-sync.test.ts
  • src/lib/agent-sync.ts
💤 Files with no reviewable changes (1)
  • src/genie-commands/uninstall.ts

Comment thread src/genie-commands/uninstall.test.ts
namastex888 and others added 4 commits July 14, 2026 23:24
gh release download inherited runCommandSilent's 4s default while pulling a
37MB+ platform tarball; genie update v5.260714.8 timed out at 4000ms on a
healthy connection (2026-07-14) on both dev and stable channels. The verify
steps got dedicated timeouts after the identical May incident (PR #2421) —
the download now gets the same treatment, pinned by the existing runner-seam
test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(update): give the release download its own 5-minute timeout
@socket-security

socket-security Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedmarkdown-link-check@​3.14.29910010082100
Addedmarkdownlint-cli2@​0.23.09910010089100

View full report

@socket-security

socket-security Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm cheerio is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ? → npm/markdown-link-check@3.14.2 → npm/cheerio@1.2.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/cheerio@1.2.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm validator is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ? → npm/markdown-link-check@3.14.2 → npm/validator@13.15.35

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/validator@13.15.35. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

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