feat(halt-self-feedback): M003 S03 — HaltWatchdog self-feedback integration

T01: Added integration test auto-halt-self-feedback.test.mjs that proves:
  - HaltWatchdog.check() creates a self-feedback DB entry with
    kind=runaway-loop:idle-halt, severity=high, blocking=true
  - Markdown projection (.sf/SELF-FEEDBACK.md) is regenerated
  - Deduplication works (one entry per idle period)
  - New heartbeat resets and creates a new entry for the next idle period

T02: Enhanced evidence string to include elapsedMs, iteration, and
thresholdMs explicitly (R003 actionable context requirement).

Tests: 36/36 pass across auto-halt-self-feedback,
auto-halt-watchdog-notify, and self-feedback-db suites.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mikael Hugo 2026-05-15 18:19:39 +02:00
parent 5cd5e14160
commit 6a2c61d5ee
2 changed files with 3 additions and 1 deletions

View file

@ -175,7 +175,7 @@ export class HaltWatchdog {
kind: "runaway-loop:idle-halt",
severity: "high",
summary: `Autonomous loop stuck — no heartbeat for ${Math.round(elapsedMs / 1000)}s at iteration ${iteration}`,
evidence: `Last heartbeat at ${new Date(this.lastActionTimestamp).toISOString()}; threshold ${this.thresholdMs}ms`,
evidence: `Last heartbeat at ${new Date(this.lastActionTimestamp).toISOString()}; elapsed ${elapsedMs}ms; threshold ${this.thresholdMs}ms; iteration ${iteration}`,
},
this.basePath,
);

View file

@ -65,7 +65,9 @@ test("HaltWatchdog.check()_when_idle_exceeds_threshold_creates_self_feedback_db_
assert.equal(entries[0].blocking, true);
assert.match(entries[0].summary, /iteration 42/);
assert.match(entries[0].summary, /no heartbeat for/);
assert.match(entries[0].evidence, /elapsed/);
assert.match(entries[0].evidence, /threshold 10ms/);
assert.match(entries[0].evidence, /iteration 42/);
const markdownPath = join(testDir, ".sf", "SELF-FEEDBACK.md");
assert.equal(existsSync(markdownPath), true);