feat(senpi): OmO-native (senpi) attach/observe adapter - #4
Conversation
|
@greptile-apps review |
|
@greptile-apps review |
|
@greptile-apps review |
| if (leftoverIds.length === 0 && leftoverRootKeys.length === 0) { | ||
| rmSync(statePath, { force: true }); | ||
| return { path: statePath, id, removed: existed }; |
There was a problem hiding this comment.
Stale remover deletes replacement state
The empty-state removal path calls rmSync without checking that its lease is still held. If this writer stalls after the renewal at line 337, another writer can reclaim the expired lease and save a new trust entry. When the original callback resumes, it deletes that replacement writer’s hooks-state.json. Renew or assert ownership immediately before deleting the state file so a reclaimed writer fails instead of removing newer trust data.
Artifacts
Authored reclaimed-lease deletion repro source
- The test copies source into a temporary sandbox, pauses only the original remover before its empty-state deletion, ages and reclaims its token, commits a replacement entry, and resumes deletion, with the takeaway.
Observed reclaimed-lease repro output
- The executed repro output confirms writer 2’s replacement state existed before resume and was absent after the original remover resumed, with the takeaway.
…s-owner mtime writes
…restore tail dual gate and schedule coverage
|
@greptile-apps review |
| await lease.renew(); | ||
| rmSync(statePath, { force: true }); |
There was a problem hiding this comment.
Lease expiry deletes replacement state
If the removing writer is descheduled longer than staleMs after the final lease.renew(), another writer can reclaim the lease and commit replacement trust state before this callback resumes. This unconditional rmSync then deletes the replacement writer's hooks-state.json, losing newly committed trust entries. Assert the lease is still held immediately before deletion, or use a fenced deletion operation that cannot remove state written by a replacement owner.
Artifacts
Delayed-removal fixture source
- Captured source of the deterministic fixture that pauses immediately after final lease renewal and before rmSync, takeaway: it exercises the claimed timing window.
Replacement-writer helper source
- Captured source of the separate writer that reclaims the stale lease and writes replacement hooks-state.json state, takeaway: a second writer is exercised in the pause window.
Executed stale-lease replacement output
- Captured successful Vitest execution reports replacement state present before delayed rmSync and deleted afterward, takeaway: the current implementation permits the claimed schedule.
What this is
An attach-only observe adapter for OmO native (senpi) coding sessions, plus everything the first public release of this package needed to be safe to consume: the 0.3.0 release contract, shared processing mechanics, and a security hardening pass from the 2026-08-28 review. 77 commits over
main, atca3e4de.This PR pairs with Cockpit PR #9. Cockpit consumes this branch through a git pin and its OmO adapter is built directly on the exports here, so the two diffs should be read together.
The senpi adapter
The adapter attaches to existing sessions; it never spawns, resumes, or drives an agent. Surfaces:
./senpiand./senpi/processingas exact barrel subpaths: session v3 Zod contracts, agent-home resolution, discovery with header-cwd verification, tree-linear projection with compaction handling (retainedTail plus legacy firstKeptEntryId), a bounded JSONL cursor with revisioned checkpoints, tail with splice mutations, watch with stable-cursor quiescence, and native block reduce/fold.docs/upstream/senpi/with two-directional drift tests in CI, plus the adapter reference doc and the live-store smoke probe (pnpm senpi:smoke).Release preparation
StaleCheckpointConflictcarries structured revision data instead of callers matching on error prose. A contract test pins its shape (name, constructor fields,isStaleCheckpointConflict) as a cross-repo contract, because Cockpit matches on it.src/internal/after fixtures locked both adapters' semantic output. Tails now read from the checkpoint rather than byte zero, and unchanged polls return without reprojection. The senpi and grok semantic parsers stay separate.Security hardening from the review
The Greptile review ran on this branch with no untriaged security or P0/P1 findings.
Pairing with Cockpit
Cockpit PR #9 pins
github:libar-dev/agent-harness-kit#ca3e4deand consumes./senpi,./senpi/processing, and./grok/processingthrough dynamicimport()only (the kit is ESM-only; Cockpit's main bundle is CJS). Where Cockpit needs to match a thrown conflict, it does so through the pinnedStaleCheckpointConflictname contract rather than importing the class, so neither repo's internals leak into the other. The prepack order tolerates archive contexts (a codeload tarball has no.git), which is what makes the pin installable from a clean checkout.Verification
pnpm run build && pnpm run check && pnpm run test:runall exit 0, and Cockpit's clean install against the pin reproducibly builds (pnpm install && pnpm typecheck && pnpm buildfrom wiped node_modules on the Cockpit side).Scope guards
No runtime dependency on senpi/OmO packages, no imports from grok or Claude internals, no
auth.jsonreads, no new runtime npm dependencies, cursor and marker internals unexported, root barrel untouched.Merge gate
Do not merge until Cockpit PR #9 has landed and been tested against this pin. Intended order: Cockpit #8, Cockpit #9, then this PR. After merge, publication of 0.3.0 to npm remains a separate owner decision.
Greptile Summary
The change expands the Senpi integration with incremental processing, hook trust management, shared lease locking, package-consumer checks, and immutable CI action references. However, removing the final trust entry can delete trust state that a replacement writer committed after reclaiming an expired lease.
Confidence Score: 4/5
Not merge-safe until trust-state deletion verifies that its lease is still held at the deletion commit point.
One accepted P1 non-security finding remains: an expired removing writer can delete a replacement writer's newly committed trust state. The score for one non-security P1 finding is 4.
Files Needing Attention: src/senpi/trust-writer.ts
What T-Rex did
Reviews (5): Last reviewed commit: "fix(senpi): renew trust lease at the des..." | Re-trigger Greptile