Commit Graph

8 Commits

Author SHA1 Message Date
hongming-personal 8e97a39dcf rfc: add concierge-identity sibling anti-pattern (hardcoded in core → should be a template) 2026-06-14 10:25:14 +00:00
hongming-personal 6d787ca7ad docs(rfc): decouple workspace config + skill delivery from Secrets Manager 2026-06-14 10:16:42 +00:00
claude-ceo-assistant a3d3bec5c3 Merge pull request 'feat(requests): P1 — unified requests/inbox data model + endpoints (RFC)' (#2525) from feat/unified-requests-inbox-p1 into main 2026-06-10 14:14:21 +00:00
claude-ceo-assistant 12fbe21e47 docs(rfc): Agent Liveness — no-hang guarantee (tool timeouts + non-blocking A2A + stall watchdog)
Specs the 3-layer fix for silently-hung agents (JRS lost ~2.5h today): L1 bounded
tool execution, L2 non-blocking A2A rollout, L3 platform stall-watchdog with
probe->restart across all tenants. CTO design-approved; awaiting build sign-off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 11:19:57 +00:00
devops-engineer 59e5b20724 feat(requests): P1 — unified requests/inbox data model + endpoints (RFC)
Implements Phase 1 of the unified-requests-inbox RFC: a single `requests`
subsystem that generalizes `user_tasks` (agent→user worklist asks) and
`approval_requests` (the destructive-action gate) into one inbox keyed by
`kind ∈ {task, approval}`, where requester and recipient may each be a user
OR an agent. Responding is asynchronous — the requester never blocks; a
REQUEST_RESPONDED event signals it to pick the answer up on its next tick.

Schema (migrations/20260610120000_requests.{up,down}.sql, idempotent):
- `requests`: kind, requester_{type,id}, org_id, recipient_{type,id}, title,
  detail, status (pending|info_requested|done|rejected|approved|cancelled),
  responder_{type,id}, priority, created/updated/responded_at. recipient_id /
  requester_id are plain TEXT with NO FK (a party may be a user, not a
  workspaces row). Indexes for inbox, org-pending, and outgoing reads.
- `request_messages`: the More-Info / "chat about this" thread (FK → requests,
  ON DELETE CASCADE), indexed by (request_id, created_at).
- Idempotent backfill (ON CONFLICT (id) DO NOTHING) copies historical
  user_tasks (kind=task; dismissed→rejected) and approval_requests
  (kind=approval; denied→rejected, escalated→pending) into the unified inbox
  so the tabs show pre-cutover items.

Store (internal/handlers/request_store.go): RequestStore mirrors UserTaskStore
— per-request over global db.DB, events.EventEmitter for testability, sentinel
errors. Create / Get / Messages / ListInbox / ListOutgoing / ListPendingForOrg
(LEFT JOIN workspaces for the agent name) / Respond (validates action↔kind:
approval→approved|rejected, task→done|rejected) / RequestInfo / AddMessage
(flips info_requested when the recipient asks back) / Cancel. Mutations
broadcast REQUEST_CREATED / REQUEST_RESPONDED / REQUEST_MESSAGE anchored on the
agent party so the canvas/inbox is signalled.

Handler (internal/handlers/requests.go) + routes
(internal/router/router.go), mirroring the approvals/user-tasks auth split:
- wsAuth (workspace token): POST /workspaces/:id/requests, GET .../requests
  (outgoing), GET .../requests/inbox, plus agent-side
  .../requests/:requestId/{get,respond,messages,cancel}.
- AdminAuth (canvas user): GET /requests/pending?kind=task|approval (the tabs),
  and /requests/:requestId/{get,respond,messages,cancel}. The org_id anchor is
  resolved via orgRootID (org_scope.go) — the workspaces table has no org_id
  column.

Events (internal/events/types.go): adds REQUEST_CREATED, REQUEST_RESPONDED,
REQUEST_MESSAGE to the taxonomy + AllEventTypes; drift snapshot
(types_test.go) updated. Canvas TS mirror is a later phase (not touched here).

Tests (internal/handlers/requests_test.go): 20 cases via the existing sqlmock
harness — create (task + approval, agent recipient), inbox vs outgoing,
get+thread, respond (valid + invalid action-for-kind + not-found), More-Info
message → info_requested (recipient flips, requester doesn't), cancel, org
pending list + kind filter, recipient routing.

This is P1 of the unified-requests RFC. Follow-ons: P2 MCP tools + approval
shims, P3 canvas Tasks/Approvals tabs UI, P4 idle-nudge worker. Not included
here.

RFC: docs/design/rfc-unified-requests-inbox.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 10:23:24 +00:00
core-devops 6a87864176 feat(user-tasks): workspace-scoped read/update/delete of own tasks
A workspace can now manage the asks it raised (not just create them),
mirroring how it would manage its own resources:

REST (WorkspaceAuth, scoped by workspace_id so an agent only touches tasks
it raised):
- GET    /workspaces/:id/user-tasks            — list own tasks (any status)
- PATCH  /workspaces/:id/user-tasks/:taskId    — update own {title,detail,status}
- DELETE /workspaces/:id/user-tasks/:taskId    — delete own task

MCP (in-workspace a2a bridge, available to every agent):
- list_user_tasks()                            — read own asks + status
- update_user_task(user_task_id, title?, detail?, status?)
- delete_user_task(user_task_id)

These complement the existing request_user_action (create) and the user-side
/resolve. Confirms the design: any workspace (not just platform) can create
and manage tasks; the Home list stays org-wide. Handler tests cover
list/update/delete (+ not-found). go build + vet clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:02:00 -07:00
core-devops 3a6f447874 feat(user-tasks): agent→user action requests primitive + concierge wiring
New `user_tasks` primitive — things an agent asks the *user* to do (e.g.
"Review the draft"). Any workspace can raise one; they surface in the
concierge Home Tasks list org-wide. Mirrors the approvals subsystem.

Backend (workspace-server):
- migration 20260607000000_user_tasks (id, workspace_id, title, detail,
  status pending|done|dismissed, timestamps).
- handlers/user_tasks.go — Create (POST /workspaces/:id/user-tasks),
  ListAll (GET /user-tasks/pending, AdminAuth, cross-workspace),
  Resolve (POST /workspaces/:id/user-tasks/:taskId/resolve done|dismissed).
- events USER_TASK_REQUESTED / USER_TASK_RESOLVED (+ drift-test snapshot).
- router wiring mirroring the approvals auth split.
- MCP tool `request_user_action(title, detail?)` on the in-workspace a2a
  bridge — available to EVERY agent, not gated like send_message_to_user.
- user_tasks_test.go (create/resolve happy + validation paths).

Canvas: concierge Home Tasks tab now reads /user-tasks/pending (org-wide)
with Done/Dismiss → resolve, replacing the interim schedules wiring; live
tab count.

Design SSOT: docs/design/rfc-user-tasks.md.
Follow-up (next commit): workspace-scoped read/update/delete of own tasks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:58:40 -07:00
core-devops 79be721591 docs(rfc): org-level platform agent — tenant-resident concierge (design SSOT)
Architecture RFC for an always-on per-tenant platform agent that holds the
platform-management MCP natively, joins A2A as a first-class kind='platform'
participant at the org root, and is the user's default concierge. Captures the
SSOT mapping, the platform-as-root + re-parenting model, the two-MCP runtime,
and the server-side approval gate. Pre-implementation; needs CTO sign-off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 03:01:18 -07:00