@songsid/agend 2.3.0-beta.24 → 2.3.0-beta.26
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/dist/adapter-world.js.map +1 -1
- package/dist/agend-home.d.ts +5 -0
- package/dist/agend-home.js +7 -0
- package/dist/agend-home.js.map +1 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +8 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/apply-job.js.map +1 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +5 -0
- package/dist/auth-api.js +21 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +4 -0
- package/dist/authority/authority-state.js +17 -8
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/authority/web-authority.d.ts +14 -6
- package/dist/authority/web-authority.js +19 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.d.ts +2 -2
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-package.js.map +1 -1
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.js +1 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-kas-store.js.map +1 -1
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/opencode-permission.js.map +1 -1
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/session-signals.js.map +1 -1
- package/dist/backend-availability.js.map +1 -1
- package/dist/backend-command.js.map +1 -1
- package/dist/backend-outage.js.map +1 -1
- package/dist/binary-probe.js.map +1 -1
- package/dist/bug-report.js.map +1 -1
- package/dist/bundled-skills.js.map +1 -1
- package/dist/cache-service.js +1 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.js +29 -4
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +54 -14
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +10 -1
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +2 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/sticker-download.js.map +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/classic-channel-manager.js +3 -2
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli-flags.js.map +1 -1
- package/dist/cli.js +15 -9
- package/dist/cli.js.map +1 -1
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.js.map +1 -1
- package/dist/completion-install.js.map +1 -1
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.js +20 -6
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +11 -3
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.js.map +1 -1
- package/dist/context-guardian.js.map +1 -1
- package/dist/coredump-filter.js.map +1 -1
- package/dist/cpu-profile.js.map +1 -1
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.js +73 -3
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.js.map +1 -1
- package/dist/darwin-memory.js.map +1 -1
- package/dist/dashboard-live.d.ts +8 -0
- package/dist/dashboard-live.js +35 -0
- package/dist/dashboard-live.js.map +1 -0
- package/dist/dashboard-permissions.d.ts +69 -0
- package/dist/dashboard-permissions.js +138 -0
- package/dist/dashboard-permissions.js.map +1 -0
- package/dist/decision-list.js.map +1 -1
- package/dist/delivery-consumed-watch.js.map +1 -1
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-outbox.test.js.map +1 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/diagnostic-redaction.js.map +1 -1
- package/dist/doctor.js.map +1 -1
- package/dist/e2e-isolation.js.map +1 -1
- package/dist/event-log.js.map +1 -1
- package/dist/export-import.js +3 -2
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-label.js.map +1 -1
- package/dist/fleet-lock.js +3 -2
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +77 -6
- package/dist/fleet-manager.js +488 -147
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.js +3 -2
- package/dist/fleet-process-handlers.js.map +1 -1
- package/dist/fleet-startup.d.ts +14 -0
- package/dist/fleet-startup.js +30 -0
- package/dist/fleet-startup.js.map +1 -0
- package/dist/fleet-traffic.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +0 -20
- package/dist/forged-envelope-scan.js +3 -2
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +2 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +2 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +36 -12
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +45 -14
- package/dist/host-memory.js.map +1 -1
- package/dist/instance-config-impact.js +6 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.js +1 -1
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +2 -0
- package/dist/instructions.js +6 -2
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.js.map +1 -1
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-log-gate.js.map +1 -1
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +22 -0
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.js +3 -2
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.js.map +1 -1
- package/dist/login-manager.js.map +1 -1
- package/dist/login-shell.js.map +1 -1
- package/dist/memory-pressure.js.map +1 -1
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.js.map +1 -1
- package/dist/network-family.js.map +1 -1
- package/dist/operator-control-paths.js +3 -4
- package/dist/operator-control-paths.js.map +1 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +68 -68
- package/dist/outbound-schemas.js +1 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.js.map +1 -1
- package/dist/pane-context-cache.js.map +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/private-dir.js.map +1 -1
- package/dist/probe-worker-pool.js.map +1 -1
- package/dist/profile-control.js.map +1 -1
- package/dist/prompt-file-ref.js.map +1 -1
- package/dist/provider-probe.js.map +1 -1
- package/dist/provider-secret-registry.js.map +1 -1
- package/dist/public-link-auto-open.d.ts +32 -0
- package/dist/public-link-auto-open.js +86 -0
- package/dist/public-link-auto-open.js.map +1 -0
- package/dist/public-link-owner.d.ts +10 -0
- package/dist/public-link-owner.js +36 -0
- package/dist/public-link-owner.js.map +1 -0
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.js.map +1 -1
- package/dist/public-web-gateway.js +4 -2
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +35 -1
- package/dist/public-web-link.js +142 -43
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +5 -0
- package/dist/quickstart.js +25 -16
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/resource-report.js.map +1 -1
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.js.map +1 -1
- package/dist/runtime-cpu-profile.js.map +1 -1
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/task-board-text.js +16 -11
- package/dist/scheduler/task-board-text.js.map +1 -1
- package/dist/scheduler/task-board.d.ts +50 -10
- package/dist/scheduler/task-board.js +138 -44
- package/dist/scheduler/task-board.js.map +1 -1
- package/dist/scheduler/types.d.ts +1 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-index.js.map +1 -1
- package/dist/secret-file.js.map +1 -1
- package/dist/secret-store.js.map +1 -1
- package/dist/service-installer.d.ts +7 -1
- package/dist/service-installer.js +13 -1
- package/dist/service-installer.js.map +1 -1
- package/dist/service-plan.d.ts +33 -4
- package/dist/service-plan.js +177 -8
- package/dist/service-plan.js.map +1 -1
- package/dist/session-oom.d.ts +21 -0
- package/dist/session-oom.js +139 -0
- package/dist/session-oom.js.map +1 -0
- package/dist/settings-api.js +6 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +71 -1
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +4 -0
- package/dist/settings-confirmation.js +2 -0
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-control.js.map +1 -1
- package/dist/settings-effect.js +6 -1
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +1 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +13 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/settings-transaction.js.map +1 -1
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-host.d.ts +5 -1
- package/dist/setup-host.js +8 -1
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +5 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +4 -0
- package/dist/spawn-gate.js +15 -5
- package/dist/spawn-gate.js.map +1 -1
- package/dist/startup-memory-deadline.d.ts +23 -0
- package/dist/startup-memory-deadline.js +55 -0
- package/dist/startup-memory-deadline.js.map +1 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/storm-window.js.map +1 -1
- package/dist/systemd-peer-bus.js.map +1 -1
- package/dist/target-queue-worker.js.map +1 -1
- package/dist/task-board-summary.d.ts +4 -4
- package/dist/task-board-summary.js +4 -4
- package/dist/task-board-summary.js.map +1 -1
- package/dist/task-board-tool.js +3 -2
- package/dist/task-board-tool.js.map +1 -1
- package/dist/task-board-waker.js +8 -4
- package/dist/task-board-waker.js.map +1 -1
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.js.map +1 -1
- package/dist/tmux-manager.d.ts +1 -0
- package/dist/tmux-manager.js +2 -1
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +1 -1
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-archiver.js.map +1 -1
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.js.map +1 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/lease.js +3 -2
- package/dist/tunnel/lease.js.map +1 -1
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/public-fetch.js.map +1 -1
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +26 -2
- package/dist/ui/chat-render.js +1 -15
- package/dist/ui/chat-store.js +171 -61
- package/dist/ui/chat-strings.js +7 -2
- package/dist/ui/chat-thread.js +48 -1
- package/dist/ui/fleet-canvas-layout.js +3 -0
- package/dist/ui/fleet-canvas.js +23 -20
- package/dist/ui/fleet-office-editor.js +149 -0
- package/dist/ui/fleet-office-model.js +358 -0
- package/dist/ui/fleet-office-pack.js +199 -0
- package/dist/ui/fleet-office-skin.js +474 -0
- package/dist/ui/fleet-office-store.js +49 -0
- package/dist/ui/fleet-office-zones.js +177 -0
- package/dist/ui/fleet-office.js +434 -0
- package/dist/ui/fleet-org.js +18 -5
- package/dist/ui/guest-refused.html +41 -0
- package/dist/ui/image-lightbox.js +9 -3
- package/dist/ui/panel-chat.js +14 -13
- package/dist/ui/panel-settings.js +30 -12
- package/dist/ui/settings-dialogs.js +15 -6
- package/dist/ui/settings-model.js +40 -3
- package/dist/ui/settings-strings.js +38 -0
- package/dist/ui/settings-web-authority.js +7 -2
- package/dist/ui/shared/agend-auth.js +2 -0
- package/dist/ui/shared/app-i18n.js +2 -2
- package/dist/ui/shared/app-prefs.js +2 -0
- package/dist/ui/shared/app-shell.js +12 -0
- package/dist/ui/shared/app-store.js +1 -0
- package/dist/ui/shared/app-stream.js +2 -1
- package/dist/ui/shared/app.css +132 -3
- package/dist/ui/shared/guest-refused.js +35 -0
- package/dist/ui/shared/header-tools.js +2 -2
- package/dist/ui/shared/instance-nav.js +25 -8
- package/dist/ui/shared/ui-dialog.js +2 -2
- package/dist/ui/shared/usage-dialog.js +152 -6
- package/dist/ui/shared/view-strings.js +20 -0
- package/dist/ui/shared/web-authorize.js +3 -1
- package/dist/update-check.js.map +1 -1
- package/dist/update-dispatch.js.map +1 -1
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.js.map +1 -1
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/providers.d.ts +8 -0
- package/dist/usage/providers.js +6 -2
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/usage/usage-api.js +2 -1
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.js +1 -1
- package/dist/usage-rollup.js.map +1 -1
- package/dist/user-systemd.js.map +1 -1
- package/dist/view-api.js +1 -1
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-ambient.js.map +1 -1
- package/dist/web-api.d.ts +15 -2
- package/dist/web-api.js +174 -25
- package/dist/web-api.js.map +1 -1
- package/dist/web-app-icon.js.map +1 -1
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-auth.js +5 -4
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.js.map +1 -1
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +41 -11
- package/dist/web-chat-history.js +93 -22
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-effect-bundle.d.ts +2 -2
- package/dist/web-effect-library.js.map +1 -1
- package/dist/web-effect-playback.js.map +1 -1
- package/dist/web-effect-profiles.d.ts +16 -16
- package/dist/web-effect-profiles.js +3 -2
- package/dist/web-effect-profiles.js.map +1 -1
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect.d.ts +7 -7
- package/dist/web-effect.js.map +1 -1
- package/dist/web-experimental.js.map +1 -1
- package/dist/web-guest-access.js +1 -1
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-guest-rooms.js.map +1 -1
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-icons.js.map +1 -1
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-images.js.map +1 -1
- package/dist/web-libavoid.js.map +1 -1
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.js.map +1 -1
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-office-store.d.ts +104 -0
- package/dist/web-office-store.js +236 -0
- package/dist/web-office-store.js.map +1 -0
- package/dist/web-owner-css-store.js.map +1 -1
- package/dist/web-owner-css.js.map +1 -1
- package/dist/web-png.js.map +1 -1
- package/dist/web-prefs.js +2 -0
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-profile.js.map +1 -1
- package/dist/web-reactions.d.ts +2 -1
- package/dist/web-request-context.d.ts +5 -0
- package/dist/web-request-context.js.map +1 -1
- package/dist/web-returning-device.js +1 -1
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-schedules.js.map +1 -1
- package/dist/web-send-dedupe.d.ts +36 -0
- package/dist/web-send-dedupe.js +69 -0
- package/dist/web-send-dedupe.js.map +1 -0
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.js +1 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +1 -0
- package/dist/web-settings-patch.js +6 -4
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.js.map +1 -1
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-terminal.js.map +1 -1
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-upload.d.ts +5 -1
- package/dist/web-upload.js +6 -4
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.js.map +1 -1
- package/dist/webhook-emitter.js.map +1 -1
- package/dist/windows-shortcuts.js +1 -1
- package/dist/windows-shortcuts.js.map +1 -1
- package/dist/workflow-templates/default.md +1 -1
- package/dist/ws-server.js.map +1 -1
- package/dist/yaml-shared-nodes.js.map +1 -1
- package/launcher/agend-install.cjs +281 -6
- package/launcher/private-home.cjs +43 -0
- package/package.json +3 -2
- package/templates/windows-shortcuts.ps1 +1 -1
|
@@ -112,6 +112,11 @@ export interface Card {
|
|
|
112
112
|
priority: CardPriority;
|
|
113
113
|
size: CardSize | null;
|
|
114
114
|
needsReview: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* #2434: opened on the board (createCards), not the `task` tool's own plain task. Before #2434 a main task's default
|
|
117
|
+
* "needs review" marked it; an agent's main task no longer waits for review, so the board says so on its own.
|
|
118
|
+
*/
|
|
119
|
+
onBoard: boolean;
|
|
115
120
|
/** uuids of the cards to finish first (what the fleet's `task` tool has always stored). */
|
|
116
121
|
deps: string[];
|
|
117
122
|
goal: string;
|
|
@@ -358,9 +363,28 @@ export interface SearchHit {
|
|
|
358
363
|
text: string;
|
|
359
364
|
} | null;
|
|
360
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* #2434: who confirms a card in review. The person confirms the cards they handed out (#2426's rule for a blocked card,
|
|
368
|
+
* for review too); an agent's card is the agents' own business: its instance dispatcher confirms it, and one nobody
|
|
369
|
+
* handed out its assignee (or the instance that opened it). A person may still confirm any card.
|
|
370
|
+
*/
|
|
371
|
+
export declare const personConfirms: (card: Pick<Card, "dispatcher">) => boolean;
|
|
372
|
+
/** Who that is, in words (an error, the card's text). */
|
|
373
|
+
export declare function confirmerOf(card: Pick<Card, "dispatcher" | "assignee">): string;
|
|
361
374
|
/** "m3", "M - 3" → "M-3"; null when it is not a card number. */
|
|
362
375
|
export declare function cardCode(raw: string): string | null;
|
|
363
|
-
/**
|
|
376
|
+
/**
|
|
377
|
+
* An instance dispatcher that is no longer in the fleet (deleted): `gone(name)`, asked of the fleet. Its cards have no one
|
|
378
|
+
* left to answer or confirm them but the person. Unknown (no `gone`): every dispatcher is there.
|
|
379
|
+
*/
|
|
380
|
+
export type GoneDispatcher = (name: string) => boolean;
|
|
381
|
+
/**
|
|
382
|
+
* #2425: whether a card waits for the person — in review needing their confirmation, or blocked on a question the person
|
|
383
|
+
* owns; both only when they handed it out (#2434: an agent's card in review is its dispatcher's to confirm), or when the
|
|
384
|
+
* instance that handed it out was deleted since (`gone`: nobody else is left to answer it). The one rule for
|
|
385
|
+
* waitingForPerson's query, Needs you and a button's route.
|
|
386
|
+
*/
|
|
387
|
+
export declare function waitsForPerson(card: Pick<Card, "status" | "needsReview" | "dispatcher">, gone?: GoneDispatcher): boolean;
|
|
364
388
|
export declare function requiresReview(card: Pick<Card, "needsReview">): boolean;
|
|
365
389
|
/**
|
|
366
390
|
* What a finished card still lacks for the person's confirmation: unchecked acceptance items, no result. A main task
|
|
@@ -478,7 +502,10 @@ export declare class TaskBoard {
|
|
|
478
502
|
cards: Card[];
|
|
479
503
|
total: number;
|
|
480
504
|
};
|
|
481
|
-
/**
|
|
505
|
+
/**
|
|
506
|
+
* On the board's terms: opened on it (#2434), in a project, a sub task, one with sub tasks, or one that waits for
|
|
507
|
+
* review (every main task opened on the board before #2434 did).
|
|
508
|
+
*/
|
|
482
509
|
isOnBoard(card: Card): boolean;
|
|
483
510
|
/**
|
|
484
511
|
* An instance's work, for `task mine`: what it is doing, what is blocked or waits for the person, what it can start
|
|
@@ -488,11 +515,24 @@ export declare class TaskBoard {
|
|
|
488
515
|
/** Who holds a live card (open, in progress, blocked, waiting for the person): the instances, and any other name. */
|
|
489
516
|
liveAssignees(): string[];
|
|
490
517
|
myWork(name: string): MyWork;
|
|
518
|
+
/** #2434: whether `actor` confirms `card` (finishes it from review): the person their cards, an agent's its dispatcher. */
|
|
519
|
+
confirms(card: Card, actor: Actor): boolean;
|
|
520
|
+
/** #2434: the cards an instance handed out that wait in review for its confirmation (its `task mine`). */
|
|
521
|
+
toConfirm(name: string): Card[];
|
|
491
522
|
/**
|
|
492
|
-
* What waits for the person (step 3: Needs you): cards in review that need their confirmation,
|
|
493
|
-
* oldest first, each with when it started waiting (its last
|
|
523
|
+
* What waits for the person (step 3: Needs you, and the daily summary): cards in review that need their confirmation,
|
|
524
|
+
* and blocked cards whose question is theirs to answer — oldest first, each with when it started waiting (its last
|
|
525
|
+
* move to that status).
|
|
526
|
+
*
|
|
527
|
+
* A blocked card asks the person only when the person handed it out (dispatcher kind "person"). One an instance handed
|
|
528
|
+
* out is that instance's to decide (step 2's wakes: its question goes there, not here). One with no dispatcher is an
|
|
529
|
+
* instance's own "I'm waiting" — every card the `task` tool kept before the board, an agent's card for itself, a
|
|
530
|
+
* reviewer's "waiting on the author" — and is no question to the person: 2.3.0-beta.24 listed 28 such cards, weeks
|
|
531
|
+
* old, as "stuck, asking you" (#2425). Nothing is changed on the cards; they stay on the board as they are. One an
|
|
532
|
+
* instance handed out that was deleted since (`gone`) has nobody else to answer or confirm it: it falls back to the
|
|
533
|
+
* person.
|
|
494
534
|
*/
|
|
495
|
-
waitingForPerson(): Array<{
|
|
535
|
+
waitingForPerson(gone?: GoneDispatcher): Array<{
|
|
496
536
|
card: Card;
|
|
497
537
|
since: string;
|
|
498
538
|
}>;
|
|
@@ -509,7 +549,7 @@ export declare class TaskBoard {
|
|
|
509
549
|
* Step 3, the daily summary (task-board-summary.ts): what waits for the person now, what got done and what was
|
|
510
550
|
* opened in [since, until) (not cancelled), and every live main task's project and assignee.
|
|
511
551
|
*/
|
|
512
|
-
summaryRead(since: string, until: string): {
|
|
552
|
+
summaryRead(since: string, until: string, gone?: GoneDispatcher): {
|
|
513
553
|
waiting: Card[];
|
|
514
554
|
done: Card[];
|
|
515
555
|
created: Card[];
|
|
@@ -559,8 +599,8 @@ export declare class TaskBoard {
|
|
|
559
599
|
*/
|
|
560
600
|
legacyClaim(actor: Actor, uuid: string, assignee: string): Card;
|
|
561
601
|
/**
|
|
562
|
-
* `task done`: from open or claimed. A card that needs
|
|
563
|
-
*
|
|
602
|
+
* `task done`: from open or claimed. A card that needs confirmation goes to review instead, so no instance finishes
|
|
603
|
+
* one it does not confirm alone; the one who confirms it finishes it, from review too (#2434). On the board, an instance finishes as it would there: its own card, with a result
|
|
564
604
|
* (an open one is claimed first, under the same rules).
|
|
565
605
|
*/
|
|
566
606
|
legacyComplete(actor: Actor, uuid: string, result?: string): Card;
|
|
@@ -615,8 +655,8 @@ export declare class TaskBoard {
|
|
|
615
655
|
private applyMove;
|
|
616
656
|
/**
|
|
617
657
|
* A main task with sub tasks follows them: open until something starts, in progress while they run, and when they
|
|
618
|
-
* are all done, review (or done, for one that
|
|
619
|
-
* to done. A blocked or cancelled main task is left alone, and so is one without sub tasks (it is moved by hand).
|
|
658
|
+
* are all done, review (or done, for one that needs no confirmation). Only whoever confirms it (#2434) moves it
|
|
659
|
+
* from review to done. A blocked or cancelled main task is left alone, and so is one without sub tasks (it is moved by hand).
|
|
620
660
|
*/
|
|
621
661
|
/** What a main task's sub tasks make its status (its own, when it is blocked, cancelled or has none). */
|
|
622
662
|
private derivedStatus;
|
|
@@ -97,6 +97,29 @@ function toDispatcher(input, actor) {
|
|
|
97
97
|
*/
|
|
98
98
|
const openedForItself = (c) => c.assignee !== null && c.createdBy === c.assignee && c.dispatcher === null;
|
|
99
99
|
const isDispatcher = (card, actor) => card.dispatcher?.kind === "instance" && !isPerson(actor) && card.dispatcher.name === actor.name;
|
|
100
|
+
/**
|
|
101
|
+
* #2434: who confirms a card in review. The person confirms the cards they handed out (#2426's rule for a blocked card,
|
|
102
|
+
* for review too); an agent's card is the agents' own business: its instance dispatcher confirms it, and one nobody
|
|
103
|
+
* handed out its assignee (or the instance that opened it). A person may still confirm any card.
|
|
104
|
+
*/
|
|
105
|
+
export const personConfirms = (card) => card.dispatcher?.kind === "person";
|
|
106
|
+
function confirms(card, actor) {
|
|
107
|
+
if (isPerson(actor))
|
|
108
|
+
return true;
|
|
109
|
+
if (personConfirms(card))
|
|
110
|
+
return false;
|
|
111
|
+
if (card.dispatcher?.kind === "instance")
|
|
112
|
+
return card.dispatcher.name === actor.name;
|
|
113
|
+
return card.assignee === actor.name || (card.assignee === null && card.createdBy === actor.name);
|
|
114
|
+
}
|
|
115
|
+
/** Who that is, in words (an error, the card's text). */
|
|
116
|
+
export function confirmerOf(card) {
|
|
117
|
+
if (card.dispatcher?.kind === "person")
|
|
118
|
+
return "the person";
|
|
119
|
+
if (card.dispatcher?.kind === "instance")
|
|
120
|
+
return card.dispatcher.name;
|
|
121
|
+
return card.assignee ?? "its assignee";
|
|
122
|
+
}
|
|
100
123
|
function normalizeAssignee(raw) {
|
|
101
124
|
const v = raw?.trim() ?? "";
|
|
102
125
|
if (v === "" || v.toLowerCase() === "none")
|
|
@@ -110,7 +133,16 @@ export function cardCode(raw) {
|
|
|
110
133
|
const m = CODE_RE.exec(raw);
|
|
111
134
|
return m ? `${m[1].toUpperCase()}-${Number(m[2])}` : null;
|
|
112
135
|
}
|
|
113
|
-
|
|
136
|
+
const orphaned = (card, gone) => !!gone && card.dispatcher?.kind === "instance" && gone(card.dispatcher.name);
|
|
137
|
+
/**
|
|
138
|
+
* #2425: whether a card waits for the person — in review needing their confirmation, or blocked on a question the person
|
|
139
|
+
* owns; both only when they handed it out (#2434: an agent's card in review is its dispatcher's to confirm), or when the
|
|
140
|
+
* instance that handed it out was deleted since (`gone`: nobody else is left to answer it). The one rule for
|
|
141
|
+
* waitingForPerson's query, Needs you and a button's route.
|
|
142
|
+
*/
|
|
143
|
+
export function waitsForPerson(card, gone) {
|
|
144
|
+
return (personConfirms(card) || orphaned(card, gone)) && ((card.status === "review" && card.needsReview) || card.status === "blocked");
|
|
145
|
+
}
|
|
114
146
|
export function requiresReview(card) {
|
|
115
147
|
return card.needsReview;
|
|
116
148
|
}
|
|
@@ -148,6 +180,7 @@ function toCard(r) {
|
|
|
148
180
|
priority: r.priority ?? "normal",
|
|
149
181
|
size: r.size ?? null,
|
|
150
182
|
needsReview: Number(r.needs_review) === 1,
|
|
183
|
+
onBoard: Number(r.on_board) === 1,
|
|
151
184
|
deps: parseJsonArray(r.depends_on, []).filter((d) => typeof d === "string"),
|
|
152
185
|
goal: r.description ?? "",
|
|
153
186
|
scope: r.scope ?? "",
|
|
@@ -250,6 +283,7 @@ export class TaskBoard {
|
|
|
250
283
|
add("seen_entry_id", "INTEGER NOT NULL DEFAULT 0");
|
|
251
284
|
add("dispatcher", "TEXT");
|
|
252
285
|
add("dispatcher_kind", "TEXT");
|
|
286
|
+
add("on_board", "INTEGER NOT NULL DEFAULT 0"); // #2434; a row before it: its needs_review says so
|
|
253
287
|
this.db.exec(`
|
|
254
288
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_code ON tasks(code);
|
|
255
289
|
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_id);
|
|
@@ -753,9 +787,12 @@ export class TaskBoard {
|
|
|
753
787
|
const rows = this.db.prepare(`SELECT * ${from} ORDER BY CASE kind WHEN 'main' THEN 0 ELSE 1 END, ${STATUS_ORDER}, ${PRIORITY_ORDER}, sort LIMIT ?`).all(...params, limit);
|
|
754
788
|
return { cards: rows.map(toCard), total: n };
|
|
755
789
|
}
|
|
756
|
-
/**
|
|
790
|
+
/**
|
|
791
|
+
* On the board's terms: opened on it (#2434), in a project, a sub task, one with sub tasks, or one that waits for
|
|
792
|
+
* review (every main task opened on the board before #2434 did).
|
|
793
|
+
*/
|
|
757
794
|
isOnBoard(card) {
|
|
758
|
-
return card.projectId !== null || card.kind === "sub" || card.needsReview || this.activeSubs(card.uuid).length > 0;
|
|
795
|
+
return card.onBoard || card.projectId !== null || card.kind === "sub" || card.needsReview || this.activeSubs(card.uuid).length > 0;
|
|
759
796
|
}
|
|
760
797
|
/**
|
|
761
798
|
* An instance's work, for `task mine`: what it is doing, what is blocked or waits for the person, what it can start
|
|
@@ -800,16 +837,39 @@ export class TaskBoard {
|
|
|
800
837
|
mains: coordinating.map((card) => ({ card, progress: this.progress(card) })),
|
|
801
838
|
};
|
|
802
839
|
}
|
|
840
|
+
/** #2434: whether `actor` confirms `card` (finishes it from review): the person their cards, an agent's its dispatcher. */
|
|
841
|
+
confirms(card, actor) { return confirms(card, actor); }
|
|
842
|
+
/** #2434: the cards an instance handed out that wait in review for its confirmation (its `task mine`). */
|
|
843
|
+
toConfirm(name) {
|
|
844
|
+
return this.db.prepare("SELECT * FROM tasks WHERE status = 'review' AND needs_review = 1 AND (dispatcher_kind IS NULL OR dispatcher_kind != 'person') AND dispatcher = ? AND (assignee IS NULL OR assignee != ?) ORDER BY updated_at")
|
|
845
|
+
.all(name, name).map(toCard);
|
|
846
|
+
}
|
|
803
847
|
/**
|
|
804
|
-
* What waits for the person (step 3: Needs you): cards in review that need their confirmation,
|
|
805
|
-
* oldest first, each with when it started waiting (its last
|
|
848
|
+
* What waits for the person (step 3: Needs you, and the daily summary): cards in review that need their confirmation,
|
|
849
|
+
* and blocked cards whose question is theirs to answer — oldest first, each with when it started waiting (its last
|
|
850
|
+
* move to that status).
|
|
851
|
+
*
|
|
852
|
+
* A blocked card asks the person only when the person handed it out (dispatcher kind "person"). One an instance handed
|
|
853
|
+
* out is that instance's to decide (step 2's wakes: its question goes there, not here). One with no dispatcher is an
|
|
854
|
+
* instance's own "I'm waiting" — every card the `task` tool kept before the board, an agent's card for itself, a
|
|
855
|
+
* reviewer's "waiting on the author" — and is no question to the person: 2.3.0-beta.24 listed 28 such cards, weeks
|
|
856
|
+
* old, as "stuck, asking you" (#2425). Nothing is changed on the cards; they stay on the board as they are. One an
|
|
857
|
+
* instance handed out that was deleted since (`gone`) has nobody else to answer or confirm it: it falls back to the
|
|
858
|
+
* person.
|
|
806
859
|
*/
|
|
807
|
-
waitingForPerson() {
|
|
808
|
-
const
|
|
860
|
+
waitingForPerson(gone) {
|
|
861
|
+
const waiting = "((status = 'review' AND needs_review = 1) OR status = 'blocked')";
|
|
862
|
+
const rows = [
|
|
863
|
+
...this.db.prepare(`SELECT * FROM tasks WHERE dispatcher_kind = 'person' AND ${waiting}`).all().map(toCard),
|
|
864
|
+
...(gone ? this.db.prepare(`SELECT * FROM tasks WHERE dispatcher IS NOT NULL AND (dispatcher_kind IS NULL OR dispatcher_kind != 'person') AND ${waiting}`).all()
|
|
865
|
+
.map(toCard).filter((card) => orphaned(card, gone)) : []),
|
|
866
|
+
];
|
|
809
867
|
const moved = this.db.prepare("SELECT at FROM task_events WHERE task_id = ? AND type = 'moved' AND json_extract(data, '$.to') = ? ORDER BY id DESC LIMIT 1");
|
|
810
868
|
return rows.map((card) => {
|
|
811
869
|
const at = moved.get(card.uuid, card.status)?.at;
|
|
812
|
-
|
|
870
|
+
// Never updatedAt (#2425): a card edited every minute (a note, a heartbeat) would get a new `since` — and so a new
|
|
871
|
+
// Needs-you item id, posted again at the bottom as if it were new, once a minute.
|
|
872
|
+
return { card, since: at ?? card.submittedAt ?? card.createdAt };
|
|
813
873
|
}).sort((a, b) => a.since.localeCompare(b.since));
|
|
814
874
|
}
|
|
815
875
|
/** Cards by their numbers, in one read (the ones that exist; #2341 review: the cards a summary line named). */
|
|
@@ -897,10 +957,10 @@ export class TaskBoard {
|
|
|
897
957
|
* Step 3, the daily summary (task-board-summary.ts): what waits for the person now, what got done and what was
|
|
898
958
|
* opened in [since, until) (not cancelled), and every live main task's project and assignee.
|
|
899
959
|
*/
|
|
900
|
-
summaryRead(since, until) {
|
|
960
|
+
summaryRead(since, until, gone) {
|
|
901
961
|
const between = (sql) => this.db.prepare(sql).all(since, until).map(toCard);
|
|
902
962
|
return {
|
|
903
|
-
waiting: this.waitingForPerson().map((w) => w.card),
|
|
963
|
+
waiting: this.waitingForPerson(gone).map((w) => w.card),
|
|
904
964
|
done: between("SELECT * FROM tasks WHERE status = 'done' AND done_at >= ? AND done_at < ? ORDER BY sort"),
|
|
905
965
|
created: between("SELECT * FROM tasks WHERE status != 'cancelled' AND created_at >= ? AND created_at < ? ORDER BY sort"),
|
|
906
966
|
mains: this.db.prepare("SELECT project_id, assignee FROM tasks WHERE kind = 'main' AND status != 'cancelled'").all()
|
|
@@ -942,13 +1002,14 @@ export class TaskBoard {
|
|
|
942
1002
|
const acceptance = checkAcceptance(spec.acceptance ?? []);
|
|
943
1003
|
if (acceptance.length > CARD_LIMITS.acceptanceItems)
|
|
944
1004
|
throw new TaskBoardError("too_long", `at most ${CARD_LIMITS.acceptanceItems} acceptance items`, "acceptance_max", [CARD_LIMITS.acceptanceItems]);
|
|
945
|
-
const needsReview = spec.needsReview ?? kind === "main";
|
|
946
|
-
if (!needsReview && kind === "main" && !isPerson(actor))
|
|
947
|
-
throw new TaskBoardError("forbidden", "only a person can open a main task that skips their confirmation");
|
|
948
1005
|
const now = this.nowIso();
|
|
949
1006
|
const assignee = spec.assignee !== undefined ? normalizeAssignee(spec.assignee) : isPerson(actor) ? null : actor.name;
|
|
950
1007
|
const opener = isPerson(actor) ? { kind: "person", name: actor.name }
|
|
951
1008
|
: actor.kind === "instance" && assignee && assignee !== actor.name ? { kind: "instance", name: actor.name } : null;
|
|
1009
|
+
const dispatcher = spec.dispatcher !== undefined ? toDispatcher(spec.dispatcher, actor) : (parent?.dispatcher ?? opener);
|
|
1010
|
+
// #2434: a main task waits for the person's confirmation when the person handed it out; an agent's needs none
|
|
1011
|
+
// unless it asks for one (its dispatcher then confirms it).
|
|
1012
|
+
const needsReview = spec.needsReview ?? (kind === "main" && dispatcher?.kind === "person");
|
|
952
1013
|
const card = {
|
|
953
1014
|
uuid: randomUUID(),
|
|
954
1015
|
code: this.nextCode(kind === "main" ? "M" : "S"),
|
|
@@ -958,10 +1019,11 @@ export class TaskBoard {
|
|
|
958
1019
|
title,
|
|
959
1020
|
status: "open",
|
|
960
1021
|
assignee,
|
|
961
|
-
dispatcher
|
|
1022
|
+
dispatcher,
|
|
962
1023
|
priority: spec.priority ?? "normal",
|
|
963
1024
|
size: spec.size ?? null,
|
|
964
1025
|
needsReview,
|
|
1026
|
+
onBoard: true,
|
|
965
1027
|
deps: this.checkDeps({ uuid: null, kind, parent: parent?.uuid ?? null }, (spec.dependsOn ?? []).map((d) => this.resolveRef(d, created))),
|
|
966
1028
|
goal: checkText("the goal", spec.goal ?? "", CARD_LIMITS.goal),
|
|
967
1029
|
scope: checkText("the scope", spec.scope ?? "", CARD_LIMITS.scope),
|
|
@@ -1048,11 +1110,24 @@ export class TaskBoard {
|
|
|
1048
1110
|
set("size", patch.size);
|
|
1049
1111
|
if (patch.priority !== undefined)
|
|
1050
1112
|
set("priority", patch.priority);
|
|
1051
|
-
if (patch.dispatcher !== undefined)
|
|
1052
|
-
|
|
1113
|
+
if (patch.dispatcher !== undefined) {
|
|
1114
|
+
const next = toDispatcher(patch.dispatcher, actor);
|
|
1115
|
+
// #2434: the person's card stays theirs — an instance re-dispatching it would take it out of their confirmation.
|
|
1116
|
+
const moved = JSON.stringify(next) !== JSON.stringify(card.dispatcher);
|
|
1117
|
+
if (ai && personConfirms(card) && moved) {
|
|
1118
|
+
throw new TaskBoardError("forbidden", `${card.code} was handed out by the person; only they hand it to someone else`);
|
|
1119
|
+
}
|
|
1120
|
+
// #2436 review: nor an agent's card that waits for its dispatcher's confirmation — dropping or replacing the
|
|
1121
|
+
// dispatcher would let its assignee confirm it itself. Only that dispatcher (or a person) hands it on.
|
|
1122
|
+
if (ai && moved && card.needsReview && card.dispatcher?.kind === "instance" && card.dispatcher.name !== actor.name) {
|
|
1123
|
+
throw new TaskBoardError("forbidden", `${card.code} waits for ${card.dispatcher.name}'s confirmation; only they hand it to someone else`);
|
|
1124
|
+
}
|
|
1125
|
+
set("dispatcher", next, "dispatcher", (d) => d?.name ?? null);
|
|
1126
|
+
}
|
|
1053
1127
|
if (patch.needsReview !== undefined) {
|
|
1054
|
-
if (ai && card.needsReview && !patch.needsReview)
|
|
1055
|
-
throw new TaskBoardError("forbidden", "only a person can clear \"needs review\"");
|
|
1128
|
+
if (ai && card.needsReview && !patch.needsReview && !confirms(card, actor)) {
|
|
1129
|
+
throw new TaskBoardError("forbidden", personConfirms(card) ? "only a person can clear \"needs review\"" : `only ${confirmerOf(card)} can clear "needs review" on ${card.code}`);
|
|
1130
|
+
}
|
|
1056
1131
|
set("needsReview", patch.needsReview);
|
|
1057
1132
|
}
|
|
1058
1133
|
if (patch.dependsOn !== undefined) {
|
|
@@ -1220,7 +1295,7 @@ export class TaskBoard {
|
|
|
1220
1295
|
const now = this.nowIso();
|
|
1221
1296
|
const card = {
|
|
1222
1297
|
uuid: randomUUID(), code: this.nextCode("M"), kind: "main", projectId: null, parent: null, title: params.title, status: "open",
|
|
1223
|
-
assignee: params.assignee ?? null, priority: params.priority ?? "normal", size: null, needsReview: false,
|
|
1298
|
+
assignee: params.assignee ?? null, priority: params.priority ?? "normal", size: null, needsReview: false, onBoard: false,
|
|
1224
1299
|
// Opened for another instance: the opener handed it out (its blocked question goes to it).
|
|
1225
1300
|
dispatcher: actor.kind === "instance" && params.assignee && params.assignee !== actor.name ? { kind: "instance", name: actor.name } : null,
|
|
1226
1301
|
deps: this.checkDeps({ uuid: null, kind: "main", parent: null }, params.depends_on ?? []),
|
|
@@ -1273,8 +1348,8 @@ export class TaskBoard {
|
|
|
1273
1348
|
});
|
|
1274
1349
|
}
|
|
1275
1350
|
/**
|
|
1276
|
-
* `task done`: from open or claimed. A card that needs
|
|
1277
|
-
*
|
|
1351
|
+
* `task done`: from open or claimed. A card that needs confirmation goes to review instead, so no instance finishes
|
|
1352
|
+
* one it does not confirm alone; the one who confirms it finishes it, from review too (#2434). On the board, an instance finishes as it would there: its own card, with a result
|
|
1278
1353
|
* (an open one is claimed first, under the same rules).
|
|
1279
1354
|
*/
|
|
1280
1355
|
legacyComplete(actor, uuid, result) {
|
|
@@ -1282,8 +1357,10 @@ export class TaskBoard {
|
|
|
1282
1357
|
const card = this.byUuid(uuid);
|
|
1283
1358
|
if (!card)
|
|
1284
1359
|
throw new Error(`Task "${uuid}" not found`);
|
|
1285
|
-
|
|
1286
|
-
|
|
1360
|
+
// #2434: a card in review is finished by whoever confirms it (an agent's card: its dispatcher).
|
|
1361
|
+
const confirming = card.status === "review" && confirms(card, actor);
|
|
1362
|
+
if (card.status !== "claimed" && card.status !== "open" && !confirming) {
|
|
1363
|
+
throw new Error(`Task "${uuid}" is ${card.status}, cannot complete (must be open or claimed${card.status === "review" ? `; it waits for ${confirmerOf(card)}'s confirmation` : ""})`);
|
|
1287
1364
|
}
|
|
1288
1365
|
const open = this.children(card.uuid).filter((k) => !isFinished(k));
|
|
1289
1366
|
if (open.length)
|
|
@@ -1292,7 +1369,7 @@ export class TaskBoard {
|
|
|
1292
1369
|
this.event(actor, card, "updated", { changes: { result: { from: card.result, to: result } } });
|
|
1293
1370
|
card.result = result;
|
|
1294
1371
|
}
|
|
1295
|
-
const to = requiresReview(card) && !
|
|
1372
|
+
const to = requiresReview(card) && !confirms(card, actor) ? "review" : "done";
|
|
1296
1373
|
if (this.heldToBoardRules(card, actor)) {
|
|
1297
1374
|
if (card.status === "open") {
|
|
1298
1375
|
this.checkManualMove(card, actor, "claimed", "", { finishing: true });
|
|
@@ -1345,9 +1422,9 @@ export class TaskBoard {
|
|
|
1345
1422
|
if (derived)
|
|
1346
1423
|
this.checkDerivedMove(card, actor, to, "");
|
|
1347
1424
|
else {
|
|
1348
|
-
if (card.status === "review" && to === "done")
|
|
1349
|
-
throw new Error(`Task "${card.code}" is waiting for
|
|
1350
|
-
if (to === "done" && requiresReview(card))
|
|
1425
|
+
if (card.status === "review" && to === "done" && !confirms(card, actor))
|
|
1426
|
+
throw new Error(`Task "${card.code}" is waiting for ${confirmerOf(card)}'s confirmation`);
|
|
1427
|
+
if (to === "done" && card.status !== "review" && requiresReview(card) && !confirms(card, actor))
|
|
1351
1428
|
to = "review";
|
|
1352
1429
|
if (held && to !== card.status)
|
|
1353
1430
|
this.checkManualMove(card, actor, to, "");
|
|
@@ -1414,7 +1491,13 @@ export class TaskBoard {
|
|
|
1414
1491
|
this.checkOneAtATime(card, actor);
|
|
1415
1492
|
}
|
|
1416
1493
|
else if (from === "review") {
|
|
1417
|
-
if (ai) {
|
|
1494
|
+
if (ai && !own && confirms(card, actor)) {
|
|
1495
|
+
// #2434: an agent's card sent back by the instance that confirms it, as the person sends theirs back.
|
|
1496
|
+
if (!reason)
|
|
1497
|
+
throw new TaskBoardError("invalid", "sending work back needs a reason", "sendback_reason");
|
|
1498
|
+
this.entry(card, "reject", actor, reason);
|
|
1499
|
+
}
|
|
1500
|
+
else if (ai) {
|
|
1418
1501
|
if (!own)
|
|
1419
1502
|
throw notOwner();
|
|
1420
1503
|
if (startsWork)
|
|
@@ -1458,14 +1541,24 @@ export class TaskBoard {
|
|
|
1458
1541
|
}
|
|
1459
1542
|
case "done": {
|
|
1460
1543
|
if (ai) {
|
|
1461
|
-
if (from === "review")
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1544
|
+
if (from === "review") {
|
|
1545
|
+
if (!confirms(card, actor)) {
|
|
1546
|
+
throw new TaskBoardError("forbidden", personConfirms(card) ? `${card.code} is waiting for the person's confirmation: only they finish it`
|
|
1547
|
+
: `${card.code} is waiting for ${confirmerOf(card)}'s confirmation: only they finish it`);
|
|
1548
|
+
}
|
|
1549
|
+
if (reason)
|
|
1550
|
+
this.entry(card, "approve", actor, reason);
|
|
1551
|
+
}
|
|
1552
|
+
else {
|
|
1553
|
+
if (from !== "claimed")
|
|
1554
|
+
throw new TaskBoardError("invalid", `only a card in progress can be done (${card.code} is ${from})`);
|
|
1555
|
+
if (!own)
|
|
1556
|
+
throw notOwner();
|
|
1557
|
+
if (requiresReview(card) && !confirms(card, actor)) {
|
|
1558
|
+
throw new TaskBoardError("needs_review", personConfirms(card) ? `${card.code} needs the person's confirmation; move it to review`
|
|
1559
|
+
: `${card.code} needs ${confirmerOf(card)}'s confirmation; move it to review`);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1469
1562
|
}
|
|
1470
1563
|
else if (from === "review" && reason) {
|
|
1471
1564
|
this.entry(card, "approve", actor, reason);
|
|
@@ -1671,8 +1764,8 @@ export class TaskBoard {
|
|
|
1671
1764
|
}
|
|
1672
1765
|
/**
|
|
1673
1766
|
* A main task with sub tasks follows them: open until something starts, in progress while they run, and when they
|
|
1674
|
-
* are all done, review (or done, for one that
|
|
1675
|
-
* to done. A blocked or cancelled main task is left alone, and so is one without sub tasks (it is moved by hand).
|
|
1767
|
+
* are all done, review (or done, for one that needs no confirmation). Only whoever confirms it (#2434) moves it
|
|
1768
|
+
* from review to done. A blocked or cancelled main task is left alone, and so is one without sub tasks (it is moved by hand).
|
|
1676
1769
|
*/
|
|
1677
1770
|
/** What a main task's sub tasks make its status (its own, when it is blocked, cancelled or has none). */
|
|
1678
1771
|
derivedStatus(main) {
|
|
@@ -1705,7 +1798,7 @@ export class TaskBoard {
|
|
|
1705
1798
|
this.save(main);
|
|
1706
1799
|
this.event(actor, main, "moved", { from, to: next, auto: true });
|
|
1707
1800
|
if (next === "review")
|
|
1708
|
-
this.say("review_waiting", [main.code, main.title], `${main.code} "${main.title}": every sub task is done; it is waiting for
|
|
1801
|
+
this.say("review_waiting", [main.code, main.title], `${main.code} "${main.title}": every sub task is done; it is waiting for ${confirmerOf(main)}'s confirmation`);
|
|
1709
1802
|
else if (from === "done" || from === "review")
|
|
1710
1803
|
this.say("back_to", [main.code, next], `${main.code} has unfinished sub tasks again; it is back to ${next}`);
|
|
1711
1804
|
if (next === "done")
|
|
@@ -1824,7 +1917,8 @@ export class TaskBoard {
|
|
|
1824
1917
|
add(card, card.assignee, "cancelled", e.actor, why);
|
|
1825
1918
|
continue;
|
|
1826
1919
|
}
|
|
1827
|
-
//
|
|
1920
|
+
// An agent's card waits for its instance dispatcher to confirm it (#2434: its own to confirm, nobody to ask). A
|
|
1921
|
+
// person's card has no instance dispatcher, so no notice: the person has it in Needs you.
|
|
1828
1922
|
if (d.to === "review" && !isPerson(e.actor) && requiresReview(card))
|
|
1829
1923
|
add(card, dispatcherOf(), "to_confirm", e.actor);
|
|
1830
1924
|
if (d.auto) {
|
|
@@ -1836,9 +1930,9 @@ export class TaskBoard {
|
|
|
1836
1930
|
add(card, card.assignee, "start", e.actor);
|
|
1837
1931
|
else if (d.from === "blocked" && d.to === "claimed")
|
|
1838
1932
|
add(card, card.assignee, "answered", e.actor, comments.get(card.uuid));
|
|
1839
|
-
else if (d.from === "review" && (d.to === "claimed" || d.to === "open")
|
|
1933
|
+
else if (d.from === "review" && (d.to === "claimed" || d.to === "open"))
|
|
1840
1934
|
add(card, card.assignee, "sent_back", e.actor, d.reason);
|
|
1841
|
-
else if (d.from === "review" && d.to === "done"
|
|
1935
|
+
else if (d.from === "review" && d.to === "done") {
|
|
1842
1936
|
add(card, card.assignee, "approved", e.actor, d.reason);
|
|
1843
1937
|
add(card, dispatcherOf(), "approved", e.actor, d.reason);
|
|
1844
1938
|
}
|
|
@@ -2071,8 +2165,8 @@ export class TaskBoard {
|
|
|
2071
2165
|
}
|
|
2072
2166
|
insert(card) {
|
|
2073
2167
|
this.db.prepare(`INSERT INTO tasks (id, code, kind, project_id, parent_id, title, description, status, priority, assignee, dispatcher, dispatcher_kind, created_by, depends_on, result,
|
|
2074
|
-
scope, acceptance, context, state, blocked_reason, size, needs_review, version, sort, created_at, updated_at, started_at, submitted_at, done_at, seen_entry_id)
|
|
2075
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(card.uuid, card.code, card.kind, card.projectId, card.parent, card.title, card.goal === "" ? null : card.goal, card.status, card.priority, card.assignee, card.dispatcher?.name ?? null, card.dispatcher?.kind ?? null, card.createdBy, card.deps.length ? JSON.stringify(card.deps) : null, card.result === "" ? null : card.result, card.scope, JSON.stringify(card.acceptance), card.context, card.state, card.blockedReason, card.size, card.needsReview ? 1 : 0, card.version, card.sort, card.createdAt, card.updatedAt, card.startedAt, card.submittedAt, card.doneAt, card.seenEntryId);
|
|
2168
|
+
scope, acceptance, context, state, blocked_reason, size, needs_review, version, sort, created_at, updated_at, started_at, submitted_at, done_at, seen_entry_id, on_board)
|
|
2169
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(card.uuid, card.code, card.kind, card.projectId, card.parent, card.title, card.goal === "" ? null : card.goal, card.status, card.priority, card.assignee, card.dispatcher?.name ?? null, card.dispatcher?.kind ?? null, card.createdBy, card.deps.length ? JSON.stringify(card.deps) : null, card.result === "" ? null : card.result, card.scope, JSON.stringify(card.acceptance), card.context, card.state, card.blockedReason, card.size, card.needsReview ? 1 : 0, card.version, card.sort, card.createdAt, card.updatedAt, card.startedAt, card.submittedAt, card.doneAt, card.seenEntryId, card.onBoard ? 1 : 0);
|
|
2076
2170
|
}
|
|
2077
2171
|
/** Empty text is stored as NULL in the columns the `task` tool has always had (description, result, depends_on). */
|
|
2078
2172
|
save(card) {
|