commandmate 0.44.3 → 0.45.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 +266 -266
- package/.next/app-path-routes-manifest.json +18 -18
- package/.next/build-manifest.json +5 -5
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +26 -26
- 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/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 +2 -2
- 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 +2 -2
- 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_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 +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 +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 +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 +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_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_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.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.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 +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_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_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_client-reference-manifest.js +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_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 +2 -2
- 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 +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_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_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_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +4 -4
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +18 -18
- package/.next/server/chunks/1503.js +2 -2
- package/.next/server/chunks/1559.js +2 -2
- package/.next/server/chunks/1944.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/22.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2460.js +1 -1
- package/.next/server/chunks/2710.js +2 -2
- package/.next/server/chunks/2908.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/4802.js +1 -1
- package/.next/server/chunks/5048.js +1 -1
- package/.next/server/chunks/5064.js +1 -1
- package/.next/server/chunks/5292.js +7 -0
- package/.next/server/chunks/5625.js +2 -2
- package/.next/server/chunks/5737.js +1 -1
- package/.next/server/chunks/6065.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/850.js +1 -1
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8918.js +4 -6
- package/.next/server/chunks/9051.js +1 -1
- package/.next/server/chunks/9130.js +1 -1
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9584.js +1 -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/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1464.09cd37fee202ec4b.js +1 -0
- package/.next/static/chunks/2053-390e77fce43b555c.js +1 -0
- package/.next/static/chunks/{2407-06d35bb1aa02de80.js → 2407-dd4a0f04f1349221.js} +1 -1
- package/.next/static/chunks/{2751-9ef0f4b450bd4ef0.js → 2751-5f0b2702accd164d.js} +1 -1
- package/.next/static/chunks/{282.6b6f2e31a96674dd.js → 282.a1013532fd9a61b4.js} +1 -1
- package/.next/static/chunks/3237.94c29281d9ec122e.js +1 -0
- package/.next/static/chunks/3480.2e21f62e5e9d3ba5.js +1 -0
- package/.next/static/chunks/4290.c06dbe243819fea0.js +66 -0
- package/.next/static/chunks/{5222.305dc0ebba9c0784.js → 5222.39e2034d3fce233c.js} +1 -1
- package/.next/static/chunks/{7095.8c869e553133a40e.js → 7095.87323a4fdf426341.js} +1 -1
- package/.next/static/chunks/{7485.442b21101fca7257.js → 7485.8a2a9d7c5396aa26.js} +3 -3
- package/.next/static/chunks/app/{layout-0d1750b833f5cc3e.js → layout-07d040cb3d3ea657.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-35f0e31a725d1c89.js +1 -0
- package/.next/static/chunks/{webpack-021f0741f22dd16a.js → webpack-165d8df9acd1c5d4.js} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/skill-format.d.ts +8 -0
- package/dist/cli/commands/skill-format.d.ts.map +1 -1
- package/dist/cli/commands/skill-format.js +13 -3
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +71 -3
- package/dist/cli/types/api-responses.d.ts +7 -10
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.d.ts +21 -0
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +38 -1
- package/dist/server/locales/en/worktree.json +5 -1
- package/dist/server/locales/ja/worktree.json +5 -1
- package/dist/server/src/lib/detection/model-info-extractor.js +57 -3
- package/dist/server/src/lib/detection/status-detector.js +1 -1
- package/dist/server/src/lib/git/git-exec.js +23 -5
- package/dist/server/src/lib/hooks/sources/claude/self-resume.js +213 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +24 -7
- package/dist/server/src/lib/session/agent-event-dedup.js +2 -2
- package/dist/server/src/lib/session/agent-event-state.js +2 -1
- package/dist/server/src/lib/session/agent-event-turn.js +51 -0
- package/dist/server/src/lib/session/current-output-builder.js +0 -5
- package/dist/server/src/lib/skills/install-plan.js +1 -0
- package/dist/server/src/lib/skills/preview-diff.js +24 -3
- package/dist/server/src/lib/skills/uninstall-plan.js +1 -0
- package/dist/server/src/lib/verification/env-clean-gate.js +6 -5
- package/docs/en/user-guide/commands-guide.md +0 -1
- package/package.json +3 -2
- package/release-notes/0.45.0.json +41 -0
- package/scripts/hooks/cmate-agent-event.sh +20 -0
- package/.next/server/chunks/4672.js +0 -5
- package/.next/static/chunks/2053-85a974ddfe7498fe.js +0 -1
- package/.next/static/chunks/4290.6cf86f68d73b6e77.js +0 -82
- package/.next/static/chunks/4459.a94b52985a76509a.js +0 -1
- package/.next/static/chunks/5951.616956b6aa5df63f.js +0 -1
- package/.next/static/chunks/9856.15463dd58437e2ac.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-e36898c3a80e7302.js +0 -1
- /package/.next/static/{tWwHQzmvc-rv9KKUtDWfQ → TPWbZB3zBp3Zv_eFEOlmt}/_buildManifest.js +0 -0
- /package/.next/static/{tWwHQzmvc-rv9KKUtDWfQ → TPWbZB3zBp3Zv_eFEOlmt}/_ssgManifest.js +0 -0
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
* | copilot | footer: `← open sidebar · … · tab next tab GPT-5 mini · Medium` |
|
|
43
43
|
* | copilot | notice: `● Model changed from gpt-5.6-terra (xhigh) to gpt-5-mini (medium) for this session.` |
|
|
44
44
|
* | opencode | step: `▣ Build · GPT-5.6 Luna · 3.1s` |
|
|
45
|
+
* | opencode2 | step: `Build · Mistral Large 4 · 253ms` (no `▣`, 2.0.18, #3443) |
|
|
45
46
|
*
|
|
46
47
|
* The copilot and opencode rows were added by Issue #1912 and read off the live
|
|
47
48
|
* fixtures #1885 / #1895 / #1893 / #1896 recorded, not off a fresh capture.
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
* @see Issue #1784, Phase 2 of the model/effort visibility series
|
|
63
64
|
*/
|
|
64
65
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
-
exports.ANTIGRAVITY_MODEL_ID_EFFORT_PATTERN = exports.COMMAND_CODE_BANNER_MODELS_PATTERN = exports.OPENCODE_STEP_MODEL_PATTERN = exports.COPILOT_MODEL_CHANGE_PATTERN = exports.ANTIGRAVITY_BANNER_MODEL_PATTERN = exports.ANTIGRAVITY_STATUS_BAR_HINT_PATTERN = exports.CLAUDE_MODEL_SWITCH_PATTERN = exports.CLAUDE_EFFORT_ROW_PATTERN = exports.CLAUDE_STARTUP_BANNER_V2_1_28X_PATTERN = exports.CLAUDE_STARTUP_BANNER_PATTERN = exports.CODEX_STATUS_BAR_WITH_TRAILER_PATTERN = exports.CODEX_FOOTER_EFFORT_SLOT_PATTERN = exports.CODEX_FOOTER_MODEL_PATTERN = exports.REASONING_EFFORT_LEVELS = void 0;
|
|
66
|
+
exports.ANTIGRAVITY_MODEL_ID_EFFORT_PATTERN = exports.COMMAND_CODE_BANNER_MODELS_PATTERN = exports.OPENCODE_V2_STEP_MODEL_PATTERN = exports.OPENCODE_STEP_MODEL_PATTERN = exports.COPILOT_MODEL_CHANGE_PATTERN = exports.ANTIGRAVITY_BANNER_MODEL_PATTERN = exports.ANTIGRAVITY_STATUS_BAR_HINT_PATTERN = exports.CLAUDE_MODEL_SWITCH_PATTERN = exports.CLAUDE_EFFORT_ROW_PATTERN = exports.CLAUDE_STARTUP_BANNER_V2_1_28X_PATTERN = exports.CLAUDE_STARTUP_BANNER_PATTERN = exports.CODEX_STATUS_BAR_WITH_TRAILER_PATTERN = exports.CODEX_FOOTER_EFFORT_SLOT_PATTERN = exports.CODEX_FOOTER_MODEL_PATTERN = exports.REASONING_EFFORT_LEVELS = void 0;
|
|
66
67
|
exports.resolveEffortToken = resolveEffortToken;
|
|
67
68
|
exports.extractModelInfo = extractModelInfo;
|
|
68
69
|
exports.deriveEffortFromModelId = deriveEffortFromModelId;
|
|
@@ -684,6 +685,58 @@ function readOpencodeStepMarker(line) {
|
|
|
684
685
|
const model = match[1].trim();
|
|
685
686
|
return isPlausibleModelLabel(model) ? { model, effort: null } : null;
|
|
686
687
|
}
|
|
688
|
+
/**
|
|
689
|
+
* opencode2's step row (Issue #3443): v1's marker without the `▣`.
|
|
690
|
+
*
|
|
691
|
+
* Measured on opencode2 2.0.18 (`tests/fixtures/opencode-agent-health-3420/`):
|
|
692
|
+
*
|
|
693
|
+
* ` Error: Unauthorized`
|
|
694
|
+
* ` Build · Mistral Large 4 · 721ms`
|
|
695
|
+
* ` ┃` (the next user turn, or the composer)
|
|
696
|
+
*
|
|
697
|
+
* Without the `▣` the shape `<word> · <text> · <duration>` is ordinary prose, so
|
|
698
|
+
* it is only read under three guards, each of which a v1 step row also meets:
|
|
699
|
+
*
|
|
700
|
+
* - the duration is required (a row with two `·` and nothing timed is not one);
|
|
701
|
+
* - the row is transcript text, not inside a `┃` block — the user's own input
|
|
702
|
+
* and shell output are drawn inside one, the composer bar too;
|
|
703
|
+
* - the next non-blank row opens a `┃` block (the next user turn or the
|
|
704
|
+
* composer): the step row closes a reply, so a reply line that merely has the
|
|
705
|
+
* shape is followed by more reply, or by the step row itself.
|
|
706
|
+
*
|
|
707
|
+
* No /g. No nested quantifiers: `[^·]+?` is bounded by literal `·`.
|
|
708
|
+
*/
|
|
709
|
+
exports.OPENCODE_V2_STEP_MODEL_PATTERN = /^\s*[A-Za-z][A-Za-z0-9-]*\s+·\s+([^·]+?)\s+·\s+[\d.]+\s?m?s\s*$/;
|
|
710
|
+
/** A row that opens or continues opencode's `┃` block (a user turn or the composer). */
|
|
711
|
+
const OPENCODE_BLOCK_ROW_PATTERN = /^\s*[┃╹]/;
|
|
712
|
+
function readOpencodeV2StepRow(lines, index) {
|
|
713
|
+
const match = exports.OPENCODE_V2_STEP_MODEL_PATTERN.exec(lines[index]);
|
|
714
|
+
if (!match)
|
|
715
|
+
return null;
|
|
716
|
+
const model = match[1].trim();
|
|
717
|
+
if (!isPlausibleModelLabel(model))
|
|
718
|
+
return null;
|
|
719
|
+
for (let next = index + 1; next < lines.length; next++) {
|
|
720
|
+
if (lines[next].trim() === '')
|
|
721
|
+
continue;
|
|
722
|
+
return OPENCODE_BLOCK_ROW_PATTERN.test(lines[next]) ? { model, effort: null } : null;
|
|
723
|
+
}
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* The lowest opencode step row, `▣` (v1) or not (opencode2, #3443). Both tool
|
|
728
|
+
* ids read both shapes: `opencode` may be running a 2.x binary, and a v1 frame
|
|
729
|
+
* never draws a `▣`-less row that passes {@link readOpencodeV2StepRow}'s guards.
|
|
730
|
+
*/
|
|
731
|
+
function readOpencodeStepRow(captureText) {
|
|
732
|
+
const lines = captureText.split('\n').map((line) => (0, ansi_1.stripAnsi)(line));
|
|
733
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
734
|
+
const result = readOpencodeStepMarker(lines[i]) ?? readOpencodeV2StepRow(lines, i);
|
|
735
|
+
if (result)
|
|
736
|
+
return result;
|
|
737
|
+
}
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
687
740
|
// =============================================================================
|
|
688
741
|
// Command Code (Issue #2358)
|
|
689
742
|
// =============================================================================
|
|
@@ -792,7 +845,7 @@ function scanFromEnd(captureText, read) {
|
|
|
792
845
|
* Pure and side-effect free. Never throws, and answers `{ model: null, effort:
|
|
793
846
|
* null }` for every tool it has no rule for (gemini / vibe-local — neither
|
|
794
847
|
* prints a model on its pane in any captured frame; copilot and opencode were
|
|
795
|
-
* added by Issue #1912) and for every frame that does not show the chrome it
|
|
848
|
+
* added by Issue #1912, opencode-v2 by #3443) and for every frame that does not show the chrome it
|
|
796
849
|
* looks for.
|
|
797
850
|
*
|
|
798
851
|
* **Answering null is a correct outcome, not a failure.** tmux keeps a
|
|
@@ -842,7 +895,8 @@ function extractModelInfo(cliToolId, captureText) {
|
|
|
842
895
|
return sameModel(bar.model, notice.model) ? { model: bar.model, effort: notice.effort } : bar;
|
|
843
896
|
}
|
|
844
897
|
case 'opencode':
|
|
845
|
-
|
|
898
|
+
case 'opencode-v2':
|
|
899
|
+
return readOpencodeStepRow(captureText) ?? unknown();
|
|
846
900
|
case 'command-code':
|
|
847
901
|
// Issue #2358. The banner is the only source — hooks carry no model — and
|
|
848
902
|
// bottom-up is the same "last banner wins" rule Claude uses: a relaunch in
|
|
@@ -76,7 +76,7 @@ exports.SELECTION_LIST_REASONS = new Set([
|
|
|
76
76
|
* The `running` reasons that mean "the agent is producing output right now"
|
|
77
77
|
* (Issue #1912).
|
|
78
78
|
*
|
|
79
|
-
* `current-output-builder` derives `thinking`
|
|
79
|
+
* `current-output-builder` derives `thinking` from this, and it
|
|
80
80
|
* was a single `=== THINKING_INDICATOR` comparison until opencode grew a second
|
|
81
81
|
* one: branch A of the opencode block answers `opencode_processing_indicator`
|
|
82
82
|
* for the footer that reads `esc interrupt`, which is opencode's ONLY signal
|
|
@@ -60,13 +60,33 @@ async function execGitCommand(args, cwd) {
|
|
|
60
60
|
}
|
|
61
61
|
catch (error) {
|
|
62
62
|
// Log error server-side only (no client exposure)
|
|
63
|
-
|
|
63
|
+
const fields = {
|
|
64
64
|
args: args.join(' '),
|
|
65
|
+
worktree: path_1.default.basename(cwd),
|
|
65
66
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
66
|
-
}
|
|
67
|
+
};
|
|
68
|
+
// Issue #3416: a read killed by the 1s timeout is an EXPECTED outcome on a
|
|
69
|
+
// loaded host (callers already degrade null to '(unknown)' / not dirty), so
|
|
70
|
+
// it is a warn. Any other failure (git exited non-zero) stays an ERROR.
|
|
71
|
+
if (isExecTimeout(error)) {
|
|
72
|
+
logger.warn('git:command-failed', { ...fields, timedOut: true, timeoutMs: GIT_COMMAND_TIMEOUT_MS });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
logger.error('git:command-failed', fields);
|
|
76
|
+
}
|
|
67
77
|
return null;
|
|
68
78
|
}
|
|
69
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* True when execFile rejected because the child was killed by `timeout`
|
|
82
|
+
* (Node sets `killed` and leaves stderr empty) rather than because git failed.
|
|
83
|
+
*/
|
|
84
|
+
function isExecTimeout(error) {
|
|
85
|
+
const err = error;
|
|
86
|
+
return (err?.killed === true ||
|
|
87
|
+
err?.code === 'ERR_CHILD_PROCESS_EXEC_TIMEOUT' ||
|
|
88
|
+
err?.code === 'ETIMEDOUT');
|
|
89
|
+
}
|
|
70
90
|
/**
|
|
71
91
|
* Execute a READ-ONLY git command like {@link execGitCommand} (never throws,
|
|
72
92
|
* same default 1s timeout) but return the stderr alongside the outcome instead
|
|
@@ -92,9 +112,7 @@ async function execGitCommandCapture(args, cwd, timeout = GIT_COMMAND_TIMEOUT_MS
|
|
|
92
112
|
}
|
|
93
113
|
catch (error) {
|
|
94
114
|
const err = error;
|
|
95
|
-
const timedOut = err
|
|
96
|
-
err.code === 'ERR_CHILD_PROCESS_EXEC_TIMEOUT' ||
|
|
97
|
-
err.code === 'ETIMEDOUT';
|
|
115
|
+
const timedOut = isExecTimeout(err);
|
|
98
116
|
return {
|
|
99
117
|
ok: false,
|
|
100
118
|
stdout: '',
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a Claude Code `Stop` leaves background work behind that will wake the
|
|
4
|
+
* agent again (Issue #3430) — the Claude half of #2614.
|
|
5
|
+
*
|
|
6
|
+
* Claude Code ends a turn with work still running in two measured ways: a
|
|
7
|
+
* `Bash` call that outlived its timeout (or was started with
|
|
8
|
+
* `run_in_background`) and a `Monitor`. When that work finishes Claude queues a
|
|
9
|
+
* `<task-notification>` and, if the session is idle, opens a new turn on it by
|
|
10
|
+
* itself. Measured on 2026-10-08 (worktree commandmate-issue-3423): a worker
|
|
11
|
+
* ended its turn at 23:37:53 "waiting for the related-tests run to finish",
|
|
12
|
+
* `wait --verify` read that `Stop` as the end and verified an uncommitted
|
|
13
|
+
* worktree, and the notification opened the turn that committed at 23:38:32.
|
|
14
|
+
*
|
|
15
|
+
* ## What is read, and why not the `Stop` payload
|
|
16
|
+
*
|
|
17
|
+
* The payload carries `background_tasks`, but only its empty form has ever been
|
|
18
|
+
* captured (`tests/fixtures/hooks/claude/stop.json`), so its shape is a guess.
|
|
19
|
+
* The transcript names the same work in structured fields, measured on the
|
|
20
|
+
* transcripts under `~/.claude/projects` written in the four days to 2026-10-08:
|
|
21
|
+
*
|
|
22
|
+
* - a background `Bash`: `toolUseResult.backgroundTaskId` (1,008 results);
|
|
23
|
+
* - a `Monitor`: `toolUseResult.taskId` beside a boolean `persistent`
|
|
24
|
+
* (115 results);
|
|
25
|
+
* - a background subagent: `toolUseResult.isAsync: true` and `agentId`
|
|
26
|
+
* (30 results);
|
|
27
|
+
* - a `TaskStop`: `toolUseResult.task_id` (39 results). A stopped task is never
|
|
28
|
+
* notified, so this is what retires it.
|
|
29
|
+
*
|
|
30
|
+
* and each finished task is retired by the notification Claude delivers for it:
|
|
31
|
+
* a `type: "user"` prompt or a `queued_command` attachment whose text begins
|
|
32
|
+
* with `<task-notification>` and carries `<task-id>…</task-id>` — the id above.
|
|
33
|
+
* A notice that is only enqueued is not yet delivered, and the session will open
|
|
34
|
+
* a turn on it, so its task still counts as pending.
|
|
35
|
+
*
|
|
36
|
+
* ## Erring towards "finished"
|
|
37
|
+
*
|
|
38
|
+
* Every doubt answers "nothing pending", which is what every Claude `Stop` meant
|
|
39
|
+
* before this Issue: no transcript path, a path outside `~/.claude/projects`, a
|
|
40
|
+
* file that cannot be read, a line that does not parse. A persistent `Monitor`
|
|
41
|
+
* (a watch for the whole session, never notified on its own) is not counted
|
|
42
|
+
* either. A task that really is never notified — a process that died with its
|
|
43
|
+
* session — is bounded by `commandmate wait`'s `SELF_RESUME_HOLD_MS`.
|
|
44
|
+
*
|
|
45
|
+
* @module lib/hooks/sources/claude/self-resume
|
|
46
|
+
*/
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.CLAUDE_SELF_RESUME_TAIL_BYTES = exports.CLAUDE_TRANSCRIPT_PATH_FIELD = void 0;
|
|
49
|
+
exports.pendingClaudeBackgroundTasks = pendingClaudeBackgroundTasks;
|
|
50
|
+
exports.claudeStopLeavesBackgroundWork = claudeStopLeavesBackgroundWork;
|
|
51
|
+
const fs_1 = require("fs");
|
|
52
|
+
const os_1 = require("os");
|
|
53
|
+
const path_1 = require("path");
|
|
54
|
+
const transcript_history_1 = require("../transcript-history");
|
|
55
|
+
const queued_notice_1 = require("./queued-notice");
|
|
56
|
+
const transcript_1 = require("./transcript");
|
|
57
|
+
/** The `Stop` payload field naming the session's transcript. */
|
|
58
|
+
exports.CLAUDE_TRANSCRIPT_PATH_FIELD = 'transcript_path';
|
|
59
|
+
/**
|
|
60
|
+
* How much of the transcript's tail is read on a `Stop`.
|
|
61
|
+
*
|
|
62
|
+
* A task is started before it is notified, so a window that holds the start
|
|
63
|
+
* holds the notification too; a start older than the window is simply not seen
|
|
64
|
+
* (the "finished" direction). 4 MiB is `CLAUDE_TRANSCRIPT_TAIL_BYTES`, the first
|
|
65
|
+
* read of `./history`, which holds 99% of turns whole (#2470).
|
|
66
|
+
*/
|
|
67
|
+
exports.CLAUDE_SELF_RESUME_TAIL_BYTES = 4 * 1024 * 1024;
|
|
68
|
+
const TASK_ID_PATTERN = /<task-id>([^<]+)<\/task-id>/;
|
|
69
|
+
function isRecord(value) {
|
|
70
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
71
|
+
}
|
|
72
|
+
function nonEmptyString(value) {
|
|
73
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
74
|
+
}
|
|
75
|
+
/** The background task a tool result started, or null. */
|
|
76
|
+
function startedTaskId(result) {
|
|
77
|
+
const bash = nonEmptyString(result.backgroundTaskId);
|
|
78
|
+
if (bash)
|
|
79
|
+
return bash;
|
|
80
|
+
// Monitor. `persistent: true` watches for the life of the session and is not
|
|
81
|
+
// work the turn is waiting on.
|
|
82
|
+
const monitor = nonEmptyString(result.taskId);
|
|
83
|
+
if (monitor && result.persistent === false)
|
|
84
|
+
return monitor;
|
|
85
|
+
const agent = nonEmptyString(result.agentId);
|
|
86
|
+
if (agent && result.isAsync === true)
|
|
87
|
+
return agent;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
/** The task a `<task-notification>` text retires, or null. */
|
|
91
|
+
function notifiedTaskId(text) {
|
|
92
|
+
if (typeof text !== 'string')
|
|
93
|
+
return null;
|
|
94
|
+
if (!text.trimStart().startsWith(queued_notice_1.CLAUDE_TASK_NOTIFICATION_PREFIX))
|
|
95
|
+
return null;
|
|
96
|
+
return TASK_ID_PATTERN.exec(text)?.[1] ?? null;
|
|
97
|
+
}
|
|
98
|
+
/** Every text a delivered `type: "user"` record carries. */
|
|
99
|
+
function userTexts(record) {
|
|
100
|
+
const message = record.message;
|
|
101
|
+
if (!isRecord(message))
|
|
102
|
+
return [];
|
|
103
|
+
const content = message.content;
|
|
104
|
+
if (typeof content === 'string')
|
|
105
|
+
return [content];
|
|
106
|
+
if (!Array.isArray(content))
|
|
107
|
+
return [];
|
|
108
|
+
return content.filter(isRecord).filter((b) => b.type === 'text').map((b) => b.text);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The ids of background tasks started in `text` (transcript JSONL) and not yet
|
|
112
|
+
* delivered a notification or stopped, in the order they were started.
|
|
113
|
+
*
|
|
114
|
+
* Pure. Lines that do not parse are skipped, as is everything a subagent wrote
|
|
115
|
+
* into the parent's file (`isSidechain: true`).
|
|
116
|
+
*/
|
|
117
|
+
function pendingClaudeBackgroundTasks(text) {
|
|
118
|
+
const started = [];
|
|
119
|
+
const retired = new Set();
|
|
120
|
+
for (const line of text.split('\n')) {
|
|
121
|
+
if (line.trim() === '')
|
|
122
|
+
continue;
|
|
123
|
+
let record;
|
|
124
|
+
try {
|
|
125
|
+
record = JSON.parse(line);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!isRecord(record) || record.isSidechain === true)
|
|
131
|
+
continue;
|
|
132
|
+
if (record.type === 'user') {
|
|
133
|
+
const result = record.toolUseResult;
|
|
134
|
+
if (isRecord(result)) {
|
|
135
|
+
const id = startedTaskId(result);
|
|
136
|
+
if (id)
|
|
137
|
+
started.push(id);
|
|
138
|
+
const stopped = nonEmptyString(result.task_id);
|
|
139
|
+
if (stopped)
|
|
140
|
+
retired.add(stopped);
|
|
141
|
+
}
|
|
142
|
+
for (const t of userTexts(record)) {
|
|
143
|
+
const id = notifiedTaskId(t);
|
|
144
|
+
if (id)
|
|
145
|
+
retired.add(id);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (record.type === 'attachment' && isRecord(record.attachment)) {
|
|
149
|
+
if (record.attachment.type !== 'queued_command')
|
|
150
|
+
continue;
|
|
151
|
+
const id = notifiedTaskId(record.attachment.prompt);
|
|
152
|
+
if (id)
|
|
153
|
+
retired.add(id);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return [...new Set(started)].filter((id) => !retired.has(id));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The last `maxBytes` of a file, starting at a line boundary; null when it
|
|
160
|
+
* cannot be read.
|
|
161
|
+
*/
|
|
162
|
+
function readTail(path, maxBytes) {
|
|
163
|
+
let fd = null;
|
|
164
|
+
try {
|
|
165
|
+
fd = (0, fs_1.openSync)(path, 'r');
|
|
166
|
+
const size = (0, fs_1.fstatSync)(fd).size;
|
|
167
|
+
const start = Math.max(0, size - maxBytes);
|
|
168
|
+
const buffer = Buffer.alloc(size - start);
|
|
169
|
+
let read = 0;
|
|
170
|
+
while (read < buffer.length) {
|
|
171
|
+
const n = (0, fs_1.readSync)(fd, buffer, read, buffer.length - read, start + read);
|
|
172
|
+
if (n === 0)
|
|
173
|
+
break;
|
|
174
|
+
read += n;
|
|
175
|
+
}
|
|
176
|
+
const text = buffer.subarray(0, read).toString('utf8');
|
|
177
|
+
// A window opened mid-file starts mid-line; that line is dropped.
|
|
178
|
+
return start === 0 ? text : text.slice(text.indexOf('\n') + 1);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
if (fd !== null) {
|
|
185
|
+
try {
|
|
186
|
+
(0, fs_1.closeSync)(fd);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Nothing to do: the answer is already decided.
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Whether this `Stop` payload's session still has background work that has not
|
|
196
|
+
* been notified — i.e. whether Claude will open another turn by itself.
|
|
197
|
+
*
|
|
198
|
+
* Synchronous: it runs inside event normalization. `false` for every case it
|
|
199
|
+
* cannot vouch for (see the module comment).
|
|
200
|
+
*/
|
|
201
|
+
function claudeStopLeavesBackgroundWork(payload, options = {}) {
|
|
202
|
+
const hint = nonEmptyString(payload[exports.CLAUDE_TRANSCRIPT_PATH_FIELD]);
|
|
203
|
+
if (!hint)
|
|
204
|
+
return false;
|
|
205
|
+
const root = (0, path_1.join)(options.homeDir ?? (0, os_1.homedir)(), ...transcript_1.CLAUDE_PROJECTS_DIR_SEGMENTS);
|
|
206
|
+
const path = (0, transcript_history_1.acceptPathUnderRoot)(root, '.jsonl', hint);
|
|
207
|
+
if (!path)
|
|
208
|
+
return false;
|
|
209
|
+
const text = readTail(path, options.tailBytes ?? exports.CLAUDE_SELF_RESUME_TAIL_BYTES);
|
|
210
|
+
if (text === null)
|
|
211
|
+
return false;
|
|
212
|
+
return pendingClaudeBackgroundTasks(text).length > 0;
|
|
213
|
+
}
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
35
|
exports.claudeAgentEventSource = void 0;
|
|
36
36
|
exports.encodeClaudeVerdict = encodeClaudeVerdict;
|
|
37
|
+
exports.extractClaudeEventDetail = extractClaudeEventDetail;
|
|
37
38
|
const uat_isolation_1 = require("../../../../config/uat-isolation");
|
|
38
39
|
const agent_event_types_1 = require("../../../../lib/hooks/agent-event-types");
|
|
39
40
|
const ask_user_question_payload_1 = require("../../../../lib/hooks/ask-user-question-payload");
|
|
@@ -44,6 +45,7 @@ const event_mapper_1 = require("../event-mapper");
|
|
|
44
45
|
const hook_event_vocabulary_1 = require("../hook-event-vocabulary");
|
|
45
46
|
const model_switch_1 = require("./model-switch");
|
|
46
47
|
const queued_notice_1 = require("./queued-notice");
|
|
48
|
+
const self_resume_1 = require("./self-resume");
|
|
47
49
|
const tool_id_1 = require("./tool-id");
|
|
48
50
|
/**
|
|
49
51
|
* The no-decision body, byte for byte what the #1721 spike returned for D5.
|
|
@@ -85,6 +87,20 @@ function encodeClaudeVerdict(verdict) {
|
|
|
85
87
|
},
|
|
86
88
|
};
|
|
87
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* The subtype of one Claude event.
|
|
92
|
+
*
|
|
93
|
+
* Every event but `stop` is the shared snake_case reading (S2). A `stop` is
|
|
94
|
+
* {@link SELF_RESUME_PENDING_DETAIL} when the session's transcript shows
|
|
95
|
+
* background work that has not been notified yet (Issue #3430), and has no
|
|
96
|
+
* subtype otherwise — which is what every Claude `stop` had before.
|
|
97
|
+
*/
|
|
98
|
+
function extractClaudeEventDetail(event, payload) {
|
|
99
|
+
if (event === 'stop' && (0, self_resume_1.claudeStopLeavesBackgroundWork)(payload)) {
|
|
100
|
+
return agent_event_types_1.SELF_RESUME_PENDING_DETAIL;
|
|
101
|
+
}
|
|
102
|
+
return (0, hook_event_vocabulary_1.extractSnakeCaseEventDetail)(event, payload);
|
|
103
|
+
}
|
|
88
104
|
/**
|
|
89
105
|
* Claude Code as an event source.
|
|
90
106
|
*
|
|
@@ -127,11 +143,12 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
|
|
|
127
143
|
// JSONL when the poller asks (#2121); the gate dispatches on this word
|
|
128
144
|
// rather than on the tool id.
|
|
129
145
|
transcriptHistory: 'pull',
|
|
130
|
-
// Issue #2614
|
|
131
|
-
//
|
|
132
|
-
// `
|
|
133
|
-
//
|
|
134
|
-
|
|
146
|
+
// Issue #3430 (#2614 for Claude). A `Stop` whose transcript shows a
|
|
147
|
+
// background `Bash` / `Monitor` / subagent not yet notified carries
|
|
148
|
+
// `SELF_RESUME_PENDING_DETAIL`: the notification opens the next turn by
|
|
149
|
+
// itself. The payload's `background_tasks` is still unread — only its empty
|
|
150
|
+
// form has been captured. See `./self-resume` and `extractDetail` below.
|
|
151
|
+
stopReportsSelfResume: true,
|
|
135
152
|
},
|
|
136
153
|
// S1. A plain name table is enough *for this tool* — one native name, one
|
|
137
154
|
// word, no predicates — so it is expressed as rules built from the table
|
|
@@ -163,8 +180,8 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
|
|
|
163
180
|
// Issue #3330. A background-task notice attached to the running turn fires
|
|
164
181
|
// `UserPromptSubmit` too, and continues that turn rather than opening one.
|
|
165
182
|
promptJoinsOpenTurn: queued_notice_1.isClaudeQueuedNoticePrompt,
|
|
166
|
-
// S2.
|
|
167
|
-
extractDetail:
|
|
183
|
+
// S2, plus the `Stop` that leaves background work behind (Issue #3430).
|
|
184
|
+
extractDetail: extractClaudeEventDetail,
|
|
168
185
|
// S7. Both parsers are strict and answer null for anything they cannot vouch
|
|
169
186
|
// for; the callers turn null into "no structured data", which degrades to the
|
|
170
187
|
// behaviour of a machine without hooks rather than into a guess.
|
|
@@ -322,8 +322,8 @@ function shortSessionTag(sessionId) {
|
|
|
322
322
|
/**
|
|
323
323
|
* Forget every `stop` one session of one instance has claimed (Issue #3289).
|
|
324
324
|
*
|
|
325
|
-
* Every subtype: antigravity
|
|
326
|
-
* beside the plain one.
|
|
325
|
+
* Every subtype: antigravity (#2614) and claude (#3430) post `stop` /
|
|
326
|
+
* `self_resume_pending` beside the plain one.
|
|
327
327
|
*/
|
|
328
328
|
function releaseStopClaims(composite, sessionId) {
|
|
329
329
|
releaseClaims(composite, ['stop'], sessionId);
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* @module lib/session/agent-event-state
|
|
40
40
|
*/
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.STRUCTURED_PROMPT_PROVISIONAL_MAX_AGE_MS = exports.recordAskUserQuestion = exports.getAskUserQuestion = exports.clearAskUserQuestion = exports.isAwaitingInstruction = exports.getAwaitingInstruction = exports.STRUCTURED_STATE_MAX_AGE_MS = exports.getStructuredSessionState = exports.observeScraperCompletionEvidence = exports.joinOpenTurnFromDuplicate = exports.getPublishedAgentTurn = exports.getPendingDecisions = exports.getAgentTurn = exports.closeAgentTurn = exports.recordCapturedModelInfo = exports.recordAgentReportedModel = exports.recordAgentReportedEffort = exports.onAgentModelChange = exports.isSameAgentModelName = exports.getResolvedAgentModelInfo = exports.getLastReportedAgentEffort = exports.getLastKnownAgentModel = exports.getLastKnownAgentEffort = exports.getLastCapturedModelInfo = exports.getAgentModelBaseline = exports.AGENT_MODEL_EFFORT_SUFFIX_PATTERN = exports.shortSessionTag = exports.LIFECYCLE_AGENT_EVENT_TYPES = exports.isDuplicateAgentEvent = exports.getRecentEventKeyCount = exports.getRecentEventIdentityCount = exports.getAgentEventDropCounts = exports.classifyAgentEventDelivery = exports.agentEventKeyClaimedAt = exports.AGENT_EVENT_DEDUP_WINDOW_MS = void 0;
|
|
42
|
+
exports.STRUCTURED_PROMPT_PROVISIONAL_MAX_AGE_MS = exports.recordAskUserQuestion = exports.getAskUserQuestion = exports.clearAskUserQuestion = exports.isAwaitingInstruction = exports.getAwaitingInstruction = exports.STRUCTURED_STATE_MAX_AGE_MS = exports.getStructuredSessionState = exports.observeScraperCompletionEvidence = exports.joinOpenTurnFromDuplicate = exports.isPreToolUseOutsideTurn = exports.getPublishedAgentTurn = exports.getPendingDecisions = exports.getAgentTurn = exports.closeAgentTurn = exports.recordCapturedModelInfo = exports.recordAgentReportedModel = exports.recordAgentReportedEffort = exports.onAgentModelChange = exports.isSameAgentModelName = exports.getResolvedAgentModelInfo = exports.getLastReportedAgentEffort = exports.getLastKnownAgentModel = exports.getLastKnownAgentEffort = exports.getLastCapturedModelInfo = exports.getAgentModelBaseline = exports.AGENT_MODEL_EFFORT_SUFFIX_PATTERN = exports.shortSessionTag = exports.LIFECYCLE_AGENT_EVENT_TYPES = exports.isDuplicateAgentEvent = exports.getRecentEventKeyCount = exports.getRecentEventIdentityCount = exports.getAgentEventDropCounts = exports.classifyAgentEventDelivery = exports.agentEventKeyClaimedAt = exports.AGENT_EVENT_DEDUP_WINDOW_MS = void 0;
|
|
43
43
|
exports.recordAgentStopEvent = recordAgentStopEvent;
|
|
44
44
|
exports.getLastStopEventAt = getLastStopEventAt;
|
|
45
45
|
exports.recordAgentEvent = recordAgentEvent;
|
|
@@ -92,6 +92,7 @@ Object.defineProperty(exports, "closeAgentTurn", { enumerable: true, get: functi
|
|
|
92
92
|
Object.defineProperty(exports, "getAgentTurn", { enumerable: true, get: function () { return agent_event_turn_2.getAgentTurn; } });
|
|
93
93
|
Object.defineProperty(exports, "getPendingDecisions", { enumerable: true, get: function () { return agent_event_turn_2.getPendingDecisions; } });
|
|
94
94
|
Object.defineProperty(exports, "getPublishedAgentTurn", { enumerable: true, get: function () { return agent_event_turn_2.getPublishedAgentTurn; } });
|
|
95
|
+
Object.defineProperty(exports, "isPreToolUseOutsideTurn", { enumerable: true, get: function () { return agent_event_turn_2.isPreToolUseOutsideTurn; } });
|
|
95
96
|
Object.defineProperty(exports, "joinOpenTurnFromDuplicate", { enumerable: true, get: function () { return agent_event_turn_2.joinOpenTurnFromDuplicate; } });
|
|
96
97
|
Object.defineProperty(exports, "observeScraperCompletionEvidence", { enumerable: true, get: function () { return agent_event_turn_2.observeScraperCompletionEvidence; } });
|
|
97
98
|
var agent_event_structured_state_2 = require("../../lib/session/agent-event-structured-state");
|
|
@@ -20,6 +20,7 @@ exports.closeAgentTurn = closeAgentTurn;
|
|
|
20
20
|
exports.observeScraperCompletionEvidence = observeScraperCompletionEvidence;
|
|
21
21
|
exports.fenceTurnForNewGeneration = fenceTurnForNewGeneration;
|
|
22
22
|
exports.applyTurnTransition = applyTurnTransition;
|
|
23
|
+
exports.isPreToolUseOutsideTurn = isPreToolUseOutsideTurn;
|
|
23
24
|
exports.joinOpenTurnFromDuplicate = joinOpenTurnFromDuplicate;
|
|
24
25
|
exports.openDecision = openDecision;
|
|
25
26
|
exports.releaseAllDecisions = releaseAllDecisions;
|
|
@@ -313,6 +314,7 @@ function fenceTurnForNewGeneration(key, at) {
|
|
|
313
314
|
* | `user_prompt_submit` | **opens a new one** | release | yes |
|
|
314
315
|
* | `user_prompt_submit` (joins, #3330)| continues, else opens | release | yes |
|
|
315
316
|
* | `pre_tool_use` | continues, else opens | unchanged| yes |
|
|
317
|
+
* | `pre_tool_use` (after its stop) | unchanged (#3437) | unchanged| no |
|
|
316
318
|
* | `post_tool_use` | continues, else opens | release | yes |
|
|
317
319
|
* | `stop` (this session) | **closes** `stop` | release | yes |
|
|
318
320
|
* | `stop` (another session) | unchanged | unchanged| no |
|
|
@@ -377,6 +379,22 @@ function fenceTurnForNewGeneration(key, at) {
|
|
|
377
379
|
* still dropped by the window in front of it ({@link isDuplicateAgentEvent}),
|
|
378
380
|
* and dropped or applied, none of them moves the turn.
|
|
379
381
|
*
|
|
382
|
+
* The `after its stop` row is the other exception (Issue #3437), and it is
|
|
383
|
+
* narrower than it reads: it applies only to a source that reports its
|
|
384
|
+
* prompts ({@link AgentEventRecord.promptOpensTurns}), and only when the
|
|
385
|
+
* instance's last turn was closed by the agent's own `stop`. In production on
|
|
386
|
+
* 2026-10-07 a Claude `PreToolUse(AskUserQuestion)` landed 2.5 s after the
|
|
387
|
+
* `Stop`, with no `UserPromptSubmit`, no picker on the pane (the scraper read
|
|
388
|
+
* `ready` throughout), and nothing in the session's transcript after the
|
|
389
|
+
* `Stop` — something other than the conversation the `Stop` had just ended.
|
|
390
|
+
* It opened a turn whose `stop` never came, and a `wait` adopted that turn.
|
|
391
|
+
* Every turn of such a source begins with its prompt, and a tool call that
|
|
392
|
+
* continues past a `Stop` (a Stop hook that blocks) still reports its
|
|
393
|
+
* `post_tool_use`, which opens the turn as before. Sources whose turns begin
|
|
394
|
+
* with a tool event are untouched: Command Code's `pre_tool_use` and
|
|
395
|
+
* antigravity's self-resume `post_tool_use` (#2614) open turns because
|
|
396
|
+
* neither sends `user_prompt_submit`.
|
|
397
|
+
*
|
|
380
398
|
* `idle_prompt` is the one row that publishes `ready` **without** closing the
|
|
381
399
|
* turn, and that is a measurement rather than an oversight: #1839 caught Claude
|
|
382
400
|
* emitting it 62 s into a turn that ran nothing, so it cannot be a turn
|
|
@@ -409,6 +427,12 @@ function applyTurnTransition(key, record) {
|
|
|
409
427
|
// Deliberately leaves the dialog alone (Issue #1726). It is the
|
|
410
428
|
// `AskUserQuestion` invocation, and a picker being *about to be drawn* is
|
|
411
429
|
// not a fact this state can carry.
|
|
430
|
+
//
|
|
431
|
+
// Issue #3437: and from a source that reports its prompts, it is not the
|
|
432
|
+
// start of a turn when the agent's own `Stop` is the last thing that
|
|
433
|
+
// ended one. See the `after its stop` row above.
|
|
434
|
+
if (record.promptOpensTurns === true && endedByOwnStop(key))
|
|
435
|
+
return;
|
|
412
436
|
openTurn(key, record, generation, { continueOpen: true });
|
|
413
437
|
return;
|
|
414
438
|
case 'stop':
|
|
@@ -432,6 +456,33 @@ function applyTurnTransition(key, record) {
|
|
|
432
456
|
return;
|
|
433
457
|
}
|
|
434
458
|
}
|
|
459
|
+
/**
|
|
460
|
+
* Whether this instance's turn was last ended by the agent's own `stop`, with
|
|
461
|
+
* nothing opening a turn since (Issue #3437).
|
|
462
|
+
*
|
|
463
|
+
* Only `stop`: every other close is this server's own inference (`stale`,
|
|
464
|
+
* `scraper_evidence`, `resync_idle`) or a session that went away
|
|
465
|
+
* (`session_end`, `generation`), and an agent that keeps working after one of
|
|
466
|
+
* those must be allowed to open the turn it is in.
|
|
467
|
+
*/
|
|
468
|
+
function endedByOwnStop(key) {
|
|
469
|
+
const turn = fencedTurn(key);
|
|
470
|
+
return turn !== null && turn.closedAt !== null && turn.closedBy === 'stop';
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Whether a `pre_tool_use` from a source that reports its prompts falls outside
|
|
474
|
+
* any turn: the instance's last turn was ended by the agent's own `stop` and
|
|
475
|
+
* nothing has opened one since (Issue #3446).
|
|
476
|
+
*
|
|
477
|
+
* The same reading {@link applyTurnTransition} uses to leave such an event's
|
|
478
|
+
* turn closed (#3437), exposed so the intake can decide the question that event
|
|
479
|
+
* carries on the same facts. Asked after the event was applied, it still holds,
|
|
480
|
+
* because the transition did not open a turn; for a source that does not report
|
|
481
|
+
* its prompts it is always false, because that event opened one.
|
|
482
|
+
*/
|
|
483
|
+
function isPreToolUseOutsideTurn(worktreeId, cliToolId, instanceId, promptOpensTurns) {
|
|
484
|
+
return promptOpensTurns && endedByOwnStop((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId));
|
|
485
|
+
}
|
|
435
486
|
/** The three fields the turn keeps from a record. */
|
|
436
487
|
function displayOf(record) {
|
|
437
488
|
return { event: record.event, at: record.at, detail: record.detail };
|
|
@@ -479,12 +479,7 @@ function buildRunningPayload({ worktreeId, cliToolId, instanceId, sessionName, p
|
|
|
479
479
|
realtimeSnippet,
|
|
480
480
|
lineCount: totalLines,
|
|
481
481
|
lastCapturedLine,
|
|
482
|
-
isComplete: isPromptWaiting,
|
|
483
|
-
isGenerating: published.thinking,
|
|
484
482
|
thinking: published.thinking,
|
|
485
|
-
// Issue #2607: named after the tool actually running. A fixed "Claude" was
|
|
486
|
-
// published for every agent, and `capture --json` readers took it at its word.
|
|
487
|
-
thinkingMessage: published.thinking ? `${(0, types_1.getCliToolDisplayName)(cliToolId)} is thinking...` : null,
|
|
488
483
|
isPromptWaiting,
|
|
489
484
|
promptData,
|
|
490
485
|
...(promptAnswerable !== undefined ? { promptAnswerable } : {}),
|
|
@@ -496,6 +496,7 @@ async function createSkillInstallPlan(input) {
|
|
|
496
496
|
headState: git.headState,
|
|
497
497
|
headCommit: git.headCommit,
|
|
498
498
|
workingTreeDirty: git.dirty,
|
|
499
|
+
...(git.dirtyUnknown ? { workingTreeUnknown: true } : {}),
|
|
499
500
|
installRoot: primary.preview.installRoot,
|
|
500
501
|
installRoots,
|
|
501
502
|
currentTreeHash: primary.preview.currentTreeHash,
|
|
@@ -37,6 +37,7 @@ exports.readSkillGitTargetState = readSkillGitTargetState;
|
|
|
37
37
|
exports.findGitIgnoredPaths = findGitIgnoredPaths;
|
|
38
38
|
exports.buildUnifiedDiff = buildUnifiedDiff;
|
|
39
39
|
exports.buildSkillPreviewDiff = buildSkillPreviewDiff;
|
|
40
|
+
exports.workingTreeWarning = workingTreeWarning;
|
|
40
41
|
const crypto_1 = require("crypto");
|
|
41
42
|
const fs_1 = require("fs");
|
|
42
43
|
const path_1 = __importDefault(require("path"));
|
|
@@ -88,6 +89,8 @@ exports.SkillPreviewWarning = {
|
|
|
88
89
|
HEAD_UNRESOLVED: 'SKILL_PREVIEW_HEAD_UNRESOLVED',
|
|
89
90
|
/** The worktree has uncommitted changes. */
|
|
90
91
|
WORKING_TREE_DIRTY: 'SKILL_PREVIEW_WORKING_TREE_DIRTY',
|
|
92
|
+
/** `git status` could not be read, so uncommitted changes may exist (Issue #3445). */
|
|
93
|
+
WORKING_TREE_STATUS_UNKNOWN: 'SKILL_PREVIEW_WORKING_TREE_STATUS_UNKNOWN',
|
|
91
94
|
/** At least one destination path is ignored or excluded by git. */
|
|
92
95
|
PATH_GIT_IGNORED: 'SKILL_PREVIEW_PATH_GIT_IGNORED',
|
|
93
96
|
/** At least one diff body was cut short. */
|
|
@@ -338,7 +341,13 @@ async function readSkillGitTargetState(worktreePath) {
|
|
|
338
341
|
headState,
|
|
339
342
|
branch: branch && branch.length > 0 ? branch : null,
|
|
340
343
|
headCommit: commit,
|
|
341
|
-
|
|
344
|
+
// Issue #3435: an unread `status` (null, e.g. the 1s timeout) must not
|
|
345
|
+
// read as clean. This flag only drives the advisory WORKING_TREE_DIRTY
|
|
346
|
+
// warning and the target display, so the fail-safe side is "dirty".
|
|
347
|
+
dirty: status === null || status.length > 0,
|
|
348
|
+
// Issue #3445: say the guess is a guess, so the display can tell "has
|
|
349
|
+
// changes" from "could not check". Absent on success (shape unchanged).
|
|
350
|
+
...(status === null ? { dirtyUnknown: true } : {}),
|
|
342
351
|
};
|
|
343
352
|
}
|
|
344
353
|
/**
|
|
@@ -603,6 +612,17 @@ function buildSkillPreviewDiff(input) {
|
|
|
603
612
|
plannedTreeHash: computeSkillTreeHash(plannedTree),
|
|
604
613
|
};
|
|
605
614
|
}
|
|
615
|
+
/**
|
|
616
|
+
* The working-tree caveat for a target (Issue #3445): an unread status is still
|
|
617
|
+
* a caveat (fail-safe), but worded as "could not check" rather than "dirty".
|
|
618
|
+
*/
|
|
619
|
+
function workingTreeWarning(git) {
|
|
620
|
+
if (git.dirtyUnknown)
|
|
621
|
+
return exports.SkillPreviewWarning.WORKING_TREE_STATUS_UNKNOWN;
|
|
622
|
+
if (git.dirty)
|
|
623
|
+
return exports.SkillPreviewWarning.WORKING_TREE_DIRTY;
|
|
624
|
+
return null;
|
|
625
|
+
}
|
|
606
626
|
function collectWarnings(input, entries, stats, anyCrlf) {
|
|
607
627
|
const warnings = [];
|
|
608
628
|
if (input.git.headState === 'detached')
|
|
@@ -611,8 +631,9 @@ function collectWarnings(input, entries, stats, anyCrlf) {
|
|
|
611
631
|
warnings.push(exports.SkillPreviewWarning.UNBORN_HEAD);
|
|
612
632
|
if (input.git.headState === 'unknown')
|
|
613
633
|
warnings.push(exports.SkillPreviewWarning.HEAD_UNRESOLVED);
|
|
614
|
-
|
|
615
|
-
|
|
634
|
+
const dirtyWarning = workingTreeWarning(input.git);
|
|
635
|
+
if (dirtyWarning)
|
|
636
|
+
warnings.push(dirtyWarning);
|
|
616
637
|
if (entries.some((entry) => entry.gitIgnored))
|
|
617
638
|
warnings.push(exports.SkillPreviewWarning.PATH_GIT_IGNORED);
|
|
618
639
|
if (stats.truncatedFiles > 0)
|
|
@@ -419,6 +419,7 @@ function createSkillUninstallPlan(input) {
|
|
|
419
419
|
headState: input.git.headState,
|
|
420
420
|
headCommit: input.git.headCommit,
|
|
421
421
|
workingTreeDirty: input.git.dirty,
|
|
422
|
+
...(input.git.dirtyUnknown ? { workingTreeUnknown: true } : {}),
|
|
422
423
|
installRoot: assessment.installRoot,
|
|
423
424
|
currentTreeHash: assessment.currentTreeHash,
|
|
424
425
|
},
|