test(coven): drive the released v0.4.7 daemon through the SDK client - #338
Merged
Merged
Conversation
Adds a daemon canary that installs @opencoven/cli@0.4.7 from npm at a locked integrity, starts `coven daemon serve` in an owned temporary COVEN_HOME, and drives it through the built client: draft, replay and mismatch refusal, revise and stale-revision refusal, activate, pause, and disable, with adoption replay and checkpoint resume across a daemon restart. The canary reports, without failing, that v0.4.7 lifecycle events carry the legacy routine-projection digest rather than the definition's integrity. Peer identity is harness-asserted: the canary launched the daemon under its own uid in a private home and checks that ownership. Refs #80, OpenCoven/coven#1054. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Interruption cleanup and final subscription-page validation need correction.
Review effort: Balanced
Findings: 2
Open (2)
What changed in this PR
Adds a released-daemon canary for the SDK’s Automations client, extending verification beyond stubbed transports and contract artifacts.
Changes:
- Exercises lifecycle commands, adoption replay, and checkpoint resume across daemon restart.
- Pins Coven v0.4.7 and verifies npm signatures before running the canary in CI.
- Adds regression tests and documents verification limits.
| File | Description |
|---|---|
| tests/automations-v1-daemon-canary.spec.ts | Tests pins, scenarios, security checks, and process handling. |
| scripts/verify-automations-v1-daemon.mjs | Implements the daemon canary and lifecycle management. |
| scripts/verify-automations-v1-daemon.d.mts | Declares canary interfaces and results. |
| README.md | Documents usage, coverage, and limitations. |
| package.json | Adds the canary command. |
| docs/ROADMAP.md | Records daemon-canary coverage and digest observations. |
| conformance/automations-v1-daemon/package.json | Pins the released CLI dependency. |
| conformance/automations-v1-daemon/package-lock.json | Locks CLI and platform-package integrity. |
| .github/workflows/ci.yml | Installs, authenticates, and runs the released daemon. |
Files not reviewed (1)
- conformance/automations-v1-daemon/package-lock.json: Generated file
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The daemon canary accepted a subscription that ended right after its events. It now requires the final empty page, at `after` and `nextAfter` 4 with a checkpoint, as the subscribe() contract documents. SIGINT or SIGTERM exited Node before the cleanup in `finally` ran, leaving the daemon and its owned home behind. The canary now aborts on either signal: every step races the abort, a pending restart refuses to start a daemon, and the single cleanup path stops the daemon and removes its home before exiting 130 or 143. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Refs #80, OpenCoven/coven#1054. This adds a canary that drives the released Coven v0.4.7 daemon through this SDK's built client. Until now, the SDK's command and replay behaviour was proven only against stubbed transports and the contract bundle's golden vectors.
What CI now does
The exact-runtime lane (Node 24.18.1), after
pnpm verifyhas built the packages:conformance/automations-v1-daemon/{package.json,package-lock.json}to runner temp storage.npm ci --ignore-scripts, which installs@opencoven/cli@0.4.7and its platform package at the lockedsha512integrity.npm audit signatures, which checks the registry signatures and provenance attestations.pnpm canary:automations-v1-daemon -- --coven …/bin/coven.js --expect-version 0.4.7.The canary refuses a binary that reports any other version. It starts
coven daemon servethrough the npm wrapper users run, in an owned temporaryCOVEN_HOMEwithHOME,PATH(Node,/usr/binand/bin) andNO_COLORonly. It discovers the daemon withdiscoverCovenEndpoint, then:capabilities()available, with the 11 actions the scenario usescreateDraftintegrityequalscomputeDefinitionDigest()replayedrev 1 withfirstCommittedAtrejectedADOPTION_REPLAY_MISMATCHreviseat 1reviseat 1rejectedREVISION_CONFLICT,currentRevision: 2activate,pauseget()reads back paused rev 4coven.sockanddaemon.json; rediscovery finds a new pidactivatekeyreplayedrev 3 (adoption survives the restart)disablesubscribe()from the pre-restart checkpointrevised, activated, paused, disabled(sequences 1–4), then the final empty page atafter = nextAfter = 4with its checkpointevents({ after: 2 })list(),occurrenceHistory(),runHistory()The schedule is set twelve hours from the activation hour, so nothing fires and the history assertions are deterministic. Output:
Finding: lifecycle events carry the routine-projection digest
v0.4.7 events have a different
payload.definitionDigestfrom the definition'sintegrity. Thedefinition.createdevent carries a different value. Thedefinition.revised(rev 2) anddefinition.paused(rev 4) events carry the same value. The event digest ismigration::definition_digest(definition_json), a hash of the legacy routine row, which has no revision. Occurrences copy that column (occurrences.rs), and runs and receipts carry it forward (receipts.rs).So a caller who passes a definition's
integritytoverifyReceipt()as the expecteddefinitionDigestwill getDEFINITION_DIGEST_MISMATCHagainst a v0.4.7 receipt. The contract's golden fixtures, by contrast, bind the receipt digest to the definition document'sintegrity. The canary reports this aseventDefinitionDigest=differs-from-definition-integrityrather than failing on it, so a Coven fix shows up as a changed summary. The README documents it, and the details are on Coven #1054.Limits (also in the README)
0700home and the socket belong to its uid before asserting that uid. It does not certify the SDK's Unix peer check.get()returns the legacy routine projection, not the stored rich body.Changes
scripts/verify-automations-v1-daemon.mjs+.d.mts: the canary. Failure output includes the daemon's own output. Cleanup sends SIGTERM first, then kills the native pid recorded indaemon.json, because the npm wrapper cannot forward SIGKILL. SIGINT and SIGTERM abort the run: every step races the abort, and a pending restart refuses to start a daemon. The one cleanup path then runs, and the process exits 130 or 143. The owned temp root is removed on every path.conformance/automations-v1-daemon/:package.json+ npmpackage-lock.json(v3) pinning@opencoven/cli@0.4.7and its four platform packages. It sits outside the pnpm workspace and is not covered by Dependabot's root npm entry, so a version bump stays a deliberate change..github/workflows/ci.yml: the new step. This PR is pushed over SSH because it changes a workflow.package.json:canary:automations-v1-daemon.tests/automations-v1-daemon-canary.spec.ts, 26 tests:sha512integrity);coven: a version refusal, and a failing scenario that must stop the daemon and leave no temp root;README.md,docs/ROADMAP.md.Verification
@opencoven/cli@0.4.7from npm, both through the wrapper (bin/coven.js) and with the nativecli-macos/bin/covendirectly. A run takes about 1.8 s. Afterwards nocvn-*temp root and no canary daemon remained.runner.temp:npm ciandnpm audit signaturespassed ("2 packages have verified registry signatures", "2 packages have verified attestations"), and the canary passed.--expect-version 0.4.6is refused with the reported version, as are a missing binary and bad arguments.pnpm typecheckandpnpm lintare clean; the new spec passes 26/26;pnpm testpassed on the first commit: 92 files, 3,147 passed, 2 skipped.verify (24.18.1)log shows the signature and attestation checks, then the same summary line as above.The second commit addresses both Copilot findings: the canary now requires the final empty page, and it cleans up on SIGINT and SIGTERM.
🤖 Generated with Claude Code