feat(nerve): ship deterministic wakeup routing - #3
Merged
Merged
Conversation
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.
Intent
Ship Nerve v1 for github.com/thellmwhisperer/roca-firstmate while leaving Scribe behavior unchanged and changing the plugin Dresser skill. Do not install or test against any live captain La Roca. Nerve v1 must have no resident process or KeepAlive daemon by default; an eventual daemon subcommand is optional. Mirror freshness is ingest-on-read: every plugin verb first fingerprint-sweeps Markdown mtimes and ingests changes before answering. Attach is the thinker default gesture: on first use register the workspace as a firstmate seat, print the chart get-or-create with watermark plus the latest handoff, and subscribe in the same gesture because attaching is subscribing. Follow must listen to the database WAL through FSEvents and, for each unhandled wakeup of its destination, print exactly one line to stdout and mark it handled with the same generation. Destinations are captain, companion, and machine; mobile is later and must not block v1. Tick is ephemeral: it is born, runs the silence clock, drains orphan wakeups, reconciles fingerprints, keeps no in-memory state, and dies. The plugin skill must teach attach first and three follow recipes: native millisecond wakes through Claude Monitor or asyncRewake, OpenCode promptAsync and never pure mode, Pi TypeScript extension, Grok background-notify, and probable Hermes hooks; injection in seconds for Codex CLI and Cursor CLI by piping follow to fm-send; passive desktop sync on attach and pending wakeups on open. State the three latencies as milliseconds, seconds, and on open. Everything is deterministic AXI with zero inference. Tests and public text use fabricated homes only and contain no live paths, UUIDs, corpus counts, or live-install details. Deliver a green non-draft PR and arm GitHub native rebase auto-merge only after checks are green; never merge red.
What Changed
attach,follow, and ephemeraltickflows with ingest-on-read fingerprint sweeps, foreground WAL subscriptions, seat leases, generation acknowledgements, and orphan recovery.captain,companion, andmachinedestinations, persistent seats, handled generations, updated package metadata, and expanded coverage.Risk Assessment
✅ Low: The final wording fix satisfies the remaining Dresser criterion, all previously identified state-transition defects remain resolved, and no additional material source risks were found.
Testing
No baseline test output was supplied; all targeted automated tests and fabricated CLI flows passed, reviewer-visible transcripts and persisted database evidence were captured, the worktree contains only the intentional Dresser contract-test improvement, and PR/CI/auto-merge remain with the outer pipeline phases.
Evidence: First-use attach
First-use attach registered an opaque seat, ingested 14 fabricated Markdown files, created the chart with watermark, printed the latest fabricated handoff, drained pending wakeups, and remained subscribed.Evidence: Attach WAL delivery
After one fabricated captain.md rewrite, the attached process emitted exactly one JSON line for generation 14 with handled_generation 14.Evidence: Chart ingest-on-read
Chart ingest-on-read regenerated the chart, exposed captain.md version 2, and reported one pending wakeup before follow consumed it.Evidence: Ephemeral tick
Tick reconciled all 13 files unchanged, created one silence wakeup, drained two orphan wakeups for captain and machine, printed their generation-confirmed lines, and exited.Evidence: Persisted SQLite state
captain_current_version=2; generation_14_confirmed=14/14; unhandled_after_tick=0; opaque_workspace_seat=yes; all_handled_match_generation=yesPipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 5 issues found → auto-fixed (2) ✅
internal/nerve/nerve.go:275- The intent requires follow to emit exactly one line per unhandled wakeup. Here stdout is written beforetx.Commit(): if the write succeeds but commit fails or the process dies, the row remains unhandled and the next follower emits it again. SQLite and stdout cannot provide atomic exactly-once delivery; either authorize/document at-least-once delivery with downstream generation deduplication/acknowledgement, or introduce a transactional delivery boundary.cmd/roca-firstmate/main.go:452- The required Dresser follow recipes invokefollowwithout--seat-id, and this path therefore supplies an empty seat tonerve.Follow. The active follower never refreshes a lease: after the prior attach lease expires,ticktreats its destination as orphaned and can consume its wakeups. If attach remains running instead, attach and the adapter race to consume the same destination. Make the adapter-owning process register/derive and heartbeat its seat, or change the documented recipe to consume the attach stream directly.internal/nerve/nerve.go:337- Orphan status is checked before delivery rather than at the claim boundary. A seat can attach afterorphanDestinationsreturns but beforeDrain;claimNextthen marks the wakeup handled despite a live subscriber. Recheck the absence of an unexpired destination seat inside the same transaction/query that claims an orphan wakeup.internal/nerve/nerve.go:396- Overlapping ticks can both select the same stalesilence_generation, each insert a silence wakeup, and then have the second conditional seat update affect zero rows; its result is not checked, so both commits succeed. Atomically advance/claim the seat generation first (for example with conditionalUPDATE … RETURNING) and insert only for the winner.cmd/roca-firstmate/main.go:389- The public contract says only an opaque workspace fingerprint is stored, but attach persistsfilepath.Base(workspace)as the seat label. This can disclose the repository/workspace name in the federated database. Use an opaque default or require an explicitly authorized human-readable seat label.🔧 Fix: Harden Nerve ownership and atomic wakeup recovery
1 error still open:
skills/dresser/SKILL.md:39- The intent requires the plugin skill to teach native Claude wakes through “Claude Monitor or asyncRewake,” but this bullet says Monitor with asyncRewake, collapsing the two required alternatives into one coupled path. Enumerate Monitor and asyncRewake separately, or confirm they are intentionally the same adapter path.🔧 Fix: Separate Claude native wake alternatives
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
go test ./internal/nerve -run 'Test(Drain|RegisterSeat|Tick|LastHandoff)' -count=1 -vgo test ./internal/scribe -run 'Test(BackfillMirrorsEveryFabricatedMarkdownFamilyAndIsIncremental|FileEventCreatesVersionThenTriggerCreatesWakeup|TotalIngestKeepsArbitraryAndNestedMarkdown|CursorStoresNoAbsoluteHomePath|LaRocaPublicPackageContractsCompileForTheExternalPlugin)' -count=1 -vgo test ./cmd/roca-firstmate -run 'Test(OpenDatabaseMigratesFabricatedV1BeforeUse|OpenDatabaseMigratesFabricatedV2WakeupState|RunScribeBackfillsFabricatedHome)' -count=1 -vgo test ./schema -run 'Test(WakeupsRejectsUnknownDestination|HandledWakeupRequiresItsGeneration|ShippedDatabaseMatchesSchemaSQL|PluginManifestDescribesTheShippedDatabase|ChecksumsCoverExactlyTheInstallPayload|ShippedDatabaseHasNoMirroredRows|FabricatedHomeHasTheFiveFamiliesAndNoLivePaths|DresserSkillTeachesChartSQLAndFirstmateDoor|RepoHasNoSessionStartHooks|TelemetryTablesRemainFreeForLaterAdditiveSchema)' -count=1 -vgo test ./schema -run '^TestDresserSkillTeachesNerveV1Contract$' -count=1 -vgo test ./internal/chart -run 'Test(EmptyDBCreatesChartAndSecondCallIsCached|NewRowRegeneratesChart|HandledWakeupRegeneratesChart|TOONIsBoundedAndHasHelp|JSONEnvelope)' -count=1 -vBuilt./cmd/roca-firstmate, then ran first-useattachagainst a copied fabricated home containing a fabricated handoffRewrote one copiedcaptain.md, invokedchart, and observed exactly one subsequent WAL-delivered JSON line from the attached processExpired a fabricated seat lease, inserted a fabricated machine wakeup, and rantick --silence-after 5mQueried the evidence SQLite database for versioning, opaque seat identity, pending wakeups, destinations, and handled-generation equalityScanned changed public text and source for live absolute paths and UUID-shaped identifiers✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.