@chorus-aidlc/chorus 0.14.4 → 0.14.6
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 +192 -192
- package/.next/standalone/.next/app-path-routes-manifest.json +32 -32
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +27 -27
- 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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +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 +1 -1
- 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_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +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_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +1 -1
- 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_client-reference-manifest.js +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_client-reference-manifest.js +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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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_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_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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +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_client-reference-manifest.js +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_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_client-reference-manifest.js +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_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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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 +5 -5
- 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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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]/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_client-reference-manifest.js +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_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_client-reference-manifest.js +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/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.js +1 -1
- package/.next/standalone/.next/server/app/api/search/route.js.nft.json +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +2 -2
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/app/login.html +2 -2
- package/.next/standalone/.next/server/app/login.rsc +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 +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/app/settings.html +2 -2
- package/.next/standalone/.next/server/app/settings.rsc +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +32 -32
- package/.next/standalone/.next/server/chunks/1114.js +1 -1
- package/.next/standalone/.next/server/chunks/3219.js +1 -1
- package/.next/standalone/.next/server/chunks/6515.js +2 -2
- package/.next/standalone/.next/server/chunks/6528.js +1 -0
- package/.next/standalone/.next/server/chunks/8454.js +1 -1
- package/.next/standalone/.next/server/middleware-manifest.json +1 -1
- 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/package.json +1 -1
- package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +1 -1
- package/.next/standalone/public/chorus-plugin/agents/code-reviewer.md +1 -1
- package/.next/standalone/public/chorus-plugin/bin/chorus-api.sh +18 -4
- package/.next/standalone/public/chorus-plugin/bin/chorus-paths.sh +69 -0
- package/.next/standalone/public/chorus-plugin/bin/on-post-verify-task.sh +7 -1
- package/.next/standalone/public/chorus-plugin/bin/on-pre-spawn-agent.sh +10 -2
- package/.next/standalone/public/chorus-plugin/bin/on-session-end.sh +36 -23
- package/.next/standalone/public/chorus-plugin/bin/on-session-start.sh +6 -0
- package/.next/standalone/public/chorus-plugin/bin/on-subagent-start.sh +15 -5
- package/.next/standalone/public/chorus-plugin/bin/on-subagent-stop.sh +10 -2
- package/.next/standalone/public/chorus-plugin/bin/on-task-completed.sh +6 -0
- package/.next/standalone/public/chorus-plugin/bin/on-teammate-idle.sh +6 -0
- package/.next/standalone/public/chorus-plugin/bin/on-user-prompt.sh +14 -2
- package/.next/standalone/public/chorus-plugin/bin/test-syntax.sh +65 -1
- package/.next/standalone/public/chorus-plugin/bin/tests/test-code-review-recovery-contract.sh +75 -0
- package/.next/standalone/public/chorus-plugin/bin/tests/test-quick-dev-verification-contract.sh +47 -0
- package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +5 -3
- package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +2 -2
- package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +15 -11
- package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +2 -2
- package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +2 -2
- 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 +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +15 -11
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/steering/chorus.md +3 -1
- package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +1 -1
- package/.next/standalone/public/kiro-plugin/bin/on-post-verify-task.sh +2 -1
- package/.next/standalone/public/skill/brainstorm-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/chorus/SKILL.md +5 -3
- package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +2 -2
- package/.next/standalone/public/skill/develop-chorus/SKILL.md +2 -2
- package/.next/standalone/public/skill/idea-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/package.json +1 -1
- package/.next/standalone/public/skill/proposal-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +15 -11
- package/.next/standalone/public/skill/review-chorus/SKILL.md +2 -2
- package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/yolo-chorus/SKILL.md +2 -2
- package/README.ja.md +2 -0
- package/README.ko.md +2 -0
- package/README.md +2 -0
- package/README.zh.md +2 -0
- package/cli/claude-spawner.mjs +11 -8
- package/cli/codex-spawner.mjs +46 -11
- package/cli/kiro-spawner.mjs +8 -6
- package/cli/spawner-select.mjs +1 -6
- package/package.json +1 -1
- /package/.next/standalone/.next/static/{WVmgQzimrMNvGtHx6Cqm1 → t-ZaS6bNyv62NUlewVISp}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{WVmgQzimrMNvGtHx6Cqm1 → t-ZaS6bNyv62NUlewVISp}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# chorus-paths.sh — single source of truth for the Claude Code plugin's
|
|
3
|
+
# GLOBAL local-state layout. Sourced by chorus-api.sh and every hook that
|
|
4
|
+
# touches state. NOT an executable subcommand — sourcing it defines the
|
|
5
|
+
# resolved path variables in the caller's shell.
|
|
6
|
+
#
|
|
7
|
+
# Layout (aligned with the daemon's global ~/.chorus/ convention):
|
|
8
|
+
#
|
|
9
|
+
# ~/.chorus/plugin/<cwd-slug>/<sessionId>/
|
|
10
|
+
# ├── state.json (+ state.json.lock)
|
|
11
|
+
# ├── sessions/ <agentName>.json
|
|
12
|
+
# ├── pending/ PreToolUse:Task -> SubagentStart handoff
|
|
13
|
+
# ├── claimed/ claimed pending files, keyed by agent_id
|
|
14
|
+
# └── .mcp_headers.* / .mcp_response.* MCP handshake temp files
|
|
15
|
+
#
|
|
16
|
+
# Inputs (env):
|
|
17
|
+
# CHORUS_SESSION_ID Claude Code session id (from a hook's stdin event).
|
|
18
|
+
# When empty, state falls back to a stable
|
|
19
|
+
# "<slug>/no-session" bucket so resolution NEVER fails.
|
|
20
|
+
# CLAUDE_PROJECT_DIR Project dir; defaults to $PWD.
|
|
21
|
+
# CHORUS_PLUGIN_STATE_ROOT Optional override of the global root (used by tests
|
|
22
|
+
# to point at a throwaway directory).
|
|
23
|
+
#
|
|
24
|
+
# Outputs (vars set in the caller's shell):
|
|
25
|
+
# CHORUS_PLUGIN_ROOT The global root (default ~/.chorus/plugin).
|
|
26
|
+
# CHORUS_CWD_SLUG Readable slug for the project dir.
|
|
27
|
+
# CHORUS_STATE_DIR The resolved per-session state directory.
|
|
28
|
+
#
|
|
29
|
+
# Design constraints:
|
|
30
|
+
# - Pure variable assignment + function definitions. Runs no external command
|
|
31
|
+
# that can make the *sourcing* shell exit non-zero (the slug helper is only
|
|
32
|
+
# invoked to compute CHORUS_CWD_SLUG, and `sed` on a here-string cannot fail
|
|
33
|
+
# the caller under `set -e` in the way a pipeline might — we keep it simple).
|
|
34
|
+
# - Bash 3.2 compatible (macOS /bin/bash): no ${var//search/replace} global
|
|
35
|
+
# substitution, no associative arrays, no `realpath`, no `readarray`.
|
|
36
|
+
# - The resolved CHORUS_STATE_DIR is NEVER empty.
|
|
37
|
+
|
|
38
|
+
# --- 1. Global root (honor test override) --------------------------------
|
|
39
|
+
CHORUS_PLUGIN_ROOT="${CHORUS_PLUGIN_STATE_ROOT:-${HOME:-/tmp}/.chorus/plugin}"
|
|
40
|
+
|
|
41
|
+
# --- 2. cwd -> readable slug ---------------------------------------------
|
|
42
|
+
# Mirrors Claude Code's own ~/.claude/projects/<-abs-path> encoding:
|
|
43
|
+
# make the path absolute, strip trailing slashes, then replace every
|
|
44
|
+
# non-alphanumeric character with '-'. "/home/ubuntu/dev/ai-pm" becomes
|
|
45
|
+
# "-home-ubuntu-dev-ai-pm". This is a legible directory name, not a hash.
|
|
46
|
+
chorus_slug_for_dir() {
|
|
47
|
+
local _csd_dir="${1:-$PWD}"
|
|
48
|
+
# Make absolute without depending on realpath.
|
|
49
|
+
case "$_csd_dir" in
|
|
50
|
+
/*) : ;;
|
|
51
|
+
*) _csd_dir="$PWD/$_csd_dir" ;;
|
|
52
|
+
esac
|
|
53
|
+
printf '%s' "$_csd_dir" | sed -e 's#/*$##' -e 's#[^A-Za-z0-9]#-#g'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
CHORUS_CWD_SLUG="$(chorus_slug_for_dir "${CLAUDE_PROJECT_DIR:-$PWD}")"
|
|
57
|
+
|
|
58
|
+
# --- 3. Per-session partition --------------------------------------------
|
|
59
|
+
# Every Claude Code hook event carries the same top-level session_id (sub-agents
|
|
60
|
+
# are distinguished by a separate agent_id), so all hooks in one session resolve
|
|
61
|
+
# to the same <sessionId> dir. When no session id is available (e.g. a hook with
|
|
62
|
+
# no stdin, or a manual invocation) fall back to a stable shared bucket so the
|
|
63
|
+
# path is always valid and non-empty.
|
|
64
|
+
_chorus_sid="${CHORUS_SESSION_ID:-}"
|
|
65
|
+
if [ -z "$_chorus_sid" ]; then
|
|
66
|
+
_chorus_sid="no-session"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
CHORUS_STATE_DIR="${CHORUS_PLUGIN_ROOT}/${CHORUS_CWD_SLUG}/${_chorus_sid}"
|
|
@@ -62,6 +62,11 @@ if [ -z "$EVENT" ]; then
|
|
|
62
62
|
exit 0
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
|
+
# Export the CC session id so chorus-api.sh's mcp-tool calls write their handshake
|
|
66
|
+
# temp files under this session's global state partition (not a no-session bucket).
|
|
67
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
68
|
+
export CHORUS_SESSION_ID
|
|
69
|
+
|
|
65
70
|
# Extract taskUuid from .tool_input
|
|
66
71
|
TASK_UUID=$(printf '%s' "$EVENT" | jq -r '.tool_input.taskUuid // empty' 2>/dev/null) || true
|
|
67
72
|
|
|
@@ -315,7 +320,8 @@ ACTION REQUESTED: spawn code-reviewer for this idea — an independent, read-onl
|
|
|
315
320
|
1. Spawn the code-reviewer in FOREGROUND, passing it ideaUuid="${idea_uuid}" and the review round number (read prior code-review verdict comments on the idea to determine it). It reviews cross-task integration, architecture/convention consistency, security, regression/performance, feature-level test coverage, and overall code soundness, then posts ONE VERDICT comment on the idea.
|
|
316
321
|
2. Read its VERDICT on the idea (chorus_get_comments targetType="idea").
|
|
317
322
|
3. PASS / PASS WITH NOTES -> the feature may ship.
|
|
318
|
-
4. FAIL -> create new
|
|
323
|
+
4. FAIL -> the orchestrator invokes Quick Dev to create new tasks on the original approved proposal; never reopen completed tasks or apply untracked fixes. Group related small BLOCKERs by default and split only materially large or independently testable fixes.
|
|
324
|
+
5. Re-run only after every fix task passes AC self-check, independent task review, and admin verification to done. A failed or cancelled fix stops the loop and escalates. Keep maxCodeReviewRounds authoritative.
|
|
319
325
|
|
|
320
326
|
Run the code-review gateway BEFORE writing any idea-completion report — the report must not be written while a FAIL verdict is outstanding.
|
|
321
327
|
CTX
|
|
@@ -23,6 +23,11 @@ if [ ! -t 0 ]; then
|
|
|
23
23
|
EVENT=$(cat)
|
|
24
24
|
fi
|
|
25
25
|
|
|
26
|
+
# Export the CC session id so the pending dir lands in this session's partition —
|
|
27
|
+
# the SubagentStart hook resolves the same <sessionId> and claims from there.
|
|
28
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
29
|
+
export CHORUS_SESSION_ID
|
|
30
|
+
|
|
26
31
|
# Try to extract subagent_type and name from the tool input
|
|
27
32
|
AGENT_TYPE=""
|
|
28
33
|
AGENT_NAME=""
|
|
@@ -48,8 +53,11 @@ esac
|
|
|
48
53
|
#
|
|
49
54
|
# CC may internally spawn cleanup agents that bypass PreToolUse:Task —
|
|
50
55
|
# SubagentStart skips those if no pending file matches.
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
# Resolve the global per-session state dir (fail-soft to old layout).
|
|
57
|
+
# shellcheck source=chorus-paths.sh
|
|
58
|
+
[ -f "${SCRIPT_DIR}/chorus-paths.sh" ] && { . "${SCRIPT_DIR}/chorus-paths.sh" 2>/dev/null || true; }
|
|
59
|
+
PENDING_DIR="${CHORUS_STATE_DIR:-${CLAUDE_PROJECT_DIR:-.}/.chorus}/pending"
|
|
60
|
+
mkdir -p "$PENDING_DIR" 2>/dev/null || true
|
|
53
61
|
|
|
54
62
|
# Use agent name as filename; fall back to timestamp-based unique name
|
|
55
63
|
PENDING_NAME="${AGENT_NAME:-unknown-$(date +%s%N)}"
|
|
@@ -1,39 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# on-session-end.sh — SessionEnd hook
|
|
3
3
|
# Fires when Claude Code session ends.
|
|
4
|
-
#
|
|
4
|
+
# Removes THIS session's global state directory
|
|
5
|
+
# (~/.chorus/plugin/<cwd-slug>/<sessionId>/). Because state is now partitioned
|
|
6
|
+
# per session, we can delete our own directory unconditionally without racing
|
|
7
|
+
# sibling concurrent sessions of the same project.
|
|
5
8
|
|
|
6
9
|
set -euo pipefail
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
|
|
13
|
+
# Read event JSON from stdin to lift the session id.
|
|
14
|
+
EVENT=""
|
|
15
|
+
if [ ! -t 0 ]; then
|
|
16
|
+
EVENT=$(cat)
|
|
17
|
+
fi
|
|
18
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
19
|
+
export CHORUS_SESSION_ID
|
|
20
|
+
|
|
21
|
+
# Resolve this session's global state dir (fail-soft to old per-project layout).
|
|
22
|
+
# shellcheck source=chorus-paths.sh
|
|
23
|
+
if [ -f "${SCRIPT_DIR}/chorus-paths.sh" ]; then
|
|
24
|
+
. "${SCRIPT_DIR}/chorus-paths.sh" 2>/dev/null || true
|
|
25
|
+
fi
|
|
26
|
+
STATE_DIR="${CHORUS_STATE_DIR:-${CLAUDE_PROJECT_DIR:-.}/.chorus}"
|
|
9
27
|
|
|
10
28
|
# Nothing to clean up
|
|
11
29
|
if [ ! -d "$STATE_DIR" ]; then
|
|
12
30
|
exit 0
|
|
13
31
|
fi
|
|
14
32
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
REMAINING=$((REMAINING + 1))
|
|
22
|
-
done
|
|
23
|
-
if [ "$REMAINING" -gt 0 ]; then
|
|
33
|
+
# Guard: never delete the shared "no-session" fallback bucket — a degenerate
|
|
34
|
+
# session (no session id on stdin) must not wipe state that a concurrent,
|
|
35
|
+
# properly-identified session might also be using. Only self-delete when we
|
|
36
|
+
# resolved a real per-session directory.
|
|
37
|
+
case "${CHORUS_SESSION_ID:-}" in
|
|
38
|
+
""|no-session)
|
|
24
39
|
exit 0
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
# Remove only this session's directory. Session-scoped, so no sibling guard needed.
|
|
44
|
+
rm -rf "$STATE_DIR" 2>/dev/null || true
|
|
27
45
|
|
|
28
|
-
#
|
|
29
|
-
if
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if [ "$KEY_COUNT" -gt 0 ]; then
|
|
33
|
-
exit 0
|
|
34
|
-
fi
|
|
35
|
-
fi
|
|
46
|
+
# Best-effort: remove the now-possibly-empty <cwd-slug>/ parent. Fails (and is
|
|
47
|
+
# ignored) if other concurrent sessions of this project still have directories.
|
|
48
|
+
if [ -n "${CHORUS_PLUGIN_ROOT:-}" ] && [ -n "${CHORUS_CWD_SLUG:-}" ]; then
|
|
49
|
+
rmdir "${CHORUS_PLUGIN_ROOT}/${CHORUS_CWD_SLUG}" 2>/dev/null || true
|
|
36
50
|
fi
|
|
37
51
|
|
|
38
|
-
|
|
39
|
-
rm -rf "$STATE_DIR"
|
|
52
|
+
exit 0
|
|
@@ -17,6 +17,12 @@ if [ ! -t 0 ]; then
|
|
|
17
17
|
EVENT=$(cat)
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
|
+
# Extract the Claude Code session id from the event and export it so chorus-api.sh
|
|
21
|
+
# (and any sub-path we build) resolves to this session's global state partition.
|
|
22
|
+
# Fail-soft: an absent id just falls back to the shared "no-session" bucket.
|
|
23
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
24
|
+
export CHORUS_SESSION_ID
|
|
25
|
+
|
|
20
26
|
# Check if Chorus environment is configured
|
|
21
27
|
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
|
|
22
28
|
"$API" hook-output \
|
|
@@ -35,6 +35,16 @@ if [ -z "$EVENT" ]; then
|
|
|
35
35
|
exit 0
|
|
36
36
|
fi
|
|
37
37
|
|
|
38
|
+
# Export the CC session id (same for every hook in this session) so state and
|
|
39
|
+
# the pending/claimed/sessions dirs resolve to this session's global partition.
|
|
40
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
41
|
+
export CHORUS_SESSION_ID
|
|
42
|
+
|
|
43
|
+
# Resolve the global per-session state dir once (fail-soft to the old layout).
|
|
44
|
+
# shellcheck source=chorus-paths.sh
|
|
45
|
+
[ -f "${SCRIPT_DIR}/chorus-paths.sh" ] && { . "${SCRIPT_DIR}/chorus-paths.sh" 2>/dev/null || true; }
|
|
46
|
+
CHORUS_STATE_DIR="${CHORUS_STATE_DIR:-${CLAUDE_PROJECT_DIR:-.}/.chorus}"
|
|
47
|
+
|
|
38
48
|
# Extract agent info from event
|
|
39
49
|
# Note: SubagentStart only provides agent_id and agent_type — NOT the name
|
|
40
50
|
# from the Task tool call. The name is captured by on-pre-spawn-agent.sh
|
|
@@ -63,9 +73,9 @@ fi
|
|
|
63
73
|
#
|
|
64
74
|
# If no pending file exists, this is an internal/cleanup agent → skip.
|
|
65
75
|
AGENT_NAME=""
|
|
66
|
-
PENDING_DIR="${
|
|
67
|
-
CLAIMED_DIR="${
|
|
68
|
-
mkdir -p "$CLAIMED_DIR"
|
|
76
|
+
PENDING_DIR="${CHORUS_STATE_DIR}/pending"
|
|
77
|
+
CLAIMED_DIR="${CHORUS_STATE_DIR}/claimed"
|
|
78
|
+
mkdir -p "$CLAIMED_DIR" 2>/dev/null || true
|
|
69
79
|
|
|
70
80
|
CLAIMED_FILE=""
|
|
71
81
|
|
|
@@ -178,8 +188,8 @@ fi
|
|
|
178
188
|
"$API" state-set "name_for_agent_${AGENT_ID}" "$SESSION_NAME"
|
|
179
189
|
|
|
180
190
|
# === Session file: minimal metadata for other hooks (TeammateIdle, SubagentStop) ===
|
|
181
|
-
SESSIONS_DIR="${
|
|
182
|
-
mkdir -p "$SESSIONS_DIR"
|
|
191
|
+
SESSIONS_DIR="${CHORUS_STATE_DIR}/sessions"
|
|
192
|
+
mkdir -p "$SESSIONS_DIR" 2>/dev/null || true
|
|
183
193
|
|
|
184
194
|
cat > "${SESSIONS_DIR}/${SESSION_NAME}.json" <<SESSIONEOF
|
|
185
195
|
{
|
|
@@ -29,6 +29,14 @@ if [ -z "$EVENT" ]; then
|
|
|
29
29
|
exit 0
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
|
+
# Export the CC session id so state-get / sessions / claimed resolve to the same
|
|
33
|
+
# global partition that on-subagent-start wrote to (cross-hook lookup must match).
|
|
34
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
35
|
+
export CHORUS_SESSION_ID
|
|
36
|
+
# shellcheck source=chorus-paths.sh
|
|
37
|
+
[ -f "${SCRIPT_DIR}/chorus-paths.sh" ] && { . "${SCRIPT_DIR}/chorus-paths.sh" 2>/dev/null || true; }
|
|
38
|
+
CHORUS_STATE_DIR="${CHORUS_STATE_DIR:-${CLAUDE_PROJECT_DIR:-.}/.chorus}"
|
|
39
|
+
|
|
32
40
|
# Extract agent ID from event
|
|
33
41
|
# Note: SubagentStop only provides agent_id and agent_type — NOT the name.
|
|
34
42
|
# We look up the name from state (stored by SubagentStart).
|
|
@@ -84,13 +92,13 @@ if [ -n "$AGENT_NAME" ]; then
|
|
|
84
92
|
fi
|
|
85
93
|
|
|
86
94
|
# Clean up session file
|
|
87
|
-
SESSIONS_DIR="${
|
|
95
|
+
SESSIONS_DIR="${CHORUS_STATE_DIR}/sessions"
|
|
88
96
|
if [ -n "$AGENT_NAME" ] && [ -f "${SESSIONS_DIR}/${AGENT_NAME}.json" ]; then
|
|
89
97
|
rm -f "${SESSIONS_DIR}/${AGENT_NAME}.json"
|
|
90
98
|
fi
|
|
91
99
|
|
|
92
100
|
# Clean up claimed file (written by SubagentStart)
|
|
93
|
-
CLAIMED_DIR="${
|
|
101
|
+
CLAIMED_DIR="${CHORUS_STATE_DIR}/claimed"
|
|
94
102
|
if [ -n "$AGENT_ID" ] && [ -f "${CLAIMED_DIR}/${AGENT_ID}" ]; then
|
|
95
103
|
rm -f "${CLAIMED_DIR}/${AGENT_ID}"
|
|
96
104
|
fi
|
|
@@ -26,6 +26,12 @@ if [ -z "$EVENT" ]; then
|
|
|
26
26
|
exit 0
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
|
+
# Export the CC session id so chorus-api.sh's state-get resolves to the SAME
|
|
30
|
+
# <sessionId> partition on-subagent-start wrote the session_<agentId> mapping to.
|
|
31
|
+
# Without this the lookup would miss and TaskCompleted auto-checkout would stop.
|
|
32
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
33
|
+
export CHORUS_SESSION_ID
|
|
34
|
+
|
|
29
35
|
# Extract task info
|
|
30
36
|
TASK_DESCRIPTION=$(echo "$EVENT" | jq -r '.task_description // .taskDescription // .description // empty' 2>/dev/null) || true
|
|
31
37
|
TASK_SUBJECT=$(echo "$EVENT" | jq -r '.task_subject // .taskSubject // .subject // empty' 2>/dev/null) || true
|
|
@@ -25,6 +25,12 @@ if [ -z "$EVENT" ]; then
|
|
|
25
25
|
exit 0
|
|
26
26
|
fi
|
|
27
27
|
|
|
28
|
+
# Export the CC session id so chorus-api.sh's state-get resolves to the SAME
|
|
29
|
+
# <sessionId> partition on-subagent-start wrote the session_<name> mapping to.
|
|
30
|
+
# Without this the lookup would miss and teammate heartbeats would silently stop.
|
|
31
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
32
|
+
export CHORUS_SESSION_ID
|
|
33
|
+
|
|
28
34
|
# Extract teammate info from event
|
|
29
35
|
# TeammateIdle provides teammate_name (unlike SubagentStart/Stop which don't)
|
|
30
36
|
TEAMMATE_NAME=$(echo "$EVENT" | jq -r '.teammate_name // .teammateName // empty' 2>/dev/null) || true
|
|
@@ -9,14 +9,26 @@
|
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
|
|
11
11
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
-
STATE_DIR="${CLAUDE_PROJECT_DIR:-.}/.chorus"
|
|
13
|
-
SESSIONS_DIR="${STATE_DIR}/sessions"
|
|
14
12
|
|
|
15
13
|
# Skip entirely if Chorus is not configured
|
|
16
14
|
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
|
|
17
15
|
exit 0
|
|
18
16
|
fi
|
|
19
17
|
|
|
18
|
+
# Read stdin only to lift the session id (no MCP, no network — stays fast).
|
|
19
|
+
EVENT=""
|
|
20
|
+
if [ ! -t 0 ]; then
|
|
21
|
+
EVENT=$(cat)
|
|
22
|
+
fi
|
|
23
|
+
CHORUS_SESSION_ID=$(printf '%s' "$EVENT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null) || true
|
|
24
|
+
export CHORUS_SESSION_ID
|
|
25
|
+
|
|
26
|
+
# Resolve this session's global state dir (fail-soft to the old layout).
|
|
27
|
+
# shellcheck source=chorus-paths.sh
|
|
28
|
+
[ -f "${SCRIPT_DIR}/chorus-paths.sh" ] && { . "${SCRIPT_DIR}/chorus-paths.sh" 2>/dev/null || true; }
|
|
29
|
+
STATE_DIR="${CHORUS_STATE_DIR:-${CLAUDE_PROJECT_DIR:-.}/.chorus}"
|
|
30
|
+
SESSIONS_DIR="${STATE_DIR}/sessions"
|
|
31
|
+
|
|
20
32
|
# Count active session files (fast local check)
|
|
21
33
|
SESSION_COUNT=0
|
|
22
34
|
SESSION_NAMES=""
|
|
@@ -25,7 +25,11 @@ export CHORUS_API_KEY="cho_test"
|
|
|
25
25
|
export CLAUDE_PROJECT_DIR="/tmp/chorus-test-$$"
|
|
26
26
|
mkdir -p "$CLAUDE_PROJECT_DIR"
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
# Point the plugin's GLOBAL state root at a throwaway dir so this test never
|
|
29
|
+
# writes into the real ~/.chorus. chorus-paths.sh honors this override.
|
|
30
|
+
export CHORUS_PLUGIN_STATE_ROOT="/tmp/chorus-test-$$/global"
|
|
31
|
+
|
|
32
|
+
cleanup() { rm -rf "$CLAUDE_PROJECT_DIR" "/tmp/chorus-test-$$"; }
|
|
29
33
|
trap cleanup EXIT
|
|
30
34
|
|
|
31
35
|
# Mock event payloads for each hook type
|
|
@@ -81,6 +85,66 @@ run_test "on-session-end.sh" '{}'
|
|
|
81
85
|
# --- User prompt hook ---
|
|
82
86
|
run_test "on-user-prompt.sh" '{}'
|
|
83
87
|
|
|
88
|
+
# ============================================================================
|
|
89
|
+
# Global-state-layout assertions (chorus-paths.sh)
|
|
90
|
+
# ============================================================================
|
|
91
|
+
echo ""
|
|
92
|
+
echo "Global state layout:"
|
|
93
|
+
|
|
94
|
+
assert_eq() {
|
|
95
|
+
# assert_eq <label> <expected> <actual>
|
|
96
|
+
if [ "$2" = "$3" ]; then
|
|
97
|
+
printf " PASS %s\n" "$1"
|
|
98
|
+
PASS=$((PASS + 1))
|
|
99
|
+
else
|
|
100
|
+
printf " FAIL %s (expected '%s', got '%s')\n" "$1" "$2" "$3"
|
|
101
|
+
FAIL=$((FAIL + 1))
|
|
102
|
+
FAILED="$FAILED assert:$1"
|
|
103
|
+
fi
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
assert_true() {
|
|
107
|
+
# assert_true <label> <condition-cmd...>
|
|
108
|
+
local _label="$1"; shift
|
|
109
|
+
if "$@"; then
|
|
110
|
+
printf " PASS %s\n" "$_label"
|
|
111
|
+
PASS=$((PASS + 1))
|
|
112
|
+
else
|
|
113
|
+
printf " FAIL %s\n" "$_label"
|
|
114
|
+
FAIL=$((FAIL + 1))
|
|
115
|
+
FAILED="$FAILED assert:$_label"
|
|
116
|
+
fi
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# 1. chorus_slug_for_dir encodes an absolute path to a readable slug (not a hash).
|
|
120
|
+
SLUG_OUT="$( . "$DIR/chorus-paths.sh" 2>/dev/null; chorus_slug_for_dir "/home/ubuntu/dev/ai-pm" )"
|
|
121
|
+
assert_eq "slug encoding /home/ubuntu/dev/ai-pm" "-home-ubuntu-dev-ai-pm" "$SLUG_OUT"
|
|
122
|
+
|
|
123
|
+
# 2. With a session id, CHORUS_STATE_DIR resolves under the (overridden) global
|
|
124
|
+
# root at <root>/<slug>/<sessionId> — NOT under $CLAUDE_PROJECT_DIR/.chorus.
|
|
125
|
+
STATE_WITH_SID="$( export CHORUS_SESSION_ID="sess-xyz"; . "$DIR/chorus-paths.sh" 2>/dev/null; printf '%s' "$CHORUS_STATE_DIR" )"
|
|
126
|
+
EXPECT_SLUG="$( . "$DIR/chorus-paths.sh" 2>/dev/null; chorus_slug_for_dir "$CLAUDE_PROJECT_DIR" )"
|
|
127
|
+
assert_eq "state dir under global root/<slug>/<sessionId>" \
|
|
128
|
+
"${CHORUS_PLUGIN_STATE_ROOT}/${EXPECT_SLUG}/sess-xyz" "$STATE_WITH_SID"
|
|
129
|
+
case "$STATE_WITH_SID" in
|
|
130
|
+
*"/.chorus"*) assert_true "state dir is NOT the per-project .chorus" false ;;
|
|
131
|
+
*) assert_true "state dir is NOT the per-project .chorus" true ;;
|
|
132
|
+
esac
|
|
133
|
+
|
|
134
|
+
# 3. Missing session id falls back to <slug>/no-session (never empty).
|
|
135
|
+
STATE_NO_SID="$( unset CHORUS_SESSION_ID; . "$DIR/chorus-paths.sh" 2>/dev/null; printf '%s' "$CHORUS_STATE_DIR" )"
|
|
136
|
+
assert_eq "no session id -> <slug>/no-session" \
|
|
137
|
+
"${CHORUS_PLUGIN_STATE_ROOT}/${EXPECT_SLUG}/no-session" "$STATE_NO_SID"
|
|
138
|
+
|
|
139
|
+
# 4. A hook that writes state (on-pre-spawn-agent) lands its pending file under
|
|
140
|
+
# the global root, and does NOT create a .chorus/ in the project dir.
|
|
141
|
+
printf '%s' '{"session_id":"sess-place","tool_input":{"subagent_type":"general-purpose","name":"placer"}}' \
|
|
142
|
+
| "$BASH" "$DIR/on-pre-spawn-agent.sh" >/dev/null 2>&1 || true
|
|
143
|
+
assert_true "pending file written under global root" \
|
|
144
|
+
test -f "${CHORUS_PLUGIN_STATE_ROOT}/${EXPECT_SLUG}/sess-place/pending/placer"
|
|
145
|
+
assert_true "no .chorus/ created in project dir" \
|
|
146
|
+
test ! -d "${CLAUDE_PROJECT_DIR}/.chorus"
|
|
147
|
+
|
|
84
148
|
echo ""
|
|
85
149
|
echo "Results: $PASS passed, $FAIL failed"
|
|
86
150
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT=$(cd "$(dirname "$0")/../../../.." && pwd)
|
|
5
|
+
|
|
6
|
+
reviewers="
|
|
7
|
+
public/chorus-plugin/agents/code-reviewer.md
|
|
8
|
+
plugins/chorus/skills/chorus-code-reviewer/SKILL.md
|
|
9
|
+
packages/openclaw-plugin/skills/code-reviewer/SKILL.md
|
|
10
|
+
packages/chorus-pi/agents/chorus-code-reviewer.md
|
|
11
|
+
public/skill/code-reviewer-chorus/SKILL.md
|
|
12
|
+
"
|
|
13
|
+
|
|
14
|
+
lifecycle="
|
|
15
|
+
public/chorus-plugin/skills/chorus/SKILL.md
|
|
16
|
+
public/chorus-plugin/skills/develop/SKILL.md
|
|
17
|
+
public/chorus-plugin/skills/review/SKILL.md
|
|
18
|
+
public/chorus-plugin/skills/yolo/SKILL.md
|
|
19
|
+
plugins/chorus/skills/chorus/SKILL.md
|
|
20
|
+
plugins/chorus/skills/develop/SKILL.md
|
|
21
|
+
plugins/chorus/skills/review/SKILL.md
|
|
22
|
+
plugins/chorus/skills/yolo/SKILL.md
|
|
23
|
+
packages/openclaw-plugin/skills/chorus/SKILL.md
|
|
24
|
+
packages/openclaw-plugin/skills/develop/SKILL.md
|
|
25
|
+
packages/openclaw-plugin/skills/review/SKILL.md
|
|
26
|
+
packages/openclaw-plugin/skills/yolo/SKILL.md
|
|
27
|
+
public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md
|
|
28
|
+
public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md
|
|
29
|
+
public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md
|
|
30
|
+
packages/chorus-pi/skills/chorus/SKILL.md
|
|
31
|
+
packages/chorus-pi/skills/develop/SKILL.md
|
|
32
|
+
packages/chorus-pi/skills/review/SKILL.md
|
|
33
|
+
packages/chorus-pi/skills/yolo/SKILL.md
|
|
34
|
+
public/skill/chorus/SKILL.md
|
|
35
|
+
public/skill/develop-chorus/SKILL.md
|
|
36
|
+
public/skill/review-chorus/SKILL.md
|
|
37
|
+
public/skill/yolo-chorus/SKILL.md
|
|
38
|
+
"
|
|
39
|
+
|
|
40
|
+
assert_terms() {
|
|
41
|
+
file=$1
|
|
42
|
+
shift
|
|
43
|
+
for term in "$@"; do
|
|
44
|
+
if ! grep -Fq "$term" "$ROOT/$file"; then
|
|
45
|
+
printf 'FAIL: %s missing contract term: %s\n' "$file" "$term" >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
done
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for file in $reviewers; do
|
|
52
|
+
assert_terms "$file" \
|
|
53
|
+
"orchestrator" "Quick Dev" "original approved proposal" \
|
|
54
|
+
"related small BLOCKERs" "independent task review" \
|
|
55
|
+
"admin verification" "failed or cancelled" "maximum review rounds"
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
for file in $lifecycle; do
|
|
59
|
+
assert_terms "$file" \
|
|
60
|
+
"quick-dev" "approved proposal" "related small BLOCKERs" \
|
|
61
|
+
"independent task review" "admin verification" \
|
|
62
|
+
"failed or cancelled"
|
|
63
|
+
done
|
|
64
|
+
|
|
65
|
+
for file in \
|
|
66
|
+
public/chorus-plugin/skills/yolo/SKILL.md \
|
|
67
|
+
plugins/chorus/skills/yolo/SKILL.md \
|
|
68
|
+
packages/openclaw-plugin/skills/yolo/SKILL.md \
|
|
69
|
+
public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md \
|
|
70
|
+
packages/chorus-pi/skills/yolo/SKILL.md \
|
|
71
|
+
public/skill/yolo-chorus/SKILL.md; do
|
|
72
|
+
assert_terms "$file" "maxCodeReviewRounds"
|
|
73
|
+
done
|
|
74
|
+
|
|
75
|
+
printf 'Code-review recovery contract parity: PASS\n'
|
package/.next/standalone/public/chorus-plugin/bin/tests/test-quick-dev-verification-contract.sh
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT=$(cd "$(dirname "$0")/../../../.." && pwd)
|
|
5
|
+
|
|
6
|
+
skills="
|
|
7
|
+
public/chorus-plugin/skills/quick-dev/SKILL.md
|
|
8
|
+
plugins/chorus/skills/quick-dev/SKILL.md
|
|
9
|
+
packages/openclaw-plugin/skills/quick-dev/SKILL.md
|
|
10
|
+
public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md
|
|
11
|
+
packages/chorus-pi/skills/quick-dev/SKILL.md
|
|
12
|
+
public/skill/quick-dev-chorus/SKILL.md
|
|
13
|
+
"
|
|
14
|
+
|
|
15
|
+
assert_term() {
|
|
16
|
+
file=$1
|
|
17
|
+
term=$2
|
|
18
|
+
if ! grep -Fq "$term" "$ROOT/$file"; then
|
|
19
|
+
printf 'FAIL: %s missing contract term: %s\n' "$file" "$term" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for file in $skills; do
|
|
25
|
+
for term in \
|
|
26
|
+
'chorus_checkin().agent.permissions.task' \
|
|
27
|
+
'explicit `task:admin`' \
|
|
28
|
+
'name, persona, preset/role label, task ownership' \
|
|
29
|
+
'chorus_report_criteria_self_check' \
|
|
30
|
+
'independent task review' \
|
|
31
|
+
'unresolved BLOCKER' \
|
|
32
|
+
'chorus_admin_verify_task' \
|
|
33
|
+
'continue autonomously' \
|
|
34
|
+
'evidence-rich comment' \
|
|
35
|
+
'@mention the responsible human' \
|
|
36
|
+
'headless daemon sessions' \
|
|
37
|
+
'poll for the human response'; do
|
|
38
|
+
assert_term "$file" "$term"
|
|
39
|
+
done
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
if grep -Riq 'check admin role' $skills; then
|
|
43
|
+
printf 'FAIL: Quick Dev still authorizes by role wording\n' >&2
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
printf 'Quick Dev permission-aware verification parity: PASS\n'
|
|
@@ -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.14.
|
|
7
|
+
version: "0.14.6"
|
|
8
8
|
category: project-management
|
|
9
9
|
mcp_server: chorus
|
|
10
10
|
---
|
|
@@ -223,7 +223,7 @@ Use @mentions to notify specific users or agents. Mention syntax: `@[DisplayName
|
|
|
223
223
|
|
|
224
224
|
| Tool | Purpose |
|
|
225
225
|
|------|---------|
|
|
226
|
-
| `chorus_search` | Search across tasks, ideas, proposals, documents, projects, and project groups |
|
|
226
|
+
| `chorus_search` | Search compact summaries across tasks, ideas, proposals, documents, projects, and project groups; canonical UUIDs use exact lookup |
|
|
227
227
|
|
|
228
228
|
**Parameters:**
|
|
229
229
|
- `query`: Search query string
|
|
@@ -231,6 +231,8 @@ Use @mentions to notify specific users or agents. Mention syntax: `@[DisplayName
|
|
|
231
231
|
- `scopeUuid`: Project group UUID (when scope=group) or project UUID (when scope=project)
|
|
232
232
|
- `entityTypes`: Array of entity types to search (default: all types)
|
|
233
233
|
|
|
234
|
+
Prefer `chorus_search` for discovery, including exact UUID lookup. Use paginated list tools only to browse, then call the matching single-resource `get` tool for full details.
|
|
235
|
+
|
|
234
236
|
### Notifications
|
|
235
237
|
|
|
236
238
|
| Tool | Purpose |
|
|
@@ -340,7 +342,7 @@ To disable, reconfigure the plugin via `/plugin` settings or manually edit `~/.c
|
|
|
340
342
|
}
|
|
341
343
|
```
|
|
342
344
|
|
|
343
|
-
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
|
|
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.
|
|
344
346
|
|
|
345
347
|
### 6. Enable OpenSpec Mode (Optional)
|
|
346
348
|
|
|
@@ -4,7 +4,7 @@ description: Chorus Development workflow — claim tasks, report work, manage se
|
|
|
4
4
|
license: AGPL-3.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: chorus
|
|
7
|
-
version: "0.14.
|
|
7
|
+
version: "0.14.6"
|
|
8
8
|
category: project-management
|
|
9
9
|
mcp_server: chorus
|
|
10
10
|
---
|
|
@@ -237,7 +237,7 @@ Find the most recent comment containing `VERDICT:` and act on it:
|
|
|
237
237
|
|
|
238
238
|
If no new `VERDICT:` comment appears after the reviewer returns, it exhausted its `maxTurns` budget before posting. Respawn it ONCE with a concise-budget hint in the prompt: *"Stay within turn budget. Skip deep verification. Fetch task/proposal/comments, run only the core tests, and post your VERDICT comment within the first 12 turns."* If the second attempt still produces no VERDICT, review manually using the checklist and proceed.
|
|
239
239
|
|
|
240
|
-
> **Final code-review gateway (after the Idea's LAST task is verified):** when the task you just verified is the **last** task of its idea-rooted proposal, the feature is about to ship — the PostToolUse hook injects a reminder to spawn `chorus:code-reviewer` (gated by `enableCodeReviewer`, default on). Spawn it yourself in **foreground**, passing the `ideaUuid` + round number; it reviews the Idea's **aggregate** code change across all its tasks (cross-task integration, architecture, security, regression, feature-level coverage) and posts one `VERDICT` comment on the **idea**. `PASS` / `PASS WITH NOTES` → ship; `FAIL` → fix via `/chorus:quick-dev` (`chorus_create_tasks` with `proposalUuid` set to the current approved proposal so the fix tasks attach to it — do NOT reopen the verified tasks),
|
|
240
|
+
> **Final code-review gateway (after the Idea's LAST task is verified):** when the task you just verified is the **last** task of its idea-rooted proposal, the feature is about to ship — the PostToolUse hook injects a reminder to spawn `chorus:code-reviewer` (gated by `enableCodeReviewer`, default on). Spawn it yourself in **foreground**, passing the `ideaUuid` + round number; it reviews the Idea's **aggregate** code change across all its tasks (cross-task integration, architecture, security, regression, feature-level coverage) and posts one `VERDICT` comment on the **idea**. `PASS` / `PASS WITH NOTES` → ship; `FAIL` → fix via `/chorus:quick-dev` (`chorus_create_tasks` with `proposalUuid` set to the current approved proposal so the fix tasks attach to it — do NOT reopen the verified tasks). Group related small BLOCKERs by default; split only materially large or independently testable fixes. Require AC self-check, independent task review, and admin verification for every fix task. Re-run aggregate review only after every fix is successfully `done`; a failed or cancelled fix stops the loop and escalates, bounded by `maxCodeReviewRounds`. Advisory/behavioral, like the other reviewers. Run it **before** any idea-completion report.
|
|
241
241
|
|
|
242
242
|
### Step 9: Handle Review Feedback
|
|
243
243
|
|