Skip to content

Honor external edits to heartbeat-tasks.json / 心跳任务文件的外部编辑不再丢失#6131

Merged
SivanCola merged 1 commit into
esengine:main-v2from
SivanCola:fix/heartbeat-external-edit-adoption
Jul 6, 2026
Merged

Honor external edits to heartbeat-tasks.json / 心跳任务文件的外部编辑不再丢失#6131
SivanCola merged 1 commit into
esengine:main-v2from
SivanCola:fix/heartbeat-external-edit-adoption

Conversation

@SivanCola

Copy link
Copy Markdown
Collaborator

Summary

heartbeat-tasks.json is documented as human- and AI-editable (the file header in desktop/heartbeat.go and the heartbeat panel tip: "AI agents can also edit heartbeat-tasks.json"), but the engine only half-honored that contract:

Changes

  • mergeRunUpdatesLocked rebases onto the on-disk list before its full-list save. The engine owns only the run-state fields (TopicID, LastRunAt, CreatedAt backfill); task definitions added, edited, or deleted externally are adopted from disk, so the save can no longer roll an external edit back. A missing/unreadable file falls back to the in-memory list (historical behavior, and what the existing concurrent-edit test pins).
  • tick() probes the config file's mtime and adopts external edits before scheduling, so an agent-added task runs on the next 30s tick instead of waiting for Refresh/restart. The engine records the mtime after its own writes (Start/ReloadTasks/ReplaceTasks/merge) so it does not re-read files it just wrote.
  • ReplaceTasks (the UI panel save) keeps its whole-list semantics: saving what the panel shows is the user's explicit intent.

New regressions: external edit + addition survive a run-state save (in memory and on disk), and a tick adopts an externally added task (mtime forced forward so coarse filesystem timestamps cannot flake).

Validation

  • cd desktop && go test . (heartbeat suite incl. the 2 new regressions) and full go test ./... — green
  • go vet . / gofmt — clean
  • Existing TestHeartbeatMergeRunUpdatesPreservesConcurrentEditsAndDeletes still passes unchanged (missing-file fallback preserves its semantics)

Follow-up to the review discussion on #6123 (the guard correctly stopped hard-blocking this file; this PR makes the advertised editability actually work).

heartbeat-tasks.json is documented as human- and AI-editable (file
header + the heartbeat panel tip), but the engine loaded it once at
startup and then treated its in-memory copy as the source of truth:

- an externally added task was never scheduled until a manual Refresh
  or an app restart, and
- any run-state save (mergeRunUpdatesLocked writes the full list after
  a task fires) silently rolled the external edit back — the same
  "my write did not take" shape the session-data guard exists for,
  except here the product explicitly invites the edit.

Two changes make the contract real:

- mergeRunUpdatesLocked now rebases onto the on-disk list before its
  full-list save: the engine owns only the run-state fields (TopicID,
  LastRunAt, CreatedAt backfill), so external additions, edits, and
  deletions survive the save. A missing/unreadable file falls back to
  the in-memory list, preserving the historical behavior (and the
  existing concurrent-edit test).
- tick() probes the config mtime and adopts external edits before
  scheduling, so an agent-added task runs on the next tick. The engine
  records the mtime after its own writes to avoid re-reading them.
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) labels Jul 6, 2026
@SivanCola SivanCola marked this pull request as ready for review July 6, 2026 23:13
@SivanCola SivanCola requested a review from esengine as a code owner July 6, 2026 23:13
@SivanCola SivanCola merged commit f8bef2a into esengine:main-v2 Jul 6, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant