commandmate 0.45.1 → 0.46.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/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +319 -315
- package/.next/app-path-routes-manifest.json +15 -15
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +4 -4
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +9 -9
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js +9 -9
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page.js +1 -1
- package/.next/server/app/login/page.js.nft.json +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +1 -1
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page.js +1 -1
- package/.next/server/app/offline/page.js.nft.json +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +1 -1
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +12 -9
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +15 -15
- package/.next/server/chunks/1341.js +1 -1
- package/.next/server/chunks/1501.js +2 -2
- package/.next/server/chunks/1559.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2283.js +15 -13
- package/.next/server/chunks/2404.js +4 -4
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2460.js +1 -1
- package/.next/server/chunks/2560.js +1 -1
- package/.next/server/chunks/2908.js +1 -1
- package/.next/server/chunks/2984.js +25 -0
- package/.next/server/chunks/3543.js +1 -1
- package/.next/server/chunks/3945.js +1 -1
- package/.next/server/chunks/4072.js +15 -0
- package/.next/server/chunks/4207.js +1 -1
- package/.next/server/chunks/4718.js +3 -3
- package/.next/server/chunks/4837.js +3 -3
- package/.next/server/chunks/5209.js +1 -1
- package/.next/server/chunks/5292.js +2 -2
- package/.next/server/chunks/5845.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6345.js +1 -0
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6722.js +1 -0
- package/.next/server/chunks/8098.js +1 -1
- package/.next/server/chunks/8356.js +1 -1
- package/.next/server/chunks/8581.js +25 -29
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8800.js +4 -4
- package/.next/server/chunks/8918.js +5 -5
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9627.js +2 -1
- package/.next/server/chunks/9731.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages/_error.js +2 -2
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-86890b00eeecf391.js → 2407-9703c569370b8a9d.js} +1 -1
- package/.next/static/chunks/{2619-a305ad4810f1393a.js → 2619-04bc32f026a0d946.js} +1 -1
- package/.next/static/chunks/2717.1583400c272dc1d9.js +1 -0
- package/.next/static/chunks/2770-db80aedf6384d594.js +1 -0
- package/.next/static/chunks/2863-6a07ec82fb52f4dd.js +1 -0
- package/.next/static/chunks/3201-c01f1feed69020e6.js +1 -0
- package/.next/static/chunks/4768-ad6f82f034f21eae.js +1 -0
- package/.next/static/chunks/5371-0dc947683e46e78c.js +1 -0
- package/.next/static/chunks/5794-4eee51ff1e878aa6.js +1 -0
- package/.next/static/chunks/5927-54315d21f323e204.js +1 -0
- package/.next/static/chunks/602-25e45a2422d2a3ea.js +1 -0
- package/.next/static/chunks/6606-02ddc006686a6b7d.js +1 -0
- package/.next/static/chunks/6654-f3534f35f16644bc.js +1 -0
- package/.next/static/chunks/7730-011e137be64403ae.js +1 -0
- package/.next/static/chunks/8165-263172c17ae8e8c3.js +1 -0
- package/.next/static/chunks/{8407-9a72e6f07c5d5458.js → 8407-155f84e5ba05f1d5.js} +1 -1
- package/.next/static/chunks/8606-cf6bdbff44a764cf.js +1 -0
- package/.next/static/chunks/934-a37509667baa86ee.js +1 -0
- package/.next/static/chunks/9465-e5a351baa941f31b.js +1 -0
- package/.next/static/chunks/app/layout-3e357690446cd2da.js +1 -0
- package/.next/static/chunks/app/repositories/page-71f5a5ac29b0370d.js +1 -0
- package/.next/static/chunks/app/review/page-e2fd4a590646a2d8.js +1 -0
- package/.next/static/chunks/app/sessions/page-9859ed61e93e6890.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/page-52ba58712faf3378.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-effbf0796881dd5a.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/{page-c601f3b3ece6557e.js → page-373ea37b16d930c7.js} +1 -1
- package/.next/static/chunks/{webpack-ee3ccbe378c4aa06.js → webpack-468b7b33030234b3.js} +1 -1
- package/.next/static/css/743f79ff19ab91e9.css +1 -0
- package/.next/trace +13 -13
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +6 -1
- package/dist/cli/types/api-responses.d.ts +8 -6
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +13 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/locales/en/worktree.json +46 -16
- package/dist/server/locales/ja/worktree.json +46 -16
- package/dist/server/src/config/activity-bar-config.js +56 -9
- package/dist/server/src/lib/assistant-response-saver.js +13 -0
- package/dist/server/src/lib/auto-yes-poller.js +252 -54
- package/dist/server/src/lib/conversation-logger.js +14 -2
- package/dist/server/src/lib/db/chat-db.js +2 -1
- package/dist/server/src/lib/history/user-turn-recorder.js +14 -0
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +28 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/codex/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/transcript-history.js +34 -0
- package/dist/server/src/lib/log-manager.js +7 -2
- package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +22 -3
- package/dist/server/src/lib/polling/auto-yes-poller-state.js +234 -0
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/src/lib/polling/pending-scraped-response.js +119 -3
- package/dist/server/src/lib/polling/poller-owner.js +110 -0
- package/dist/server/src/lib/polling/prompt-dedup-state.js +26 -7
- package/dist/server/src/lib/polling/prompt-dedup.js +50 -22
- package/dist/server/src/lib/polling/response-checker.js +212 -36
- package/dist/server/src/lib/polling/response-dedup.js +112 -20
- package/dist/server/src/lib/polling/response-poller-core.js +178 -38
- package/dist/server/src/lib/polling/structured-history-gate.js +20 -1
- package/dist/server/src/lib/prompt-answer-sender.js +59 -12
- package/dist/server/src/lib/realtime/terminal-broadcast.js +14 -0
- package/dist/server/src/lib/session/chat-turn-progress.js +57 -6
- package/dist/server/src/lib/session/current-output-builder.js +19 -0
- package/dist/server/src/lib/session/next-action-helper.js +2 -15
- package/dist/server/src/lib/session/worktree-session-reconcile.js +83 -10
- package/dist/server/src/lib/timer-manager.js +7 -0
- package/dist/server/src/lib/tmux/tmux.js +24 -2
- package/dist/server/src/lib/verification/env-clean-gate.js +41 -0
- package/dist/server/src/lib/verification/gate-runner.js +17 -11
- package/dist/server/src/lib/verification/scope-gate.js +169 -3
- package/dist/server/src/types/sidebar.js +1 -0
- package/docs/en/architecture.md +26 -14
- package/docs/en/user-guide/webapp-guide.md +31 -18
- package/package.json +1 -1
- package/release-notes/0.46.0.json +110 -0
- package/release-notes/0.46.1.json +40 -0
- package/.next/server/chunks/1674.js +0 -15
- package/.next/server/chunks/5625.js +0 -25
- package/.next/server/chunks/6927.js +0 -1
- package/.next/server/chunks/9355.js +0 -1
- package/.next/static/chunks/1642-0f1bf8fb8161e10a.js +0 -1
- package/.next/static/chunks/2770-827a64760bab8a3a.js +0 -1
- package/.next/static/chunks/3922.0bc2e4e168d2b522.js +0 -1
- package/.next/static/chunks/4727-4c69d1aa4118cc09.js +0 -1
- package/.next/static/chunks/4768-fc0aa1d0891cac08.js +0 -1
- package/.next/static/chunks/5371-af1c2b68e983da61.js +0 -1
- package/.next/static/chunks/5521-c358c31f60e5e689.js +0 -1
- package/.next/static/chunks/6192-a67df090838b9aad.js +0 -1
- package/.next/static/chunks/6322-f1b30ed0ee43518f.js +0 -1
- package/.next/static/chunks/6654-ac431270fac1a283.js +0 -1
- package/.next/static/chunks/8165-3525fb42f1b4976e.js +0 -1
- package/.next/static/chunks/8318-01e7d1e5ad0a15a3.js +0 -1
- package/.next/static/chunks/8606-79c36d4c204bbd38.js +0 -1
- package/.next/static/chunks/9619-6c17a271f7f98fbb.js +0 -1
- package/.next/static/chunks/998-2eb5883186abd0bd.js +0 -1
- package/.next/static/chunks/app/layout-eaa6365f8f942e88.js +0 -1
- package/.next/static/chunks/app/repositories/page-6f7511f4ac8449e2.js +0 -1
- package/.next/static/chunks/app/review/page-95f749caae382f46.js +0 -1
- package/.next/static/chunks/app/sessions/page-ebfed2c80e916fb8.js +0 -1
- package/.next/static/chunks/app/skills/[skillId]/page-e4b14031f946c007.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-3372b78fde232b1f.js +0 -1
- package/.next/static/css/6faeb04a0b6819d4.css +0 -1
- /package/.next/static/{vYIpFRCU_Mt0wtG8F_3-6 → QxDf7lm-JJkWoj-TyWiSB}/_buildManifest.js +0 -0
- /package/.next/static/{vYIpFRCU_Mt0wtG8F_3-6 → QxDf7lm-JJkWoj-TyWiSB}/_ssgManifest.js +0 -0
|
@@ -52,6 +52,7 @@ exports.publishChatTurnProgress = publishChatTurnProgress;
|
|
|
52
52
|
const types_1 = require("../../lib/realtime/types");
|
|
53
53
|
const logger_1 = require("../../lib/logger");
|
|
54
54
|
const global_state_1 = require("../global-state");
|
|
55
|
+
const poller_owner_1 = require("../../lib/polling/poller-owner");
|
|
55
56
|
// Issue #3215: the name is the one these lines have always been logged under.
|
|
56
57
|
// It is what an operator greps for, so it did not move with the code.
|
|
57
58
|
const logger = (0, logger_1.createLogger)('current-output-builder');
|
|
@@ -169,6 +170,19 @@ function logChatTurnProgressOutcome(target, outcome, turnKey, extra = {}) {
|
|
|
169
170
|
* @returns The frame to broadcast, or null when there is nothing new to say
|
|
170
171
|
*/
|
|
171
172
|
async function buildChatTurnProgress(target, source, now = Date.now()) {
|
|
173
|
+
const prepared = await prepareChatTurnProgress(target, source, now);
|
|
174
|
+
return prepared === null ? null : commitChatTurnProgress(target, prepared);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The half of {@link buildChatTurnProgress} that awaits: the throttle, the read
|
|
178
|
+
* and the bound — and nothing remembered about the body (Issue #3705).
|
|
179
|
+
*
|
|
180
|
+
* Split so that {@link emitChatTurnProgress} can remember a body only once it is
|
|
181
|
+
* actually going out. Remembered at the build and refused at the broadcast (a
|
|
182
|
+
* poller snapshot superseded in the `await` between the two), the body stood
|
|
183
|
+
* as "already sent" and suppressed the successor's identical frame.
|
|
184
|
+
*/
|
|
185
|
+
async function prepareChatTurnProgress(target, source, now) {
|
|
172
186
|
const key = chatTurnProgressKey(target);
|
|
173
187
|
const state = chatTurnProgressState.get(key) ?? newChatTurnProgressState();
|
|
174
188
|
if (now - state.askedAt < types_1.CHAT_TURN_PROGRESS_MIN_INTERVAL_MS)
|
|
@@ -186,20 +200,43 @@ async function buildChatTurnProgress(target, source, now = Date.now()) {
|
|
|
186
200
|
}
|
|
187
201
|
if (!draft || draft.body.length === 0)
|
|
188
202
|
return null;
|
|
203
|
+
// Issue #3705: the frame of a poller snapshot whose tick was superseded while
|
|
204
|
+
// the transcript was read is not built — and, above all, not remembered: the
|
|
205
|
+
// turn key and body are what suppress the successor's identical frame.
|
|
206
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
207
|
+
return null;
|
|
189
208
|
const bounded = (0, types_1.truncateChatTurnProgressBody)(draft.body);
|
|
190
209
|
if (draft.turnKey === state.turnKey && bounded.body === state.body)
|
|
191
210
|
return null;
|
|
192
|
-
|
|
193
|
-
|
|
211
|
+
return {
|
|
212
|
+
turnKey: draft.turnKey,
|
|
213
|
+
body: bounded.body,
|
|
214
|
+
partial: bounded.truncated || draft.partial === true,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Remember a prepared frame and give it its version — synchronous, so the
|
|
219
|
+
* caller can make it the last step before the broadcast (Issue #3705). The
|
|
220
|
+
* no-change rule is applied again against what is remembered NOW, since another
|
|
221
|
+
* frame may have gone out while the read was in flight.
|
|
222
|
+
*/
|
|
223
|
+
function commitChatTurnProgress(target, prepared) {
|
|
224
|
+
const key = chatTurnProgressKey(target);
|
|
225
|
+
const state = chatTurnProgressState.get(key) ?? newChatTurnProgressState();
|
|
226
|
+
if (prepared.turnKey === state.turnKey && prepared.body === state.body)
|
|
227
|
+
return null;
|
|
228
|
+
state.turnKey = prepared.turnKey;
|
|
229
|
+
state.body = prepared.body;
|
|
194
230
|
state.version += 1;
|
|
231
|
+
chatTurnProgressState.set(key, state);
|
|
195
232
|
return {
|
|
196
233
|
type: types_1.CHAT_TURN_PROGRESS_EVENT_TYPE,
|
|
197
234
|
worktreeId: target.worktreeId,
|
|
198
235
|
cliToolId: target.cliToolId,
|
|
199
236
|
instanceId: target.instanceId ?? target.cliToolId,
|
|
200
|
-
turnKey:
|
|
201
|
-
body:
|
|
202
|
-
partial:
|
|
237
|
+
turnKey: prepared.turnKey,
|
|
238
|
+
body: prepared.body,
|
|
239
|
+
partial: prepared.partial,
|
|
203
240
|
version: state.version,
|
|
204
241
|
done: false,
|
|
205
242
|
};
|
|
@@ -232,9 +269,18 @@ async function emitChatTurnProgress(target, source, now = Date.now()) {
|
|
|
232
269
|
logChatTurnProgressOutcome(target, 'no-subscribers', null);
|
|
233
270
|
return false;
|
|
234
271
|
}
|
|
235
|
-
const
|
|
272
|
+
const prepared = await prepareChatTurnProgress(target, source, now);
|
|
236
273
|
// Not logged: null is the throttle, an unchanged body, or a turn with no
|
|
237
274
|
// text yet — the quiet, correct majority of ticks.
|
|
275
|
+
if (!prepared)
|
|
276
|
+
return false;
|
|
277
|
+
// Issue #3705: asked after the build's `await`, and BEFORE the body is
|
|
278
|
+
// remembered — a frame refused here leaves nothing behind that would make
|
|
279
|
+
// the successor's same body look already sent. From here to the broadcast
|
|
280
|
+
// there is no `await`.
|
|
281
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
282
|
+
return false;
|
|
283
|
+
const event = commitChatTurnProgress(target, prepared);
|
|
238
284
|
if (!event)
|
|
239
285
|
return false;
|
|
240
286
|
broadcast(target.worktreeId, event);
|
|
@@ -302,6 +348,11 @@ async function publishChatTurnProgress(db, worktreeId, cliToolId, instanceId) {
|
|
|
302
348
|
// sessions nobody is watching, which is the bargain that was already being
|
|
303
349
|
// struck one frame later.
|
|
304
350
|
const { hasRoomSubscribers } = await Promise.resolve().then(() => __importStar(require('../../lib/ws-server')));
|
|
351
|
+
// Issue #3705: the progress of a superseded tick's snapshot is not started.
|
|
352
|
+
// The detached read below keeps the snapshot's owner in its async context
|
|
353
|
+
// and asks again before it remembers or broadcasts anything.
|
|
354
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
355
|
+
return;
|
|
305
356
|
if (!hasRoomSubscribers(worktreeId)) {
|
|
306
357
|
logChatTurnProgressOutcome(target, 'no-subscribers', null);
|
|
307
358
|
return;
|
|
@@ -48,6 +48,7 @@ const auto_yes_dialog_gate_1 = require("../../lib/polling/auto-yes-dialog-gate")
|
|
|
48
48
|
const layer_disagreement_1 = require("../../lib/session/layer-disagreement");
|
|
49
49
|
const structured_prompt_1 = require("../../lib/session/structured-prompt");
|
|
50
50
|
const chat_turn_progress_1 = require("./chat-turn-progress");
|
|
51
|
+
const poller_owner_1 = require("../../lib/polling/poller-owner");
|
|
51
52
|
const structured_status_merge_1 = require("./structured-status-merge");
|
|
52
53
|
const current_output_history_writers_1 = require("./current-output-history-writers");
|
|
53
54
|
const detection_divergence_1 = require("./detection-divergence");
|
|
@@ -74,6 +75,11 @@ const logger = (0, logger_1.createLogger)('current-output-builder');
|
|
|
74
75
|
*/
|
|
75
76
|
async function buildCurrentOutput(db, worktreeId, cliToolId, instanceId, resolution) {
|
|
76
77
|
const payload = await buildPayload(db, worktreeId, cliToolId, instanceId);
|
|
78
|
+
// Issue #3705: the payload's own writers asked after their awaits (see
|
|
79
|
+
// `buildPayload`); the progress frame below is one more write, of the turn
|
|
80
|
+
// the payload describes.
|
|
81
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
82
|
+
throw new poller_owner_1.RetiredSnapshotError();
|
|
77
83
|
// Issue #2199. Fire-and-forget, and placed HERE rather than in the poller for
|
|
78
84
|
// one reason: this is the function both live paths run through. The WebSocket
|
|
79
85
|
// push calls it from `broadcastTerminalSnapshot` on every generating poller
|
|
@@ -565,6 +571,15 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
|
|
|
565
571
|
const sessionName = cliTool.getSessionName(worktreeId, instanceId);
|
|
566
572
|
const { stopEventAt, eventSource, askUserQuestion, structuredEvents } = readAgentEvents(worktreeId, cliToolId, instanceId, resolvedInstanceId);
|
|
567
573
|
const running = await cliTool.isRunning(worktreeId, instanceId);
|
|
574
|
+
// Issue #3705: a terminal snapshot the response poller started for a tick
|
|
575
|
+
// that has since been superseded writes nothing from here on — not the
|
|
576
|
+
// latch, the starting state, the unclassified-frame row, the structured
|
|
577
|
+
// prompt row or the status evidence — because they would describe the turn
|
|
578
|
+
// that ended on top of the successor's. Thrown, not answered, so the payload
|
|
579
|
+
// type stays what the route reads; `broadcastTerminalSnapshot` catches it.
|
|
580
|
+
// Never thrown outside a poller snapshot (`maySnapshotPublish`).
|
|
581
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
582
|
+
throw new poller_owner_1.RetiredSnapshotError();
|
|
568
583
|
if (!running) {
|
|
569
584
|
// Issue #1926: the latch describes a process, and this one is gone. Dropped
|
|
570
585
|
// rather than aged out so the next session on this key starts with no
|
|
@@ -632,6 +647,10 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
|
|
|
632
647
|
const sessionState = (0, db_1.getSessionState)(db, worktreeId, resolvedInstanceId);
|
|
633
648
|
const lastCapturedLine = sessionState?.lastCapturedLine || 0;
|
|
634
649
|
const output = await (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, status_capture_config_1.STATUS_CAPTURE_LINES, instanceId);
|
|
650
|
+
// Issue #3705: the last `await` of the build. Everything below it, through
|
|
651
|
+
// `observeStatusEvidence`, runs without one.
|
|
652
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
653
|
+
throw new poller_owner_1.RetiredSnapshotError();
|
|
635
654
|
const lines = output.split('\n');
|
|
636
655
|
const totalLines = lines.length;
|
|
637
656
|
// Issue #1670: `content` is "everything the poller has not saved yet", which
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* Next Action Helper - Derived state for worktree next actions and review status.
|
|
4
4
|
*
|
|
5
5
|
* Issue #600: UX refresh - provides getNextAction() and getReviewStatus()
|
|
6
|
-
* for Review screen and
|
|
6
|
+
* for the Review screen (via `/api/worktrees`) and the sidebar row
|
|
7
|
+
* (`toBranchItem` in `src/types/sidebar.ts`).
|
|
7
8
|
*
|
|
8
9
|
* Uses exhaustive check (satisfies never) pattern to catch future
|
|
9
10
|
* SessionStatus extensions at compile time [DR2-005].
|
|
10
11
|
*/
|
|
11
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
13
|
exports.NEXT_ACTION_KEYS = void 0;
|
|
13
|
-
exports.isNextActionKey = isNextActionKey;
|
|
14
14
|
exports.getNextAction = getNextAction;
|
|
15
15
|
exports.getReviewStatus = getReviewStatus;
|
|
16
16
|
/**
|
|
@@ -31,19 +31,6 @@ exports.NEXT_ACTION_KEYS = {
|
|
|
31
31
|
checkStalled: 'nextAction.checkStalled',
|
|
32
32
|
running: 'nextAction.running',
|
|
33
33
|
};
|
|
34
|
-
const NEXT_ACTION_KEY_SET = new Set(Object.values(exports.NEXT_ACTION_KEYS));
|
|
35
|
-
/**
|
|
36
|
-
* Whether a value is a key this module produces (Issue #1787).
|
|
37
|
-
*
|
|
38
|
-
* `Worktree.nextAction` is a plain `string` on the wire, and a server that
|
|
39
|
-
* predates this Issue still sends the old English literal. Callers must gate
|
|
40
|
-
* `t()` on this: next-intl reports a missing key by rendering the key path, so
|
|
41
|
-
* feeding it `"Approve / Reject"` would put `worktree.Approve / Reject` on
|
|
42
|
-
* screen. Anything that fails this test is rendered verbatim instead.
|
|
43
|
-
*/
|
|
44
|
-
function isNextActionKey(value) {
|
|
45
|
-
return NEXT_ACTION_KEY_SET.has(value);
|
|
46
|
-
}
|
|
47
34
|
/**
|
|
48
35
|
* Determine the next action for a given session state.
|
|
49
36
|
*
|
|
@@ -86,6 +86,8 @@ const session_ownership_1 = require("../../lib/tmux/session-ownership");
|
|
|
86
86
|
const control_mode_tmux_transport_1 = require("../../lib/tmux/control-mode-tmux-transport");
|
|
87
87
|
const auto_yes_manager_1 = require("../../lib/polling/auto-yes-manager");
|
|
88
88
|
const response_poller_1 = require("../../lib/polling/response-poller");
|
|
89
|
+
const auto_yes_poller_state_1 = require("../../lib/polling/auto-yes-poller-state");
|
|
90
|
+
const auto_yes_enter_fallback_1 = require("../../lib/polling/auto-yes-enter-fallback");
|
|
89
91
|
const ws_server_1 = require("../../lib/ws-server");
|
|
90
92
|
const logger_1 = require("../../lib/logger");
|
|
91
93
|
const logger = (0, logger_1.createLogger)('worktree-session-reconcile');
|
|
@@ -152,8 +154,9 @@ function planSessionRenames(db, rename, errors) {
|
|
|
152
154
|
// getSessionName validates already; assert it explicitly so the guarantee
|
|
153
155
|
// is stated where the name is about to be handed to tmux (Issue #1621).
|
|
154
156
|
(0, validation_1.validateSessionName)(newName);
|
|
155
|
-
if (oldName !== newName)
|
|
156
|
-
plans.push({ oldName, newName, rename, source: 'roster' });
|
|
157
|
+
if (oldName !== newName) {
|
|
158
|
+
plans.push({ oldName, newName, rename, cliToolId, instanceId, source: 'roster' });
|
|
159
|
+
}
|
|
157
160
|
}
|
|
158
161
|
catch (error) {
|
|
159
162
|
errors.push(`session name for ${rename.oldId}/${instanceId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -284,8 +287,16 @@ function discoverSessionRenames(renames, liveNames, knownIds, result) {
|
|
|
284
287
|
: attributed.cliToolId;
|
|
285
288
|
const newName = tool.getSessionName(rename.newId, instanceId);
|
|
286
289
|
(0, validation_1.validateSessionName)(newName);
|
|
287
|
-
if (name !== newName)
|
|
288
|
-
plans.push({
|
|
290
|
+
if (name !== newName) {
|
|
291
|
+
plans.push({
|
|
292
|
+
oldName: name,
|
|
293
|
+
newName,
|
|
294
|
+
rename,
|
|
295
|
+
cliToolId: attributed.cliToolId,
|
|
296
|
+
instanceId,
|
|
297
|
+
source: 'live',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
289
300
|
}
|
|
290
301
|
catch (error) {
|
|
291
302
|
result.errors.push(`attribute session ${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -374,6 +385,10 @@ function allocateTempName(taken, ordinal) {
|
|
|
374
385
|
}
|
|
375
386
|
/**
|
|
376
387
|
* Rename the live tmux sessions in two stages so no intermediate state collides.
|
|
388
|
+
*
|
|
389
|
+
* @returns The plans whose session was renamed in BOTH stages (Issue #3713: a
|
|
390
|
+
* stage-2 `false` — the session vanished from its temporary name — is not
|
|
391
|
+
* one; it is reported as skipped).
|
|
377
392
|
*/
|
|
378
393
|
async function renameSessionsTwoStage(plans, live, deps, result) {
|
|
379
394
|
if (plans.length === 0)
|
|
@@ -426,7 +441,14 @@ async function renameSessionsTwoStage(plans, live, deps, result) {
|
|
|
426
441
|
const completed = [];
|
|
427
442
|
for (const { plan, tempName } of staged) {
|
|
428
443
|
try {
|
|
429
|
-
await deps.renameSession(tempName, plan.newName)
|
|
444
|
+
if (!(await deps.renameSession(tempName, plan.newName))) {
|
|
445
|
+
result.skippedSessions.push({
|
|
446
|
+
oldName: plan.oldName,
|
|
447
|
+
newName: plan.newName,
|
|
448
|
+
reason: 'session no longer exists',
|
|
449
|
+
});
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
430
452
|
result.renamedSessions.push({ oldName: plan.oldName, newName: plan.newName });
|
|
431
453
|
completed.push(plan);
|
|
432
454
|
// The control-mode attach survived the rename; only the registry key is
|
|
@@ -453,6 +475,37 @@ async function renameSessionsTwoStage(plans, live, deps, result) {
|
|
|
453
475
|
}
|
|
454
476
|
return completed;
|
|
455
477
|
}
|
|
478
|
+
/** The Auto-Yes composite key of a plan's instance under `worktreeId`. */
|
|
479
|
+
function autoYesKeyOf(plan, worktreeId) {
|
|
480
|
+
return (0, auto_yes_manager_1.buildCompositeKey)(worktreeId, plan.cliToolId, plan.instanceId);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Carry Auto-Yes's memory of an answer stopped part-way, and of a send still in
|
|
484
|
+
* flight, to the new key of each session that moved (Issue #3713).
|
|
485
|
+
*
|
|
486
|
+
* Only for the renames that succeeded in both stages: a refused, failed or
|
|
487
|
+
* vanished rename leaves the destination's live session — and its memory —
|
|
488
|
+
* alone. Not part of {@link migrateRuntimeState}, which still runs for every
|
|
489
|
+
* requested pair: a grant, a response poller or a WebSocket room is about the
|
|
490
|
+
* worktree, this memory is about one process.
|
|
491
|
+
*/
|
|
492
|
+
function moveAutoYesPartialAnswers(completed, sourceEpochs) {
|
|
493
|
+
const moves = [];
|
|
494
|
+
for (const plan of completed) {
|
|
495
|
+
const sourceEpoch = sourceEpochs.get(plan);
|
|
496
|
+
if (sourceEpoch === undefined)
|
|
497
|
+
continue;
|
|
498
|
+
moves.push({
|
|
499
|
+
oldKey: autoYesKeyOf(plan, plan.rename.oldId),
|
|
500
|
+
newKey: autoYesKeyOf(plan, plan.rename.newId),
|
|
501
|
+
sourceEpoch,
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
const received = (0, auto_yes_poller_state_1.movePartialAnswers)(moves);
|
|
505
|
+
if (received.length > 0) {
|
|
506
|
+
logger.info('reconcile:auto-yes-partial-answers-moved', { keys: received });
|
|
507
|
+
}
|
|
508
|
+
}
|
|
456
509
|
/**
|
|
457
510
|
* Move the in-process state that is keyed on a worktree ID.
|
|
458
511
|
*
|
|
@@ -468,15 +521,27 @@ function migrateRuntimeState(db, renames, result) {
|
|
|
468
521
|
const runningAutoYesPollers = new Set((0, auto_yes_manager_1.getAutoYesPollerCompositeKeys)());
|
|
469
522
|
const movedAutoYes = (0, auto_yes_manager_1.migrateAutoYesStateWorktreeIds)(renames);
|
|
470
523
|
result.movedAutoYesKeys = movedAutoYes.map((move) => move.newKey);
|
|
524
|
+
// The poller's timer chain captures the worktree ID, so re-keying its map
|
|
525
|
+
// would leave it polling the old session. Stop and restart instead — the
|
|
526
|
+
// Auto-Yes *state* (deadline, stop pattern) is what must survive, and it
|
|
527
|
+
// already has. Every old poller is stopped before any successor starts
|
|
528
|
+
// (Issue #3713): in a swap (A↔B) with both running, stop A → start B would
|
|
529
|
+
// find B's own poller still there ("already_running"), and the stop B that
|
|
530
|
+
// follows would leave the B side with none.
|
|
531
|
+
const restarts = [];
|
|
471
532
|
for (const move of movedAutoYes) {
|
|
472
533
|
if (!runningAutoYesPollers.has(move.oldKey))
|
|
473
534
|
continue;
|
|
474
535
|
try {
|
|
475
|
-
// The poller's timer chain captures the worktree ID, so re-keying its map
|
|
476
|
-
// would leave it polling the old session. Stop and restart instead — the
|
|
477
|
-
// Auto-Yes *state* (deadline, stop pattern) is what must survive, and it
|
|
478
|
-
// already has.
|
|
479
536
|
(0, auto_yes_manager_1.stopAutoYesPolling)(move.oldKey);
|
|
537
|
+
restarts.push(move);
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
result.errors.push(`auto-yes poller ${move.newKey}: ${error instanceof Error ? error.message : String(error)}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
for (const move of restarts) {
|
|
544
|
+
try {
|
|
480
545
|
const started = (0, auto_yes_manager_1.startAutoYesPolling)(move.newWorktreeId, move.cliToolId, move.instanceId);
|
|
481
546
|
if (started.started) {
|
|
482
547
|
result.restartedAutoYesPollers.push(move.newKey);
|
|
@@ -572,7 +637,15 @@ async function reconcileWorktreeSessions(db, renamesOrOldId, newIdOrOptions, may
|
|
|
572
637
|
result.planSources.discovered++;
|
|
573
638
|
}
|
|
574
639
|
const ownedPlans = excludeForeignSessionPlans(db, plans, live, livePaths, deps, result);
|
|
575
|
-
|
|
640
|
+
// Issue #3713: each source session's epoch, read before the first rename's
|
|
641
|
+
// await — a session begun under the old key while the renames run is not the
|
|
642
|
+
// one that moves, and its memory stays where it is.
|
|
643
|
+
const sourceEpochs = new Map(ownedPlans.map((plan) => [plan, (0, auto_yes_enter_fallback_1.getEnterFallbackSessionEpoch)(autoYesKeyOf(plan, plan.rename.oldId))]));
|
|
644
|
+
const completed = await renameSessionsTwoStage(ownedPlans, live, deps, result);
|
|
645
|
+
// No await between the renames and this: Auto-Yes's memory of an answer
|
|
646
|
+
// stopped part-way (and of a send still in flight) follows exactly the
|
|
647
|
+
// sessions that moved, before any poller restarts below.
|
|
648
|
+
moveAutoYesPartialAnswers(completed, sourceEpochs);
|
|
576
649
|
}
|
|
577
650
|
// Runtime state moves after the sessions: a poller that ticks in between
|
|
578
651
|
// fails one capture against a name that is briefly gone, which is a logged
|
|
@@ -53,6 +53,13 @@ async function executeTimer(timerId) {
|
|
|
53
53
|
const instanceId = timer.instanceId;
|
|
54
54
|
// [Issue #539] Check if session is running before sending
|
|
55
55
|
const isRunning = await cliTool.isRunning(timer.worktreeId, instanceId);
|
|
56
|
+
// [Issue #3707] A cancel can succeed while the await above is pending.
|
|
57
|
+
// Re-read synchronously (no await between this read and the update below,
|
|
58
|
+
// so better-sqlite3 makes read+update atomic) and bail out unless the
|
|
59
|
+
// timer is still pending; otherwise 'cancelled' would be overwritten.
|
|
60
|
+
const current = (0, timer_db_1.getTimerById)(db, timerId);
|
|
61
|
+
if (!current || current.status !== 'pending')
|
|
62
|
+
return;
|
|
56
63
|
if (!isRunning) {
|
|
57
64
|
logger.warn('timer:no-session', { timerId, worktreeId: timer.worktreeId, instanceId });
|
|
58
65
|
(0, timer_db_1.updateTimerStatus)(db, timerId, timer_constants_1.TIMER_STATUS.NO_SESSION);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides functions to manage tmux sessions for Claude CLI integration
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.DIRECT_INPUT_TEXT_CHUNK_BYTES = exports.REPAINT_INVALIDATE_DELAY_MS = exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = void 0;
|
|
7
|
+
exports.DIRECT_INPUT_TEXT_CHUNK_BYTES = exports.REPAINT_INVALIDATE_DELAY_MS = exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = exports.SpecialKeysAbortedError = void 0;
|
|
8
8
|
exports.exactTarget = exactTarget;
|
|
9
9
|
exports.reconcileSessionGeometry = reconcileSessionGeometry;
|
|
10
10
|
exports.hasSession = hasSession;
|
|
@@ -577,6 +577,21 @@ function isSendableSpecialKey(key) {
|
|
|
577
577
|
}
|
|
578
578
|
/** Delay between individual key presses for TUI apps that need processing time (ms). */
|
|
579
579
|
const SPECIAL_KEY_DELAY_MS = 100;
|
|
580
|
+
/**
|
|
581
|
+
* {@link sendSpecialKeys} stopped between two keys because its
|
|
582
|
+
* `shouldContinue` said so (Issue #3706). Not wrapped in the transport error.
|
|
583
|
+
*/
|
|
584
|
+
class SpecialKeysAbortedError extends Error {
|
|
585
|
+
keysSent;
|
|
586
|
+
constructor(
|
|
587
|
+
/** How many keys reached tmux before the stop (always at least one). */
|
|
588
|
+
keysSent) {
|
|
589
|
+
super(`Special key sequence stopped after ${keysSent} key(s)`);
|
|
590
|
+
this.keysSent = keysSent;
|
|
591
|
+
this.name = 'SpecialKeysAbortedError';
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
exports.SpecialKeysAbortedError = SpecialKeysAbortedError;
|
|
580
595
|
/**
|
|
581
596
|
* Send tmux special keys (unquoted key names like Down, Up, Enter, Space).
|
|
582
597
|
* Used for cursor-based navigation in CLI tool prompts (e.g., Claude Code AskUserQuestion).
|
|
@@ -587,9 +602,11 @@ const SPECIAL_KEY_DELAY_MS = 100;
|
|
|
587
602
|
*
|
|
588
603
|
* @param sessionName - Target session name
|
|
589
604
|
* @param keys - Array of tmux special key names (e.g., ['Down', 'Down', 'Space', 'Enter'])
|
|
605
|
+
* @param options - Optional `shouldContinue`, asked after each delay (Issue #3706)
|
|
590
606
|
* @throws {Error} If any key name is not in the allowed set, or if tmux command fails
|
|
607
|
+
* @throws {SpecialKeysAbortedError} If `shouldContinue` returned false between two keys
|
|
591
608
|
*/
|
|
592
|
-
async function sendSpecialKeys(sessionName, keys) {
|
|
609
|
+
async function sendSpecialKeys(sessionName, keys, options) {
|
|
593
610
|
if (keys.length === 0)
|
|
594
611
|
return;
|
|
595
612
|
// Validate all keys are in the allowed set (command injection prevention)
|
|
@@ -604,10 +621,15 @@ async function sendSpecialKeys(sessionName, keys) {
|
|
|
604
621
|
// Delay between key presses (skip after the last key)
|
|
605
622
|
if (i < keys.length - 1) {
|
|
606
623
|
await new Promise(resolve => setTimeout(resolve, SPECIAL_KEY_DELAY_MS));
|
|
624
|
+
if (options?.shouldContinue && !options.shouldContinue()) {
|
|
625
|
+
throw new SpecialKeysAbortedError(i + 1);
|
|
626
|
+
}
|
|
607
627
|
}
|
|
608
628
|
}
|
|
609
629
|
}
|
|
610
630
|
catch (error) {
|
|
631
|
+
if (error instanceof SpecialKeysAbortedError)
|
|
632
|
+
throw error;
|
|
611
633
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
612
634
|
throw new Error(`Failed to send special keys to tmux session: ${errorMessage}`);
|
|
613
635
|
}
|
|
@@ -39,6 +39,7 @@ exports.ENV_CLEAN_GUIDANCE = exports.MAX_REPORTED_ENV_CHANGES = exports.isLivePi
|
|
|
39
39
|
exports.resolveRequireEnvClean = resolveRequireEnvClean;
|
|
40
40
|
exports.attributeSessionName = attributeSessionName;
|
|
41
41
|
exports.attributeAnchor = attributeAnchor;
|
|
42
|
+
exports.isZcompdumpEntry = isZcompdumpEntry;
|
|
42
43
|
exports.demoVitestPid = demoVitestPid;
|
|
43
44
|
exports.attributeHomeEntry = attributeHomeEntry;
|
|
44
45
|
exports.resolveTaskSessionName = resolveTaskSessionName;
|
|
@@ -200,6 +201,17 @@ exports.readLivePidCwd = readLivePidCwd;
|
|
|
200
201
|
* established.
|
|
201
202
|
*/
|
|
202
203
|
const DEMO_VITEST_HOME_ENTRY = /^\.commandmate-demo-vitest-([1-9]\d*)$/;
|
|
204
|
+
/**
|
|
205
|
+
* zsh's `compinit` cache: `~/.zcompdump` itself, and the `~/.zcompdump.<host>.<pid>`
|
|
206
|
+
* scratch file it writes before renaming (#3664). A worker's shell start makes
|
|
207
|
+
* it; the pid in it is already gone by the time the gate looks. Only these two
|
|
208
|
+
* shapes — any other `.zcompdump*` name stays a violation.
|
|
209
|
+
*/
|
|
210
|
+
const ZCOMPDUMP_HOME_ENTRY = /^\.zcompdump(?:\.[A-Za-z0-9._-]+\.[1-9]\d*)?$/;
|
|
211
|
+
/** Whether a `$HOME` entry name is a zsh compinit cache file (#3664). */
|
|
212
|
+
function isZcompdumpEntry(name) {
|
|
213
|
+
return ZCOMPDUMP_HOME_ENTRY.test(name);
|
|
214
|
+
}
|
|
203
215
|
const isLivePid = (pid) => {
|
|
204
216
|
try {
|
|
205
217
|
process.kill(pid, 0);
|
|
@@ -560,6 +572,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
560
572
|
removedByOtherRepository: [],
|
|
561
573
|
removedStaleDemoVitest: [],
|
|
562
574
|
ignoredByConfig: [],
|
|
575
|
+
ignoredBuiltIn: [],
|
|
563
576
|
};
|
|
564
577
|
}
|
|
565
578
|
if (!after || after.status !== 'ok') {
|
|
@@ -575,6 +588,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
575
588
|
removedByOtherRepository: [],
|
|
576
589
|
removedStaleDemoVitest: [],
|
|
577
590
|
ignoredByConfig: [],
|
|
591
|
+
ignoredBuiltIn: [],
|
|
578
592
|
};
|
|
579
593
|
}
|
|
580
594
|
const beforeKeys = new Set(before.entries.map((entry) => entry.key));
|
|
@@ -582,10 +596,12 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
582
596
|
// Only `home-entries`, and only by the whole name: the same string under
|
|
583
597
|
// `~/.commandmate` is a different directory and stays counted.
|
|
584
598
|
const isIgnoredByConfig = (entry) => probeId === 'home-entries' && ignoredHomeEntries.has(entry.key);
|
|
599
|
+
const isIgnoredBuiltIn = (entry) => probeId === 'home-entries' && isZcompdumpEntry(entry.key);
|
|
585
600
|
const added = [];
|
|
586
601
|
const ignoredAdded = [];
|
|
587
602
|
const taskSessionAdded = [];
|
|
588
603
|
const ignoredByConfig = [];
|
|
604
|
+
const ignoredBuiltIn = [];
|
|
589
605
|
for (const entry of after.entries) {
|
|
590
606
|
if (beforeKeys.has(entry.key))
|
|
591
607
|
continue;
|
|
@@ -594,6 +610,10 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
594
610
|
ignoredByConfig.push(toChange(entry, owner));
|
|
595
611
|
continue;
|
|
596
612
|
}
|
|
613
|
+
if (isIgnoredBuiltIn(entry)) {
|
|
614
|
+
ignoredBuiltIn.push(toChange(entry, owner));
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
597
617
|
if (probeId === 'tmux-sessions' && taskSession && entry.key === taskSession) {
|
|
598
618
|
// Additions only: a task session that existed at task start and is gone
|
|
599
619
|
// falls through to `removed` below like everything else (#1624).
|
|
@@ -619,6 +639,9 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
619
639
|
if (isIgnoredByConfig(entry)) {
|
|
620
640
|
ignoredByConfig.push(change);
|
|
621
641
|
}
|
|
642
|
+
else if (isIgnoredBuiltIn(entry)) {
|
|
643
|
+
ignoredBuiltIn.push(change);
|
|
644
|
+
}
|
|
622
645
|
else if (tmuxServerSurvived &&
|
|
623
646
|
change.owner !== 'self' &&
|
|
624
647
|
otherServerSessions.has(entry.key)) {
|
|
@@ -648,6 +671,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
|
648
671
|
removedByOtherRepository,
|
|
649
672
|
removedStaleDemoVitest,
|
|
650
673
|
ignoredByConfig,
|
|
674
|
+
ignoredBuiltIn,
|
|
651
675
|
};
|
|
652
676
|
});
|
|
653
677
|
// A measured violation is a verdict and outranks an unmeasured probe; an
|
|
@@ -722,6 +746,20 @@ function formatIgnoredByConfig(changes) {
|
|
|
722
746
|
const names = changes.map((change) => change.key).join(', ');
|
|
723
747
|
return [` ignored (options.envCleanIgnoreHomeEntries): ${names}`];
|
|
724
748
|
}
|
|
749
|
+
/** Built-in `home-entries` exclusions (zsh compinit cache), on their own line (#3672). */
|
|
750
|
+
function formatIgnoredBuiltIn(changes) {
|
|
751
|
+
if (changes.length === 0)
|
|
752
|
+
return [];
|
|
753
|
+
const names = changes.map((change) => change.key).join(', ');
|
|
754
|
+
return [` ignored (built-in): ${names}`];
|
|
755
|
+
}
|
|
756
|
+
/** Additions excused as another worktree's, named on a clean report (#3683). */
|
|
757
|
+
function formatIgnoredAttributed(changes) {
|
|
758
|
+
if (changes.length === 0)
|
|
759
|
+
return [];
|
|
760
|
+
const names = changes.map((change) => change.key).join(', ');
|
|
761
|
+
return [` ignored (attributed to another worktree): ${names}`];
|
|
762
|
+
}
|
|
725
763
|
/**
|
|
726
764
|
* The header's account of what could be excused, so a report judged against a
|
|
727
765
|
* baseline written before #2472 says why the task's own session was not.
|
|
@@ -752,6 +790,8 @@ function formatEnvCleanReport(diff) {
|
|
|
752
790
|
lines.push(...formatRemovedByOtherRepository(probe.removedByOtherRepository));
|
|
753
791
|
lines.push(...formatRemovedStaleDemoVitest(probe.removedStaleDemoVitest));
|
|
754
792
|
lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
|
|
793
|
+
lines.push(...formatIgnoredBuiltIn(probe.ignoredBuiltIn));
|
|
794
|
+
lines.push(...formatIgnoredAttributed(probe.ignoredAdded));
|
|
755
795
|
continue;
|
|
756
796
|
}
|
|
757
797
|
lines.push(` ${probe.probeId} VIOLATED (${label}): +${probe.added.length} -${probe.removed.length}`);
|
|
@@ -762,6 +802,7 @@ function formatEnvCleanReport(diff) {
|
|
|
762
802
|
lines.push(...formatRemovedByOtherRepository(probe.removedByOtherRepository));
|
|
763
803
|
lines.push(...formatRemovedStaleDemoVitest(probe.removedStaleDemoVitest));
|
|
764
804
|
lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
|
|
805
|
+
lines.push(...formatIgnoredBuiltIn(probe.ignoredBuiltIn));
|
|
765
806
|
for (const excused of probe.ignoredAdded) {
|
|
766
807
|
lines.push(` · ${excused.key} (ignored: belongs to another worktree)`);
|
|
767
808
|
}
|
|
@@ -751,7 +751,10 @@ function namesOpencodeInstance(db, worktreeId, instanceId) {
|
|
|
751
751
|
* gates — the precise failure `verify-completion.sh` was written to catch.
|
|
752
752
|
*
|
|
753
753
|
* Contract files are evidence of the *orchestrator*, not of the agent, so
|
|
754
|
-
* neither side counts them (see {@link CONTRACT_DIR_PREFIX}).
|
|
754
|
+
* neither side counts them (see {@link CONTRACT_DIR_PREFIX}). Nor is the
|
|
755
|
+
* orchestrator's module-reference fold commit (orchestrate 6-4, judged by
|
|
756
|
+
* scope-gate's `collectBranchCommitChanges`): a branch that holds only a fold
|
|
757
|
+
* has no work of the worker's in it (#3633).
|
|
755
758
|
*
|
|
756
759
|
* ## The opencode second witness (Issue #2043)
|
|
757
760
|
*
|
|
@@ -796,18 +799,20 @@ async function evaluateWorkEvidence(worktreePath, baseRef, requireCommit, agentE
|
|
|
796
799
|
// pathspec is not exclusions alone, and it anchors both patterns at the root
|
|
797
800
|
// rather than at cwd. A setup commit that only carries the contract must not
|
|
798
801
|
// read as a commit's worth of work.
|
|
799
|
-
const revList = await runGit([
|
|
800
|
-
'rev-list',
|
|
801
|
-
'--count',
|
|
802
|
-
`${base}..HEAD`,
|
|
803
|
-
'--',
|
|
804
|
-
':(top)',
|
|
805
|
-
`:(exclude,top)${scope_gate_1.CONTRACT_DIR_PREFIX}`,
|
|
806
|
-
], worktreePath);
|
|
802
|
+
const revList = await runGit(['rev-list', `${base}..HEAD`, '--', ':(top)', `:(exclude,top)${scope_gate_1.CONTRACT_DIR_PREFIX}`], worktreePath);
|
|
807
803
|
if (revList.code !== 0) {
|
|
808
|
-
return done('error', `work-evidence: 'git rev-list
|
|
804
|
+
return done('error', `work-evidence: 'git rev-list ${base}..HEAD' failed.`, null);
|
|
809
805
|
}
|
|
810
|
-
|
|
806
|
+
// The orchestrator's fold commit is not the worker's (#3633), by the same
|
|
807
|
+
// rule the scope gate drops what only folds touched (#3588).
|
|
808
|
+
const branchChanges = await (0, scope_gate_1.collectBranchCommitChanges)(worktreePath, base);
|
|
809
|
+
if ('error' in branchChanges) {
|
|
810
|
+
return done('error', `work-evidence: ${branchChanges.error}`, null);
|
|
811
|
+
}
|
|
812
|
+
const foldShas = new Set(branchChanges.changes.filter((c) => c.fold).map((c) => c.sha));
|
|
813
|
+
const branchShas = revList.stdout.split('\n').filter((sha) => sha.trim() !== '');
|
|
814
|
+
const foldCount = branchShas.filter((sha) => foldShas.has(sha)).length;
|
|
815
|
+
const commitCount = branchShas.length - foldCount;
|
|
811
816
|
// -z -uall for the same reasons scope-gate uses them: the human format
|
|
812
817
|
// C-quotes paths with spaces and joins renames with ` -> `, and the default
|
|
813
818
|
// untracked mode collapses a fresh `.commandmate/tasks/` to one directory
|
|
@@ -841,6 +846,7 @@ async function evaluateWorkEvidence(worktreePath, baseRef, requireCommit, agentE
|
|
|
841
846
|
const summary = `work-evidence: baseRef=${baseRef} commits=${commitCount} uncommitted=${uncommittedCount}` +
|
|
842
847
|
(requireCommit.required ? ' requireCommit=true' : '') +
|
|
843
848
|
' (contract files excluded)' +
|
|
849
|
+
(foldCount > 0 ? ` (${foldCount} orchestrator fold commit(s) excluded)` : '') +
|
|
844
850
|
(skillInstalledCount > 0
|
|
845
851
|
? ` (${skillInstalledCount} CommandMate-installed Skill file(s) excluded)`
|
|
846
852
|
: '') +
|