Files
PaperClipAI/server
Nicky LeachandPaperclip 47aef634e5 Add branch incoherence containment (#9131)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run inside git worktrees; the heartbeat system establishes a
workspace branch and tracks it through checkout, realization, restore,
and finalization
> - When the live git branch diverges from the recorded workspace branch
mid-change (branch incoherence), the heartbeat must fail closed with
`workspace_validation_failed` and block the source issue with a recovery
action
> - There were no embedded-Postgres tests covering this fail-closed
behavior across the three interlock call sites: fresh git-worktree
realization, persisted workspace restore, and heartbeat finalization
> - This PR adds a single test file covering all three call sites with
an embedded-Postgres heartbeat test harness and asserts the exact
fail-closed outcome and evidence fields
> - The benefit is confidence that branch-incoherence containment is
correct and regressions in the interlock chain are caught before they
silently corrupt workspace state

## Linked Issues or Issue Description

Refs: #6425 (related: enforce issue branch matches workspace on
wake/checkout)

No pre-existing public GitHub issue for this specific reproduction test
gap. The underlying problem:

**Bug / gap:** The heartbeat's branch-incoherence containment was
untested by any embedded-Postgres integration test. All three call sites
— fresh git-worktree realization, persisted workspace restore, and
finalization — could regress without detection. The fail-closed path
(`workspace_validation_failed` + source-issue block + deduped recovery
action) and the evidence fields surfaced to operators were unverified.

## What Changed

- Added
`server/src/__tests__/heartbeat-workspace-branch-containment.test.ts`
with embedded-Postgres integration tests covering:
- **Fresh git-worktree realization** — heartbeat detects branch
divergence at workspace setup and fails closed
- **Persisted workspace restore** — re-entering a previously-established
workspace with a diverged branch fails closed instead of being silently
coerced into a generic reuse-failure path
- **Heartbeat finalization** — any late-stage branch incoherence
detected at finalization fails closed
- Asserts fail-closed behavior in all three cases: run status =
`workspace_validation_failed`, source issue status = `blocked`, exactly
one deduped workspace-validation recovery action on the blocked issue,
sibling issues on same/other workspaces retain their status
- Asserts evidence completeness: `expectedBranch`, `liveBranch`,
`expectedHead`, `liveHead`, `cleanliness`, `ancestryVerdict`,
`plainLanguageReason`, and `recoveryGuidance` fields are present and
correct on the run
- Ensures release/promotion errors after setup failures are logged (not
silently swallowed), making cleanup failures observable

## Verification

```bash
pnpm exec vitest run server/src/__tests__/heartbeat-workspace-branch-containment.test.ts
pnpm --filter @paperclipai/server typecheck
```

All 3 tests pass, typecheck clean.

## Risks

Low. Test-only change — no production code paths are modified. The tests
use an embedded-Postgres harness and do not touch any shared or live
database.

## Model Used

Claude Sonnet 4.6 (`claude-sonnet-4-6`) via Claude Code — tool use mode,
standard context window.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-06 22:02:52 -07:00
..