Repository navigation
Conversation
…you between computers (BRA-3274) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ent, and simplify the store Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, and never lose items on a failed read or write Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@Stener1 is attempting to deploy a commit to the seanbrydonio's projects Team on Vercel. A member of the Team first needs to authorize it. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 6, 2026
This branch has not been deployed
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.
Summary
A plugin's
storageis per computer, so a snooze or "resolved" a person sets on one laptop is news to their other one, and a plugin has nowhere on the box to keep what an agent asks. Each box now keeps a small list of attention items: asks an agent posts, and a person's marks on items a plugin builds from the box's own signals. Every app paired with the box reads the same list. ("Attention" is a working name: the box's inbox already means held prompts.)sequenceDiagram participant A as Laptop A (plugin) participant Box as berthd (attention.json) participant B as Laptop B (plugin) A->>Box: PATCH /v1/attention/{key} {snoozed_until, revision} Box-->>A: item, revision+1 Box-)B: attention.updated {key, revision, status} B->>Box: GET /v1/attention Note over Box: session stopped → settle at once (session.stopped observer)<br/>program exited → settle when two sweeps miss it (refreshTurns, 10 s)revisionon, so an agent replaces its own ask instead of adding another; a post with asessionand no key issession:<name>. A post or update that names a revision that has gone by is refused (409).markthere, so a plugin can snooze or resolve an item it builds itself (a waiting agent, a run's gate).open→answeredorclosed. An open item about a session closes assession_endedwhen the session is stopped (at once), or when its program ends (once two sweeps, each with a listing taken after the item last changed, miss it).attention.json.corrupt-<time>. A settle changes memory only after the file holds it.before:attention.postandbefore:attention.updategates can refuse.Docs:
reference/plugin-sdk#attention, the box routes inapp-api, events and gates, and a changelog line. Based on 4ebd998 (the commit before #207); it merges clean ontomain.Evidence
A real box and two laptop agents paired with it, each with its own pairing code (
.claude/skills/verify-berthd/scripts/attention-live.sh), driven in two browsers byscenarios/attention-two-laptops-live.mjswith a small test plugin. Resultok: true, no console errors on either laptop.nothingbelow.After: laptop B reads the snooze laptop A made, from the box.
Steps the scenario asserts with literal text:
Unit tests (
go test -race ./internal/box -run 'Attention|AMark|ItemsSettle|AnAgentReplaces|ASweep|ASettle', 3× under-race): key and revision replace, marks, settle on session end, the two-miss rule and a post after the listing, ageing out, a restart, a file that can't be read or isn't JSON, a settle whose write fails.app/src/lib/attention.test.ts: paths are escaped (/,#),getisundefinedfor no item.Checks run locally (fork PRs wait for a maintainer before CI):
go vet ./...,go test -race ./...(onlyTestTheCatalogIsCappedfails, as onmainon this machine: it counts the machine's own commands), the app'stypecheck:plugins,check:*,test,build,tsc -p e2e, and the docs build.cargo checkis untouched (no Rust change). Codex review and adversarial review ran once; their findings (a sweep against a stale listing, a short listing, a load error taken as empty, a settle not saved, a post to an exited session) are fixed in the last commit with tests.Merge Danger
Door: two-way
Additive: a new state file (
~/.berth/…/attention.json), new routes, a capability, new events and gates. Nothing existing reads or writes them. Reverting leaves an unused file behind.Blast Radius: small
Only plugins that call
berth.attentionsee it. The one shared path touched isrefreshTurns, which now also sweeps the store (a map walk, a file write only when something settles), and asession.stoppedobserver that hands off to a goroutine. The plugin SDK gainsattentiononBerthPluginContext: a plugin written against it should checkinfo(box).capabilitiesand thatberth.attentionexists, as documented.🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.