* test(scm): end-to-end integration coverage for SCM observer (#109)
Adds backend/internal/integration/scm_observer_test.go, the regression
guard for the SCM observer wiring landed in PR #114. Drives
scmobserve.Observer.Poll against a real sqlite.Store, a real
lifecycle.Manager with a recording messenger spy, and a canned
observe/scm.Provider, asserting the full observation -> reducer ->
store -> messenger pipeline.
Three table-driven subtests, each on its own tmpdir fixture:
- A CI-failing observation persists the pr row (provider-neutral
columns + semantic hashes), persists pr_checks mirroring the
observation, delivers exactly one nudge with the failed-log tail,
persists last_nudge_signature, and produces no additional nudge on
an identical re-poll.
- A Merged: true observation MarkTerminated's the session and sends
no nudge.
- A branch with no open PR writes nothing and sends no nudge.
Closes#109
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(scm): address review — drop string key indirection, document idempotency path
- Key cannedSCMProvider.observations/reviews by PR number directly so
the fake no longer carries a string key that resembled (but did not
actually need to mirror) the observer's internal prKey. Every case
in this test uses scmTestRepo, so number alone is unambiguous.
- Add an explicit pointer in the CI-failing subtest noting it
exercises the hash-match short-circuit in prepareForPersistence;
the ETag-driven 304 short-circuit on the same SHA is covered by
observe/scm/observer_test.go (Poll_RepoETag304SkipsDetectPR,
Poll_CIETagChangeRefreshesWhenRepoUnchanged).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>