#19482: fix(agents): only seed HEARTBEAT.md on brand-new workspaces
agents
size: XS
Cluster:
Heartbeat Functionality Improvements
## Problem
`ensureAgentWorkspace()` creates HEARTBEAT.md for every workspace missing the file — including existing workspaces where the user intentionally removed it. The empty template was designed as a heartbeat blocker for fresh installs; without it, the heartbeat runs without guidance and the agent is left to figure out what to do on its own.
This was introduced in #12027 which removed HEARTBEAT.md creation entirely. The intended behavior (from #11807) is to only create it on brand-new workspaces.
## Fix
Gate `writeFileIfMissing(heartbeatPath, ...)` behind the existing `isBrandNewWorkspace` check. Only genuinely new workspaces receive the template. Existing workspaces that deliberately removed the file no longer have it recreated on every session start.
## Tests
Two new e2e tests in `workspace.e2e.test.ts`:
- `creates HEARTBEAT.md for brand-new workspaces` — verifies the template is still seeded for fresh installs
- `does not create HEARTBEAT.md for existing workspaces that lack it` — verifies the file is not recreated when a user removed it
All 10 workspace tests pass.
Fixes #16065
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR correctly fixes a regression where `HEARTBEAT.md` was being recreated for every workspace that lacked the file — including existing workspaces where the user had intentionally removed it. The fix is minimal and well-targeted: `writeFileIfMissing(heartbeatPath, heartbeatTemplate)` is now guarded by the existing `isBrandNewWorkspace` check, consistent with how `ensureGitRepo` is already gated.
**Key changes:**
- `src/agents/workspace.ts`: `HEARTBEAT.md` creation is now inside `if (isBrandNewWorkspace)` (line 317). The underlying `isBrandNewWorkspace` computation already includes `heartbeatPath` in its six-file check (line 289), so a workspace where all other files exist but `HEARTBEAT.md` was deleted will correctly evaluate to `false` — the fix is logically sound.
- `src/agents/workspace.e2e.test.ts`: Two new tests added — one confirming `HEARTBEAT.md` is seeded on fresh installs, one confirming it isn't recreated on existing workspaces. The second test's setup only pre-writes two of the six core files, which means it doesn't precisely model the described scenario (a fully-initialized workspace that had `HEARTBEAT.md` removed), though it still exercises the correct code path.
- One minor style note: `heartbeatTemplate` is unconditionally loaded (line 308) even when `isBrandNewWorkspace` is `false`, though this is low-impact given the in-process template cache.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge; the change is a narrow, well-scoped guard around an existing code path with no risk of data loss or behavioral regression.
- The fix is a one-line conditional guard that only restricts behavior (prevents HEARTBEAT.md recreation on existing workspaces) — it cannot break existing workspaces. The `isBrandNewWorkspace` check already included `heartbeatPath`, ensuring the logic handles the user-deleted-HEARTBEAT.md case correctly. Two new e2e tests cover both the positive and negative path. The test for the "existing workspace" scenario is slightly under-specified but still validates the correct outcome.
- No files require special attention; the test setup in `workspace.e2e.test.ts` for the "existing workspace" scenario could be more precise but does not affect correctness.
<sub>Last reviewed commit: acc511a</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#11807: fix: Make HEARTBEAT.md creation match documentation
by HenryLoenwind · 2026-02-08
87.3%
#22917: fix: Use agent's configured workspace when spawned as subagent
by jriff · 2026-02-21
76.3%
#12786: fix: drop heartbeat runs that arrive while another run is active
by mcaxtr · 2026-02-09
75.7%
#17488: fix(agents): skip workspace deletion when shared with other agents
by soumikbhatta · 2026-02-15
74.7%
#2884: fix: Create memory directory and symlink identity files during work...
by webdevtodayjason · 2026-01-27
74.5%
#19406: fix(heartbeat): filter error payloads from heartbeat reply selection
by namabile · 2026-02-17
74.0%
#19745: fix(heartbeat): enforce interval check regardless of trigger source
by misterdas · 2026-02-18
73.9%
#13577: fix(onboard): validate workspace directory before setup steps
by mcaxtr · 2026-02-10
73.8%
#21553: fix: resolve workspace template dir in bundled dist/ layout
by echoVic · 2026-02-20
73.6%
#12365: test(heartbeat): don't skip empty HEARTBEAT.md for cron wake events
by tyclaudius-ai · 2026-02-09
73.5%