@chorus-aidlc/chorus 0.17.3 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-build-manifest.json +345 -341
- package/.next/standalone/.next/app-path-routes-manifest.json +35 -35
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +27 -27
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/settings/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new.html +2 -2
- package/.next/standalone/.next/server/app/admin/companies/new.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies.html +2 -2
- package/.next/standalone/.next/server/app/admin/companies.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin.html +2 -2
- package/.next/standalone/.next/server/app/admin.rsc +2 -2
- package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agent-connections/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent-connections/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/comments/route.js +1 -1
- package/.next/standalone/.next/server/app/api/comments/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/control/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/control/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/control/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/execution-state/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/execution-state/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/executions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/executions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/pending-turns/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/resume/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/resume/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/resume/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/transcript/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/transcript/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/transcript/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon/turn-advance/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js +1 -1
- package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/notifications/route.js +1 -1
- package/.next/standalone/.next/server/app/api/events/notifications/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/route.js +1 -1
- package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/conversational/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/conversational/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/conversational/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mcp/route.js +1 -1
- package/.next/standalone/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route.js +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mentionables/route.js +1 -1
- package/.next/standalone/.next/server/app/api/mentionables/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/preferences/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/preferences/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/read-all/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/read-all/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/pin/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/visit/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/references/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/references/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +2 -2
- package/.next/standalone/.next/server/app/index.rsc +2 -2
- package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/admin.html +2 -2
- package/.next/standalone/.next/server/app/login/admin.rsc +2 -2
- package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/callback.html +2 -2
- package/.next/standalone/.next/server/app/login/callback.rsc +2 -2
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace.html +2 -2
- package/.next/standalone/.next/server/app/login/pick-workspace.rsc +2 -2
- package/.next/standalone/.next/server/app/login.html +2 -2
- package/.next/standalone/.next/server/app/login.rsc +2 -2
- package/.next/standalone/.next/server/app/onboarding/page.js +2 -2
- package/.next/standalone/.next/server/app/onboarding/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/onboarding.html +2 -2
- package/.next/standalone/.next/server/app/onboarding.rsc +3 -3
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects.html +2 -2
- package/.next/standalone/.next/server/app/projects.rsc +3 -3
- package/.next/standalone/.next/server/app/settings.html +2 -2
- package/.next/standalone/.next/server/app/settings.rsc +4 -4
- package/.next/standalone/.next/server/app-paths-manifest.json +35 -35
- package/.next/standalone/.next/server/chunks/1318.js +1 -1
- package/.next/standalone/.next/server/chunks/{5201.js → 1416.js} +2 -2
- package/.next/standalone/.next/server/chunks/1559.js +2 -2
- package/.next/standalone/.next/server/chunks/{3630.js → 2195.js} +1 -1
- package/.next/standalone/.next/server/chunks/2460.js +1 -0
- package/.next/standalone/.next/server/chunks/2572.js +2 -2
- package/.next/standalone/.next/server/chunks/2758.js +1 -0
- package/.next/standalone/.next/server/chunks/2961.js +1 -1
- package/.next/standalone/.next/server/chunks/3419.js +1 -1
- package/.next/standalone/.next/server/chunks/4066.js +1 -0
- package/.next/standalone/.next/server/chunks/4827.js +1 -1
- package/.next/standalone/.next/server/chunks/5245.js +1 -1
- package/.next/standalone/.next/server/chunks/5453.js +1 -1
- package/.next/standalone/.next/server/chunks/5489.js +1 -1
- package/.next/standalone/.next/server/chunks/6113.js +1 -1
- package/.next/standalone/.next/server/chunks/6506.js +2 -2
- package/.next/standalone/.next/server/chunks/6737.js +1 -0
- package/.next/standalone/.next/server/chunks/679.js +1 -1
- package/.next/standalone/.next/server/chunks/7368.js +1 -1
- package/.next/standalone/.next/server/chunks/7530.js +1 -1
- package/.next/standalone/.next/server/chunks/7578.js +2 -2
- package/.next/standalone/.next/server/chunks/7675.js +1 -0
- package/.next/standalone/.next/server/chunks/7789.js +1 -0
- package/.next/standalone/.next/server/chunks/{1201.js → 8030.js} +2 -2
- package/.next/standalone/.next/server/chunks/920.js +1 -1
- package/.next/standalone/.next/server/chunks/9213.js +1 -1
- package/.next/standalone/.next/server/chunks/9378.js +1 -1
- package/.next/standalone/.next/server/chunks/9931.js +1 -1
- package/.next/standalone/.next/server/instrumentation.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/11595.f080a1d100972212.js +1 -0
- package/.next/standalone/.next/static/chunks/14628-283d3983d1fb36c9.js +1 -0
- package/.next/standalone/.next/static/chunks/{29305-f587e7e81bc0b200.js → 17562-56f932146e9e6c94.js} +4 -4
- package/.next/standalone/.next/static/chunks/25080-25ad29e64c855338.js +1 -0
- package/.next/standalone/.next/static/chunks/28698-7fb271ffc6e63a26.js +1 -0
- package/.next/standalone/.next/static/chunks/{95225-96b44da3ebd6ddad.js → 32736-aeaaa1e4c4d5529b.js} +1 -1
- package/.next/standalone/.next/static/chunks/33456.20313bd67a5c41cc.js +1 -0
- package/.next/standalone/.next/static/chunks/4860.3b555a398cdffb19.js +1 -0
- package/.next/standalone/.next/static/chunks/75257-99c0ce24b436847b.js +1 -0
- package/.next/standalone/.next/static/chunks/79919-0c6dcda1dd8646f0.js +1 -0
- package/.next/standalone/.next/static/chunks/91328-f501e3c3ca519a92.js +1 -0
- package/.next/standalone/.next/static/chunks/94643-e54eff17e941a93b.js +1 -0
- package/.next/standalone/.next/static/chunks/99373.b8a95d1bec5ad4e7.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-f3c6431432d42c7c.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/{page-77b175e52a85f3cb.js → page-5d723f974bdad33b.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-8d3b1f4d8b76d66c.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/page-57c698dea2fa6e29.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/{page-69d3162667f85677.js → page-d2bb622855e746f1.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-fc255dc3612032b9.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/{page-a3f83031dfbafc81.js → page-f032ee8a80d1f56a.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-46a0ddfd0421b0a8.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/{page-3c7ff3a40a4615ac.js → page-3a83748ce0ae1c4f.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/{page-7b8e11fdc5b596d0.js → page-8af9bb9f96ab0258.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-b02939820affdae5.js +1 -0
- package/.next/standalone/.next/static/chunks/app/onboarding/page-d2c0c7951114e763.js +1 -0
- package/.next/standalone/.next/static/chunks/{webpack-dffb97a4feb8faba.js → webpack-de8a36d232a91d6b.js} +1 -1
- package/.next/standalone/.next/static/css/44f13b43a3de716d.css +1 -0
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +2 -2
- package/.next/standalone/public/chorus-plugin/agents/code-reviewer.md +1 -0
- package/.next/standalone/public/chorus-plugin/agents/proposal-reviewer.md +12 -3
- package/.next/standalone/public/chorus-plugin/agents/task-reviewer.md +4 -0
- package/.next/standalone/public/chorus-plugin/bin/chorus-api.sh +1 -1
- package/.next/standalone/public/chorus-plugin/bin/on-post-submit-for-verify.sh +3 -3
- package/.next/standalone/public/chorus-plugin/bin/on-post-submit-proposal.sh +3 -3
- package/.next/standalone/public/chorus-plugin/bin/on-post-verify-task.sh +2 -2
- package/.next/standalone/public/chorus-plugin/bin/on-pre-spawn-agent.sh +22 -9
- package/.next/standalone/public/chorus-plugin/bin/on-session-start.sh +39 -64
- package/.next/standalone/public/chorus-plugin/bin/on-subagent-start.sh +44 -29
- package/.next/standalone/public/chorus-plugin/bin/on-subagent-stop.sh +100 -29
- package/.next/standalone/public/chorus-plugin/bin/resolve-spec-mode.sh +107 -0
- package/.next/standalone/public/chorus-plugin/bin/test-syntax.sh +6 -2
- package/.next/standalone/public/chorus-plugin/bin/tests/test-resolver-drift.sh +46 -0
- package/.next/standalone/public/chorus-plugin/bin/tests/test-skill-harness-fidelity-negative.sh +328 -0
- package/.next/standalone/public/chorus-plugin/bin/tests/test-skill-harness-fidelity.sh +372 -0
- package/.next/standalone/public/chorus-plugin/bin/tests/test-spec-mode-resolution.sh +83 -0
- package/.next/standalone/public/chorus-plugin/bin/tests/test-subagent-session-name.sh +599 -0
- package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +11 -6
- package/.next/standalone/public/chorus-plugin/skills/chorus-cli/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +14 -9
- package/.next/standalone/public/chorus-plugin/skills/docs/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +27 -31
- package/.next/standalone/public/chorus-plugin/skills/orchestrate/SKILL.md +11 -1
- package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +14 -7
- package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +6 -4
- package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +10 -8
- package/.next/standalone/public/chorus-plugin/skills/spec-lite/SKILL.md +147 -0
- package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +49 -34
- package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-code-reviewer.json +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-proposal-reviewer.json +2 -1
- package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-task-reviewer.json +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-cli/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +9 -7
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-docs/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-idea/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-openspec-aware/SKILL.md +35 -27
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-orchestrate/SKILL.md +9 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +14 -7
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +8 -8
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-spec-lite/SKILL.md +147 -0
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +39 -25
- package/.next/standalone/public/kiro-plugin/.kiro/steering/chorus.md +11 -6
- package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +1 -1
- package/.next/standalone/public/kiro-plugin/bin/on-agent-spawn.sh +41 -0
- package/.next/standalone/public/kiro-plugin/bin/on-post-submit-for-verify.sh +3 -3
- package/.next/standalone/public/kiro-plugin/bin/on-post-submit-proposal.sh +3 -3
- package/.next/standalone/public/kiro-plugin/bin/on-post-verify-task.sh +2 -2
- package/.next/standalone/public/kiro-plugin/bin/resolve-spec-mode.sh +107 -0
- package/.next/standalone/public/kiro-plugin/manifest.txt +2 -0
- package/.next/standalone/public/skill/chorus/SKILL.md +11 -1
- package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +1 -0
- package/.next/standalone/public/skill/develop-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/orchestrate-chorus/SKILL.md +11 -1
- package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +5 -2
- package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/review-chorus/SKILL.md +5 -3
- package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +4 -0
- package/.next/standalone/public/skill/yolo-chorus/SKILL.md +23 -7
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/README.zh.md +3 -3
- package/chorus.mjs +30 -2
- package/cli/agent-cli-config.mjs +323 -0
- package/cli/agent-launcher.mjs +44 -16
- package/cli/child-exit.mjs +77 -0
- package/cli/claude-spawner.mjs +26 -14
- package/cli/codex-spawner.mjs +27 -16
- package/cli/control-handler.mjs +104 -6
- package/cli/credentials.mjs +7 -0
- package/cli/daemon-config.mjs +14 -0
- package/cli/daemon-rest-client.mjs +98 -29
- package/cli/daemon.mjs +37 -7
- package/cli/dsh-managed-config.mjs +26 -28
- package/cli/dsh-spawner.mjs +27 -16
- package/cli/init/steps/credential-seed.mjs +1 -1
- package/cli/kiro-spawner.mjs +26 -16
- package/cli/launch-diagnostics.mjs +67 -0
- package/cli/login.mjs +17 -1
- package/cli/pi-spawner.mjs +23 -13
- package/cli/prompts.mjs +52 -2
- package/cli/spawner-select.mjs +6 -11
- package/package.json +1 -1
- package/.next/standalone/.next/server/chunks/1114.js +0 -1
- package/.next/standalone/.next/server/chunks/1155.js +0 -1
- package/.next/standalone/.next/server/chunks/6465.js +0 -1
- package/.next/standalone/.next/server/chunks/8105.js +0 -1
- package/.next/standalone/.next/server/chunks/8232.js +0 -1
- package/.next/standalone/.next/static/chunks/11595.f7c3ef5cd7fc8feb.js +0 -1
- package/.next/standalone/.next/static/chunks/33456.c81079032acc2966.js +0 -1
- package/.next/standalone/.next/static/chunks/45262-38b332523f00a223.js +0 -1
- package/.next/standalone/.next/static/chunks/46021-f5d072b0cbcb7fac.js +0 -1
- package/.next/standalone/.next/static/chunks/4860.f0cfb1201191ae88.js +0 -1
- package/.next/standalone/.next/static/chunks/66609-64a01d5cb415465b.js +0 -1
- package/.next/standalone/.next/static/chunks/79919-c5a2a3fd8f5f9204.js +0 -1
- package/.next/standalone/.next/static/chunks/94394-38194b81b489275c.js +0 -1
- package/.next/standalone/.next/static/chunks/94643-f1bdf37fb3bb6adb.js +0 -1
- package/.next/standalone/.next/static/chunks/96482-2b3bdb2544d72e5a.js +0 -1
- package/.next/standalone/.next/static/chunks/99373.3c23ac2efbd4db02.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-66328332f62c7371.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-87ceae13c4950fc9.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/page-45e95154e546460e.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-b7b2017e5be69564.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-8b06834ca0f663bb.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-efe5326c47aca9ca.js +0 -1
- package/.next/standalone/.next/static/chunks/app/onboarding/page-0ce33b9327fe3d8c.js +0 -1
- package/.next/standalone/.next/static/css/1d9cf83f50b6db00.css +0 -1
- /package/.next/standalone/.next/static/{wuqYN129vOIGymh_NEdZe → dot63ILT878Tloqi7Czj_}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{wuqYN129vOIGymh_NEdZe → dot63ILT878Tloqi7Czj_}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test-subagent-session-name.sh — Regression test for Claude Code sub-agent
|
|
3
|
+
# session NAMING (on-pre-spawn-agent.sh + on-subagent-start.sh).
|
|
4
|
+
#
|
|
5
|
+
# The defect this guards against: `tool_input.name` does not exist on CC's Task
|
|
6
|
+
# tool, so the name was empty at PreToolUse time, the pending filename became
|
|
7
|
+
# `unknown-$(date +%s%N)`, and SubagentStart used that filename as the session
|
|
8
|
+
# name — every sub-agent session showed up in Chorus as `unknown-<19 digits>`.
|
|
9
|
+
#
|
|
10
|
+
# The fix: the session name comes from the SubagentStart event's own
|
|
11
|
+
# `agent_type`, falling back to `worker-<agent_id first 8>`. The pending file is
|
|
12
|
+
# only a SPAWN GATE (proof the SubagentStart came from a real Task call), never a
|
|
13
|
+
# name channel.
|
|
14
|
+
#
|
|
15
|
+
# Harness mechanism — why we copy the hooks:
|
|
16
|
+
# Both hooks resolve their MCP wrapper as `API="${SCRIPT_DIR}/chorus-api.sh"`
|
|
17
|
+
# from `dirname "$0"`, so a PATH shim would NOT be picked up. We therefore
|
|
18
|
+
# COPY each hook into a sandbox dir next to a stub `chorus-api.sh` that RECORDS
|
|
19
|
+
# (tool, payload) pairs to a log instead of calling a server — the same
|
|
20
|
+
# convention as tests/test-on-post-verify-task.sh.
|
|
21
|
+
#
|
|
22
|
+
# We deliberately do NOT copy `chorus-paths.sh` into the sandbox: that file
|
|
23
|
+
# unconditionally recomputes CHORUS_STATE_DIR from ~/.chorus. Both hooks source
|
|
24
|
+
# it fail-soft (`[ -f ... ] && ...`), so with it absent they honor the
|
|
25
|
+
# CHORUS_STATE_DIR we export, and the test never touches the real ~/.chorus.
|
|
26
|
+
#
|
|
27
|
+
# Cases:
|
|
28
|
+
# 1. positive — agent_type "claude" -> session name == "claude"
|
|
29
|
+
# 2. fallback — empty agent_type -> name == worker-<agentId8>
|
|
30
|
+
# 3. no unknown-* — asserted in every case, on the session name AND on the
|
|
31
|
+
# pending filename
|
|
32
|
+
# 4. parallel batch — two same-second Task spawns of the same subagent_type
|
|
33
|
+
# write two DISTINCT pending files; two SubagentStart runs
|
|
34
|
+
# each claim one and each get its OWN event's agent_type
|
|
35
|
+
# as the name (FIFO mis-pairing can no longer mis-name)
|
|
36
|
+
# 5. gate — SubagentStart with an empty pending dir issues NO
|
|
37
|
+
# chorus_create_session and exits 0
|
|
38
|
+
# 6. skip parity — a Task spawn of a skip-listed type (chorus:task-reviewer)
|
|
39
|
+
# writes NO pending file, so it cannot be FIFO-claimed
|
|
40
|
+
# later by an unrelated agent
|
|
41
|
+
# 7. shared stop — TEARDOWN of a shared type-named session (on-subagent-stop.sh).
|
|
42
|
+
# Two same-type sub-agents reuse ONE session, so the stop
|
|
43
|
+
# hook refcounts holders on disk
|
|
44
|
+
# (<state>/holders/<sanitized name>/<agentId>): the FIRST
|
|
45
|
+
# exit must NOT close the session, must NOT check the
|
|
46
|
+
# sibling's task out, must NOT auto-verify and must leave
|
|
47
|
+
# session_<name> / sessions/<name>.json /
|
|
48
|
+
# agent_for_session_<uuid> intact; the LAST exit must tear
|
|
49
|
+
# everything down exactly as before.
|
|
50
|
+
# 8. single stop — the one-agent case is unchanged: close + full cleanup.
|
|
51
|
+
#
|
|
52
|
+
# Offline, self-contained, Bash 3.2 compatible. Run:
|
|
53
|
+
# /bin/bash public/chorus-plugin/bin/tests/test-subagent-session-name.sh
|
|
54
|
+
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
|
|
57
|
+
REPO_ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)"
|
|
58
|
+
PRE_SPAWN_HOOK="$REPO_ROOT/public/chorus-plugin/bin/on-pre-spawn-agent.sh"
|
|
59
|
+
SUBAGENT_START_HOOK="$REPO_ROOT/public/chorus-plugin/bin/on-subagent-start.sh"
|
|
60
|
+
SUBAGENT_STOP_HOOK="$REPO_ROOT/public/chorus-plugin/bin/on-subagent-stop.sh"
|
|
61
|
+
|
|
62
|
+
[ -f "$PRE_SPAWN_HOOK" ] || { echo "FAIL: missing $PRE_SPAWN_HOOK" >&2; exit 1; }
|
|
63
|
+
[ -f "$SUBAGENT_START_HOOK" ] || { echo "FAIL: missing $SUBAGENT_START_HOOK" >&2; exit 1; }
|
|
64
|
+
[ -f "$SUBAGENT_STOP_HOOK" ] || { echo "FAIL: missing $SUBAGENT_STOP_HOOK" >&2; exit 1; }
|
|
65
|
+
|
|
66
|
+
PASS=0
|
|
67
|
+
FAIL=0
|
|
68
|
+
FAILED=""
|
|
69
|
+
|
|
70
|
+
pass() {
|
|
71
|
+
echo " PASS $1"
|
|
72
|
+
PASS=$((PASS + 1))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fail() {
|
|
76
|
+
echo " FAIL $1: $2"
|
|
77
|
+
FAIL=$((FAIL + 1))
|
|
78
|
+
FAILED="$FAILED $1"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# ----- Sandbox -----
|
|
82
|
+
|
|
83
|
+
SANDBOX=$(mktemp -d)
|
|
84
|
+
cleanup() { rm -rf "$SANDBOX"; }
|
|
85
|
+
trap cleanup EXIT
|
|
86
|
+
|
|
87
|
+
HOOK_DIR="$SANDBOX/hooks"
|
|
88
|
+
mkdir -p "$HOOK_DIR"
|
|
89
|
+
cp "$PRE_SPAWN_HOOK" "$HOOK_DIR/on-pre-spawn-agent.sh"
|
|
90
|
+
cp "$SUBAGENT_START_HOOK" "$HOOK_DIR/on-subagent-start.sh"
|
|
91
|
+
cp "$SUBAGENT_STOP_HOOK" "$HOOK_DIR/on-subagent-stop.sh"
|
|
92
|
+
chmod +x "$HOOK_DIR/on-pre-spawn-agent.sh" "$HOOK_DIR/on-subagent-start.sh" \
|
|
93
|
+
"$HOOK_DIR/on-subagent-stop.sh"
|
|
94
|
+
|
|
95
|
+
# ----- Stub: chorus-api.sh -----
|
|
96
|
+
# Records every call as one line: <cmd>|<tool>|<payload> in $CHORUS_RECORD.
|
|
97
|
+
# mcp-tool chorus_list_sessions -> the sessions this sandbox has created so
|
|
98
|
+
# far (a per-case registry file), so
|
|
99
|
+
# reuse-by-name behaves like production
|
|
100
|
+
# mcp-tool chorus_create_session -> a fresh canned uuid, appended to the registry
|
|
101
|
+
# mcp-tool chorus_reopen_session -> flips registry status back to active
|
|
102
|
+
# mcp-tool chorus_close_session -> flips registry status to closed
|
|
103
|
+
# mcp-tool chorus_get_session -> $CHORUS_STUB_SESSION_JSON if set, else {}
|
|
104
|
+
# state-set/get/delete -> recorded AND backed by a real file store,
|
|
105
|
+
# so SubagentStop's state lookups resolve
|
|
106
|
+
# hook-output -> real jq, same JSON shape as production
|
|
107
|
+
cat > "$HOOK_DIR/chorus-api.sh" <<'STUB'
|
|
108
|
+
#!/usr/bin/env bash
|
|
109
|
+
set -euo pipefail
|
|
110
|
+
cmd="${1:-}"; shift || true
|
|
111
|
+
rec="${CHORUS_RECORD:-/dev/null}"
|
|
112
|
+
store="${CHORUS_STATE_DIR:-/tmp}/stubstate"
|
|
113
|
+
sessions_db="${CHORUS_STATE_DIR:-/tmp}/stub-sessions.json"
|
|
114
|
+
key_file() { printf '%s/%s' "$store" "$(printf '%s' "$1" | tr -c '[:alnum:]._-' '_')"; }
|
|
115
|
+
case "$cmd" in
|
|
116
|
+
mcp-tool)
|
|
117
|
+
tool="${1:-}"; payload="${2:-}"
|
|
118
|
+
printf 'mcp-tool|%s|%s\n' "$tool" "$payload" >> "$rec"
|
|
119
|
+
[ -f "$sessions_db" ] || echo '[]' > "$sessions_db"
|
|
120
|
+
case "$tool" in
|
|
121
|
+
chorus_list_sessions)
|
|
122
|
+
jq -c '{sessions: ., total: length}' "$sessions_db"
|
|
123
|
+
;;
|
|
124
|
+
chorus_create_session)
|
|
125
|
+
nm=$(printf '%s' "$payload" | jq -r '.name // empty')
|
|
126
|
+
n=$(jq 'length' "$sessions_db")
|
|
127
|
+
uuid=$(printf '11111111-2222-3333-4444-%012d' "$((n + 1))")
|
|
128
|
+
tmp=$(mktemp)
|
|
129
|
+
jq --arg u "$uuid" --arg n "$nm" '. + [{uuid:$u, name:$n, status:"active"}]' \
|
|
130
|
+
"$sessions_db" > "$tmp" && mv "$tmp" "$sessions_db"
|
|
131
|
+
jq -n --arg u "$uuid" --arg n "$nm" '{uuid:$u, name:$n}'
|
|
132
|
+
;;
|
|
133
|
+
chorus_reopen_session)
|
|
134
|
+
u=$(printf '%s' "$payload" | jq -r '.sessionUuid // empty')
|
|
135
|
+
tmp=$(mktemp)
|
|
136
|
+
jq --arg u "$u" 'map(if .uuid == $u then .status = "active" else . end)' \
|
|
137
|
+
"$sessions_db" > "$tmp" && mv "$tmp" "$sessions_db"
|
|
138
|
+
jq -n --arg u "$u" '{uuid:$u}'
|
|
139
|
+
;;
|
|
140
|
+
chorus_close_session)
|
|
141
|
+
u=$(printf '%s' "$payload" | jq -r '.sessionUuid // empty')
|
|
142
|
+
tmp=$(mktemp)
|
|
143
|
+
jq --arg u "$u" 'map(if .uuid == $u then .status = "closed" else . end)' \
|
|
144
|
+
"$sessions_db" > "$tmp" && mv "$tmp" "$sessions_db"
|
|
145
|
+
echo '{}'
|
|
146
|
+
;;
|
|
147
|
+
chorus_get_session)
|
|
148
|
+
if [ -n "${CHORUS_STUB_SESSION_JSON:-}" ] && [ -f "${CHORUS_STUB_SESSION_JSON}" ]; then
|
|
149
|
+
cat "${CHORUS_STUB_SESSION_JSON}"
|
|
150
|
+
else
|
|
151
|
+
echo '{}'
|
|
152
|
+
fi
|
|
153
|
+
;;
|
|
154
|
+
*) echo '{}' ;;
|
|
155
|
+
esac
|
|
156
|
+
;;
|
|
157
|
+
state-set)
|
|
158
|
+
printf 'state-set|%s|%s\n' "${1:-}" "${2:-}" >> "$rec"
|
|
159
|
+
mkdir -p "$store" 2>/dev/null || true
|
|
160
|
+
printf '%s' "${2:-}" > "$(key_file "${1:-}")"
|
|
161
|
+
;;
|
|
162
|
+
state-get)
|
|
163
|
+
printf 'state-get|%s|\n' "${1:-}" >> "$rec"
|
|
164
|
+
f="$(key_file "${1:-}")"
|
|
165
|
+
if [ -f "$f" ]; then cat "$f"; else echo ""; fi
|
|
166
|
+
;;
|
|
167
|
+
state-delete)
|
|
168
|
+
printf 'state-delete|%s|\n' "${1:-}" >> "$rec"
|
|
169
|
+
rm -f "$(key_file "${1:-}")" 2>/dev/null || true
|
|
170
|
+
;;
|
|
171
|
+
hook-output)
|
|
172
|
+
sm="${1:-}"; ac="${2:-}"; hen="${3:-}"
|
|
173
|
+
printf 'hook-output|%s|%s\n' "$hen" "$sm" >> "$rec"
|
|
174
|
+
if [ -n "$ac" ]; then
|
|
175
|
+
jq -n --arg sm "$sm" --arg ac "$ac" --arg hen "$hen" \
|
|
176
|
+
'{systemMessage:$sm, hookSpecificOutput:{hookEventName:$hen, additionalContext:$ac}}'
|
|
177
|
+
else
|
|
178
|
+
jq -n --arg sm "$sm" '{systemMessage:$sm}'
|
|
179
|
+
fi
|
|
180
|
+
;;
|
|
181
|
+
*)
|
|
182
|
+
echo "stub chorus-api.sh: unknown cmd $cmd" >&2; exit 2 ;;
|
|
183
|
+
esac
|
|
184
|
+
STUB
|
|
185
|
+
chmod +x "$HOOK_DIR/chorus-api.sh"
|
|
186
|
+
|
|
187
|
+
# ----- Per-case state -----
|
|
188
|
+
|
|
189
|
+
STATE_DIR=""
|
|
190
|
+
RECORD=""
|
|
191
|
+
LAST_RC=0
|
|
192
|
+
LAST_STDERR=""
|
|
193
|
+
STUB_SESSION_JSON=""
|
|
194
|
+
|
|
195
|
+
new_case() {
|
|
196
|
+
# $1 = case slug
|
|
197
|
+
STATE_DIR="$SANDBOX/state/$1"
|
|
198
|
+
RECORD="$SANDBOX/rec/$1.log"
|
|
199
|
+
mkdir -p "$STATE_DIR" "$SANDBOX/rec"
|
|
200
|
+
: > "$RECORD"
|
|
201
|
+
STUB_SESSION_JSON=""
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Start a fresh recording window inside the current case, so an assertion can
|
|
205
|
+
# say "this hook run issued no chorus_close_session" without earlier runs' calls
|
|
206
|
+
# leaking in. State and the session registry are untouched.
|
|
207
|
+
rec_reset() { : > "$RECORD"; }
|
|
208
|
+
|
|
209
|
+
# run_hook <hook-file> <event-json>
|
|
210
|
+
run_hook() {
|
|
211
|
+
local hook="$1"
|
|
212
|
+
local event="$2"
|
|
213
|
+
local err
|
|
214
|
+
err=$(mktemp)
|
|
215
|
+
LAST_RC=0
|
|
216
|
+
printf '%s' "$event" \
|
|
217
|
+
| env -i \
|
|
218
|
+
HOME="$SANDBOX/home" \
|
|
219
|
+
PATH="$PATH" \
|
|
220
|
+
CHORUS_URL="http://127.0.0.1:0" \
|
|
221
|
+
CHORUS_API_KEY="cho_test" \
|
|
222
|
+
CHORUS_STATE_DIR="$STATE_DIR" \
|
|
223
|
+
CHORUS_RECORD="$RECORD" \
|
|
224
|
+
CHORUS_STUB_SESSION_JSON="$STUB_SESSION_JSON" \
|
|
225
|
+
CLAUDE_PROJECT_DIR="$SANDBOX/project" \
|
|
226
|
+
/bin/bash "$HOOK_DIR/$hook" >/dev/null 2>"$err" || LAST_RC=$?
|
|
227
|
+
LAST_STDERR=$(cat "$err")
|
|
228
|
+
rm -f "$err"
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
pre_spawn() {
|
|
232
|
+
# $1 = subagent_type
|
|
233
|
+
run_hook "on-pre-spawn-agent.sh" \
|
|
234
|
+
"$(printf '{"session_id":"cc-sess-1","tool_name":"Task","tool_input":{"subagent_type":"%s","description":"do work","prompt":"go"}}' "$1")"
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
subagent_start() {
|
|
238
|
+
# $1 = agent_id, $2 = agent_type (may be empty)
|
|
239
|
+
run_hook "on-subagent-start.sh" \
|
|
240
|
+
"$(printf '{"session_id":"cc-sess-1","agent_id":"%s","agent_type":"%s"}' "$1" "$2")"
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
subagent_stop() {
|
|
244
|
+
# $1 = agent_id
|
|
245
|
+
run_hook "on-subagent-stop.sh" \
|
|
246
|
+
"$(printf '{"session_id":"cc-sess-1","agent_id":"%s"}' "$1")"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# How many times a given MCP tool was called in the current recording window.
|
|
250
|
+
tool_count() {
|
|
251
|
+
grep -c "^mcp-tool|$1|" "$RECORD" 2>/dev/null || true
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# Stub state store introspection (same key sanitization as the stub).
|
|
255
|
+
state_key_file() {
|
|
256
|
+
printf '%s/stubstate/%s' "$STATE_DIR" "$(printf '%s' "$1" | tr -c '[:alnum:]._-' '_')"
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
state_has() {
|
|
260
|
+
[ -f "$(state_key_file "$1")" ]
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
state_val() {
|
|
264
|
+
cat "$(state_key_file "$1")" 2>/dev/null || true
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
holder_count() {
|
|
268
|
+
# $1 = sanitized session name
|
|
269
|
+
ls -1 "$STATE_DIR/holders/$1" 2>/dev/null | grep -c . || true
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
pending_count() {
|
|
273
|
+
ls -1 "$STATE_DIR/pending" 2>/dev/null | grep -c . || true
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
pending_names() {
|
|
277
|
+
ls -1 "$STATE_DIR/pending" 2>/dev/null || true
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
# All names passed to chorus_create_session, one per line, in call order.
|
|
281
|
+
created_names() {
|
|
282
|
+
grep '^mcp-tool|chorus_create_session|' "$RECORD" 2>/dev/null \
|
|
283
|
+
| sed 's/^mcp-tool|chorus_create_session|//' \
|
|
284
|
+
| while IFS= read -r payload; do
|
|
285
|
+
printf '%s' "$payload" | jq -r '.name // empty'
|
|
286
|
+
done
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
created_count() {
|
|
290
|
+
grep -c '^mcp-tool|chorus_create_session|' "$RECORD" 2>/dev/null || true
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# Guard used by every case: a name must never look like the pre-fix placeholder.
|
|
294
|
+
assert_not_unknown() {
|
|
295
|
+
# $1 = case name, $2 = label, $3 = value
|
|
296
|
+
case "$3" in
|
|
297
|
+
unknown-*)
|
|
298
|
+
fail "$1" "$2 is the pre-fix placeholder shape 'unknown-*' (got '$3')"
|
|
299
|
+
return 1
|
|
300
|
+
;;
|
|
301
|
+
esac
|
|
302
|
+
return 0
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
echo "Sandbox: $SANDBOX"
|
|
306
|
+
echo ""
|
|
307
|
+
|
|
308
|
+
# ===== Case 1: positive — session name == event agent_type =====
|
|
309
|
+
new_case "positive"
|
|
310
|
+
pre_spawn "claude"
|
|
311
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
312
|
+
fail "positive" "on-pre-spawn-agent.sh exited $LAST_RC: $LAST_STDERR"
|
|
313
|
+
else
|
|
314
|
+
pending="$(pending_names)"
|
|
315
|
+
if ! assert_not_unknown "positive-pending-filename" "pending filename" "$pending"; then
|
|
316
|
+
:
|
|
317
|
+
else
|
|
318
|
+
pass "positive-pending-filename (no unknown-* filename: '$pending')"
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
subagent_start "agentid00deadbeef" "claude"
|
|
322
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
323
|
+
fail "positive" "on-subagent-start.sh exited $LAST_RC: $LAST_STDERR"
|
|
324
|
+
else
|
|
325
|
+
name="$(created_names)"
|
|
326
|
+
if [ "$name" != "claude" ]; then
|
|
327
|
+
fail "positive" "expected chorus_create_session name 'claude', got '$name'"
|
|
328
|
+
elif ! assert_not_unknown "positive" "session name" "$name"; then
|
|
329
|
+
:
|
|
330
|
+
else
|
|
331
|
+
pass "positive (session name == event agent_type 'claude')"
|
|
332
|
+
fi
|
|
333
|
+
fi
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
# ===== Case 2: fallback — empty agent_type -> worker-<agentId first 8> =====
|
|
337
|
+
# The pending file is written by a normal "claude" spawn; the SubagentStart event
|
|
338
|
+
# then arrives with an EMPTY agent_type. The name must be derived from agent_id,
|
|
339
|
+
# never from the pending file's name/filename.
|
|
340
|
+
new_case "fallback"
|
|
341
|
+
pre_spawn "claude"
|
|
342
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
343
|
+
fail "fallback" "on-pre-spawn-agent.sh exited $LAST_RC: $LAST_STDERR"
|
|
344
|
+
else
|
|
345
|
+
subagent_start "abcdef1234567890" ""
|
|
346
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
347
|
+
fail "fallback" "on-subagent-start.sh exited $LAST_RC: $LAST_STDERR"
|
|
348
|
+
else
|
|
349
|
+
name="$(created_names)"
|
|
350
|
+
if [ "$name" != "worker-abcdef12" ]; then
|
|
351
|
+
fail "fallback" "expected name 'worker-abcdef12' (worker- + agent_id first 8), got '$name'"
|
|
352
|
+
elif ! assert_not_unknown "fallback" "session name" "$name"; then
|
|
353
|
+
:
|
|
354
|
+
else
|
|
355
|
+
pass "fallback (empty agent_type -> 'worker-abcdef12')"
|
|
356
|
+
fi
|
|
357
|
+
fi
|
|
358
|
+
fi
|
|
359
|
+
|
|
360
|
+
# ===== Case 3: parallel batch — two same-second spawns of the SAME type =====
|
|
361
|
+
# Two PreToolUse:Task invocations of "claude" within the same second must produce
|
|
362
|
+
# two DISTINCT pending files (BSD date has no %N, so uniqueness comes from $$).
|
|
363
|
+
# Then two SubagentStart events — deliberately of DIFFERENT types — each claim
|
|
364
|
+
# one file FIFO and each must be named after their OWN event's agent_type, which
|
|
365
|
+
# is what makes plain FIFO claiming safe in a mixed batch.
|
|
366
|
+
new_case "parallel"
|
|
367
|
+
pre_spawn "claude"
|
|
368
|
+
rc1=$LAST_RC
|
|
369
|
+
pre_spawn "claude"
|
|
370
|
+
rc2=$LAST_RC
|
|
371
|
+
if [ "$rc1" -ne 0 ] || [ "$rc2" -ne 0 ]; then
|
|
372
|
+
fail "parallel-distinct-pending" "on-pre-spawn-agent.sh exited $rc1/$rc2: $LAST_STDERR"
|
|
373
|
+
else
|
|
374
|
+
n="$(pending_count)"
|
|
375
|
+
if [ "$n" != "2" ]; then
|
|
376
|
+
fail "parallel-distinct-pending" "expected 2 distinct pending files from 2 same-second spawns of the same type, got $n: $(pending_names | tr '\n' ' ')"
|
|
377
|
+
else
|
|
378
|
+
bad=0
|
|
379
|
+
for f in $(pending_names); do
|
|
380
|
+
assert_not_unknown "parallel-distinct-pending" "pending filename" "$f" || bad=1
|
|
381
|
+
done
|
|
382
|
+
[ "$bad" -eq 0 ] && pass "parallel-distinct-pending (2 distinct non-unknown pending files)"
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
subagent_start "aaaaaaaa11112222" "claude"
|
|
386
|
+
rc1=$LAST_RC
|
|
387
|
+
subagent_start "bbbbbbbb33334444" "general-purpose"
|
|
388
|
+
rc2=$LAST_RC
|
|
389
|
+
if [ "$rc1" -ne 0 ] || [ "$rc2" -ne 0 ]; then
|
|
390
|
+
fail "parallel-names" "on-subagent-start.sh exited $rc1/$rc2: $LAST_STDERR"
|
|
391
|
+
else
|
|
392
|
+
names="$(created_names | tr '\n' ',')"
|
|
393
|
+
if [ "$names" != "claude,general-purpose," ]; then
|
|
394
|
+
fail "parallel-names" "expected each session named after its OWN event agent_type ('claude','general-purpose'), got '$names'"
|
|
395
|
+
else
|
|
396
|
+
pass "parallel-names (each spawn named from its own event agent_type)"
|
|
397
|
+
fi
|
|
398
|
+
if [ "$(pending_count)" != "0" ]; then
|
|
399
|
+
fail "parallel-claimed" "expected both pending files claimed, still pending: $(pending_names | tr '\n' ' ')"
|
|
400
|
+
else
|
|
401
|
+
pass "parallel-claimed (both pending files claimed exactly once)"
|
|
402
|
+
fi
|
|
403
|
+
fi
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
# ===== Case 4: gate — empty pending dir -> no session, exit 0 =====
|
|
407
|
+
new_case "gate"
|
|
408
|
+
mkdir -p "$STATE_DIR/pending"
|
|
409
|
+
subagent_start "cccccccc55556666" "claude"
|
|
410
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
411
|
+
fail "gate" "expected exit 0 with an empty pending dir, got $LAST_RC: $LAST_STDERR"
|
|
412
|
+
elif [ "$(created_count)" != "0" ]; then
|
|
413
|
+
fail "gate" "expected NO chorus_create_session with an empty pending dir, got $(created_count): $(created_names | tr '\n' ' ')"
|
|
414
|
+
else
|
|
415
|
+
pass "gate (empty pending dir -> no session created, exit 0)"
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
# ===== Case 5: skip-list parity — skipped type writes no pending file =====
|
|
419
|
+
# on-subagent-start.sh exits early on chorus:task-reviewer, so
|
|
420
|
+
# on-pre-spawn-agent.sh must not leave a pending file for it — otherwise that
|
|
421
|
+
# orphan could be FIFO-claimed by an unrelated internal agent, defeating the gate.
|
|
422
|
+
new_case "skip-parity"
|
|
423
|
+
pre_spawn "chorus:task-reviewer"
|
|
424
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
425
|
+
fail "skip-parity" "on-pre-spawn-agent.sh exited $LAST_RC: $LAST_STDERR"
|
|
426
|
+
elif [ "$(pending_count)" != "0" ]; then
|
|
427
|
+
fail "skip-parity" "skip-listed type left an orphan pending file: $(pending_names | tr '\n' ' ')"
|
|
428
|
+
else
|
|
429
|
+
pass "skip-parity (chorus:task-reviewer leaves no pending file)"
|
|
430
|
+
fi
|
|
431
|
+
|
|
432
|
+
# ===== Case 6: same-type parallel — FIRST stop must NOT tear down the session ==
|
|
433
|
+
# Two "claude" sub-agents run in parallel. Because the session name is the
|
|
434
|
+
# repeating agent_type, the second SubagentStart reuses the FIRST one's session,
|
|
435
|
+
# so ONE session row has TWO holders. When the first sibling exits, the stop hook
|
|
436
|
+
# must leave everything the surviving sibling depends on alone.
|
|
437
|
+
SHARED_A="aaaa000011112222"
|
|
438
|
+
SHARED_B="bbbb000033334444"
|
|
439
|
+
|
|
440
|
+
new_case "shared-stop"
|
|
441
|
+
printf '%s\n' \
|
|
442
|
+
'{"checkins":[{"taskUuid":"task-of-a","checkoutAt":null},{"taskUuid":"task-of-b","checkoutAt":null}]}' \
|
|
443
|
+
> "$STATE_DIR/session-detail.json"
|
|
444
|
+
STUB_SESSION_JSON="$STATE_DIR/session-detail.json"
|
|
445
|
+
|
|
446
|
+
pre_spawn "claude"; rc1=$LAST_RC
|
|
447
|
+
pre_spawn "claude"; rc2=$LAST_RC
|
|
448
|
+
subagent_start "$SHARED_A" "claude"; rc3=$LAST_RC
|
|
449
|
+
subagent_start "$SHARED_B" "claude"; rc4=$LAST_RC
|
|
450
|
+
|
|
451
|
+
if [ "$rc1" -ne 0 ] || [ "$rc2" -ne 0 ] || [ "$rc3" -ne 0 ] || [ "$rc4" -ne 0 ]; then
|
|
452
|
+
fail "shared-stop-setup" "setup hooks exited $rc1/$rc2/$rc3/$rc4: $LAST_STDERR"
|
|
453
|
+
else
|
|
454
|
+
SHARED_UUID="$(state_val "session_claude")"
|
|
455
|
+
if [ "$(created_count)" != "1" ]; then
|
|
456
|
+
fail "shared-stop-setup" "expected the 2nd same-type start to REUSE one session (1 create), got $(created_count) creates"
|
|
457
|
+
elif [ -z "$SHARED_UUID" ]; then
|
|
458
|
+
fail "shared-stop-setup" "no shared session uuid in state key session_claude"
|
|
459
|
+
elif [ "$(holder_count claude)" != "2" ]; then
|
|
460
|
+
fail "shared-stop-holders" "expected 2 holder entries in holders/claude, got $(holder_count claude): $(ls -1 "$STATE_DIR/holders/claude" 2>/dev/null | tr '\n' ' ')"
|
|
461
|
+
else
|
|
462
|
+
pass "shared-stop-holders (2 same-type starts share 1 session and register 2 holders)"
|
|
463
|
+
fi
|
|
464
|
+
|
|
465
|
+
# --- first sibling exits ---
|
|
466
|
+
rec_reset
|
|
467
|
+
subagent_stop "$SHARED_A"
|
|
468
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
469
|
+
fail "shared-stop-first" "on-subagent-stop.sh exited $LAST_RC: $LAST_STDERR"
|
|
470
|
+
else
|
|
471
|
+
bad=""
|
|
472
|
+
[ "$(tool_count chorus_close_session)" = "0" ] \
|
|
473
|
+
|| bad="$bad closed-the-shared-session"
|
|
474
|
+
[ "$(tool_count chorus_session_checkout_task)" = "0" ] \
|
|
475
|
+
|| bad="$bad checked-out-a-siblings-task"
|
|
476
|
+
[ "$(tool_count chorus_get_task)" = "0" ] \
|
|
477
|
+
|| bad="$bad ran-the-auto-verify-block"
|
|
478
|
+
[ -f "$STATE_DIR/sessions/claude.json" ] \
|
|
479
|
+
|| bad="$bad removed-sessions/claude.json"
|
|
480
|
+
state_has "session_claude" \
|
|
481
|
+
|| bad="$bad deleted-name-keyed-state"
|
|
482
|
+
state_has "agent_for_session_${SHARED_UUID}" \
|
|
483
|
+
|| bad="$bad deleted-reverse-map-agent_for_session"
|
|
484
|
+
state_has "session_${SHARED_B}" \
|
|
485
|
+
|| bad="$bad deleted-siblings-session_<agentId>"
|
|
486
|
+
[ "$(holder_count claude)" = "1" ] \
|
|
487
|
+
|| bad="$bad holder-count-not-1-after-own-entry-removed"
|
|
488
|
+
if state_has "session_${SHARED_A}" || state_has "name_for_agent_${SHARED_A}"; then
|
|
489
|
+
bad="$bad kept-own-id-keyed-state"
|
|
490
|
+
fi
|
|
491
|
+
[ -f "$STATE_DIR/claimed/${SHARED_A}" ] && bad="$bad kept-own-claimed-file" || true
|
|
492
|
+
if [ -n "$bad" ]; then
|
|
493
|
+
fail "shared-stop-first" "first stop of a shared session:$bad"
|
|
494
|
+
else
|
|
495
|
+
pass "shared-stop-first (no close/checkout/auto-verify; shared state + sessions/claude.json intact; own state gone)"
|
|
496
|
+
fi
|
|
497
|
+
fi
|
|
498
|
+
|
|
499
|
+
# --- last sibling exits: full teardown, exactly as the single-agent case ---
|
|
500
|
+
rec_reset
|
|
501
|
+
subagent_stop "$SHARED_B"
|
|
502
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
503
|
+
fail "shared-stop-last" "on-subagent-stop.sh exited $LAST_RC: $LAST_STDERR"
|
|
504
|
+
else
|
|
505
|
+
bad=""
|
|
506
|
+
[ "$(tool_count chorus_close_session)" = "1" ] \
|
|
507
|
+
|| bad="$bad close_session-calls=$(tool_count chorus_close_session)"
|
|
508
|
+
[ "$(tool_count chorus_session_checkout_task)" = "2" ] \
|
|
509
|
+
|| bad="$bad checkout-calls=$(tool_count chorus_session_checkout_task)(expected both open checkins)"
|
|
510
|
+
[ "$(tool_count chorus_get_task)" -ge 1 ] 2>/dev/null \
|
|
511
|
+
|| bad="$bad auto-verify-block-did-not-run"
|
|
512
|
+
[ -f "$STATE_DIR/sessions/claude.json" ] && bad="$bad sessions/claude.json-not-removed" || true
|
|
513
|
+
[ -d "$STATE_DIR/holders/claude" ] && bad="$bad holder-dir-not-removed" || true
|
|
514
|
+
state_has "session_claude" && bad="$bad session_<name>-not-deleted" || true
|
|
515
|
+
state_has "agent_for_session_${SHARED_UUID}" && bad="$bad agent_for_session-not-deleted" || true
|
|
516
|
+
state_has "session_${SHARED_B}" && bad="$bad session_<agentId>-not-deleted" || true
|
|
517
|
+
state_has "name_for_agent_${SHARED_B}" && bad="$bad name_for_agent-not-deleted" || true
|
|
518
|
+
[ -f "$STATE_DIR/claimed/${SHARED_B}" ] && bad="$bad claimed-file-not-removed" || true
|
|
519
|
+
if [ -n "$bad" ]; then
|
|
520
|
+
fail "shared-stop-last" "last stop of a shared session:$bad"
|
|
521
|
+
else
|
|
522
|
+
pass "shared-stop-last (close + auto-checkout of both checkins + all 4 state keys, session file, holder dir and claimed file removed)"
|
|
523
|
+
fi
|
|
524
|
+
fi
|
|
525
|
+
fi
|
|
526
|
+
|
|
527
|
+
# ===== Case 7: single agent — teardown on its only stop is unchanged =====
|
|
528
|
+
new_case "single-stop"
|
|
529
|
+
printf '%s\n' '{"checkins":[{"taskUuid":"task-solo","checkoutAt":null}]}' \
|
|
530
|
+
> "$STATE_DIR/session-detail.json"
|
|
531
|
+
STUB_SESSION_JSON="$STATE_DIR/session-detail.json"
|
|
532
|
+
SOLO="dddd000077778888"
|
|
533
|
+
|
|
534
|
+
pre_spawn "claude"; rc1=$LAST_RC
|
|
535
|
+
subagent_start "$SOLO" "claude"; rc2=$LAST_RC
|
|
536
|
+
if [ "$rc1" -ne 0 ] || [ "$rc2" -ne 0 ]; then
|
|
537
|
+
fail "single-stop-setup" "setup hooks exited $rc1/$rc2: $LAST_STDERR"
|
|
538
|
+
else
|
|
539
|
+
SOLO_UUID="$(state_val "session_claude")"
|
|
540
|
+
rec_reset
|
|
541
|
+
subagent_stop "$SOLO"
|
|
542
|
+
if [ "$LAST_RC" -ne 0 ]; then
|
|
543
|
+
fail "single-stop" "on-subagent-stop.sh exited $LAST_RC: $LAST_STDERR"
|
|
544
|
+
else
|
|
545
|
+
bad=""
|
|
546
|
+
[ "$(tool_count chorus_close_session)" = "1" ] \
|
|
547
|
+
|| bad="$bad close_session-calls=$(tool_count chorus_close_session)"
|
|
548
|
+
[ "$(tool_count chorus_session_checkout_task)" = "1" ] \
|
|
549
|
+
|| bad="$bad checkout-calls=$(tool_count chorus_session_checkout_task)"
|
|
550
|
+
[ -f "$STATE_DIR/sessions/claude.json" ] && bad="$bad session-file-not-removed" || true
|
|
551
|
+
[ -d "$STATE_DIR/holders/claude" ] && bad="$bad holder-dir-not-removed" || true
|
|
552
|
+
state_has "session_claude" && bad="$bad session_<name>-not-deleted" || true
|
|
553
|
+
state_has "agent_for_session_${SOLO_UUID}" && bad="$bad agent_for_session-not-deleted" || true
|
|
554
|
+
state_has "session_${SOLO}" && bad="$bad session_<agentId>-not-deleted" || true
|
|
555
|
+
state_has "name_for_agent_${SOLO}" && bad="$bad name_for_agent-not-deleted" || true
|
|
556
|
+
[ -f "$STATE_DIR/claimed/${SOLO}" ] && bad="$bad claimed-file-not-removed" || true
|
|
557
|
+
if [ -n "$bad" ]; then
|
|
558
|
+
fail "single-stop" "single-agent stop regressed:$bad"
|
|
559
|
+
else
|
|
560
|
+
pass "single-stop (only holder -> close + full cleanup, unchanged behaviour)"
|
|
561
|
+
fi
|
|
562
|
+
fi
|
|
563
|
+
fi
|
|
564
|
+
|
|
565
|
+
# ===== Case 8: no unknown-* anywhere across all cases =====
|
|
566
|
+
# Belt-and-braces sweep: no session name recorded by ANY case may match
|
|
567
|
+
# unknown-*, and no pending filename left behind may either. (We match on the
|
|
568
|
+
# `name` field only — the create description legitimately contains
|
|
569
|
+
# "type: unknown" for the empty-agent_type fallback.)
|
|
570
|
+
sweep_bad=""
|
|
571
|
+
for rec in "$SANDBOX"/rec/*.log; do
|
|
572
|
+
[ -f "$rec" ] || continue
|
|
573
|
+
while IFS= read -r payload; do
|
|
574
|
+
[ -n "$payload" ] || continue
|
|
575
|
+
nm=$(printf '%s' "$payload" | jq -r '.name // empty')
|
|
576
|
+
case "$nm" in
|
|
577
|
+
unknown-*) sweep_bad="$sweep_bad $(basename "$rec"):$nm" ;;
|
|
578
|
+
esac
|
|
579
|
+
done <<SWEEP
|
|
580
|
+
$(grep '^mcp-tool|chorus_create_session|' "$rec" 2>/dev/null | sed 's/^mcp-tool|chorus_create_session|//')
|
|
581
|
+
SWEEP
|
|
582
|
+
done
|
|
583
|
+
for f in $(find "$SANDBOX/state" -type f -name 'unknown-*' 2>/dev/null); do
|
|
584
|
+
sweep_bad="$sweep_bad file:$f"
|
|
585
|
+
done
|
|
586
|
+
if [ -n "$sweep_bad" ]; then
|
|
587
|
+
fail "no-unknown-sweep" "found pre-fix 'unknown-*' artifacts:$sweep_bad"
|
|
588
|
+
else
|
|
589
|
+
pass "no-unknown-sweep (no unknown-* session name or pending filename anywhere)"
|
|
590
|
+
fi
|
|
591
|
+
|
|
592
|
+
echo ""
|
|
593
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
594
|
+
|
|
595
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
596
|
+
echo "Failed:$FAILED"
|
|
597
|
+
exit 1
|
|
598
|
+
fi
|
|
599
|
+
exit 0
|
|
@@ -4,7 +4,7 @@ description: Chorus AI Agent collaboration platform — overview, common tools,
|
|
|
4
4
|
license: AGPL-3.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: chorus
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.18.1"
|
|
8
8
|
category: project-management
|
|
9
9
|
mcp_server: chorus
|
|
10
10
|
---
|
|
@@ -344,9 +344,13 @@ To disable, reconfigure the plugin via `/plugin` settings or manually edit `~/.c
|
|
|
344
344
|
|
|
345
345
|
When enabled, reviewers run as read-only sub-agents and post a VERDICT comment on the proposal/task/idea. Three possible outcomes: **PASS** (no issues), **PASS WITH NOTES** (minor non-blocking notes), or **FAIL** (BLOCKERs found). Results are advisory — they do not block approval, verification, or ship; the code-review gateway in particular is behavioral (it does not change the Idea's stored status). On a code-review FAIL, fix it via the `/chorus:quick-dev` workflow: `chorus_create_tasks` with `proposalUuid` set to the current approved proposal so the fix tasks attach to it. Group related small BLOCKERs into one cohesive task by default; split only materially large or independently testable fixes. Each fix task must self-check its acceptance criteria and pass independent task review plus admin verification. Re-run the gateway only after every fix task is successfully `done`; if there is a failed or cancelled fix task, stop and escalate instead. Disabling reduces token usage but removes the independent quality gate.
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
**First-principles alignment (a stage-tailored instruction in all three reviewers).** Each reviewer also checks, top-down, that the work still serves the *original Idea's intent*. It resolves the Idea from the entity under review (proposal-reviewer → the proposal's `inputUuids[0]`; task-reviewer → its proposal's `inputUuids[0]`; code-reviewer → the given `ideaUuid`), reads it with the existing `chorus_get_idea` + `chorus_get_elaboration` + `chorus_get_comments`, and builds the intent **baseline** from **human input only** — the Idea content + elaboration answers where `answeredBy.type == "user"` + comments where `author.type == "user"`. Agent-answered elaboration and agent-authored comments are audit context only: they cannot expand, shrink, or override the baseline. It flags **scope creep** (work beyond intent), **requirement loss / shrink** (intent dropped or reduced), or **semantic drift** (passes AC but misses the point). Unauthorized drift is a **BLOCKER → VERDICT: FAIL / reject**, downgraded to a cited `NOTE` only when traceable to a **human** authorization: a human-authored Idea comment (`author.type == "user"`), a human-answered elaboration entry (`answeredBy.type == "user"`), or an explicit human override at the gate. **An agent's own comment never authorizes**, so a drifting agent cannot self-clear. The alignment finding folds into the existing VERDICT; the dimension is skipped when the entity has no attached Idea.
|
|
348
348
|
|
|
349
|
-
|
|
349
|
+
### 6. Spec mode: OpenSpec (default when usable) vs spec-lite (fallback)
|
|
350
|
+
|
|
351
|
+
The SessionStart hook resolves one **spec mode** per session and prints a `## Spec Mode` section stating it. Resolution: an explicit `CHORUS_SPEC_MODE` (`lite`/`openspec`/`off`) wins; when unset, **OpenSpec is the default whenever it is usable** — the `enableOpenSpec` toggle on (default) and `CHORUS_OPENSPEC_MODE` ≠ `off`, an `openspec/` directory at the project root, and the `openspec` CLI on `PATH`. When OpenSpec is absent or disabled, the mode falls back to **spec-lite** — a Chorus-native, git-tracked model: a durable local spec `.chorus/specs/<slug>/spec.md` per capability (edited in place, **never synced** to Chorus), plus one dated folder per change effort `.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` of plain-markdown docs named by Document type (`prd.md`, `tech_design.md`, …), each of those dated-folder docs mirrored 1:1 into a persistent Chorus Document (see the `spec-lite` skill). `CHORUS_SPEC_MODE=off` selects free-form (no spec artifact).
|
|
352
|
+
|
|
353
|
+
OpenSpec spec-driven path: `/proposal`, `/develop`, `/yolo` write `proposal.md` / `design.md` / spec deltas on disk and mirror them into Chorus drafts.
|
|
350
354
|
|
|
351
355
|
**When the user wants it on** (e.g. they ran `/chorus enable openspec` after the `(OpenSpec off — …)` banner), actually **enable it for them** — run whichever steps are missing, don't just describe them:
|
|
352
356
|
|
|
@@ -355,9 +359,9 @@ npm i -g @fission-ai/openspec # 1. install the CLI if it's not on PATH (gl
|
|
|
355
359
|
openspec init --tools claude # 2. scaffold openspec/ + wire up Claude Code's native commands/skills
|
|
356
360
|
```
|
|
357
361
|
|
|
358
|
-
`openspec init` is interactive if you omit `--tools`; pass `--tools claude` to run it unattended. Chorus's detection only needs the `openspec/` directory, but wiring up Claude Code also gives OpenSpec its own commands + skills. The
|
|
362
|
+
`openspec init` is interactive if you omit `--tools`; pass `--tools claude` to run it unattended. Chorus's detection only needs the `openspec/` directory, but wiring up Claude Code also gives OpenSpec its own commands + skills. The spec mode is resolved **once at SessionStart**, so it can't flip mid-session — after the steps succeed, tell the user to **re-launch the session**; the `## Spec Mode` section then reads `CHORUS_SPEC_MODE=openspec (…)` and the stage skills fold in the `openspec-aware` skill automatically.
|
|
359
363
|
|
|
360
|
-
To turn
|
|
364
|
+
To turn OpenSpec off, flip `enableOpenSpec` to `false` or set `CHORUS_OPENSPEC_MODE=off` — the mode then falls back to **spec-lite** (or set `CHORUS_SPEC_MODE=off` for free-form). The `## Spec Mode` section always states the resolved mode + reason.
|
|
361
365
|
|
|
362
366
|
### 7. Daemon auto-start via `chorus agents add`
|
|
363
367
|
|
|
@@ -438,7 +442,8 @@ This is the core overview skill. For stage-specific workflows, use:
|
|
|
438
442
|
| **Development** | `/develop` | Claim Tasks, report work, session & sub-agent management, Agent Teams integration |
|
|
439
443
|
| **Review** | `/review` | Approve/reject Proposals, verify Tasks, project governance |
|
|
440
444
|
| **Docs** | `/docs` | Consult the live Chorus documentation site to answer product-usage questions — UI workflow, agent/plugin setup, API/MCP, deployment, operations |
|
|
441
|
-
| **OpenSpec mode** | `openspec-aware` |
|
|
445
|
+
| **OpenSpec mode** | `openspec-aware` | **Shared sub-procedure** invoked by `/proposal`, `/develop`, and `/yolo` when the resolved spec mode is a usable OpenSpec (the default when `openspec/` + CLI present and not disabled). Scaffolds `openspec/changes/<slug>/` on disk and mirrors files into Chorus document drafts via the `chorus-api.sh` wrapper. No-op when the mode isn't a usable OpenSpec. See `.claude/skills/openspec-aware/SKILL.md`. |
|
|
446
|
+
| **spec-lite mode** | `spec-lite` | **Shared sub-procedure** and the fallback when OpenSpec isn't usable (or `CHORUS_SPEC_MODE=lite`). Durable local `.chorus/specs/<slug>/spec.md` (never synced) + dated per-change folders of Chorus-typed docs mirrored 1:1 into Chorus via `--arg-file`. No CLI/validation/archive. See `.claude/skills/spec-lite/SKILL.md`. |
|
|
442
447
|
|
|
443
448
|
### Getting Started
|
|
444
449
|
|