commandmate 0.22.2 → 0.23.0
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 +108 -108
- package/.next/app-path-routes-manifest.json +21 -21
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_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.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +1 -1
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +3 -3
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/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/daily-summary/route.js +1 -1
- package/.next/server/app/api/daily-summary/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/route.js.nft.json +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route.js +1 -1
- package/.next/server/app/api/fs/browse/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route.js.nft.json +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 +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 +1 -1
- 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 +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.js +1 -1
- package/.next/server/app/api/metrics/vibe/route.js.nft.json +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/subscriptions/route.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.js.nft.json +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route.js +1 -1
- package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route.js +1 -1
- package/.next/server/app/api/repositories/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/[id]/todos/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.js +1 -1
- package/.next/server/app/api/repositories/excluded/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/skills/installations/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route.js +1 -1
- package/.next/server/app/api/skills/operations/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route.js +1 -1
- package/.next/server/app/api/skills/reindex/route.js.nft.json +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.js +1 -4
- package/.next/server/app/api/tasks/[taskId]/cancel/route.js.nft.json +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.js +1 -4
- package/.next/server/app/api/tasks/[taskId]/route.js.nft.json +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route.js +1 -1
- package/.next/server/app/api/templates/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route.js +1 -1
- package/.next/server/app/api/templates/route.js.nft.json +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/todos/route.js +1 -1
- package/.next/server/app/api/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/verification/runs/route.js.nft.json +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 +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]/cli-tool/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +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 +2 -2
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
- 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]/execution-logs/[logId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js.nft.json +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 +2 -2
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js.nft.json +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]/interrupt/route.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +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 +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -1
- 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.js +3 -3
- package/.next/server/app/api/worktrees/[id]/marp-render/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/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]/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 +2 -2
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
- 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 +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +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 +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +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]/start-polling/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/tasks/route.js.nft.json +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 +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +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/route.js +1 -4
- package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +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]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/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/chat/page_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +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 +2 -2
- 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 +21 -21
- package/.next/server/chunks/1029.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2546.js +1 -1
- package/.next/server/chunks/3241.js +1 -0
- package/.next/server/chunks/3417.js +1 -1
- package/.next/server/chunks/406.js +10 -6
- package/.next/server/chunks/4444.js +1 -1
- package/.next/server/chunks/5959.js +4 -5
- package/.next/server/chunks/5998.js +1 -12
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6274.js +3 -3
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6781.js +1 -0
- package/.next/server/chunks/7458.js +6 -0
- package/.next/server/chunks/{3753.js → 7970.js} +57 -32
- package/.next/server/chunks/8536.js +1 -1
- package/.next/server/chunks/8807.js +180 -127
- package/.next/server/chunks/9058.js +1 -1
- package/.next/server/chunks/9067.js +1 -1
- package/.next/server/chunks/9360.js +1 -1
- package/.next/server/chunks/9687.js +2 -2
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/server/src/middleware.js.map +1 -1
- package/.next/static/chunks/{6488-53a3e1d78e4fe8f7.js → 6488-95ba9d24a76f0cc5.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/{page-6dc0b8c4e808ea3e.js → page-966a451ae7b0903a.js} +1 -1
- package/.next/trace +12 -12
- package/dist/server/src/config/log-config.js +10 -1
- package/dist/server/src/config/safe-directory.js +103 -0
- package/dist/server/src/config/system-directories.js +74 -9
- package/dist/server/src/lib/cli-tools/antigravity.js +19 -2
- package/dist/server/src/lib/cli-tools/codex.js +95 -1
- package/dist/server/src/lib/cli-tools/copilot.js +30 -1
- package/dist/server/src/lib/cli-tools/gemini.js +28 -2
- package/dist/server/src/lib/cli-tools/opencode.js +51 -2
- package/dist/server/src/lib/git/git-default-branch.js +59 -0
- package/dist/server/src/lib/hooks/agent-event-service.js +205 -0
- package/dist/server/src/lib/hooks/agent-event-types.js +7 -86
- package/dist/server/src/lib/hooks/hook-settings-generator.js +26 -11
- package/dist/server/src/lib/hooks/permission-decision-service.js +269 -0
- package/dist/server/src/lib/hooks/sources/abstain.js +78 -0
- package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +372 -0
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +225 -0
- package/dist/server/src/lib/hooks/sources/antigravity/tool-id.js +16 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +143 -0
- package/dist/server/src/lib/hooks/sources/claude/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +465 -0
- package/dist/server/src/lib/hooks/sources/codex/source.js +138 -0
- package/dist/server/src/lib/hooks/sources/codex/tool-id.js +15 -0
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +473 -0
- package/dist/server/src/lib/hooks/sources/copilot/source.js +210 -0
- package/dist/server/src/lib/hooks/sources/copilot/tool-id.js +15 -0
- package/dist/server/src/lib/hooks/sources/define-source.js +169 -0
- package/dist/server/src/lib/hooks/sources/event-mapper.js +157 -0
- package/dist/server/src/lib/hooks/sources/gemini/event-vocabulary.js +102 -0
- package/dist/server/src/lib/hooks/sources/gemini/settings-generator.js +315 -0
- package/dist/server/src/lib/hooks/sources/gemini/shared-config-tree.js +103 -0
- package/dist/server/src/lib/hooks/sources/gemini/source.js +151 -0
- package/dist/server/src/lib/hooks/sources/gemini/tool-id.js +17 -0
- package/dist/server/src/lib/hooks/sources/hook-event-vocabulary.js +111 -0
- package/dist/server/src/lib/hooks/sources/index.js +62 -0
- package/dist/server/src/lib/hooks/sources/legacy-relay.js +84 -0
- package/dist/server/src/lib/hooks/sources/opencode/client.js +299 -0
- package/dist/server/src/lib/hooks/sources/opencode/ingest.js +261 -0
- package/dist/server/src/lib/hooks/sources/opencode/mappers.js +154 -0
- package/dist/server/src/lib/hooks/sources/opencode/payloads.js +189 -0
- package/dist/server/src/lib/hooks/sources/opencode/ports.js +295 -0
- package/dist/server/src/lib/hooks/sources/opencode/runtime.js +159 -0
- package/dist/server/src/lib/hooks/sources/opencode/source.js +250 -0
- package/dist/server/src/lib/hooks/sources/opencode/subscription.js +422 -0
- package/dist/server/src/lib/hooks/sources/opencode/tool-id.js +14 -0
- package/dist/server/src/lib/hooks/sources/opencode/turn-gate.js +193 -0
- package/dist/server/src/lib/hooks/sources/pending-decisions.js +127 -0
- package/dist/server/src/lib/hooks/sources/registry.js +111 -0
- package/dist/server/src/lib/hooks/sources/types.js +46 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +82 -0
- package/dist/server/src/lib/session/claude-session.js +10 -3
- package/dist/server/src/lib/tasks/contract-message.js +175 -0
- package/dist/server/src/lib/verification/env-clean-gate.js +320 -0
- package/dist/server/src/lib/verification/env-snapshot.js +474 -0
- package/dist/server/src/lib/verification/gate-runner.js +802 -0
- package/dist/server/src/lib/verification/scope-gate.js +402 -0
- package/dist/server/src/lib/verification/verify-config.js +281 -0
- package/package.json +1 -1
- package/scripts/hooks/cmate-agent-event.sh +73 -3
- package/.next/server/chunks/8856.js +0 -4
- /package/.next/static/{XpKfn5x6H-mtTaXI9yNmb → wH6K6QNPHSdATFkVoIcy3}/_buildManifest.js +0 -0
- /package/.next/static/{XpKfn5x6H-mtTaXI9yNmb → wH6K6QNPHSdATFkVoIcy3}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Environment snapshots for the built-in `env-clean` gate (Issue #1740).
|
|
4
|
+
*
|
|
5
|
+
* `scope` judges what a delegation changed *inside* the repository. Nothing
|
|
6
|
+
* judged what it changed *outside* one, so the failures of 2026-08-06 all passed
|
|
7
|
+
* every gate: a worker's `pkill -f "node dist/server/server.js"` stopped the
|
|
8
|
+
* user's production server (#1739), another left `~/.commandmate-uat-1726` in
|
|
9
|
+
* `$HOME`, another left an isolated server listening on 3779, and a fourth wrote
|
|
10
|
+
* into `~/.commandmate/hooks` (#1722). This module records the four observable
|
|
11
|
+
* facts those failures moved, so the pair (task start, task end) can be diffed.
|
|
12
|
+
*
|
|
13
|
+
* The one rule the whole design hangs on: **a probe that could not answer is
|
|
14
|
+
* never an empty answer.** Reporting "no listeners found" when `lsof` is missing
|
|
15
|
+
* would hand out a green verdict computed from nothing — the #1614 failure mode
|
|
16
|
+
* of shipping a 0 that was never measured. Every probe therefore carries its own
|
|
17
|
+
* {@link EnvProbeStatus}, and {@link EnvProbeResult.entries} is only meaningful
|
|
18
|
+
* when that status is `ok`.
|
|
19
|
+
*
|
|
20
|
+
* Server-only: spawns processes and reads the filesystem.
|
|
21
|
+
*
|
|
22
|
+
* @module lib/verification/env-snapshot
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.ENV_SNAPSHOT_RETENTION_MS = exports.ENV_SNAPSHOT_DIR_NAME = exports.VOLATILE_ENTRY_PATTERNS = exports.MCBD_SESSION_PREFIX = exports.COMMANDMATE_PROCESS_PATTERN = exports.DEFAULT_ENV_PROBE_DEPS = exports.ENV_PROBE_LABELS = exports.ENV_PROBE_IDS = exports.ENV_SNAPSHOT_VERSION = void 0;
|
|
26
|
+
exports.probeListeners = probeListeners;
|
|
27
|
+
exports.probeTmuxSessions = probeTmuxSessions;
|
|
28
|
+
exports.probeHomeEntries = probeHomeEntries;
|
|
29
|
+
exports.probeCommandmateEntries = probeCommandmateEntries;
|
|
30
|
+
exports.captureEnvSnapshot = captureEnvSnapshot;
|
|
31
|
+
exports.resolveEnvSnapshotDir = resolveEnvSnapshotDir;
|
|
32
|
+
exports.saveEnvSnapshot = saveEnvSnapshot;
|
|
33
|
+
exports.loadEnvSnapshot = loadEnvSnapshot;
|
|
34
|
+
exports.isEnvSnapshot = isEnvSnapshot;
|
|
35
|
+
const child_process_1 = require("child_process");
|
|
36
|
+
const fs_1 = require("fs");
|
|
37
|
+
const os_1 = require("os");
|
|
38
|
+
const path_1 = require("path");
|
|
39
|
+
const env_1 = require("../../lib/env");
|
|
40
|
+
const logger_1 = require("../../lib/logger");
|
|
41
|
+
const logger = (0, logger_1.createLogger)('lib/verification/env-snapshot');
|
|
42
|
+
/** Bumped only when a stored snapshot stops being readable by this module. */
|
|
43
|
+
exports.ENV_SNAPSHOT_VERSION = 1;
|
|
44
|
+
/**
|
|
45
|
+
* The four facts the gate watches, one per row of the Issue's table.
|
|
46
|
+
*
|
|
47
|
+
* Ordered as the report prints them: the two that cost a running system first,
|
|
48
|
+
* then the two that only cost disk.
|
|
49
|
+
*/
|
|
50
|
+
exports.ENV_PROBE_IDS = [
|
|
51
|
+
'listeners',
|
|
52
|
+
'tmux-sessions',
|
|
53
|
+
'home-entries',
|
|
54
|
+
'commandmate-entries',
|
|
55
|
+
];
|
|
56
|
+
/** Human label used in the gate report. */
|
|
57
|
+
exports.ENV_PROBE_LABELS = {
|
|
58
|
+
listeners: 'CommandMate TCP listeners',
|
|
59
|
+
'tmux-sessions': 'mcbd-* tmux sessions',
|
|
60
|
+
'home-entries': '$HOME entries',
|
|
61
|
+
'commandmate-entries': '~/.commandmate entries',
|
|
62
|
+
};
|
|
63
|
+
/** Probes are bounded: a hung `lsof` must not hold a verification run open. */
|
|
64
|
+
const PROBE_TIMEOUT_MS = 5000;
|
|
65
|
+
/** Output kept per probe command; far above any real listing. */
|
|
66
|
+
const PROBE_MAX_BUFFER = 4 * 1024 * 1024;
|
|
67
|
+
function runCommand(command, args) {
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
(0, child_process_1.execFile)(command, args, { timeout: PROBE_TIMEOUT_MS, maxBuffer: PROBE_MAX_BUFFER, encoding: 'utf8' }, (error, stdout, stderr) => {
|
|
70
|
+
if (!error) {
|
|
71
|
+
resolve({ code: 0, stdout, stderr, failure: null });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const withCode = error;
|
|
75
|
+
// execFile reports a non-zero exit as `code: <number>` and a spawn
|
|
76
|
+
// failure or timeout as `code: 'ENOENT'` / `killed: true`. Only the
|
|
77
|
+
// first is an answer; the rest are the absence of one.
|
|
78
|
+
if (typeof withCode.code === 'number' && !withCode.killed) {
|
|
79
|
+
resolve({ code: withCode.code, stdout, stderr, failure: null });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
resolve({
|
|
83
|
+
code: null,
|
|
84
|
+
stdout,
|
|
85
|
+
stderr,
|
|
86
|
+
failure: withCode.killed
|
|
87
|
+
? `${command} exceeded ${PROBE_TIMEOUT_MS}ms and was terminated`
|
|
88
|
+
: `${command} could not be run: ${error.message}`,
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
exports.DEFAULT_ENV_PROBE_DEPS = {
|
|
94
|
+
run: runCommand,
|
|
95
|
+
readDir: (path) => (0, fs_1.readdirSync)(path),
|
|
96
|
+
homeDir: () => (0, os_1.homedir)(),
|
|
97
|
+
};
|
|
98
|
+
// =============================================================================
|
|
99
|
+
// Probe: TCP listeners
|
|
100
|
+
// =============================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Command lines that make a listening socket "CommandMate's".
|
|
103
|
+
*
|
|
104
|
+
* Recording *every* listener would make the gate useless within a minute: a
|
|
105
|
+
* browser, a language server or a container runtime opens and closes ports
|
|
106
|
+
* constantly, and each one would read as a violation. The Issue scopes the item
|
|
107
|
+
* to "CommandMate 関連" for exactly that reason, so relevance is decided from
|
|
108
|
+
* the owning process's command line rather than from the port number — a
|
|
109
|
+
* developer's `commandmate start --port 3179` is as relevant as port 3000.
|
|
110
|
+
*/
|
|
111
|
+
exports.COMMANDMATE_PROCESS_PATTERN = /commandmate|dist\/server\/server\.js|next-server|next (dev|start)|server\.ts/i;
|
|
112
|
+
/** `ps` line: leading pid, then the full command line. */
|
|
113
|
+
function parseProcessTable(stdout) {
|
|
114
|
+
const table = new Map();
|
|
115
|
+
for (const line of stdout.split('\n')) {
|
|
116
|
+
const match = /^\s*(\d+)\s+(.*)$/.exec(line);
|
|
117
|
+
if (!match)
|
|
118
|
+
continue;
|
|
119
|
+
table.set(Number(match[1]), match[2].trim());
|
|
120
|
+
}
|
|
121
|
+
return table;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* `lsof -F` output: one field per line, the field's letter first.
|
|
125
|
+
*
|
|
126
|
+
* A `p` line opens a process block and every following field belongs to it
|
|
127
|
+
* until the next `p`.
|
|
128
|
+
*/
|
|
129
|
+
function parseLsofFields(stdout) {
|
|
130
|
+
const blocks = [];
|
|
131
|
+
let current = null;
|
|
132
|
+
for (const line of stdout.split('\n')) {
|
|
133
|
+
if (line === '')
|
|
134
|
+
continue;
|
|
135
|
+
const letter = line[0];
|
|
136
|
+
const value = line.slice(1);
|
|
137
|
+
if (letter === 'p') {
|
|
138
|
+
const pid = Number(value);
|
|
139
|
+
if (!Number.isInteger(pid)) {
|
|
140
|
+
current = null;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
current = { pid, fields: new Map() };
|
|
144
|
+
blocks.push(current);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (!current)
|
|
148
|
+
continue;
|
|
149
|
+
const bucket = current.fields.get(letter);
|
|
150
|
+
if (bucket)
|
|
151
|
+
bucket.push(value);
|
|
152
|
+
else
|
|
153
|
+
current.fields.set(letter, [value]);
|
|
154
|
+
}
|
|
155
|
+
return blocks;
|
|
156
|
+
}
|
|
157
|
+
/** `*:3000`, `127.0.0.1:3000`, `[::1]:3000` → `3000`. */
|
|
158
|
+
function portOf(name) {
|
|
159
|
+
const colon = name.lastIndexOf(':');
|
|
160
|
+
if (colon < 0)
|
|
161
|
+
return null;
|
|
162
|
+
const port = name.slice(colon + 1);
|
|
163
|
+
return /^\d+$/.test(port) ? port : null;
|
|
164
|
+
}
|
|
165
|
+
function unavailable(reason) {
|
|
166
|
+
return { status: 'unavailable', entries: [], reason };
|
|
167
|
+
}
|
|
168
|
+
function ok(entries) {
|
|
169
|
+
// Deduplicated by key: one server answers on both IPv4 and IPv6, and lsof
|
|
170
|
+
// reports that as two rows for one listener.
|
|
171
|
+
const byKey = new Map();
|
|
172
|
+
for (const entry of entries) {
|
|
173
|
+
if (!byKey.has(entry.key))
|
|
174
|
+
byKey.set(entry.key, entry);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
status: 'ok',
|
|
178
|
+
entries: [...byKey.values()].sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0)),
|
|
179
|
+
reason: null,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* CommandMate processes listening on a TCP port, keyed by port.
|
|
184
|
+
*
|
|
185
|
+
* Keyed by port rather than by pid so a plain restart is invisible: what the
|
|
186
|
+
* gate is asked to notice is a port that stopped answering (the production
|
|
187
|
+
* server was killed) or one that started and stayed (an isolated server was
|
|
188
|
+
* left behind), not that a supervisor replaced a process.
|
|
189
|
+
*
|
|
190
|
+
* `lsof` failing makes the probe `unavailable` rather than empty, and so does
|
|
191
|
+
* `ps`: without the process table there is no way to tell a CommandMate server
|
|
192
|
+
* from any other listener, and guessing would be the fail-open this gate exists
|
|
193
|
+
* to prevent.
|
|
194
|
+
*/
|
|
195
|
+
async function probeListeners(deps) {
|
|
196
|
+
const listeners = await deps.run('lsof', ['-nP', '-iTCP', '-sTCP:LISTEN', '-F', 'pcn']);
|
|
197
|
+
// lsof exits 1 when it simply matched nothing, and that is a real "none".
|
|
198
|
+
if (listeners.failure !== null)
|
|
199
|
+
return unavailable(listeners.failure);
|
|
200
|
+
if (listeners.code !== 0 && listeners.code !== 1) {
|
|
201
|
+
return unavailable(`lsof exited ${listeners.code}: ${listeners.stderr.trim() || 'no diagnostic output'}`);
|
|
202
|
+
}
|
|
203
|
+
const blocks = parseLsofFields(listeners.stdout);
|
|
204
|
+
if (blocks.length === 0)
|
|
205
|
+
return ok([]);
|
|
206
|
+
const processes = await deps.run('ps', ['-A', '-o', 'pid=,command=']);
|
|
207
|
+
if (processes.failure !== null || processes.code !== 0) {
|
|
208
|
+
return unavailable(processes.failure ??
|
|
209
|
+
`ps exited ${processes.code}: ${processes.stderr.trim() || 'no diagnostic output'}`);
|
|
210
|
+
}
|
|
211
|
+
const table = parseProcessTable(processes.stdout);
|
|
212
|
+
const relevant = blocks.filter((block) => {
|
|
213
|
+
const commandLine = table.get(block.pid);
|
|
214
|
+
return commandLine !== undefined && exports.COMMANDMATE_PROCESS_PATTERN.test(commandLine);
|
|
215
|
+
});
|
|
216
|
+
if (relevant.length === 0)
|
|
217
|
+
return ok([]);
|
|
218
|
+
// cwd is what attributes an added listener to a worker. Its absence weakens
|
|
219
|
+
// attribution (the entry becomes unattributed, which is the strict verdict)
|
|
220
|
+
// but does not invalidate the listing, so a failure here is not `unavailable`.
|
|
221
|
+
const cwdByPid = new Map();
|
|
222
|
+
const pids = relevant.map((block) => String(block.pid));
|
|
223
|
+
const cwds = await deps.run('lsof', ['-a', '-d', 'cwd', '-p', pids.join(','), '-F', 'pn']);
|
|
224
|
+
if (cwds.failure === null && (cwds.code === 0 || cwds.code === 1)) {
|
|
225
|
+
for (const block of parseLsofFields(cwds.stdout)) {
|
|
226
|
+
const [path] = block.fields.get('n') ?? [];
|
|
227
|
+
if (path)
|
|
228
|
+
cwdByPid.set(block.pid, path);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const entries = [];
|
|
232
|
+
for (const block of relevant) {
|
|
233
|
+
const command = block.fields.get('c')?.[0] ?? 'unknown';
|
|
234
|
+
for (const name of block.fields.get('n') ?? []) {
|
|
235
|
+
const port = portOf(name);
|
|
236
|
+
if (!port)
|
|
237
|
+
continue;
|
|
238
|
+
entries.push({
|
|
239
|
+
key: `tcp/${port}`,
|
|
240
|
+
detail: `${command} pid=${block.pid}`,
|
|
241
|
+
anchor: cwdByPid.get(block.pid) ?? null,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return ok(entries);
|
|
246
|
+
}
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// Probe: tmux sessions
|
|
249
|
+
// =============================================================================
|
|
250
|
+
/**
|
|
251
|
+
* Prefix every CommandMate session name carries (`mcbd-<cli>-<worktreeId>`).
|
|
252
|
+
*
|
|
253
|
+
* Duplicated from `lib/tmux/read-mode` rather than imported: that module is the
|
|
254
|
+
* read-mode key bindings, and pulling it in would make a verification gate
|
|
255
|
+
* depend on the terminal UI. The value is fixed by the session-name format in
|
|
256
|
+
* `lib/cli-tools/base.ts` and asserted against it in the unit tests.
|
|
257
|
+
*/
|
|
258
|
+
exports.MCBD_SESSION_PREFIX = 'mcbd-';
|
|
259
|
+
/**
|
|
260
|
+
* `mcbd-*` sessions on the default tmux server.
|
|
261
|
+
*
|
|
262
|
+
* Only `mcbd-*` names are recorded: every other session belongs to the user and
|
|
263
|
+
* is none of a delegation's business, so watching them would only manufacture
|
|
264
|
+
* violations. Sessions of *other* worktrees stay in the set on purpose — killing
|
|
265
|
+
* a sibling worker's session is the #1624 failure this probe is here to catch.
|
|
266
|
+
*
|
|
267
|
+
* "No server running" is an answer (zero sessions), which is why it is not
|
|
268
|
+
* treated as a probe failure. `tmux` being absent, or hanging, is not.
|
|
269
|
+
*/
|
|
270
|
+
async function probeTmuxSessions(deps) {
|
|
271
|
+
const result = await deps.run('tmux', ['list-sessions', '-F', '#{session_name}']);
|
|
272
|
+
if (result.failure !== null)
|
|
273
|
+
return unavailable(result.failure);
|
|
274
|
+
if (result.code !== 0) {
|
|
275
|
+
if (/no server running|error connecting to|no sessions/i.test(result.stderr))
|
|
276
|
+
return ok([]);
|
|
277
|
+
return unavailable(`tmux list-sessions exited ${result.code}: ${result.stderr.trim() || 'no diagnostic output'}`);
|
|
278
|
+
}
|
|
279
|
+
const entries = result.stdout
|
|
280
|
+
.split('\n')
|
|
281
|
+
.map((line) => line.trim())
|
|
282
|
+
.filter((name) => name.startsWith(exports.MCBD_SESSION_PREFIX))
|
|
283
|
+
.map((name) => ({ key: name, detail: null, anchor: null }));
|
|
284
|
+
return ok(entries);
|
|
285
|
+
}
|
|
286
|
+
// =============================================================================
|
|
287
|
+
// Probe: directory listings
|
|
288
|
+
// =============================================================================
|
|
289
|
+
/**
|
|
290
|
+
* Names that appear and disappear on their own, excluded from both directory
|
|
291
|
+
* probes.
|
|
292
|
+
*
|
|
293
|
+
* SQLite creates and removes `-wal` / `-shm` beside an open database, so a
|
|
294
|
+
* server that started or stopped between the two snapshots would otherwise
|
|
295
|
+
* report two violations for something nobody did. `.DS_Store` is written by the
|
|
296
|
+
* Finder. Excluding them is not a hole: none of them is a thing a delegation can
|
|
297
|
+
* leave behind that matters.
|
|
298
|
+
*/
|
|
299
|
+
exports.VOLATILE_ENTRY_PATTERNS = [/-wal$/, /-shm$/, /-journal$/, /^\.DS_Store$/];
|
|
300
|
+
/** This module's own storage, which must not read as something a task created. */
|
|
301
|
+
exports.ENV_SNAPSHOT_DIR_NAME = 'env-snapshots';
|
|
302
|
+
function isIgnoredEntry(name) {
|
|
303
|
+
if (name === exports.ENV_SNAPSHOT_DIR_NAME)
|
|
304
|
+
return true;
|
|
305
|
+
return exports.VOLATILE_ENTRY_PATTERNS.some((pattern) => pattern.test(name));
|
|
306
|
+
}
|
|
307
|
+
function probeDirectory(deps, path, { missingIsEmpty }) {
|
|
308
|
+
let names;
|
|
309
|
+
try {
|
|
310
|
+
names = deps.readDir(path);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
const code = error.code;
|
|
314
|
+
// A directory that does not exist yet has zero entries — and if a task
|
|
315
|
+
// creates it, that shows up as an addition, which is the point.
|
|
316
|
+
if (missingIsEmpty && code === 'ENOENT')
|
|
317
|
+
return ok([]);
|
|
318
|
+
return unavailable(`could not list ${path}: ${error.message}`);
|
|
319
|
+
}
|
|
320
|
+
return ok(names
|
|
321
|
+
.filter((name) => !isIgnoredEntry(name))
|
|
322
|
+
.map((name) => ({ key: name, detail: null, anchor: null })));
|
|
323
|
+
}
|
|
324
|
+
/** Entries directly under `$HOME`. A worker leaving `~/.commandmate-uat-1726` shows up here. */
|
|
325
|
+
function probeHomeEntries(deps) {
|
|
326
|
+
return probeDirectory(deps, deps.homeDir(), { missingIsEmpty: false });
|
|
327
|
+
}
|
|
328
|
+
/** Entries directly under `~/.commandmate` — the state directory #1722 polluted. */
|
|
329
|
+
function probeCommandmateEntries(deps) {
|
|
330
|
+
return probeDirectory(deps, (0, path_1.join)(deps.homeDir(), '.commandmate'), { missingIsEmpty: true });
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Take one snapshot of all four probes.
|
|
334
|
+
*
|
|
335
|
+
* Never throws: a probe that could not answer is recorded as `unavailable` with
|
|
336
|
+
* its reason, because the pair of snapshots has to be diffable even when half
|
|
337
|
+
* the machine refused to answer. What that means for the verdict is
|
|
338
|
+
* `diffEnvSnapshots`' decision, and it is `unknown`, never `clean`.
|
|
339
|
+
*/
|
|
340
|
+
async function captureEnvSnapshot(input) {
|
|
341
|
+
const deps = input.deps ?? exports.DEFAULT_ENV_PROBE_DEPS;
|
|
342
|
+
const [listeners, tmuxSessions] = await Promise.all([
|
|
343
|
+
probeListeners(deps).catch((error) => unavailable(`listeners probe threw: ${error.message}`)),
|
|
344
|
+
probeTmuxSessions(deps).catch((error) => unavailable(`tmux probe threw: ${error.message}`)),
|
|
345
|
+
]);
|
|
346
|
+
return {
|
|
347
|
+
version: exports.ENV_SNAPSHOT_VERSION,
|
|
348
|
+
capturedAt: input.now ?? Date.now(),
|
|
349
|
+
worktreeId: input.worktreeId,
|
|
350
|
+
probes: {
|
|
351
|
+
listeners,
|
|
352
|
+
'tmux-sessions': tmuxSessions,
|
|
353
|
+
'home-entries': probeHomeEntries(deps),
|
|
354
|
+
'commandmate-entries': probeCommandmateEntries(deps),
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
// =============================================================================
|
|
359
|
+
// Persistence
|
|
360
|
+
// =============================================================================
|
|
361
|
+
/**
|
|
362
|
+
* Where baselines live: beside the database, never inside a repository.
|
|
363
|
+
*
|
|
364
|
+
* A snapshot describes the machine, not the worktree, and writing it into the
|
|
365
|
+
* worktree would put it in front of the `scope` and `work-evidence` gates — a
|
|
366
|
+
* file the orchestrator created reading as the agent's work is exactly the #1580
|
|
367
|
+
* defect.
|
|
368
|
+
*/
|
|
369
|
+
function resolveEnvSnapshotDir() {
|
|
370
|
+
return (0, path_1.join)((0, path_1.dirname)((0, env_1.getEnv)().CM_DB_PATH), exports.ENV_SNAPSHOT_DIR_NAME);
|
|
371
|
+
}
|
|
372
|
+
/** Baselines older than this are removed when a new one is written. */
|
|
373
|
+
exports.ENV_SNAPSHOT_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
374
|
+
/** Task ids are UUIDs; anything else must never become a path segment. */
|
|
375
|
+
const TASK_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
376
|
+
function snapshotPath(dir, taskId) {
|
|
377
|
+
if (!TASK_ID_PATTERN.test(taskId))
|
|
378
|
+
return null;
|
|
379
|
+
return (0, path_1.join)(dir, `${taskId}.json`);
|
|
380
|
+
}
|
|
381
|
+
function pruneOldSnapshots(dir, now) {
|
|
382
|
+
let names;
|
|
383
|
+
try {
|
|
384
|
+
names = (0, fs_1.readdirSync)(dir);
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
for (const name of names) {
|
|
390
|
+
if (!name.endsWith('.json'))
|
|
391
|
+
continue;
|
|
392
|
+
const path = (0, path_1.join)(dir, name);
|
|
393
|
+
try {
|
|
394
|
+
if (now - (0, fs_1.statSync)(path).mtimeMs > exports.ENV_SNAPSHOT_RETENTION_MS)
|
|
395
|
+
(0, fs_1.rmSync)(path, { force: true });
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
// A snapshot that cannot be stat'd or removed is not worth failing a send.
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Store the baseline for `taskId`.
|
|
404
|
+
*
|
|
405
|
+
* @returns true when the snapshot was written
|
|
406
|
+
*/
|
|
407
|
+
function saveEnvSnapshot(taskId, snapshot, dir = resolveEnvSnapshotDir()) {
|
|
408
|
+
const path = snapshotPath(dir, taskId);
|
|
409
|
+
if (!path) {
|
|
410
|
+
logger.warn('env-snapshot-rejected-task-id', { taskId });
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
|
|
415
|
+
(0, fs_1.writeFileSync)(path, JSON.stringify(snapshot), { encoding: 'utf8', mode: 0o600 });
|
|
416
|
+
pruneOldSnapshots(dir, snapshot.capturedAt);
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
logger.warn('env-snapshot-write-failed', {
|
|
421
|
+
taskId,
|
|
422
|
+
error: error instanceof Error ? error.message : String(error),
|
|
423
|
+
});
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Read the baseline for `taskId`.
|
|
429
|
+
*
|
|
430
|
+
* @returns the snapshot, or null when there is none — which the gate reports as
|
|
431
|
+
* UNKNOWN, never as "nothing changed"
|
|
432
|
+
*/
|
|
433
|
+
function loadEnvSnapshot(taskId, dir = resolveEnvSnapshotDir()) {
|
|
434
|
+
const path = snapshotPath(dir, taskId);
|
|
435
|
+
if (!path)
|
|
436
|
+
return null;
|
|
437
|
+
try {
|
|
438
|
+
const parsed = JSON.parse((0, fs_1.readFileSync)(path, 'utf8'));
|
|
439
|
+
if (!isEnvSnapshot(parsed))
|
|
440
|
+
return null;
|
|
441
|
+
return parsed;
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function isEnvProbeResult(value) {
|
|
448
|
+
if (typeof value !== 'object' || value === null)
|
|
449
|
+
return false;
|
|
450
|
+
const probe = value;
|
|
451
|
+
if (probe.status !== 'ok' && probe.status !== 'unavailable')
|
|
452
|
+
return false;
|
|
453
|
+
return Array.isArray(probe.entries);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Whether a parsed file is a snapshot this module can compare against.
|
|
457
|
+
*
|
|
458
|
+
* A truncated or older-format file is rejected rather than coerced: half a
|
|
459
|
+
* snapshot would diff into violations nobody caused, and the alternative to
|
|
460
|
+
* accepting it is UNKNOWN, which is the safe answer.
|
|
461
|
+
*/
|
|
462
|
+
function isEnvSnapshot(value) {
|
|
463
|
+
if (typeof value !== 'object' || value === null)
|
|
464
|
+
return false;
|
|
465
|
+
const snapshot = value;
|
|
466
|
+
if (snapshot.version !== exports.ENV_SNAPSHOT_VERSION)
|
|
467
|
+
return false;
|
|
468
|
+
if (typeof snapshot.capturedAt !== 'number')
|
|
469
|
+
return false;
|
|
470
|
+
const probes = snapshot.probes;
|
|
471
|
+
if (typeof probes !== 'object' || probes === null)
|
|
472
|
+
return false;
|
|
473
|
+
return exports.ENV_PROBE_IDS.every((id) => isEnvProbeResult(probes[id]));
|
|
474
|
+
}
|