@co0ontty/wand 4.106.0 → 4.106.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ai-text-runner.js +24 -14
- package/dist/build-info.d.ts +2 -0
- package/dist/build-info.js +18 -0
- package/dist/build-info.json +3 -3
- package/dist/cli.js +8 -2
- package/dist/daemon-maintenance-state.js +1 -1
- package/dist/daemon-maintenance-targets.d.ts +1 -0
- package/dist/daemon-maintenance-targets.js +25 -9
- package/dist/daemon-maintenance.d.ts +3 -0
- package/dist/daemon-maintenance.js +60 -13
- package/dist/employee-im-types.d.ts +1 -1
- package/dist/employee-input-scheduling.d.ts +4 -0
- package/dist/employee-knowledge-cli.js +5 -5
- package/dist/employee-knowledge.d.ts +3 -1
- package/dist/employee-knowledge.js +24 -8
- package/dist/git-quick-commit.d.ts +2 -0
- package/dist/git-quick-commit.js +15 -2
- package/dist/git-worktree-batch.d.ts +26 -0
- package/dist/git-worktree-batch.js +139 -0
- package/dist/global-knowledge.d.ts +12 -0
- package/dist/global-knowledge.js +124 -0
- package/dist/iteration-log.d.ts +13 -5
- package/dist/iteration-log.js +120 -59
- package/dist/knowledge-types.d.ts +12 -1
- package/dist/knowledge-types.js +4 -0
- package/dist/middleware/api-scope.js +1 -0
- package/dist/model-groups.js +6 -3
- package/dist/models/parsers/opencode.js +31 -1
- package/dist/models.js +15 -14
- package/dist/npm-update-utils.d.ts +5 -2
- package/dist/npm-update-utils.js +34 -4
- package/dist/opencode-cli.d.ts +6 -0
- package/dist/opencode-cli.js +51 -0
- package/dist/opencode-system-fallback.d.ts +1 -0
- package/dist/opencode-system-fallback.js +16 -4
- package/dist/pi-native-event-bridge.js +55 -3
- package/dist/pi-native-input.d.ts +22 -0
- package/dist/pi-native-input.js +77 -0
- package/dist/pi-tmux-host.d.ts +14 -5
- package/dist/pi-tmux-host.js +68 -17
- package/dist/process-manager.js +17 -3
- package/dist/pty-tmux-backend.d.ts +27 -2
- package/dist/pty-tmux-backend.js +471 -70
- package/dist/pty-tmux-log.d.ts +1 -1
- package/dist/pty-tmux-log.js +23 -2
- package/dist/retention-protection.d.ts +1 -1
- package/dist/retention-protection.js +3 -2
- package/dist/retention.d.ts +5 -0
- package/dist/retention.js +11 -0
- package/dist/server-knowledge-routes.js +2 -2
- package/dist/server-session-input-routes.js +38 -19
- package/dist/server-session-lifecycle-routes.js +14 -1
- package/dist/server-session-worktree-routes.js +105 -12
- package/dist/server-task-routes.js +41 -12
- package/dist/server-workspace-routes.js +77 -9
- package/dist/server.js +67 -35
- package/dist/session-registry.d.ts +17 -3
- package/dist/session-registry.js +66 -13
- package/dist/session-service.js +1 -1
- package/dist/storage/internal.d.ts +4 -3
- package/dist/storage/internal.js +3 -3
- package/dist/storage/knowledge-repository.d.ts +5 -0
- package/dist/storage/knowledge-repository.js +75 -16
- package/dist/storage/mappers.d.ts +1 -0
- package/dist/storage/mappers.js +6 -1
- package/dist/storage/migrations.js +60 -0
- package/dist/storage/session-input-repository.d.ts +19 -0
- package/dist/storage/session-input-repository.js +35 -0
- package/dist/storage/task-workflow-repository.d.ts +29 -0
- package/dist/storage/task-workflow-repository.js +110 -0
- package/dist/storage/tasks-repository.d.ts +6 -1
- package/dist/storage/tasks-repository.js +94 -34
- package/dist/storage/workspaces-repository.d.ts +7 -0
- package/dist/storage/workspaces-repository.js +28 -2
- package/dist/storage-cleanup.d.ts +7 -2
- package/dist/storage-cleanup.js +16 -0
- package/dist/storage-schema.js +2 -0
- package/dist/storage.d.ts +5 -1
- package/dist/storage.js +12 -0
- package/dist/structured-exec-host.d.ts +4 -0
- package/dist/structured-exec-pump.d.ts +1 -0
- package/dist/structured-exec-pump.js +18 -11
- package/dist/structured-opencode-adapter.d.ts +2 -1
- package/dist/structured-opencode-adapter.js +32 -8
- package/dist/structured-pi-adapter.js +13 -2
- package/dist/structured-runner.d.ts +6 -0
- package/dist/structured-session-manager-replay.d.ts +2 -0
- package/dist/structured-session-manager-replay.js +27 -0
- package/dist/structured-session-manager.d.ts +32 -21
- package/dist/structured-session-manager.js +395 -118
- package/dist/structured-tmux-host.d.ts +23 -2
- package/dist/structured-tmux-host.js +143 -20
- package/dist/task-actions.js +5 -3
- package/dist/task-archive-policy.js +2 -1
- package/dist/task-comment-dispatch.d.ts +2 -1
- package/dist/task-comment-dispatch.js +19 -6
- package/dist/task-execution-queue.d.ts +2 -0
- package/dist/task-execution-queue.js +10 -10
- package/dist/task-hierarchy.js +1 -1
- package/dist/task-read-model.d.ts +1 -1
- package/dist/task-read-model.js +2 -1
- package/dist/task-types.d.ts +34 -3
- package/dist/task-types.js +21 -5
- package/dist/task-workflow-cli.d.ts +2 -0
- package/dist/task-workflow-cli.js +29 -0
- package/dist/task-workflow-runner.d.ts +4 -0
- package/dist/task-workflow-runner.js +36 -0
- package/dist/task-workflow.d.ts +13 -0
- package/dist/task-workflow.js +48 -0
- package/dist/terminal-daemon-server.js +12 -4
- package/dist/tmux-policy.d.ts +9 -0
- package/dist/tmux-policy.js +46 -0
- package/dist/tmux-terminal-host.js +5 -2
- package/dist/tui/commands.js +2 -1
- package/dist/types.d.ts +5 -0
- package/dist/wand-task-sync.js +5 -0
- package/dist/web-ui/content/ai-teams.js +9 -9
- package/dist/web-ui/content/module-manifest.json +1 -1
- package/dist/web-ui/content/modules/{52574891ef08e29b → 014fa5c6f973badf}/host.js +3 -3
- package/dist/web-ui/content/modules/0818b1d31a11d006/employee-profile.js +1 -0
- package/dist/web-ui/content/modules/{31157ceb6d23b809 → 0a58d9ec273078e4}/chunk.js +3 -3
- package/dist/web-ui/content/modules/{bf3ee58e0da44822 → 0a979dcd165cd0cc}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{5f298a8f43dd0589 → 0c143928e8f96abc}/chunk.js +1 -1
- package/dist/web-ui/content/modules/0e9e42a319f6b8fc/workspace-window.js +1 -0
- package/dist/web-ui/content/modules/{b713cad51ca4c512 → 0f0d1769b732c0bd}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{4970319a83432ec7 → 1447886e6a1e74a4}/chunk.js +1 -1
- package/dist/web-ui/content/modules/151c734cbca31da5/host.js +1 -0
- package/dist/web-ui/content/modules/{e5174201f9d918fb → 16e4ab9c5263fcfd}/chunk.js +1 -1
- package/dist/web-ui/content/modules/17e752fb53952753/host.js +1 -0
- package/dist/web-ui/content/modules/{913187c92a98a1ac → 20ed1454fc09fa6f}/chunk.js +1 -1
- package/dist/web-ui/content/modules/255a3baf59d2b734/home.js +6 -0
- package/dist/web-ui/content/modules/{2f801e53dda62770 → 296dd81886c42b45}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{8891ca8165435ca1 → 2a01f4e525c0725e}/chunk.js +1 -1
- package/dist/web-ui/content/modules/2ab4409c82b44fba/markdown.js +1 -0
- package/dist/web-ui/content/modules/2c955eced11610c2/chunk.js +1 -0
- package/dist/web-ui/content/modules/2d7ee4f9e2c0aca4/panel.js +1 -0
- package/dist/web-ui/content/modules/{3f8830f8ad28decc → 33ae550e4a295c85}/chunk.js +1 -1
- package/dist/web-ui/content/modules/35f4aa4443696bd0/chunk.js +1 -0
- package/dist/web-ui/content/modules/388b37ffcce9d4ff/host.js +1 -0
- package/dist/web-ui/content/modules/39279604dcdac7c7/runtime.js +338 -0
- package/dist/web-ui/content/modules/{57c357d321db5df9 → 3a3cdff2a662b7d3}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{d49f106c4d106057 → 3ab646be55514243}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{16dab1297efd71a7 → 3ae88a5c5e1949d2}/chunk.js +1 -1
- package/dist/web-ui/content/modules/3e3b0e71d6ce80d8/chunk.js +1 -0
- package/dist/web-ui/content/modules/{ec33e17c00c1eb24 → 434aaaaf9604dc34}/chunk.js +1 -1
- package/dist/web-ui/content/modules/4385cd48771e1d4f/host.js +1 -0
- package/dist/web-ui/content/modules/{face3dbf117d63e3 → 4638129d60f549a0}/chunk.js +1 -1
- package/dist/web-ui/content/modules/47407209931b7011/host.js +13 -0
- package/dist/web-ui/content/modules/4829dd712d8b366b/chunk.js +1 -0
- package/dist/web-ui/content/modules/488d5b747bf374c8/chunk.js +1 -0
- package/dist/web-ui/content/modules/{ed7405f064944215 → 4ab085c195f7d76a}/sha256.js +1 -1
- package/dist/web-ui/content/modules/{f27a5d3c6c02a71c → 4c485bd44740fec7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{771439a41e737ee2 → 4ca0494308ab2bb3}/chunk.js +1 -1
- package/dist/web-ui/content/modules/4ec571218779ba3e/composer-surface-adapter.js +1 -0
- package/dist/web-ui/content/modules/{5933ce8965aa4004 → 5023bf0294c2e7cb}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{e63582a3bce48f7d → 5456e3417600bf15}/chunk.js +1 -1
- package/dist/web-ui/content/modules/55c588b0f5b41a52/host-bridge.js +1 -0
- package/dist/web-ui/content/modules/{9d941d6ff39861b8 → 5c3c8237ba7d8460}/chunk.js +1 -1
- package/dist/web-ui/content/modules/624b858da9834757/host.js +1 -0
- package/dist/web-ui/content/modules/6290be936320d4b1/host.js +1 -0
- package/dist/web-ui/content/modules/66be408793048cc3/progress.js +1 -0
- package/dist/web-ui/content/modules/67a11176a563317b/chunk.js +1 -0
- package/dist/web-ui/content/modules/{e060508ecd50fa7e → 68ef6ec7d26d78cd}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{41445c6589dba325 → 6ec3e41df31927d9}/host.js +2 -2
- package/dist/web-ui/content/modules/{97d7f267959fd385 → 6f10f369445bbcbe}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{d47d75a78ae598e3 → 7295d9ff92d5e1e7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{f383d892fef73483 → 72cd613de1a5f69b}/chunk.js +1 -1
- package/dist/web-ui/content/modules/73aae1daafeea7e7/workspaces-panel.js +4 -0
- package/dist/web-ui/content/modules/{c2f09c8a472f5d83 → 73d2689f13b9a3e9}/dialog-modal.js +1 -1
- package/dist/web-ui/content/modules/{2f97ddba3842adaa → 75cf0c048e9b92ab}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{4ba1e8c74bed7ef2 → 75dabda3b141296e}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{f3cff7792ba39df8 → 76c10b58d5f92d02}/login-visual.js +1 -1
- package/dist/web-ui/content/modules/{b63e075f222a1266 → 783583a12f5010f8}/library-bridge.js +1 -1
- package/dist/web-ui/content/modules/7e13a8a4a981f2f1/group-editor.js +1 -0
- package/dist/web-ui/content/modules/{0d76e582a7a71b2f → 7e3034fea34c6dae}/chunk.js +1 -1
- package/dist/web-ui/content/modules/80bf3291f2577a68/host.js +1 -0
- package/dist/web-ui/content/modules/{cba6f13c0b2aec1c → 82c3e08f34a6b828}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{dedd4a19bb70e327 → 83d1f4cf82c65f19}/page.js +3 -3
- package/dist/web-ui/content/modules/844f97958f25240c/shell-file-panel-drawer.js +1 -0
- package/dist/web-ui/content/modules/{62e0023451f428cf → 899cdc467044d418}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{5083a5dbb5b155b7 → 8c7ca1fe72741c07}/chunk.js +1 -1
- package/dist/web-ui/content/modules/8dae4ca2261525e4/task-board-host.js +27 -0
- package/dist/web-ui/content/modules/92195c14c74929da/list-filter-panel.js +1 -0
- package/dist/web-ui/content/modules/{a61393bfa976d8d5 → 93793696af76bcbf}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{db521a246e14e5e4 → 97cd6af3da5622b8}/chunk.js +4 -4
- package/dist/web-ui/content/modules/{8de8368570ab089d → 9d3179258249ec77}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{579d486763d47c0d → a234c484078c0568}/chunk.js +1 -1
- package/dist/web-ui/content/modules/a4d215448a089a7d/host.js +1 -0
- package/dist/web-ui/content/modules/{c0a446100d969f3e → ae003f89901c5687}/chunk.js +1 -1
- package/dist/web-ui/content/modules/ae712bdd45b9917e/employee-card.js +1 -0
- package/dist/web-ui/content/modules/{a2caed0139df4b21 → b2a15293f7965d09}/chunk.js +1 -1
- package/dist/web-ui/content/modules/b4ee65e9998f0088/host.js +61 -0
- package/dist/web-ui/content/modules/{bd3daf04a8bf4422 → b666137d17f83be9}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{831b6c7b43e800be → b66beb6c0185256b}/host.js +1 -1
- package/dist/web-ui/content/modules/{816eb9b3a000fb2c → bb03b17e877657de}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{1eab7410d5586038 → bc343afc991db1a1}/chunk.js +1 -1
- package/dist/web-ui/content/modules/bca45976ff8fe2ac/host.js +69 -0
- package/dist/web-ui/content/modules/{d434edbb2f4672e5 → c2715dbfc9eaf510}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{d6fffe2c2a3a738d → c30c220281f35d74}/toast-region.js +1 -1
- package/dist/web-ui/content/modules/c4cc46fa9b4adddc/dropdown-surface.js +1 -0
- package/dist/web-ui/content/modules/c6dd19ee3d3ffd59/brand-identity.js +1 -0
- package/dist/web-ui/content/modules/c7ea6a114e6ff8ae/host.js +1 -0
- package/dist/web-ui/content/modules/{a59734be368daa7e → c916d82c8acef9c8}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{182929e188c1ab3a → cceaedda619a737a}/host.js +1 -1
- package/dist/web-ui/content/modules/cf67f52b076b9d2d/panel-host.js +1 -0
- package/dist/web-ui/content/modules/{9e163d54ff8fd1aa → d26c86558d422313}/chunk.js +1 -1
- package/dist/web-ui/content/modules/d2b8c6c6f3706032/queue-view-adapter.js +1 -0
- package/dist/web-ui/content/modules/d52ebe2ef12a9fa8/chunk.js +3 -0
- package/dist/web-ui/content/modules/{3fe11a75284ad8ae → d552b3bff2151eb6}/host.js +2 -2
- package/dist/web-ui/content/modules/d5d6b4511ac76a6e/chunk.js +3 -0
- package/dist/web-ui/content/modules/{bd7dc4bb46731ee7 → df42e151d625463b}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{2a791cd2e14aa1e0 → e0a04f5ae56c68aa}/notice-view.js +1 -1
- package/dist/web-ui/content/modules/{438807b8bf112cd0 → e28e607c95d6f63a}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{50da446c1377c220 → e3880df97ea62d0c}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{87c7f50d9455d55e → e66196f1ece3e3ad}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{9b12c2301f3a18f3 → eb76307444ac9d71}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{c33935155289c22d → ebff7ca22cee1468}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{4861eca9a8a87ad0 → ed1c712c569960d6}/chunk.js +1 -1
- package/dist/web-ui/content/modules/ee8b9c2d4bec63d4/chunk.js +1 -0
- package/dist/web-ui/content/modules/f458a194ce4208e2/chunk.js +1 -0
- package/dist/web-ui/content/modules/{11af5d14b30e57b6 → f938e826420cfe1b}/chunk.js +1 -1
- package/dist/web-ui/content/modules/fa7b9bf6cc84bfc1/chat-render.js +81 -0
- package/dist/web-ui/content/modules/{ea8fe4b9999fd2aa → fd1fb1834f5f06df}/chunk.js +1 -1
- package/dist/web-ui/content/modules/fd3084e562a3dbd6/host.js +1 -0
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +416 -413
- package/dist/web-ui/embedded-assets.js +5 -5
- package/dist/web-ui/page-route.js +2 -2
- package/dist/web-ui/react/workspaces/types.d.ts +3 -0
- package/dist/web-ui/thinking-efforts.d.ts +2 -0
- package/dist/web-ui/thinking-efforts.js +8 -0
- package/package.json +1 -2
- package/scripts/stage-render-binaries.js +0 -1
- package/skills/wand-knowledge/SKILL.md +5 -3
- package/dist/structured-bounded-keys.d.ts +0 -19
- package/dist/structured-bounded-keys.js +0 -47
- package/dist/web-ui/content/modules/00b168a19664439e/dropdown-surface.js +0 -1
- package/dist/web-ui/content/modules/059c5fb7f128d340/task-board-host.js +0 -27
- package/dist/web-ui/content/modules/07494f5a623e4471/chat-render.js +0 -76
- package/dist/web-ui/content/modules/0a743ad3b4db6874/chunk.js +0 -3
- package/dist/web-ui/content/modules/1858670c0f84fec5/employee-profile.js +0 -1
- package/dist/web-ui/content/modules/20c47dc0442f5a04/host.js +0 -1
- package/dist/web-ui/content/modules/226241b999d12008/host.js +0 -1
- package/dist/web-ui/content/modules/23c4b8d223ec64c5/host.js +0 -61
- package/dist/web-ui/content/modules/2882c97388ff4f7b/employee-card.js +0 -1
- package/dist/web-ui/content/modules/2c90c3be260e6cce/progress.js +0 -1
- package/dist/web-ui/content/modules/2d7be9935394f397/workspace-window.js +0 -1
- package/dist/web-ui/content/modules/389a5112332ec23a/host.js +0 -1
- package/dist/web-ui/content/modules/3ea13e8b3c2deaa4/panel-host.js +0 -1
- package/dist/web-ui/content/modules/42e5c34002fcffb7/chunk.js +0 -1
- package/dist/web-ui/content/modules/4a5d669c90f545cb/host.js +0 -1
- package/dist/web-ui/content/modules/5705d25468274534/host.js +0 -1
- package/dist/web-ui/content/modules/5961ab2947c86ca1/shell-file-panel-drawer.js +0 -1
- package/dist/web-ui/content/modules/5b6e1369df7dea69/chunk.js +0 -1
- package/dist/web-ui/content/modules/6787bdcf56f743a5/host.js +0 -1
- package/dist/web-ui/content/modules/67c39b0398186a9f/host.js +0 -1
- package/dist/web-ui/content/modules/6b16f35c0627bafb/chunk.js +0 -1
- package/dist/web-ui/content/modules/6dd4f3e2f619f7a0/chunk.js +0 -1
- package/dist/web-ui/content/modules/70a2e13e0ccc8549/panel.js +0 -1
- package/dist/web-ui/content/modules/710db590e9707f73/runtime.js +0 -338
- package/dist/web-ui/content/modules/7249950f8771dbeb/workspaces-panel.js +0 -4
- package/dist/web-ui/content/modules/87dcd516ffd9f688/composer-surface-adapter.js +0 -1
- package/dist/web-ui/content/modules/8b7cd7bffdfd69e7/brand-identity.js +0 -1
- package/dist/web-ui/content/modules/8bf9917f6c3429f6/host.js +0 -1
- package/dist/web-ui/content/modules/8e612d4881fa4118/home.js +0 -6
- package/dist/web-ui/content/modules/8e6178262ea63dec/markdown.js +0 -1
- package/dist/web-ui/content/modules/96f2ae970f8c576b/host.js +0 -1
- package/dist/web-ui/content/modules/ba89cd97627e6682/queue-view-adapter.js +0 -1
- package/dist/web-ui/content/modules/c351eb11e0bdec2c/sidebar-peek.js +0 -1
- package/dist/web-ui/content/modules/ca7ca5902a35d26e/chunk.js +0 -1
- package/dist/web-ui/content/modules/d5d28ec375826ef2/chunk.js +0 -3
- package/dist/web-ui/content/modules/d6b16dedb9011c33/chunk.js +0 -1
- package/dist/web-ui/content/modules/d8a7011760f61719/group-editor.js +0 -1
- package/dist/web-ui/content/modules/d9e2b65e9679ad39/host.js +0 -75
- package/dist/web-ui/content/modules/eac72f69716dba05/chunk.js +0 -1
- package/dist/web-ui/content/modules/ebc53dedc3945514/host.js +0 -1
- package/dist/web-ui/content/modules/f43da7050badf54c/host.js +0 -1
- package/dist/web-ui/content/modules/fb2356eced24c4cc/host-bridge.js +0 -1
package/dist/task-types.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
/** done is retained for historical storage/older callers, never proof of AI approval. */
|
|
2
|
+
export const WAND_TASK_STATUSES = ["backlog", "todo", "doing", "review", "ready", "done", "archived"];
|
|
3
|
+
export function taskWorkflowStage(status) {
|
|
4
|
+
return status === "done" ? "review" : status;
|
|
5
|
+
}
|
|
6
|
+
export function taskAiVerified(task) {
|
|
7
|
+
return task.verification?.verdict === "passed" && task.verification.revision === (task.deliveryRevision ?? 0)
|
|
8
|
+
&& typeof task.verification.evidence === "string" && Boolean(task.verification.evidence.trim())
|
|
9
|
+
&& typeof task.verification.blocker === "string" && !task.verification.blocker.trim();
|
|
10
|
+
}
|
|
11
|
+
export function taskHumanAccepted(task) {
|
|
12
|
+
return Boolean(task.acceptance?.acceptedAt) && task.acceptance?.confirmedRevision === (task.deliveryRevision ?? 0)
|
|
13
|
+
&& typeof task.acceptance?.evidence === "string" && Boolean(task.acceptance.evidence.trim())
|
|
14
|
+
&& typeof task.acceptance?.blocker === "string" && !task.acceptance.blocker.trim();
|
|
15
|
+
}
|
|
2
16
|
export function isWandTaskStatus(value) {
|
|
3
17
|
return typeof value === "string" && WAND_TASK_STATUSES.includes(value);
|
|
4
18
|
}
|
|
5
|
-
/**
|
|
19
|
+
/** A new execution returns work to doing; explicit review dispatches preserve review separately. */
|
|
6
20
|
export function statusAfterWandTaskDispatch(status) {
|
|
7
|
-
|
|
21
|
+
if (status === "archived")
|
|
22
|
+
throw new Error("归档任务需要先恢复再执行。");
|
|
23
|
+
return "doing";
|
|
8
24
|
}
|
|
9
|
-
/**
|
|
25
|
+
/** 仅归档关闭活动阶段;待 AI 验收与待人工确认仍属于未完成工作。 */
|
|
10
26
|
export function isClosedWandTaskStatus(status) {
|
|
11
|
-
return status === "
|
|
27
|
+
return status === "archived";
|
|
12
28
|
}
|
|
13
29
|
/** 新建任务的默认优先级:用户没挑就是「低」,不再落成「无优先级」。 */
|
|
14
30
|
export const DEFAULT_WAND_TASK_PRIORITY = "low";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
3
|
+
import { WandStorage } from "./storage.js";
|
|
4
|
+
/** Never opens owner CLI authentication as a fallback. Exact task and runtime grant only. */
|
|
5
|
+
export async function runTaskWorkflowCli(args, input = process.stdin) {
|
|
6
|
+
if (args.length !== 2 || !args[0] || args[0].startsWith("-") || args[1] !== "--stdin")
|
|
7
|
+
throw new Error("用法:wand task:workflow <task-id> --stdin");
|
|
8
|
+
const database = process.env.WAND_TASK_DB ?? "", token = process.env.WAND_TASK_TOKEN ?? "";
|
|
9
|
+
if (!isAbsolute(database) || !existsSync(database) || !/^[A-Za-z0-9_-]{43}$/.test(token))
|
|
10
|
+
throw new Error("任务回填仅可在有任务级授权的 Wand 员工执行中使用,不能使用所有者登录替代。");
|
|
11
|
+
const chunks = [];
|
|
12
|
+
let bytes = 0;
|
|
13
|
+
for await (const chunk of input) {
|
|
14
|
+
const buffer = Buffer.from(chunk);
|
|
15
|
+
bytes += buffer.length;
|
|
16
|
+
if (bytes > 96_000)
|
|
17
|
+
throw new Error("任务回填内容过长。");
|
|
18
|
+
chunks.push(buffer);
|
|
19
|
+
}
|
|
20
|
+
const value = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
21
|
+
const storage = new WandStorage(database);
|
|
22
|
+
try {
|
|
23
|
+
const task = storage.applyEmployeeTaskWorkflow(token, args[0], value);
|
|
24
|
+
process.stdout.write(JSON.stringify({ saved: true, task }) + "\n");
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
storage.close();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WandStorage } from "./storage.js";
|
|
2
|
+
import type { StructuredRunnerAdapter, StructuredRunnerContext, StructuredRunnerExecution, StructuredRunnerObserver } from "./structured-runner.js";
|
|
3
|
+
/** Runtime-only exact-task grant, independent of owner login and knowledge authorization. */
|
|
4
|
+
export declare function startTaskWorkflowRunner(storage: WandStorage, runner: StructuredRunnerAdapter, context: StructuredRunnerContext, observer: StructuredRunnerObserver): StructuredRunnerExecution;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { shellQuote } from "./shell-quote.js";
|
|
4
|
+
/** Runtime-only exact-task grant, independent of owner login and knowledge authorization. */
|
|
5
|
+
export function startTaskWorkflowRunner(storage, runner, context, observer) {
|
|
6
|
+
const env = { ...context.env };
|
|
7
|
+
delete env.WAND_TASK_DB;
|
|
8
|
+
delete env.WAND_TASK_TOKEN;
|
|
9
|
+
if (context.session.automationId?.startsWith("dingtalk:"))
|
|
10
|
+
return runner.start({ ...context, env }, observer);
|
|
11
|
+
const scope = storage.knowledgeSessionScope(context.session.id);
|
|
12
|
+
const grant = (context.session.employeeId ?? null) === (scope?.employeeId ?? null) ? storage.issueTaskWorkflowAccess(context.session.id) : null;
|
|
13
|
+
if (!grant)
|
|
14
|
+
return runner.start({ ...context, env }, observer);
|
|
15
|
+
const js = fileURLToPath(new URL("./cli.js", import.meta.url));
|
|
16
|
+
const command = existsSync(js) ? `${shellQuote(process.execPath)} ${shellQuote(js)}` : `${shellQuote(process.execPath)} --import tsx ${shellQuote(js.replace(/\.js$/, ".ts"))}`;
|
|
17
|
+
const instruction = [
|
|
18
|
+
`当前任务回填范围仅为 ${grant.taskId},交付版本 ${grant.revision}(ID/版本不是凭据)。`,
|
|
19
|
+
`先用 wand task:context ${grant.taskId} 读取最新 updatedAt、目标、证据和状态。确实完成交付时使用 submit;被明确派发验收时,根据实际证据用 pass 或 fail。未验证项按 fail 写明 blocker,不得因会话结束或自己声称完成而通过。`,
|
|
20
|
+
`回填命令:${command} task:workflow ${grant.taskId} --stdin。stdin 为 JSON {"action":"submit|pass|fail","requestId":"同一意图固定UUID","expectedUpdatedAt":"读取到的任务.updatedAt","evidence":"实际证据","blocker":"失败或无法验证的原因,通过时为空"}。`,
|
|
21
|
+
"该能力不能人工确认、归档、跨任务写入或派发。版本冲突先保留草稿并重新读取核对;未知回执不得换 requestId 重做。权限失效等待新的执行,不回退到所有者身份。提交后需独立新一轮验收,不在同一执行自提交自验收。验收结论必须实际回填,不能仅留在回复里。",
|
|
22
|
+
].join("\n\n");
|
|
23
|
+
const cleanup = () => { try {
|
|
24
|
+
storage.revokeTaskWorkflowAccess(grant.token);
|
|
25
|
+
}
|
|
26
|
+
catch { /* storage may be shutting down */ } };
|
|
27
|
+
try {
|
|
28
|
+
const execution = runner.start({ ...context, env: { ...env, WAND_TASK_DB: storage.databasePath(), WAND_TASK_TOKEN: grant.token }, session: { ...context.session,
|
|
29
|
+
runtimeSystemPrompt: [context.session.runtimeSystemPrompt, instruction].filter(Boolean).join("\n\n") } }, observer);
|
|
30
|
+
return { ...execution, completion: execution.completion.finally(cleanup), interrupt: () => { cleanup(); execution.interrupt(); } };
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
cleanup();
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type TaskWorkflowAction, type TaskWorkflowInput, type WandTask } from "./task-types.js";
|
|
2
|
+
import type { WandTaskPatch } from "./storage/internal.js";
|
|
3
|
+
export declare const TASK_WORKFLOW_ACTIONS: readonly TaskWorkflowAction[];
|
|
4
|
+
export type TaskWorkflowActor = {
|
|
5
|
+
kind: "user";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "employee";
|
|
8
|
+
sessionId: string;
|
|
9
|
+
employeeId: string | null;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseTaskWorkflowInput(value: unknown): TaskWorkflowInput;
|
|
12
|
+
/** Pure transition; storage owns CAS, live execution checks, receipts and atomic history. */
|
|
13
|
+
export declare function taskWorkflowPatch(task: WandTask, children: WandTask[], input: TaskWorkflowInput, actor: TaskWorkflowActor, now: string): WandTaskPatch;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { HttpError } from "./http-error.js";
|
|
2
|
+
import { taskAiVerified, taskHumanAccepted, taskWorkflowStage } from "./task-types.js";
|
|
3
|
+
export const TASK_WORKFLOW_ACTIONS = ["submit", "pass", "fail", "return", "accept"];
|
|
4
|
+
const fail = (message) => { throw new HttpError(409, "task_workflow_conflict", message); };
|
|
5
|
+
export function parseTaskWorkflowInput(value) {
|
|
6
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
7
|
+
throw new HttpError(400, "bad_request", "需要工作流动作。");
|
|
8
|
+
const body = value;
|
|
9
|
+
if (Object.keys(body).some(key => !["action", "requestId", "expectedUpdatedAt", "evidence", "blocker"].includes(key)))
|
|
10
|
+
throw new HttpError(400, "bad_request", "工作流包含不支持的字段。");
|
|
11
|
+
if (!TASK_WORKFLOW_ACTIONS.includes(body.action)
|
|
12
|
+
|| typeof body.requestId !== "string" || !/^[a-zA-Z0-9:_-]{8,80}$/.test(body.requestId)
|
|
13
|
+
|| typeof body.expectedUpdatedAt !== "string" || !body.expectedUpdatedAt
|
|
14
|
+
|| typeof body.evidence !== "string" || body.evidence.length > 16000
|
|
15
|
+
|| typeof body.blocker !== "string" || body.blocker.length > 4000)
|
|
16
|
+
throw new HttpError(400, "bad_request", "工作流动作、请求标识、任务版本或交付证据无效。");
|
|
17
|
+
return { action: body.action, requestId: body.requestId, expectedUpdatedAt: body.expectedUpdatedAt, evidence: body.evidence.trim(), blocker: body.blocker.trim() };
|
|
18
|
+
}
|
|
19
|
+
/** Pure transition; storage owns CAS, live execution checks, receipts and atomic history. */
|
|
20
|
+
export function taskWorkflowPatch(task, children, input, actor, now) {
|
|
21
|
+
const { action, evidence, blocker } = input;
|
|
22
|
+
const stage = taskWorkflowStage(task.status), revision = task.deliveryRevision ?? 0;
|
|
23
|
+
if (actor.kind !== "user" && (action === "accept" || action === "return"))
|
|
24
|
+
throw new HttpError(403, "forbidden", "AI 只能提交交付或回填验收,不能代替人工确认或退回。");
|
|
25
|
+
if ((action === "submit" && stage !== "doing") || ((action === "pass" || action === "fail") && stage !== "review") || ((action === "accept" || action === "return") && stage !== "ready"))
|
|
26
|
+
fail("任务阶段已变化,请刷新并核对,不能跨阶段推进。");
|
|
27
|
+
if (["submit", "pass", "accept"].includes(action) && (!evidence || blocker))
|
|
28
|
+
fail("需要交付证据,且不能遗留缺口或未验证项。");
|
|
29
|
+
if ((action === "fail" || action === "return") && !blocker)
|
|
30
|
+
fail("失败、无法验证或退回必须写明原因。");
|
|
31
|
+
const acceptance = { evidence, blocker, acceptedAt: null };
|
|
32
|
+
if (action === "submit")
|
|
33
|
+
return { status: "review", deliveryRevision: revision + 1, verification: null, acceptance };
|
|
34
|
+
if (action === "return")
|
|
35
|
+
return { status: "doing", deliveryRevision: revision + 1, verification: null, acceptance };
|
|
36
|
+
if (action === "accept") {
|
|
37
|
+
if (!taskAiVerified(task))
|
|
38
|
+
fail("没有针对当前交付的 AI 验收通过记录,请先完成验收。");
|
|
39
|
+
if (children.some(child => !taskHumanAccepted(child)))
|
|
40
|
+
fail("仍有子任务未由人工确认,请先确认子任务。");
|
|
41
|
+
return { status: "archived", acceptance: { evidence, blocker: "", acceptedAt: now, confirmedRevision: revision } };
|
|
42
|
+
}
|
|
43
|
+
if (action === "pass" && children.some(child => !taskAiVerified(child)))
|
|
44
|
+
fail("仍有子任务未通过 AI 验收,不能通过主目标整体验收。");
|
|
45
|
+
return { status: action === "pass" ? "ready" : "doing", acceptance,
|
|
46
|
+
verification: { verdict: action === "pass" ? "passed" : "failed", evidence, blocker, reviewedAt: now, revision,
|
|
47
|
+
sourceSessionId: actor.kind === "employee" ? actor.sessionId : null, reviewerId: actor.kind === "employee" ? actor.employeeId : null } };
|
|
48
|
+
}
|
|
@@ -379,10 +379,11 @@ export async function runTerminalDaemon(configPath) {
|
|
|
379
379
|
switch (request.method) {
|
|
380
380
|
case "hello":
|
|
381
381
|
result = { protocolVersion: TERMINAL_DAEMON_PROTOCOL_VERSION, pid: process.pid,
|
|
382
|
-
buildId: TERMINAL_DAEMON_BUILD_ID, shutdownIfIdle: true };
|
|
382
|
+
buildId: TERMINAL_DAEMON_BUILD_ID, shutdownIfIdle: true, ...(tmux ? { detachTmuxOnShutdown: true } : {}) };
|
|
383
383
|
break;
|
|
384
384
|
case "shutdownIfIdle": {
|
|
385
|
-
const busy = pendingStarts.size > 0 || [...
|
|
385
|
+
const busy = pendingStarts.size > 0 || [...structuredRuns.values()].some(entry => entry.status === "running")
|
|
386
|
+
|| (!tmux && [...sessions.values()].some(entry => entry.status === "running"));
|
|
386
387
|
result = { accepted: !busy };
|
|
387
388
|
if (!busy && !retiring) {
|
|
388
389
|
// The idle check and admission closure happen in the same event-loop turn.
|
|
@@ -546,8 +547,15 @@ export async function runTerminalDaemon(configPath) {
|
|
|
546
547
|
retiring = true;
|
|
547
548
|
await Promise.allSettled(pendingStarts.values());
|
|
548
549
|
stopSocketKeepalive();
|
|
549
|
-
for (const sessionId of
|
|
550
|
-
|
|
550
|
+
for (const [sessionId, session] of sessions) {
|
|
551
|
+
if (tmux && session.process?.detach) {
|
|
552
|
+
session.process.detach();
|
|
553
|
+
session.terminalState.dispose();
|
|
554
|
+
sessions.delete(sessionId);
|
|
555
|
+
}
|
|
556
|
+
else
|
|
557
|
+
forget(sessionId);
|
|
558
|
+
}
|
|
551
559
|
for (const runId of Array.from(structuredRuns.keys()))
|
|
552
560
|
structuredForget(runId);
|
|
553
561
|
for (const client of clients)
|
package/dist/tmux-policy.d.ts
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
|
+
export interface TmuxProbeResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
version?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const TMUX_MINIMUM_VERSION = "2.9";
|
|
8
|
+
/** 探测系统 tmux 可用性与版本能力(最低要求 2.9+ 以支持 pane 管道与用户元数据)。 */
|
|
9
|
+
export declare function probeTmuxSupport(env?: NodeJS.ProcessEnv): TmuxProbeResult;
|
|
1
10
|
/** Configuration selects new executions only; existing owners remain recoverable. */
|
|
2
11
|
export declare function tmuxEnabled(env?: NodeJS.ProcessEnv): boolean;
|
package/dist/tmux-policy.js
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
export const TMUX_MINIMUM_VERSION = "2.9";
|
|
3
|
+
/** 探测系统 tmux 可用性与版本能力(最低要求 2.9+ 以支持 pane 管道与用户元数据)。 */
|
|
4
|
+
export function probeTmuxSupport(env = process.env) {
|
|
5
|
+
if (process.platform === "win32") {
|
|
6
|
+
return { ok: false, error: "tmux 执行环境仅支持 POSIX 主机系统。" };
|
|
7
|
+
}
|
|
8
|
+
const childEnv = { PATH: env.PATH, HOME: env.HOME, LANG: env.LANG };
|
|
9
|
+
let rawVersion;
|
|
10
|
+
try {
|
|
11
|
+
rawVersion = execFileSync("tmux", ["-V"], {
|
|
12
|
+
encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 3000, env: childEnv,
|
|
13
|
+
}).trim();
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
const err = error;
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: err.code === "ENOENT"
|
|
20
|
+
? "未找到 tmux 可执行文件,请确认 tmux 已安装且在系统 PATH 中。"
|
|
21
|
+
: `tmux 探测失败: ${error.message}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const match = rawVersion.match(/(\d+)\.(\d+)/);
|
|
25
|
+
if (!match) {
|
|
26
|
+
return { ok: true, version: rawVersion, path: resolveTmuxPath(childEnv) };
|
|
27
|
+
}
|
|
28
|
+
const major = Number(match[1]);
|
|
29
|
+
const minor = Number(match[2]);
|
|
30
|
+
if (major < 2 || (major === 2 && minor < 9)) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
version: rawVersion,
|
|
34
|
+
error: `tmux 版本过低(当前 ${rawVersion},最低需要 ${TMUX_MINIMUM_VERSION}+ 以支持 pane 管道与用户元数据)。`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { ok: true, version: rawVersion, path: resolveTmuxPath(childEnv) };
|
|
38
|
+
}
|
|
39
|
+
function resolveTmuxPath(env) {
|
|
40
|
+
try {
|
|
41
|
+
return execFileSync("which", ["tmux"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], env }).trim();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return "tmux";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
1
47
|
/** Configuration selects new executions only; existing owners remain recoverable. */
|
|
2
48
|
export function tmuxEnabled(env = process.env) {
|
|
3
49
|
const mode = env.WAND_TMUX_MODE;
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { createTerminalHost, TerminalDaemonClient } from "./terminal-daemon-client.js";
|
|
3
|
-
import { tmuxEnabled } from "./tmux-policy.js";
|
|
3
|
+
import { probeTmuxSupport, tmuxEnabled } from "./tmux-policy.js";
|
|
4
4
|
import { logInfo } from "./runtime-log.js";
|
|
5
5
|
/** Existing owners win even after changing the policy; unknown inventory fails closed. */
|
|
6
6
|
export async function createTmuxTerminalHost(configPath, previous, createHost = createTerminalHost) {
|
|
7
7
|
const daemonConfig = path.join(path.dirname(configPath), "tmux-terminald.json");
|
|
8
8
|
const enabled = tmuxEnabled();
|
|
9
|
+
const probe = enabled ? probeTmuxSupport() : { ok: true };
|
|
9
10
|
const { existsSync } = await import("node:fs");
|
|
10
11
|
if (!enabled && !existsSync(path.join(path.dirname(configPath), "pty-tmux"))) {
|
|
11
12
|
return { host: previous, client: null, configPath: daemonConfig };
|
|
12
13
|
}
|
|
13
14
|
let tmux;
|
|
14
15
|
try {
|
|
16
|
+
if (!probe.ok)
|
|
17
|
+
throw new Error(probe.error);
|
|
15
18
|
tmux = await createHost(daemonConfig, { persistent: true });
|
|
16
19
|
}
|
|
17
20
|
catch (cause) {
|
|
18
21
|
const unavailable = () => new Error("tmux terminal ownership is unavailable; refusing execution or maintenance", { cause });
|
|
19
|
-
logInfo(
|
|
22
|
+
logInfo(`tmux terminal backend unavailable${probe.error ? `: ${probe.error}` : ""}; existing other owners remain accessible, new PTY execution is blocked`);
|
|
20
23
|
return {
|
|
21
24
|
configPath: daemonConfig,
|
|
22
25
|
client: null,
|
package/dist/tui/commands.js
CHANGED
|
@@ -11,6 +11,7 @@ import os from "node:os";
|
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import process from "node:process";
|
|
13
13
|
import { checkPackageUpdateSync, installPackageGloballySync, normalizeUpdateChannel, resolveGlobalWandBin, resolveGlobalWandCli, } from "../npm-update-utils.js";
|
|
14
|
+
import { RUNNING_BUILD_INFO } from "../build-info.js";
|
|
14
15
|
import { whichSync } from "../path-repair.js";
|
|
15
16
|
import { computeRelaunch } from "../relaunch.js";
|
|
16
17
|
import { ensureDatabaseFile, resolveDatabasePath, WandStorage } from "../storage.js";
|
|
@@ -68,7 +69,7 @@ export function readUpdateChannel(configPath) {
|
|
|
68
69
|
}
|
|
69
70
|
/** 通过 npm dist-tag 拿到当前通道最新版本号。失败返回 latest=null。 */
|
|
70
71
|
export function checkUpdate(currentVersion, channel = "stable") {
|
|
71
|
-
const info = checkPackageUpdateSync(currentVersion, channel);
|
|
72
|
+
const info = checkPackageUpdateSync(currentVersion, channel, undefined, RUNNING_BUILD_INFO);
|
|
72
73
|
return {
|
|
73
74
|
channel: info.channel,
|
|
74
75
|
current: info.current,
|
package/dist/types.d.ts
CHANGED
|
@@ -438,6 +438,8 @@ export interface CommandRequest {
|
|
|
438
438
|
}
|
|
439
439
|
export interface InputRequest {
|
|
440
440
|
input?: string;
|
|
441
|
+
/** Structured input acceptance identity; same key must preserve the same intent. */
|
|
442
|
+
idempotencyKey?: string;
|
|
441
443
|
/**
|
|
442
444
|
* Structured sessions normally keep the HTTP request open until the whole
|
|
443
445
|
* turn finishes. Native clients can opt into an accepted snapshot instead
|
|
@@ -743,6 +745,8 @@ export interface StructuredSessionState {
|
|
|
743
745
|
lastActivityAt?: string | null;
|
|
744
746
|
/** Pi 已结束前台回复、但 CLI 仍在等待异步子任务收尾。 */
|
|
745
747
|
phase?: "responding" | "background";
|
|
748
|
+
/** Actual running input capability; absent/turn-end means wait for the whole run. */
|
|
749
|
+
inputMode?: "steer" | "turn-end";
|
|
746
750
|
/**
|
|
747
751
|
* 本轮实际使用的执行引擎:`core` = Wand 进程内 harness(目前仅 pi),
|
|
748
752
|
* `cli` = 外部 CLI runner。决定重启后能否恢复:进程内回合不会比服务活得更久。
|
|
@@ -983,6 +987,7 @@ export type WorkspaceTaskStatus = "active" | "done";
|
|
|
983
987
|
* 一个工作空间下可有多个任务,任务在侧栏列表里单独展示;每个任务的会话共享该任务的 worktree。
|
|
984
988
|
*/
|
|
985
989
|
export interface WorkspaceTask {
|
|
990
|
+
kind?: "task" | "section";
|
|
986
991
|
id: string;
|
|
987
992
|
workspaceId: string;
|
|
988
993
|
name: string;
|
package/dist/wand-task-sync.js
CHANGED
|
@@ -51,6 +51,11 @@ function taskNamingSessions(storage, card) {
|
|
|
51
51
|
const addSlim = (session) => {
|
|
52
52
|
if (!session)
|
|
53
53
|
return;
|
|
54
|
+
// An explicit verification round describes the check, not a new delivery goal.
|
|
55
|
+
// Classify by its durable dispatch purpose, never by words in the title/prompt.
|
|
56
|
+
if (session.automationId?.startsWith("wand-task-comment:")
|
|
57
|
+
&& storage.isTaskReviewComment(session.automationId.slice("wand-task-comment:".length)))
|
|
58
|
+
return;
|
|
54
59
|
add(session);
|
|
55
60
|
// boardTitleFromSession 只在 title/description 都缺时才翻 messages 找首条用户输入。
|
|
56
61
|
if (!isBlankTerminal(session) && !session.title?.trim() && !session.description?.trim()) {
|