Skip to content

upstream(sync): shared agent access + archive-aware profile selector (#6086, #5706) - #313

Merged
oscarlehuu merged 1 commit into
mainfrom
devin/issue-291-shared-access-archive-selector
Aug 22, 2026
Merged

upstream(sync): shared agent access + archive-aware profile selector (#6086, #5706)#313
oscarlehuu merged 1 commit into
mainfrom
devin/issue-291-shared-access-archive-selector

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 22, 2026

Copy link
Copy Markdown

Summary

Ports the two Tier 2 agent/Hermes behaviours from upstream Buzz (block#6086, block#5706) onto Crew's existing structures. Desktop-frontend only — no Rust, no backend, no navigation changes.

1. Archive-aware selection (block#5706). Upstream added a dedicated pickProfileAgent module; Crew already had the equivalent in unifiedAgentGroups.ts, so the archive awareness went there instead of copying a file that doesn't exist in this fork. Both entry points now take Crew's existing useIsArchivedPredicate():

buildUnifiedGroups(personas, agents, isArchived)
//  ungrouped / unknown: archived instances dropped (nothing else would resurface them)
//  groups:              full instance list kept, archived included

pickProfileAgent(agents, isArchived)
//  archived filtered *before* active/name ranking
//  -> undefined when every linked instance is archived

The ordering matters: previously an archived-but-active instance could win the ranking and a definition-card click would then navigate to (and persist) a stale archived pubkey. A matched definition group deliberately keeps its archived instances so the card itself still renders — only the target is required to be live. The predicate's fail-open-while-loading and self-exempt behaviour is load-bearing and reused as-is, so a slow archive snapshot degrades to today's behaviour rather than hiding live agents.

2. Shared access (block#6086), scoped. Only the access-propagation slice was ported, not the 5.4k-line upstream diff:

// personaManagedAgentUpdate: definition -> linked instance
if (persona.respondTo != null && persona.respondTo !== agent.respondTo) input.respondTo = ...
if (persona.respondTo === "allowlist" && allowlistChanged)             input.respondToAllowlist = ...
// respondTo == null means "definition states no policy" -> never overwrites instance access

editPersonaDialogState(persona, linkedAccess?) now seeds behaviour from the instance actually enforcing the policy (the profile panel and the definition actions menu pass it), so a definition edit can't silently re-widen access the owner narrowed on the instance. EditRespondToDialog inspects the mutation result and routes a non-fatal profileSyncError through the existing showAgentProfileSyncWarning helper instead of dropping it.

3. Config submit validation. agentAiConfigurationSubmitBlockReason derives the disabled-Save copy from the same visibility inputs the fields render from, so a disabled Save names the field the user still has to fill and a runtime-hidden provider/model field can never block saving. No new frontend capability table — visibility still comes from Rust runtime metadata.

Divergences from upstream, deliberately kept

  • Crew archive/restore/delete backend, the Agents page archive browser, and the Hermes profile lifecycle are untouched; only forward-looking discovery/selection filters archived identities.
  • No upstream pickProfileAgent.ts file; behaviour lives in Crew's unifiedAgentGroups.ts.
  • Owner-only/local Hermes access rules and fail-closed backend/relay enforcement are unchanged and remain authoritative over the ported definition-level sync.
  • Channel-first IA (upstream(sync): Guardrail — preserve channel-first IA during 0.5.18 merge #278) untouched — no Projects/Workbench rails, no navigation or sidebar changes.

desktop/src/features/agents/AGENTS.md gains rules 13–15 plus the enforcing tests, per its "keep this file true" requirement.

Related issue

Fixes #291. Parent: #285 (Buzz 0.5.18 sync). Guardrail: #278. Adjacent Hermes work: #119, #243.

Testing

TDD: tests written first and observed failing, then implemented.

Gate Result
pnpm --filter buzz check pass
pnpm --filter buzz typecheck pass
pnpm --filter buzz test pass — 5607 passed / 0 failed / 1 skipped (5608), re-run after the rebase
just test-unit buzz-cli (3) + buzz-db (1) fail identically on the base commit in a clean worktree — pre-existing, unrelated to this TS-only diff (command-inventory / migration-hash pins)
just check-compile N/A — no Rust changes
hermes-profile-binding.spec.ts + onboarding-agent-defaults.spec.ts pass — 47/47

New/extended unit coverage: ui/unifiedAgentGroups.test.mjs (archive ranking, all-archived → undefined, fail-open predicate, standalone/unknown omission, matched-group retention), ui/personaDialogState.test.mjs (instance-seeded access), profile/ui/UserProfilePanelUtils.test.mjs (owner-only + allowlist sync, null-policy no-op), ui/agentAiConfigurationPolicy.test.mjs (block reasons vs hidden fields).

E2E evidence (full-window, desktop E2E mock bridge)

Adversarial seed: the archived linked instance ("Scout Archived") is running and first in seed order, so on the base commit it would win active/name ranking and become the definition card's navigation target. The archived standalone agent ("Custom Archived") is identical to the live one except for archive state.

Agents library drops the archived standalone instance — "Custom agents (1)", Custom Live only:

Agents library, archived agent hidden

Negative control with archivedIdentities: [] on the same build → "Custom agents (2)" including Custom Archived, so the assertion above is real:

Negative control

Clicking the Scout definition card opens Scout Live (bb22a529…f260), not the running-but-archived instance:

Definition card opens live instance

Definition policy is owner-only while the linked instance is allowlist — the Edit dialog seeds "Selected people" plus the instance's allowlist chip:

Edit dialog seeds shared access

Customize AI configuration names the missing field, then enables Save; a runtime-hidden provider (Claude Code) never blocks Save:

Provider missing
Model missing
Save enabled
Hidden provider does not block Save

Regressions: archived identity absent from the composer mention picker and the channel agent picker; Hermes archived-profiles panel still renders (empty state, no error banner):

Mention picker
Channel agent picker
Hermes archives panel


DONE

  • Archive-aware grouping + definition-target selection (unifiedAgentGroups.ts, wired in UnifiedAgentsSection.tsx), definition→instance access sync (UserProfilePanelUtils.ts), instance-seeded edit state (personaDialogState.ts, passed from UserProfilePanel.tsx and usePersonaActions.openEdit), profileSyncError surfacing in EditRespondToDialog.tsx, named submit-block reasons (agentAiConfigurationPolicy.tsAgentDefinitionDialog.tsx), scoped desktop/src/features/agents/AGENTS.md rules 13–15 (renumbered during the rebase, since main added its own rule 12).
  • Tests added first and observed failing, then green: ui/unifiedAgentGroups.test.mjs (new), ui/personaDialogState.test.mjs, ui/agentAiConfigurationPolicy.test.mjs, profile/ui/UserProfilePanelUtils.test.mjs.
  • Rebased onto main @ 165a3b814. The only conflict was a rule-number collision in desktop/src/features/agents/AGENTS.md — both sides appended a rule 12; main's is kept and this PR's three rules became 13–15. No code conflicts.
  • Gates re-run on the rebased branch: pnpm --filter buzz check pass, pnpm --filter buzz typecheck pass, pnpm --filter buzz test pass (5607/5608, 1 skipped), acceptance specs hermes-profile-binding + onboarding-agent-defaults 47/47 pass. just test-unit's buzz-cli (3) + buzz-db (1) failures reproduce identically on base 2c26b74bf in a clean worktree — pre-existing. just check-compile N/A (no Rust).
  • Evidence: full-window screenshots embedded above; recording at /home/ubuntu/screencasts/pr313/pr313-edited.mp4; logs /tmp/gate-check.log, /tmp/gate-typecheck.log, /tmp/gate-test.log, /tmp/gate-test-unit.log, /tmp/evidence-red-unit.log, /tmp/accept.log, /tmp/control.log.

IN PROGRESS

  • Nothing half-implemented: the branch is complete, committed (DCO-signed) and pushed; the working tree is clean.
  • Only verification was cut short: the full committed Playwright suite was started but stopped by the wind-down order (/tmp/full.log holds two earlier aborted attempts — one hung on a temp drive spec, one hit Address already in use on port 4173; both were environment issues, since cleaned up).

TODO / NEXT

  • Run one clean cd desktop && xvfb-run -a pnpm exec playwright test (confirm nothing is listening on port 4173 first) and classify any failure against base 2c26b74bf. This is the single stated requirement left unverified.
  • Optionally exercise the Hermes archive restore/delete rows with seeded archives — only the empty state was observed.
  • CI note: this PR's NuncioCrew CI run was cancelled by the repo owner (the org's Actions pool is being serialized across the sync stack), so NuncioCrew Gate failed with desktop-fast must be success when desktop=true, got cancelled. Not a code failure; needs a re-run. Nothing under .github/ was touched.
  • Conflict risk: UserProfilePanel.tsx sits at the 1000-line ratchet ceiling (check:file-sizes), so a sibling PR adding lines there will collide; desktop/src/features/agents/AGENTS.md and unifiedAgentGroups.ts are the other likely overlap points with parallel upstream(sync): Meta — Buzz desktop-v0.5.18 pin (Tier 1 + Tier 2/3 children) #285 work.

Link to Devin session: https://app.devin.ai/sessions/fdadf46495e14ea0a0ca042c7efc5f57
Requested by: @oscarlehuu

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Author

E2E verification — archive-aware profile selector + shared access seeding

Driven manually through the desktop E2E mock bridge (pnpm --filter buzz build:e2e, headed on DISPLAY=:0, 1560x1060) with an adversarial seed: the archived linked instance ("Scout Archived") is running and first in seed order, so on the base commit it would win active/name ranking and become the definition card's navigation target. The archived standalone agent ("Custom Archived") is identical to the live one except for archive state. All screenshots are full-window.

Archive-aware library + profile selection

Agents library drops the archived standalone instance — "Custom agents (1)", Custom Live only:

pr313-T1-agents-library-archived-hidden

Negative control with archivedIdentities: [] on the same build → "Custom agents (2)" including Custom Archived, so the assertion above is real:

pr313-control-no-archive

Clicking the Scout definition card opens Scout Live (bb22a529…f260), not the running-but-archived instance:

pr313-T2-definition-card-live-instance

Shared access seeding

Definition policy is owner-only while the linked instance is allowlist — the Edit dialog seeds "Selected people" plus the instance's allowlist chip:

pr313-T3-edit-dialog-shared-access-seed

Customize AI configuration: named block reasons

Empty → Choose a provider to save custom AI configuration. (Save inert); after picking Anthropic → Choose a model to save custom AI configuration.; after picking Claude Sonnet 4.6 → reason cleared, Save enabled. Claude Code runtime hides the provider field entirely, and the hidden field never blocks Save.

pr313-T4a-save-blocked-provider
pr313-T4b-save-blocked-model
pr313-T4c-save-enabled
pr313-T4d-hidden-provider-no-block
pr313-T4d-hidden-provider-save-enabled

Regressions checked

Archived identity absent from the composer mention picker and from the channel agent picker (archived stay behind the separate collapsed "Archived (2)" section); Hermes archived-profiles panel still renders its empty state with no error banner.

pr313-T5-mention-picker-no-archived
pr313-T7-channel-agent-picker-no-archived
pr313-T6-hermes-archives-panel

Acceptance gates hermes-profile-binding.spec.ts + onboarding-agent-defaults.spec.ts: 47 passed. No bugs found; nothing observed contradicted the stated behaviour.


DONE

  • Archive-aware grouping + definition-target selection (unifiedAgentGroups.ts, wired via useIsArchivedPredicate() in UnifiedAgentsSection.tsx); definition→instance access sync (UserProfilePanelUtils.ts); instance-seeded edit state (personaDialogState.ts, threaded from UserProfilePanel.tsx, PersonaActionsMenu.tsx, usePersonaActions.openEdit); profileSyncError surfaced in EditRespondToDialog.tsx; named submit-block reasons (agentAiConfigurationPolicy.tsAgentDefinitionDialog.tsx); scoped desktop/src/features/agents/AGENTS.md rules 12–14.
  • Tests written first and observed RED, then GREEN: ui/unifiedAgentGroups.test.mjs (new), ui/personaDialogState.test.mjs, ui/agentAiConfigurationPolicy.test.mjs, profile/ui/UserProfilePanelUtils.test.mjs.
  • Gates: pnpm --filter buzz check pass · pnpm --filter buzz typecheck pass · pnpm --filter buzz test pass (5541 passed / 0 failed / 1 skipped) · acceptance E2E specs 47/47 pass. just test-unit's buzz-cli (3) + buzz-db (1) failures reproduce identically on base 2c26b74bf in a clean worktree — pre-existing. just check-compile N/A (no Rust changes).
  • Evidence: full-window screenshots above; recording /home/ubuntu/screencasts/pr313/pr313-edited.mp4; logs /tmp/accept.log, /tmp/control.log, plus RED/GREEN and gate logs in the session.

IN PROGRESS

  • No half-finished code: the branch devin/issue-291-shared-access-archive-selector is complete, DCO-signed, pushed, and the working tree is clean.
  • Only verification was cut short — the full committed Playwright suite run was killed by the wind-down order. Two earlier attempts aborted for environment reasons only (a temp manual-drive spec left in desktop/tests/e2e/ hung the run; a leftover preview server made Playwright fail with Address already in use on port 4173). Both were cleaned up before the final attempt.

TODO / NEXT

  • Run one clean cd desktop && xvfb-run -a pnpm exec playwright test (confirm nothing is listening on port 4173 first) and classify any failure against base 2c26b74bf. This is the single stated requirement left unverified.
  • Optionally exercise the Hermes archive restore/delete rows with seeded archives — only the empty state was observed.
  • CI: this PR's NuncioCrew CI run was cancelled by the repo owner while the Actions pool is being serialized across the upstream(sync): Meta — Buzz desktop-v0.5.18 pin (Tier 1 + Tier 2/3 children) #285 stack, so NuncioCrew Gate reported desktop-fast must be success when desktop=true, got cancelled. Not a code failure — it needs a re-run (the bot token cannot re-run it). Nothing under .github/ was touched.
  • Conflict risk for whoever picks this up: UserProfilePanel.tsx sits at the 1000-line check:file-sizes ratchet ceiling, so a sibling PR adding lines there will collide; unifiedAgentGroups.ts and desktop/src/features/agents/AGENTS.md are the other likely overlap points with parallel upstream(sync): Meta — Buzz desktop-v0.5.18 pin (Tier 1 + Tier 2/3 children) #285 work.

Written by Devin

devin-ai-integration Bot added a commit that referenced this pull request Aug 22, 2026
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/issue-291-shared-access-archive-selector branch from 324a613 to 1bb36ae Compare August 22, 2026 11:44
@devin-ai-integration

Copy link
Copy Markdown
Author

CI note: Desktop Smoke E2E (3) failures are pre-existing on main

The completed Desktop Smoke E2E (3) job on this PR failed with 9 tests (269 passed, 2 flaky-then-passed, 5 skipped). I reproduced the identical failure set locally on both this branch and a clean worktree at base main (165a3b814, the merge of #316), using the same command:

pnpm --filter buzz build:e2e
cd desktop && xvfb-run -a pnpm exec playwright test \
  tests/e2e/project-commit-detail.spec.ts \
  tests/e2e/message-feedback-snapshots.spec.ts \
  tests/e2e/needs-restart-screenshots.spec.ts

Both runs: 9 failed, 4 skipped, 11 passed, with exactly the same tests failing:

  • message-feedback-snapshots.spec.ts:97 — profile hover uses the channel hover surface
  • needs-restart-screenshots.spec.ts:278 — restart-diff screenshots › 03-running-restart-action
  • project-commit-detail.spec.ts:29, 411, 493, 605, 663, 729, 777

None of these specs touch the surfaces changed here (unified agent grouping / persona access sync / AI-config save validation). No code or CI configuration was changed in response; per the parent session's serialization note, CI was not re-triggered.

…lock#6086, block#5706)

Port the two Tier 2 agent/Hermes behaviours from upstream Buzz:

- Archive-aware selector: buildUnifiedGroups/pickProfileAgent take the
  useIsArchivedPredicate() predicate, drop archived standalone and
  unknown-definition instances, and resolve a definition card's target to a
  live sibling (undefined when all are archived). Matched definition groups
  keep their full instance list so the card still renders.
- Shared access: a definition's respondTo/respondToAllowlist now syncs down
  to its linked managed-agent instances, edit dialogs seed from the instance
  actually enforcing the policy, and EditRespondToDialog surfaces a
  profileSyncError through the existing warning helper.
- Config validation names the field a user still has to fill instead of
  silently disabling Save, and never names a hidden provider/model field.

Crew archive/restore/delete backend, the Agents archive browser, owner-only
access and channel-first IA are unchanged.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@cursor
cursor Bot force-pushed the devin/issue-291-shared-access-archive-selector branch from 1bb36ae to d3fae0d Compare August 22, 2026 13:18
cursor Bot pushed a commit that referenced this pull request Aug 22, 2026
@cursor

cursor Bot commented Aug 22, 2026

Copy link
Copy Markdown

Post-rebase E2E evidence (full-window)

Rebased onto origin/main @ 82187d81 (conflict-free). Head d3fae0d63. Devin's PR body could not be edited from this handoff, so evidence lives here.

Adversarial seed: archived Scout instance is running and first in seed order (would win active/name ranking on main); definition policy is owner-only while the live instance is allowlist.

Agents library hides archived standalone instances

Custom agents (1) — Custom Live only. Custom Archived is omitted from the library.

pr313-T1-agents-library-archived-hidden

Negative control (archivedIdentities: [])

Same build with no archives → Custom agents (2), including Custom Archived.

pr313-control-no-archive

Definition card opens the live instance

Scout card click opens Scout Live (bb22a529…f260), not the running-but-archived sibling. Runtime tab shows Who can send instructions: Selected people.

pr313-T2-definition-card-live-instance

Edit dialog seeds shared access from the instance

Definition is owner-only; the linked live instance is allowlist. Advanced seeds Selected people, the instance allowlist chip, and the shared-access warning.

pr313-T3-edit-dialog-shared-access-seed

Recording

Same two flows, headed on the desktop E2E mock bridge after the rebase.

pr313-archive-access-shared-seed.mp4

Local gates on the rebased head: pnpm --filter buzz check pass, typecheck pass, pnpm --filter buzz test 5613 passed / 0 failed / 1 skipped. UserProfilePanel.tsx remains 993 lines (under the 1000-line ratchet). Temp Playwright files were not committed. Do not merge. Do not close #291.

cursor Bot pushed a commit that referenced this pull request Aug 22, 2026
@cursor

cursor Bot commented Aug 22, 2026

Copy link
Copy Markdown

Durable copy of the post-rebase recording (same file as the artifact in the previous comment):

https://raw.githubusercontent.com/Nuncio-hq/crew/25a73f6aaf63e99da9e0e0094237d97ffc4de59a/pr-313--pr313-archive-access-shared-seed.mp4

@oscarlehuu
oscarlehuu merged commit cddaeb0 into main Aug 22, 2026
8 of 14 checks passed
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.

upstream(sync): Tier 2 agent/Hermes — shared access + archive-aware selector (#6086, #5706)

1 participant