Skip to content

fix: use bare peerName for the user peer to match sibling plugins#23

Closed
rrei wants to merge 2 commits into
plastic-labs:mainfrom
rrei:fix/user-peer-naming
Closed

fix: use bare peerName for the user peer to match sibling plugins#23
rrei wants to merge 2 commits into
plastic-labs:mainfrom
rrei:fix/user-peer-naming

Conversation

@rrei

@rrei rrei commented Jun 5, 2026

Copy link
Copy Markdown

Closes #22.

The user peer was derived as user:${peerName} (normalised to user-<peerName>), whereas the claude-honcho and hermes-honcho plugins use the bare peerName. In a shared workspace this split the user's memory into a separate user-<peerName> collection, so OpenCode never saw or contributed to what the other tools learned. This drops the prefix so the user peer matches the sibling plugins.

Added a regression test for the derivation and updated two fixtures that encoded the old convention. bun test (58 passing) and tsc --noEmit are green.

Summary by CodeRabbit

  • Bug Fixes
    • Simplified the user peer ID format for more consistent peer handling across the app.
    • Added a fallback to the current username when no peer name is configured.
    • Prevented user and agent peers from resolving to the same identity, helping keep their data separate.
    • Improved peer name normalization for multi-word names and other common inputs.

The user peer was derived as `user:${peerName}` (normalised to
`user-<peerName>`), whereas the claude-honcho and hermes-honcho plugins
use the bare `peerName`. In a shared workspace this split the user's
memory into a separate `user-<peerName>` collection, so OpenCode never
saw or contributed to what the other tools learned. Drop the prefix so
the user peer matches the sibling plugins.
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bbc6a2fc-83e4-4fcf-a32c-e10d0bca6233

📥 Commits

Reviewing files that changed from the base of the PR and between fe73d2e and b8d43de.

📒 Files selected for processing (2)
  • src/index.ts
  • tests/peer-collision.test.js
✅ Files skipped from review due to trivial changes (1)
  • tests/peer-collision.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/index.ts

Walkthrough

Derives a normalized user peer ID from settings.peerName via deriveUserPeerId, uses it in deriveRuntimeHandle, adds assertDistinctUserAndAgentPeers to prevent user/agent ID collisions, exports both helpers to __testing, and updates tests to match the simpler user peer ID format.

Changes

User Peer ID Normalization

Layer / File(s) Summary
Derivation helper and runtime integration
src/index.ts
Adds deriveUserPeerId(settings) (normalizes settings.peerName with "user" fallback), assertDistinctUserAndAgentPeers, updates deriveRuntimeHandle to use the new helper and assert distinct IDs, and exports helpers via __testing.
Integration test updates
tests/context-injection.test.js, tests/peer-topology.test.js
Mocks and assertions adjusted to expect caller-provided/simple user peer IDs ("user" rather than "user:user"); context mock now treats peerId === "user" as the user representation.
Unit tests for derivation and collision checks
tests/user-peer-id.test.js, tests/peer-collision.test.js
Adds tests validating deriveUserPeerId (passthrough, empty fallback, normalization) and assertDistinctUserAndAgentPeers (accepts distinct, throws on collision).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit nibbles at the prefixed tail,

trims "user:" down to a tidy trail.
Now names align and memories meet,
one gentle hop — the peers greet sweet.
Hooray for clarity, soft and neat!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: using bare peerName for the user peer to match sibling plugins, which is the core objective of the PR.
Linked Issues check ✅ Passed The PR fully addresses issue #22 by removing the user: prefix and using bare peerName, plus adds validation to prevent user-agent peer collisions.
Out of Scope Changes check ✅ Passed All changes directly support the objective of using bare peerName and preventing peer collisions; no out-of-scope changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/index.ts`:
- Around line 760-762: The code can produce identical IDs for userPeerId and
rootAgentPeerId after normalization (deriveUserPeerId and normalizeId), causing
sessionPeerConfigs keys to collide; update the logic that sets
userPeerId/rootAgentPeerId (or inside deriveUserPeerId) to detect equality after
normalization and disambiguate (for example by adding a stable prefix/suffix
like "user-" or "agent-" or falling back to a unique variant) so userPeerId !==
rootAgentPeerId, and ensure activeAgentPeerId still references the agent id
(rootAgentPeerId) while any downstream usage (e.g., sessionPeerConfigs) uses the
disambiguated ids.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12b55323-eb58-4354-a239-147d28826bfb

📥 Commits

Reviewing files that changed from the base of the PR and between fa0e5db and fe73d2e.

📒 Files selected for processing (4)
  • src/index.ts
  • tests/context-injection.test.js
  • tests/peer-topology.test.js
  • tests/user-peer-id.test.js

Comment thread src/index.ts
Removing the user: prefix means peerName and aiPeer can now normalise to the
same peer id (e.g. both "opencode"), silently merging user and agent memory
into one peer. Fail fast on that collision instead.
@rrei

rrei commented Jun 8, 2026

Copy link
Copy Markdown
Author

@ajspig @adavyas: gentle ping when you have time. Automation is green and the collision-check feedback from the first review has been addressed.

@adavyas

adavyas commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

hey @rrei ! apologies for the late review on this PR. thank you for your work on this. in order for this to not break with the legacy plugin ecosystem we've pushed out for the opencode-honcho plugin, we'd like to execute something like peerNamingStrategy: "prefixed" | "bare":

new installs get seeded with "bare" in ensureSharedGlobalSettings → new default, matches the sibling plugins.
existing installs have no such key → treated as "prefixed" → behavior unchanged on upgrade.
Anyone who wants to migrate sets it to "bare" explicitly.

this is sort of an opt-in system for existing users while shifting new installations to the new peerName.

adavyas added a commit that referenced this pull request Jun 15, 2026
PR #23 dropped the user-peer prefix unconditionally, which re-points every
existing user at an empty `<peerName>` peer and orphans their accumulated memory.

Gate it on a boolean under the opencode host block instead:

  hosts.opencode.removeUserPrefix: <boolean>

- new installs are stamped `true` at config creation (runtime + TUI) -> bare
  `<peerName>`, matching the sibling claude-honcho / hermes-honcho plugins
- existing/upgraded installs default `false` -> keep `user-<peerName>` and its
  memory; the config file is never mutated on upgrade
- it's a normal validated host setting, so anyone can opt in via the file,
  /honcho:set-config, or the TUI

Builds on @rrei's #23: keeps the bare derivation and the user/agent peer
collision guard; generalizes deriveUserPeerId to honor the flag.

Co-authored-by: Rui Rei <rui.rei@enline-transmission.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rrei

rrei commented Jun 17, 2026

Copy link
Copy Markdown
Author

hey @rrei ! apologies for the late review on this PR. thank you for your work on this. in order for this to not break with the legacy plugin ecosystem we've pushed out for the opencode-honcho plugin, we'd like to execute something like peerNamingStrategy: "prefixed" | "bare":

new installs get seeded with "bare" in ensureSharedGlobalSettings → new default, matches the sibling plugins. existing installs have no such key → treated as "prefixed" → behavior unchanged on upgrade. Anyone who wants to migrate sets it to "bare" explicitly.

this is sort of an opt-in system for existing users while shifting new installations to the new peerName.

Hey @adavyas, thanks for the review!

Good point on the backward compatibility. 👍 It didn't even cross my mind, sorry about that! 😅
The migration solution you describe is the way to go, 100% agreed. I saw that you created a separate PR that builds on top of this, already implementing the solution you indicated. Does that mean we can/should close this PR? 🤔

adavyas added a commit that referenced this pull request Jun 17, 2026
* fix: use bare peerName for the user peer to match sibling plugins

The user peer was derived as `user:${peerName}` (normalised to
`user-<peerName>`), whereas the claude-honcho and hermes-honcho plugins
use the bare `peerName`. In a shared workspace this split the user's
memory into a separate `user-<peerName>` collection, so OpenCode never
saw or contributed to what the other tools learned. Drop the prefix so
the user peer matches the sibling plugins.

* fix: reject configs where the user and agent peers collide

Removing the user: prefix means peerName and aiPeer can now normalise to the
same peer id (e.g. both "opencode"), silently merging user and agent memory
into one peer. Fail fast on that collision instead.

* feat: gate user-peer prefix on hosts.opencode.removeUserPrefix

PR #23 dropped the user-peer prefix unconditionally, which re-points every
existing user at an empty `<peerName>` peer and orphans their accumulated memory.

Gate it on a boolean under the opencode host block instead:

  hosts.opencode.removeUserPrefix: <boolean>

- new installs are stamped `true` at config creation (runtime + TUI) -> bare
  `<peerName>`, matching the sibling claude-honcho / hermes-honcho plugins
- existing/upgraded installs default `false` -> keep `user-<peerName>` and its
  memory; the config file is never mutated on upgrade
- it's a normal validated host setting, so anyone can opt in via the file,
  /honcho:set-config, or the TUI

Builds on @rrei's #23: keeps the bare derivation and the user/agent peer
collision guard; generalizes deriveUserPeerId to honor the flag.

Co-authored-by: Rui Rei <rui.rei@enline-transmission.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: mention removeUserPrefix in the config example


* fix: coerce removeUserPrefix to boolean when editing an absent field

The TUI value parser keyed "is this boolean?" off the runtime type of the
current value. For upgrade configs where hosts.opencode.removeUserPrefix is
absent, currentValue is undefined, so editing it persisted the raw string
"true"/"false" instead of a boolean — and since "false" is a truthy non-empty
string, deriveUserPeerId would route to the bare peer, the opposite of intended.

Decide boolean-ness from the field path (BOOLEAN_FIELD_KEYS) so both the
true/false options and the coercion are correct even when the field is missing.


* fix: coerce removeUserPrefix at read time and soften peer collision

Two real hardening fixes from code review (cosmetic findings dropped):

- applyRawLayer coerces BOOLEAN_KEYS at the merge chokepoint, so a config string
  "false" is no longer truthy. The README invites hand-editing, and a stray
  string "false" would otherwise drop the user- prefix and orphan a user's memory.
- deriveRuntimeHandle auto-resolves a bare/agent peer-id collision (peerName ==
  aiPeer) by falling back to the prefixed form instead of throwing on the hot
  path, which runs in unguarded hooks. assertDistinct stays as a last resort.


* fix: drop TUI surface for removeUserPrefix, keep it config-only

removeUserPrefix is now managed purely through the shared config file
(and the runtime new-install stamp / honcho_set_config), not the native
TUI editor. Revert src/tui.ts and tests/tui-behavior.test.js to their
pre-feature state.

The TUI's saveSettings still preserves the key on existing configs via
the currentOpenCodeHost spread, so configs that set it aren't disturbed
when other settings are edited.


---------

Co-authored-by: Rui Rei <rui.rei@enline-transmission.com>
@adavyas

adavyas commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

yes! this issue has been addressed and code was salvaged for PR #24 . will update the opencode plugin shortly. thank you once again for your work and raising this issue.

@adavyas adavyas closed this Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User peer naming is inconsistent with the other Honcho plugins

2 participants