mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-01 01:16:17 +02:00
agent/lambda/40faf9bf
11 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5ad1641b72 |
Revert "Squad archive dialog + role editor + transactional DeleteSquad (#2680)" (#2687)
This reverts commit
|
||
|
|
2980ead4c7 |
Squad archive dialog + role editor + transactional DeleteSquad (#2680)
* docs(squad): address plan-review feedback for archive + role plan
Resolve the 4 items the reviewer raised on MUL-2265:
1. TS schema: declare `active_issue_count` as optional (`number | null | undefined`)
so list/create/update Squad responses don't lie about their shape; only
`getSquad` parses through SquadSchema.
2. Archive semantics: restrict TransferSquadAssignees to active issues
(status NOT IN done, cancelled) so dialog count and SQL operate on one set
and terminal-state issues keep their historical assignee.
3. Index assumption: corrected — `idx_issue_assignee (assignee_type,
assignee_id)` exists and is sufficient at realistic squad cardinality;
no new index needed.
4. Fixed `*int64` test comparison and added `.loose()` to SquadSchema per
the local schemas.ts convention.
Co-authored-by: multica-agent <github@multica.ai>
* docs(squad): plan v3 — revert to count-all/transfer-all on archive
Reviewer round 2 surfaced two structural problems with plan v2's
active-only carve-out:
1. useActorName resolves squad names via ListSquads, which filters
archived_at IS NULL. A closed issue with an archived-squad assignee
would render as "Unknown Squad".
2. The status-only update path in UpdateIssue skips validateAssigneePair,
so a done/cancelled issue with an archived-squad assignee could be
reopened to in_progress, violating the "no active issue on an archived
squad" invariant enforced elsewhere.
Both problems disappear by reverting to count-all + transfer-all: after
ArchiveSquad runs, no issue points at the archived squad, so neither
case can occur. The product trade-off is that closed historical issues
now show the leader agent instead of the archived squad in their
"Assigned to" badge — consistent with existing agent-level reassignment
behavior elsewhere in the product.
Field rename: active_issue_count -> issue_count.
TransferSquadAssignees SQL is unchanged (already transfers all).
Co-authored-by: multica-agent <github@multica.ai>
* docs(squad): add Task 2b — wrap DeleteSquad transfer + archive in one tx
Reviewer round-3 flagged that the v3 invariant ("after archive no
issue points to the squad") was asserted on the happy path only.
DeleteSquad's current best-effort impl breaks it two ways:
- transfer failure → slog.Warn but archive proceeds (Unknown Squad,
reopen-into-archived-squad bugs reappear)
- archive failure after a committed transfer → 500 with squad still
active but emptied
Task 2b rewrites DeleteSquad to run TransferSquadAssignees +
ArchiveSquad inside one pgx tx, mirroring the project.go:266-314
pattern. Publish moves below Commit. Adds two regression tests that
lock both partial-write failure modes.
Co-authored-by: multica-agent <github@multica.ai>
* feat(squad): replace native confirm() with AlertDialog and rewrite role editor as combobox
Backend:
- Add CountIssuesForSquad sqlc query (counts every issue assigned to a squad,
no status filter — matches the existing transfer-all archive semantics).
- Extend SquadResponse with optional `issue_count` (`*int64` + omitempty,
populated only by GetSquad to avoid an N+1 in the list endpoint).
- Wrap DeleteSquad's transfer + archive in a single pgx transaction so the
v3 invariant ("after archive, no issue points to the squad") is durable
rather than best-effort. Promote slog.Warn to slog.Error and check the
parseUUIDOrBadRequest ok flag (silent zero-UUID was a #1661-class latent
bug). Publish only after Commit so realtime never sees rolled-back state.
- Tests cover happy path (count, transfer-all including terminal statuses)
and both rollback directions (transfer fail / archive fail) via a
fault-injecting tx wrapper.
Frontend:
- Extend Squad TS type with `issue_count?: number | null` (optional —
list/create/update legitimately omit it). Add SquadSchema with `.loose()`
and wrap getSquad with parseWithFallback so older servers and count-error
responses degrade to the dialog's "no count" copy variant.
- Replace `window.confirm()` with shadcn `ArchiveSquadConfirmDialog`
(destructive variant, leader name + count + closed-issue caveat in the
copy, Loader2 while pending). i18n keys added under squads.archive_dialog.
- Rewrite RoleEditor as a Popover + Command combobox: Pencil affordance is
always visible, suggestions aggregate other members' roles, commit only
on Enter or selecting a suggestion (blur discards), per-member savingId
drives Loader2 so the spinner only renders on the row being saved.
Co-authored-by: multica-agent <github@multica.ai>
* fix(squad): discard RoleEditor draft on close and no-op blank Enter
Two reviewer findings on
|
||
|
|
675ed02aa6 |
MUL-2216: persist Mine/All tab selection on Agents and Squads pages (#2624)
* MUL-2216: feat(agents,squads): persist Mine/All tab selection per workspace Tab selection on the Agents and Squads list pages was held in component-local state, so navigating into a detail page and back remounted the list and reset the tab to the default "Mine". Move `scope` into Zustand stores backed by `persist` + `createWorkspaceAwareStorage`, matching the pattern used by the Issues view store. Selection now survives list → detail → back navigation and page reloads, scoped per workspace. Only `scope` is persisted; `search`, `sort`, and other ephemeral filters intentionally still reset on remount. Co-authored-by: multica-agent <github@multica.ai> * fix(views): reset scope to mine when switching to a workspace with no persisted value zustand persist.rehydrate() is a no-op when storage returns null, so workspaces with no entry kept the previous workspace's in-memory scope ("all" leaked from one workspace into the next). Provide a custom merge that resets to the default "mine" when no persisted state is present. Add coverage for the missing-storage workspace-switch case for both Agents and Squads. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
43b9a1173c |
refactor(agents): drop template chooser from create-agent dialog (#2615)
* refactor(agents): drop template chooser from create-agent dialog Removes the blank-vs-template chooser, the template picker, and the template detail step. The "Create agent" entry point now opens directly on the form. The createAgentFromTemplate API and types remain untouched — this only removes the UI entry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * docs(squads): fix stale comment about createAgentFromTemplate Squad-scoped create flow no longer goes through the template path; the dialog now only calls api.createAgent then api.addSquadMember. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
77b929fd3e |
feat(squads): add agent live peek hover card on member avatars (#2608)
* feat(squads): add agent live peek hover card on member avatars Squad members tab now opens a live-state peek card on agent avatar hover/focus — workload, current issue (clickable), and last activity. Identity (description / runtime / skills / owner) stays on the existing AgentProfileCard; new AgentLivePeekCard is the second `hoverCardVariant` on ActorAvatar so the 23+ existing profile-card call sites keep their behaviour. Reuses the workspace agent-task snapshot already fetched by the presence dot, so this adds zero new requests per row. Failed terminal tasks surface as a small ⚠ on the last-activity line without polluting workload (workload stays current-state only, matching the deliberate split documented in core/agents/types.ts). Co-authored-by: multica-agent <github@multica.ai> * fix(squads): only enable hover card for agent avatars Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
5eb04f73e3 |
feat(squads): add tooltips and agent detail link to squad member row (#2603)
* feat(squads): add tooltips and agent detail link to squad member row Replace native title attributes on the make-leader and remove buttons with proper Tooltip components, and add a new icon button on agent rows that navigates to the agent detail page. All three tooltips are localised. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * fix(squads): keyboard focus visibility + AppLink for agent detail - Add group-focus-within:opacity-100 so Tab to the row's hover-only action buttons makes the container visible (previously opacity-0 kept buttons focusable but invisible). - Replace the agent-detail jump button's onClick+push() with AppLink href, restoring middle/Cmd+Click new-tab behavior. Removes the now-unused onViewAgent callback chain. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
bc613c08b3 |
fix(squad): align squad detail tab width with agent detail (#2600)
Drop mx-auto + max-w-2xl wrappers around the Members and Instructions tab content so the right pane fills the available width like the agent detail page (TabContent uses flex h-full flex-col p-4 md:p-6). Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
d1c8c213e4 |
feat: extend pinyin search to all Agent/Member/Squad selectors (#2582)
Integrate matchesPinyin into: - AssigneePicker (issue assignee selector) - IssuesHeader (assignee filter bar) - AgentPicker (autopilot agent selector) - SquadDetailPage (add member/agent picker) - QuickCreateIssue (agent/squad picker) - CreateProject (lead picker) - ProjectDetail (lead picker) - ProjectsPage (lead filter) - AgentsPage (agent search) - SquadsPage (squad search) Closes MUL-2179 extended scope. Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
f15a745182 |
feat(squads): add Create Agent entry on Squad detail (MUL-2178) (#2579)
Adds a Create Agent button on the Squad detail Members tab, visible only to workspace owner/admin (matching the AddSquadMember backend gate). The dialog reuses the existing CreateAgentDialog — both the manual and template paths now accept an optional squadId; when set, the dialog runs addSquadMember after createAgent / createAgentFromTemplate and skips the navigation to the agent detail page so the user lands back on the Members tab. Atomicity is best-effort frontend-serial (no new backend transaction): on partial failure the dialog surfaces a warning toast and the agent remains addable from the existing Add Member flow. Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
87464f6c03 |
fix(squads): i18n the Squad pages to unblock views#lint (CI red on main) (#2542)
#2505 (Squad MVP) merged with 29 hardcoded English strings in JSX text nodes — packages/views/squads/components/squads-page.tsx (4) and squad-detail-page.tsx (25). The package's eslint config enforces `i18next/no-literal-string` as ERROR for every .tsx file, so @multica/views#lint has been red on main, which Turbo cascades to @multica/web#build, @multica/desktop#build, and @multica/views#typecheck — effectively blocking every open PR's frontend CI (#2538, #2540, etc.). Rather than disabling the rule for the Squad files (which would just hide debt in a high-visibility surface), wire up a proper i18n namespace and replace every flagged literal. Namespace plumbing - New `packages/views/locales/en/squads.json` and `packages/views/locales/zh-Hans/squads.json` covering all 29 flagged strings, grouped by surface (page / inspector / name_editor / add_member_dialog / description_dialog / discard_changes_dialog / members_tab / instructions_tab). - Registered in `packages/views/locales/index.ts` and `packages/views/i18n/resources-types.ts` so `t($ => $.squads.*)` is type-safe. Component replacements - `squads-page.tsx`: add `useT("squads")`, replace 4 literals. - `squad-detail-page.tsx`: add `useT("squads")` to seven inner components that hold flagged text (`SquadDetailPage` / `InlineEdit Popover` / `AddMemberDialog` / `RoleEditor` / `SquadDescriptionEditor` / `SquadDescriptionEditorBody` / `SquadOverviewPane` / `SquadMembers Tab` / `SquadInstructionsTab` / `SquadDetailInspector`), replace all flagged literals. - Plural members count uses i18next's standard `_one` / `_other` suffixes via `t(..., { count })` — matches the convention already used in `runtimes/usage` and `agents`. Notes - A few unflagged user-facing strings remain (tab labels in squadDetailTabs array, ternary alternatives like `"Save"` inside `{x ? <Loader/> : "Save"}`, the inline `confirm()` archive prompt, the `toast.success("Leader updated")` message). The eslint rule uses `mode: "jsx-text-only"` so it only flags string children of JSX nodes; attribute strings, object-literal values, and ternary alternatives slip past. Those are real i18n gaps too but expanding scope here would gold-plate the CI-unblock fix. Verification - `pnpm --filter @multica/views lint`: 0 errors (was 29). Remaining 13 warnings are pre-existing in unrelated files and don't fail CI. - `pnpm typecheck`: 6/6 packages pass — namespace types resolve, all selector calls infer correctly. |
||
|
|
29082f7cfe |
feat: implement Squad feature MVP (#2505)
* feat: implement Squad feature MVP
- Add migration 084_squad: squad, squad_member, squad_activity_log tables
- Extend issue.assignee_type to support 'squad'
- Add sqlc queries for squad CRUD, member management, activity logs
- Add Go handler with full Squad API (CRUD, members, activity log)
- Register routes: /api/squads/*, /api/issues/{id}/squad-activity, /api/squad-activity
- Add Squad trigger logic:
- Assign Squad immediately triggers leader
- Every external comment on squad-assigned issue triggers leader
- Anti-loop: squad members' comments don't trigger leader
- Dedup: skip if leader already has pending task
- Add squad activity log API (方案 B) for leader no-op recording
- Add frontend TypeScript types (Squad, SquadMember, SquadActivityLog)
- Add protocol events: squad:created, squad:updated, squad:deleted
Co-authored-by: multica-agent <github@multica.ai>
* fix: address PR review blocking issues
1. validateAssigneePair now accepts 'squad' assignee_type
2. All squad endpoints validate workspace ownership via GetSquadInWorkspace
3. CreateSquadActivityLog restricted to squad leader agent only
4. AddSquadMember validates member exists in workspace
5. UpdateSquad auto-adds new leader to squad members
6. DeleteSquad transfers assigned issues to leader before deletion
7. IssueAssigneeType includes 'squad' in frontend types
Co-authored-by: multica-agent <github@multica.ai>
* feat: soft-delete squads via archive instead of hard delete
- Add migration 085: archived_at + archived_by columns on squad table
- ListSquads now excludes archived squads (ListAllSquads for admin)
- DeleteSquad → ArchiveSquad (sets archived_at, preserves all records)
- Transfer squad-assigned issues to leader before archiving
- SquadResponse includes archived_at/archived_by fields
- Frontend Squad type updated with nullable archived fields
Co-authored-by: multica-agent <github@multica.ai>
* feat: re-add Squads frontend entry (sidebar nav + pages)
Re-applies the frontend squad entry that was lost during a merge:
- Sidebar nav: Squads item with Users icon
- Paths: squads() and squadDetail() in workspace paths
- Routes: /squads and /squads/[id] pages
- Views: SquadsPage (list) and SquadDetailPage
- i18n: en 'Squads' / zh '小队'
- Reserved slug: 'squads'
Co-authored-by: multica-agent <github@multica.ai>
* fix: fix SquadsPage rendering - use PageHeader children pattern
PageHeader takes children, not title/actions props. The incorrect
usage caused a React rendering error. Now matches the pattern used
by autopilots and agents pages.
Co-authored-by: multica-agent <github@multica.ai>
* fix(squads): add API client methods and package export for squads pages
* feat: complete Squad frontend - create dialog, member management, API methods
- Add CreateSquadModal with name/description/leader selection
- Register 'create-squad' in modal registry
- Wire 'New Squad' button to open the modal
- Add full API client methods: createSquad, updateSquad, deleteSquad,
addSquadMember, removeSquadMember
- Rewrite SquadDetailPage with:
- Member list showing resolved names
- Add/remove member UI
- Archive squad button
- Back navigation to squads list
Co-authored-by: multica-agent <github@multica.ai>
* feat: improve Squad UI - match create agent dialog style
- CreateSquadModal: proper Dialog with Header/Description/Footer,
agent picker with avatars, textarea for description
- SquadDetailPage: centered max-w-2xl layout, ActorAvatar for members,
Crown badge for leader, textarea for member description,
improved spacing and visual hierarchy
- Renamed 'role' field label to 'Description' in add member form
(describes the member's responsibilities in the squad)
Co-authored-by: multica-agent <github@multica.ai>
* feat(squad): add avatar, instructions; drop unique-name constraint
- 086: add squad.avatar_url
- 087: drop unique constraint on squad.name (squads with the same
name are legitimate across teams; uniqueness was an accidental
product constraint)
- 088: add squad.instructions (text, default '')
- UpdateSquad now COALESCEs avatar_url + instructions
- handler exposes Instructions in SquadResponse and accepts it in
UpdateSquad
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): assignable + mention target; trigger leader on assign
- assignee picker and @mention suggestion list squads alongside
agents and members; renders squad avatar/icon
- creating or updating an issue with assignee_type=squad enqueues
a task for the squad's current leader (mirrors agent-assignee
parking-lot rule: skip backlog only)
- workspace queries/hooks expose squads where needed for the
pickers
- locales updated for new picker copy
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): agent-style detail page with members + instructions tabs
- restructure squad detail page to mirror the agent detail page:
320px inspector (creator, leader, created/updated) + tabbed
pane (Members | Instructions) with dirty-guard AlertDialog
- inline name + avatar editing on the inspector
- inline description editor (modal textarea)
- members tab: leader + member picker with role descriptions,
swap leader, edit member roles, remove
- instructions tab: ContentEditor + Save (mirrors agent pattern)
- squads list shows the squad avatar/icon
- core types + api.updateSquad accept avatar_url + instructions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): inject leader briefing on claim (protocol + roster + instructions)
When a squad's leader agent claims a task on a squad-assigned issue,
append a system-level briefing to the agent's Instructions composed of:
1. Squad Operating Protocol — hard-coded rules: leader is a
coordinator, dispatch via @mention, stop after dispatching,
resume on re-trigger, do not work outside the roster.
2. Squad Roster — leader self-row plus one row per non-archived
member with a literal mention markdown string ([@Name](mention://
agent|member/<UUID>)) the leader can paste verbatim. Round-trips
through util.ParseMentions, enforced by a contract test.
3. Squad Instructions — the user-defined squad.instructions block,
omitted entirely when empty so we do not leave a dangling heading.
Non-leader members claiming the same issue receive no briefing.
Tests cover: full squad with mixed agent/human members, lone leader,
archived agents skipped, empty user instructions, mention round-trip,
and the leader/non-leader claim-handler gate.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(squad): tell leader not to restate issue context in dispatch comment
After observing leaders padding their delegation comments with full
re-summaries of the issue body and prior discussion, make the
Operating Protocol explicit:
- assignees on Multica already have the full issue (title,
description, all comments, attachments) and workspace context;
- delegation comments should add only what cannot be inferred
(who is picked, why, extra constraints), aim for two or three
sentences;
- restating context is now an explicit hard rule violation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): unify leader evaluation into activity_log, add CLI command
- Squad member comments now trigger leader (only leader self-excluded)
- Replace squad_activity_log with activity_log (action: squad_leader_evaluated)
- Add CLI: multica squad activity <issue-id> <outcome> --reason
- Add API: POST /api/issues/{id}/squad-evaluated
- Update squad operating protocol to require evaluation recording
- Remove squad_activity_log table from schema and generated code
* feat(cli): add squad list, get, member list commands
* fix(squad): address review findings (P1+P2)
P1 fixes:
- Add 'squads' to reserved_slugs.json (source of truth)
- Add 'create-squad' to ModalType union
- Remove unused leaderOpen/selectedLeader in create-squad modal
- Replace literal JSX strings with i18n selectors (en + zh-Hans)
P2 fixes:
- Add 'squad' to mention regex (MentionRe)
- Fix human member lookup in squad briefing (use GetUser directly)
- Add squads routes to desktop app
- Add squad:created/updated/deleted to WSEventType + invalidation
- Reject archived squads as issue assignees
* fix(squad): restore zh-Hans key, publish activity event, invalidate issues on archive
- Restore create_project.title in zh-Hans modals.json (dropped by prior edit)
- Publish activity:created WS event after squad leader evaluation
- Invalidate issue queries on squad:deleted (archive transfers assignees)
- Add creator info to squad list cards
* fix(squad): realtime sync, rerun support, leader validation
- Use workspaceKeys.squads prefix for detail/member queries (realtime invalidation)
- Publish squad:updated after add/remove/role-change member mutations
- Support rerun for squad-assigned issues (targets leader agent)
- Reject assignment to squads whose leader is archived
---------
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|