@skrr-ai/cli 0.1.110 → 0.1.111
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/bin/run.js +15 -1
- package/dist/base-command.d.ts +31 -3
- package/dist/base-command.js +136 -22
- package/dist/commands/actions/list.js +2 -1
- package/dist/commands/agenda/trigger/create.js +1 -1
- package/dist/commands/agenda/trigger/list.js +2 -1
- package/dist/commands/agent-groups/list.js +2 -1
- package/dist/commands/agents/actions/list.js +2 -1
- package/dist/commands/agents/always-on/status.js +5 -0
- package/dist/commands/agents/chat.js +4 -1
- package/dist/commands/agents/duplicate.js +4 -0
- package/dist/commands/agents/eval/list.js +2 -1
- package/dist/commands/agents/files/list.js +2 -1
- package/dist/commands/agents/folders/list.js +2 -1
- package/dist/commands/agents/goals/list.js +2 -1
- package/dist/commands/agents/intuitions/list.js +8 -5
- package/dist/commands/agents/list.d.ts +12 -0
- package/dist/commands/agents/list.js +45 -8
- package/dist/commands/agents/releases/known-issues/list.js +2 -1
- package/dist/commands/agents/releases/list.js +5 -1
- package/dist/commands/agents/releases/trusted-publishers/list.js +2 -1
- package/dist/commands/agents/roles/list.js +2 -1
- package/dist/commands/agents/skills/list.js +2 -1
- package/dist/commands/agents/todos/list.js +2 -1
- package/dist/commands/agents/triggers/list.js +2 -1
- package/dist/commands/api-keys/list.js +2 -1
- package/dist/commands/apps/channel.d.ts +20 -0
- package/dist/commands/apps/channel.js +64 -0
- package/dist/commands/apps/check-draft.d.ts +12 -0
- package/dist/commands/apps/check-draft.js +41 -0
- package/dist/commands/apps/check.d.ts +42 -0
- package/dist/commands/apps/check.js +91 -0
- package/dist/commands/apps/create.d.ts +15 -0
- package/dist/commands/apps/create.js +59 -0
- package/dist/commands/apps/data/put.d.ts +18 -0
- package/dist/commands/apps/data/put.js +72 -0
- package/dist/commands/apps/data/query.d.ts +20 -0
- package/dist/commands/apps/data/query.js +88 -0
- package/dist/commands/apps/disclosure.d.ts +16 -0
- package/dist/commands/apps/disclosure.js +71 -0
- package/dist/commands/apps/file/cat.d.ts +15 -0
- package/dist/commands/apps/file/cat.js +50 -0
- package/dist/commands/apps/file/ls.d.ts +13 -0
- package/dist/commands/apps/file/ls.js +47 -0
- package/dist/commands/apps/file/mv.d.ts +15 -0
- package/dist/commands/apps/file/mv.js +49 -0
- package/dist/commands/apps/file/rm.d.ts +15 -0
- package/dist/commands/apps/file/rm.js +53 -0
- package/dist/commands/apps/file/write.d.ts +17 -0
- package/dist/commands/apps/file/write.js +81 -0
- package/dist/commands/apps/install.d.ts +19 -0
- package/dist/commands/apps/install.js +136 -0
- package/dist/commands/apps/installations/list.d.ts +11 -0
- package/dist/commands/apps/installations/list.js +49 -0
- package/dist/commands/apps/installations/show.d.ts +12 -0
- package/dist/commands/apps/installations/show.js +61 -0
- package/dist/commands/apps/layout/set.d.ts +11 -0
- package/dist/commands/apps/layout/set.js +125 -0
- package/dist/commands/apps/layout/show.d.ts +9 -0
- package/dist/commands/apps/layout/show.js +33 -0
- package/dist/commands/apps/list.d.ts +10 -0
- package/dist/commands/apps/list.js +45 -0
- package/dist/commands/apps/logs.d.ts +13 -0
- package/dist/commands/apps/logs.js +55 -0
- package/dist/commands/apps/preview.d.ts +12 -0
- package/dist/commands/apps/preview.js +39 -0
- package/dist/commands/apps/publish/propose.d.ts +14 -0
- package/dist/commands/apps/publish/propose.js +45 -0
- package/dist/commands/apps/pull.d.ts +14 -0
- package/dist/commands/apps/pull.js +56 -0
- package/dist/commands/apps/push.d.ts +15 -0
- package/dist/commands/apps/push.js +75 -0
- package/dist/commands/apps/reconsent.d.ts +13 -0
- package/dist/commands/apps/reconsent.js +67 -0
- package/dist/commands/apps/report.d.ts +20 -0
- package/dist/commands/apps/report.js +63 -0
- package/dist/commands/apps/resume.d.ts +12 -0
- package/dist/commands/apps/resume.js +36 -0
- package/dist/commands/apps/settings/set.d.ts +13 -0
- package/dist/commands/apps/settings/set.js +54 -0
- package/dist/commands/apps/settings/show.d.ts +11 -0
- package/dist/commands/apps/settings/show.js +31 -0
- package/dist/commands/apps/show.d.ts +12 -0
- package/dist/commands/apps/show.js +49 -0
- package/dist/commands/apps/suspend.d.ts +12 -0
- package/dist/commands/apps/suspend.js +35 -0
- package/dist/commands/apps/uninstall.d.ts +13 -0
- package/dist/commands/apps/uninstall.js +43 -0
- package/dist/commands/apps/upgrade.d.ts +14 -0
- package/dist/commands/apps/upgrade.js +49 -0
- package/dist/commands/apps/version/create.d.ts +14 -0
- package/dist/commands/apps/version/create.js +53 -0
- package/dist/commands/apps/version/show.d.ts +12 -0
- package/dist/commands/apps/version/show.js +39 -0
- package/dist/commands/apps/versions.d.ts +12 -0
- package/dist/commands/apps/versions.js +40 -0
- package/dist/commands/apps/webhooks/list.d.ts +12 -0
- package/dist/commands/apps/webhooks/list.js +47 -0
- package/dist/commands/characters/list.js +2 -1
- package/dist/commands/chats/files/list.js +2 -1
- package/dist/commands/chats/folders/list.js +2 -1
- package/dist/commands/chats/list.js +2 -1
- package/dist/commands/chats/spaces/list.js +2 -1
- package/dist/commands/chats/widgets/list.js +2 -1
- package/dist/commands/code/jobs/list.js +4 -1
- package/dist/commands/commerce/incidents/list.js +2 -1
- package/dist/commands/commitments/accounting.js +3 -0
- package/dist/commands/commitments/action-proposals.d.ts +8 -0
- package/dist/commands/commitments/action-proposals.js +17 -2
- package/dist/commands/commitments/cost.d.ts +11 -0
- package/dist/commands/commitments/cost.js +25 -0
- package/dist/commands/commitments/create.js +6 -1
- package/dist/commands/commitments/endpoints/list.js +2 -1
- package/dist/commands/commitments/links/list.js +2 -1
- package/dist/commands/commitments/list.js +2 -1
- package/dist/commands/commitments/liveness.d.ts +30 -0
- package/dist/commands/commitments/liveness.js +22 -5
- package/dist/commands/commitments/pack/list.js +2 -1
- package/dist/commands/commitments/preflight.js +6 -2
- package/dist/commands/commitments/update.js +10 -1
- package/dist/commands/compass/list.js +2 -1
- package/dist/commands/context.js +7 -1
- package/dist/commands/convos/list.js +3 -2
- package/dist/commands/dm/list.js +2 -1
- package/dist/commands/dm/work.d.ts +19 -0
- package/dist/commands/dm/work.js +54 -0
- package/dist/commands/feeds/list.js +2 -1
- package/dist/commands/followups/list.js +2 -1
- package/dist/commands/followups/plans/cancel.d.ts +13 -0
- package/dist/commands/followups/plans/cancel.js +26 -0
- package/dist/commands/followups/plans/create.d.ts +11 -0
- package/dist/commands/followups/plans/create.js +35 -0
- package/dist/commands/followups/plans/list.d.ts +13 -0
- package/dist/commands/followups/plans/list.js +50 -0
- package/dist/commands/followups/plans/observability.d.ts +11 -0
- package/dist/commands/followups/plans/observability.js +46 -0
- package/dist/commands/followups/plans/revise.d.ts +13 -0
- package/dist/commands/followups/plans/revise.js +35 -0
- package/dist/commands/followups/plans/show.d.ts +11 -0
- package/dist/commands/followups/plans/show.js +32 -0
- package/dist/commands/goals/key-results/list.js +2 -1
- package/dist/commands/goals/labels/list.js +3 -2
- package/dist/commands/goals/list.js +3 -2
- package/dist/commands/grants/list.js +2 -1
- package/dist/commands/harnesses/grants/list.js +2 -1
- package/dist/commands/harnesses/leases/list.js +2 -1
- package/dist/commands/harnesses/list.js +10 -1
- package/dist/commands/ingress/list.js +2 -1
- package/dist/commands/initiatives/list.js +2 -1
- package/dist/commands/instruction-blocks/list.js +2 -1
- package/dist/commands/instructions/list.js +2 -1
- package/dist/commands/integrations/connections/list.js +2 -1
- package/dist/commands/integrations/tools/list.js +2 -1
- package/dist/commands/labels/list.js +3 -2
- package/dist/commands/learning/adapters.d.ts +16 -0
- package/dist/commands/learning/adapters.js +44 -0
- package/dist/commands/machines/dedicated/list.js +2 -1
- package/dist/commands/machines/hosted/list.js +2 -1
- package/dist/commands/machines/list.js +2 -1
- package/dist/commands/machines/show.js +5 -2
- package/dist/commands/measures/list.js +2 -1
- package/dist/commands/memory/list.js +2 -1
- package/dist/commands/memory/proposals/list.js +2 -1
- package/dist/commands/memory/stores/list.js +2 -1
- package/dist/commands/memory/topics/list.js +2 -1
- package/dist/commands/memory/versions/list.js +2 -1
- package/dist/commands/messages/list.js +2 -1
- package/dist/commands/northstars/intents/list.js +2 -1
- package/dist/commands/northstars/list.js +2 -1
- package/dist/commands/northstars/recommendations/list.js +2 -1
- package/dist/commands/outbox/list.js +2 -1
- package/dist/commands/profiles/list.js +2 -1
- package/dist/commands/projects/docs/list.js +8 -1
- package/dist/commands/projects/updates/list.js +2 -1
- package/dist/commands/proposals/list.js +2 -1
- package/dist/commands/requests/comments/list.js +2 -1
- package/dist/commands/requests/list.js +2 -1
- package/dist/commands/shares/list.js +2 -1
- package/dist/commands/shortcuts/list.js +2 -1
- package/dist/commands/signals/monitors/list.js +2 -1
- package/dist/commands/signals/schemas/list.js +2 -1
- package/dist/commands/signals/sources/list.js +2 -1
- package/dist/commands/space-directory-views/list.js +2 -1
- package/dist/commands/spaces/actions/list.js +4 -3
- package/dist/commands/spaces/briefs/list.js +2 -1
- package/dist/commands/spaces/cycles/list.js +2 -1
- package/dist/commands/spaces/files/folders/list.js +2 -1
- package/dist/commands/spaces/files/list.js +3 -2
- package/dist/commands/spaces/heartbeats/list.js +3 -2
- package/dist/commands/spaces/labels/list.js +3 -2
- package/dist/commands/spaces/list.d.ts +3 -18
- package/dist/commands/spaces/list.js +28 -35
- package/dist/commands/spaces/live/cards/list.js +2 -1
- package/dist/commands/spaces/members/list.d.ts +1 -0
- package/dist/commands/spaces/members/list.js +4 -1
- package/dist/commands/spaces/show.js +2 -2
- package/dist/commands/spaces/skills/list.js +6 -2
- package/dist/commands/spaces/states/list.js +2 -1
- package/dist/commands/spaces/views/list.js +2 -1
- package/dist/commands/spaces/widgets/list.js +3 -2
- package/dist/commands/spaces/workflow-templates/list.js +2 -1
- package/dist/commands/spaces/workflows/fixtures/list.js +2 -1
- package/dist/commands/spaces/workflows/list.js +3 -2
- package/dist/commands/spaces/workflows/proposals/list.js +2 -1
- package/dist/commands/spaces/workflows/triggers/list.js +2 -1
- package/dist/commands/store/acquisitions/list.js +2 -1
- package/dist/commands/store/admissions/list.js +17 -1
- package/dist/commands/store/advisories/list.js +2 -1
- package/dist/commands/store/follows/list.js +2 -1
- package/dist/commands/store/publishers/domains/list.js +2 -1
- package/dist/commands/store/reports/list.js +2 -1
- package/dist/commands/subscriptions/list.js +2 -1
- package/dist/commands/tasks/actionability.js +7 -30
- package/dist/commands/tasks/activity.js +3 -7
- package/dist/commands/tasks/approvals/list.js +2 -1
- package/dist/commands/tasks/assign.d.ts +1 -0
- package/dist/commands/tasks/assign.js +43 -7
- package/dist/commands/tasks/attachments/list.js +2 -1
- package/dist/commands/tasks/chat/send.js +34 -0
- package/dist/commands/tasks/comments/add.js +6 -1
- package/dist/commands/tasks/comments/list.js +2 -1
- package/dist/commands/tasks/complete.js +26 -2
- package/dist/commands/tasks/continue.d.ts +18 -0
- package/dist/commands/tasks/continue.js +54 -0
- package/dist/commands/tasks/create-tree.d.ts +5 -0
- package/dist/commands/tasks/create-tree.js +399 -219
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +63 -11
- package/dist/commands/tasks/deliverable/add.js +10 -3
- package/dist/commands/tasks/deliverable/list.js +2 -1
- package/dist/commands/tasks/events/list.js +2 -1
- package/dist/commands/tasks/execution-state.d.ts +12 -0
- package/dist/commands/tasks/execution-state.js +28 -0
- package/dist/commands/tasks/expectations/assess.js +40 -5
- package/dist/commands/tasks/guide.d.ts +10 -0
- package/dist/commands/tasks/guide.js +20 -0
- package/dist/commands/tasks/labels/list.js +2 -1
- package/dist/commands/tasks/list.d.ts +19 -0
- package/dist/commands/tasks/list.js +97 -4
- package/dist/commands/tasks/move.js +10 -2
- package/dist/commands/tasks/preflight.d.ts +14 -0
- package/dist/commands/tasks/preflight.js +77 -0
- package/dist/commands/tasks/resource/list.js +2 -1
- package/dist/commands/tasks/result/submit.js +10 -1
- package/dist/commands/tasks/review.js +6 -1
- package/dist/commands/tasks/revisions.d.ts +2 -0
- package/dist/commands/tasks/revisions.js +8 -1
- package/dist/commands/tasks/show.js +17 -11
- package/dist/commands/tasks/start.d.ts +1 -0
- package/dist/commands/tasks/start.js +35 -0
- package/dist/commands/tasks/templates/list.js +2 -1
- package/dist/commands/tasks/timeline.d.ts +5 -0
- package/dist/commands/tasks/timeline.js +9 -1
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +25 -2
- package/dist/commands/tasks/updates/add.js +6 -1
- package/dist/commands/tasks/updates/list.js +2 -1
- package/dist/commands/tasks/upsert.d.ts +1 -0
- package/dist/commands/tasks/upsert.js +8 -1
- package/dist/commands/token/list.js +2 -1
- package/dist/commands/tokens/list.js +2 -1
- package/dist/commands/tones/list.js +4 -2
- package/dist/commands/triggers/list.js +2 -1
- package/dist/commands/views/list.js +2 -1
- package/dist/commands/webhooks/list.js +2 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/widgets/list.js +2 -1
- package/dist/commands/widgets/save-as-app.d.ts +13 -0
- package/dist/commands/widgets/save-as-app.js +65 -0
- package/dist/commands/work-views/list.js +2 -1
- package/dist/commands/worklog/list.js +2 -1
- package/dist/commands/workspaces/list.js +3 -2
- package/dist/commands/workspaces/members.d.ts +1 -0
- package/dist/commands/workspaces/members.js +5 -2
- package/dist/generated/managed-instruction-guides.json +2 -2
- package/dist/help.js +7 -0
- package/dist/lib/agent-proactive-baseline.d.ts +9 -0
- package/dist/lib/agent-proactive-baseline.js +44 -0
- package/dist/lib/agentic-stream.d.ts +4 -1
- package/dist/lib/agentic-stream.js +29 -4
- package/dist/lib/appData.d.ts +75 -0
- package/dist/lib/appData.js +274 -0
- package/dist/lib/appInstallations.d.ts +117 -0
- package/dist/lib/appInstallations.js +960 -0
- package/dist/lib/appSettings.d.ts +3 -0
- package/dist/lib/appSettings.js +71 -0
- package/dist/lib/appWebhooks.d.ts +7 -0
- package/dist/lib/appWebhooks.js +59 -0
- package/dist/lib/apps-command.d.ts +44 -0
- package/dist/lib/apps-command.js +164 -0
- package/dist/lib/apps.d.ts +45 -0
- package/dist/lib/apps.js +148 -0
- package/dist/lib/appsCheck.d.ts +12 -0
- package/dist/lib/appsCheck.js +173 -0
- package/dist/lib/appsFs.d.ts +58 -0
- package/dist/lib/appsFs.js +384 -0
- package/dist/lib/auth-failure.d.ts +20 -0
- package/dist/lib/auth-failure.js +40 -3
- package/dist/lib/cli-installers.d.ts +9 -2
- package/dist/lib/command-miss.js +107 -0
- package/dist/lib/commitment-loop-status.js +25 -3
- package/dist/lib/commitments.d.ts +44 -3
- package/dist/lib/commitments.js +107 -9
- package/dist/lib/compasses.d.ts +4 -0
- package/dist/lib/compasses.js +11 -0
- package/dist/lib/daemon-setup.js +7 -7
- package/dist/lib/daemonHandoff.js +3 -2
- package/dist/lib/dedicated-ssh.d.ts +2 -0
- package/dist/lib/dedicated-ssh.js +98 -28
- package/dist/lib/json-output.d.ts +33 -0
- package/dist/lib/json-output.js +37 -0
- package/dist/lib/list-output.d.ts +9 -4
- package/dist/lib/list-output.js +36 -9
- package/dist/lib/lookbackPlans.d.ts +13 -0
- package/dist/lib/lookbackPlans.js +68 -0
- package/dist/lib/machines.d.ts +27 -6
- package/dist/lib/machines.js +25 -14
- package/dist/lib/member-output.d.ts +20 -0
- package/dist/lib/member-output.js +57 -0
- package/dist/lib/preflight-copy.d.ts +7 -0
- package/dist/lib/preflight-copy.js +31 -0
- package/dist/lib/roles.d.ts +2 -2
- package/dist/lib/task-admission.d.ts +9 -0
- package/dist/lib/task-admission.js +35 -0
- package/dist/lib/task-batch.d.ts +4 -0
- package/dist/lib/task-batch.js +2 -0
- package/dist/lib/task-operations.d.ts +25 -0
- package/dist/lib/task-operations.js +123 -0
- package/dist/lib/task-preflight.d.ts +35 -0
- package/dist/lib/task-preflight.js +121 -0
- package/dist/lib/task-resource-references.d.ts +23 -0
- package/dist/lib/task-resource-references.js +119 -0
- package/dist/lib/task-spec-verification.d.ts +42 -0
- package/dist/lib/task-spec-verification.js +101 -0
- package/dist/lib/task-work.d.ts +11 -0
- package/dist/lib/task-work.js +41 -0
- package/dist/lib/task-write-attribution.d.ts +26 -0
- package/dist/lib/task-write-attribution.js +47 -0
- package/dist/lib/tasks.d.ts +13 -0
- package/dist/lib/tasks.js +61 -8
- package/dist/lib/triggers.d.ts +7 -0
- package/dist/lib/triggers.js +54 -4
- package/dist/lib/usage-discovery.d.ts +4 -0
- package/dist/lib/usage-discovery.js +14 -4
- package/dist/lib/widgetApps.d.ts +10 -0
- package/dist/lib/widgetApps.js +47 -0
- package/dist/lib/widgetStaticScan.js +25 -1
- package/dist/lib/workspaces.d.ts +11 -4
- package/dist/lib/workspaces.js +7 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +14 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +47 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.d.ts +49 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.d.ts +118 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +614 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +15 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.d.ts +5 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.js +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionRevocation.d.ts +177 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionRevocation.js +484 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +11 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +46 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.d.ts +232 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.js +372 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.d.ts +17 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.js +12 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +14 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +45 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.d.ts +49 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +24 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.d.ts +118 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +608 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +15 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.d.ts +5 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.js +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionRevocation.d.ts +177 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionRevocation.js +472 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +11 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +44 -6
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.d.ts +232 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.js +360 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.d.ts +17 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.js +12 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +30 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +25239 -18730
- package/docs/v1/operations.md +52 -0
- package/docs/v1/space-search.md +19 -0
- package/oclif.manifest.json +4719 -479
- package/package.json +23 -2
|
@@ -11,11 +11,15 @@ exports.normalizeTreeRoots = normalizeTreeRoots;
|
|
|
11
11
|
exports.planTree = planTree;
|
|
12
12
|
const core_1 = require("@oclif/core");
|
|
13
13
|
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
const node_fs_1 = require("node:fs");
|
|
14
15
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
15
16
|
const base_command_1 = require("../../base-command");
|
|
16
17
|
const prompt_1 = require("../../lib/prompt");
|
|
17
18
|
const task_batch_1 = require("../../lib/task-batch");
|
|
18
19
|
const write_target_1 = require("../../lib/write-target");
|
|
20
|
+
const json_output_1 = require("../../lib/json-output");
|
|
21
|
+
const web_url_1 = require("../../lib/web-url");
|
|
22
|
+
const task_spec_verification_1 = require("../../lib/task-spec-verification");
|
|
19
23
|
const tasks_1 = require("../../lib/tasks");
|
|
20
24
|
/**
|
|
21
25
|
* Nodes a re-run could not recognize: no externalKey of their own and no
|
|
@@ -95,10 +99,12 @@ function partialFailureResult(args) {
|
|
|
95
99
|
mapping,
|
|
96
100
|
failedAt,
|
|
97
101
|
...(args.failures ? { failures: args.failures } : {}),
|
|
98
|
-
rerun: prefix
|
|
99
|
-
? 'Re-
|
|
100
|
-
:
|
|
101
|
-
|
|
102
|
+
rerun: !prefix && !args.keyed
|
|
103
|
+
? 'Re-running creates un-keyed nodes again. Use mapping to continue by hand, or re-run with --external-key-prefix.'
|
|
104
|
+
: !failedAt.error.retryable
|
|
105
|
+
? `Correct the rejected input before retrying: ${failedAt.error.message}. No automatic retry is suggested for this refusal.`
|
|
106
|
+
: 'Re-run the same keyed file with --resume to confirm existing IDs and create only missing nodes; --verify lists what exists and what is missing without writing. A submitted write may still finish; stable keys prevent duplicates.',
|
|
107
|
+
...(args.next && failedAt.error.retryable && (prefix || args.keyed) ? { next: args.next } : {}),
|
|
102
108
|
...(warnings.length > 0 ? { warnings } : {}),
|
|
103
109
|
};
|
|
104
110
|
}
|
|
@@ -165,7 +171,8 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
165
171
|
'(a "nodes" array, each node with optional "children"; {"root":{...,"children":[...]}} is accepted too). ' +
|
|
166
172
|
'Put "me" in assigneeUserIds for yourself and "blockedByTempIds":["<tempId>"] for dependencies. ' +
|
|
167
173
|
'Setting executionMode human with an explicit assignee avoids inheriting a Space lead agent. ' +
|
|
168
|
-
'Nodes with an externalKey (or under --external-key-prefix) are created once: a re-run, --resume or --verify finds them again.'
|
|
174
|
+
'Nodes with an externalKey (or under --external-key-prefix) are created once: a re-run, --resume or --verify finds them again. ' +
|
|
175
|
+
'A nodes array also creates sibling tasks. Use --readback to check declared structured fields after applying, or --verify-spec for a read-only field comparison.';
|
|
169
176
|
static examples = [
|
|
170
177
|
'<%= config.bin %> tasks create-tree --from-json tree.json --space <space-id> --json',
|
|
171
178
|
'<%= config.bin %> tasks create-tree --from-json tree.json --space <space-id> --default-agent auto',
|
|
@@ -174,6 +181,8 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
174
181
|
'<%= config.bin %> tasks create-tree --from-json tree.json --external-key-prefix mine/ --verify --json',
|
|
175
182
|
'<%= config.bin %> tasks create-tree --from-json tree.json --external-key-prefix mine/ --resume',
|
|
176
183
|
'<%= config.bin %> tasks create-tree --from-json tree.json --space <space-id> --project OSK-P-1 --expect-target skrr.ai',
|
|
184
|
+
'<%= config.bin %> tasks create-tree --from-json tasks.json --unassigned --readback --json',
|
|
185
|
+
'<%= config.bin %> tasks create-tree --from-json tasks.json --verify-spec --json',
|
|
177
186
|
];
|
|
178
187
|
static flags = {
|
|
179
188
|
json: core_1.Flags.boolean({ description: 'Output the create-tree result as JSON' }),
|
|
@@ -186,8 +195,17 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
186
195
|
}),
|
|
187
196
|
verify: core_1.Flags.boolean({
|
|
188
197
|
description: 'Read-only: report which nodes of this tree already exist (matched by externalKey) and which are missing, and write nothing. Exits 1 when any is missing or cannot be checked.',
|
|
189
|
-
exclusive: ['fresh', 'resume', 'dry-run', 'no-batch'],
|
|
198
|
+
exclusive: ['fresh', 'resume', 'dry-run', 'no-batch', 'verify-spec', 'readback'],
|
|
190
199
|
}),
|
|
200
|
+
'verify-spec': core_1.Flags.boolean({
|
|
201
|
+
description: 'Read-only: find keyed tasks and compare the declared structured fields, including Expectations, labels and assignment. Rich-text description content is explicitly not compared. Never repairs drift.',
|
|
202
|
+
exclusive: ['fresh', 'resume', 'dry-run', 'no-batch', 'verify', 'readback', 'default-agent'],
|
|
203
|
+
}),
|
|
204
|
+
readback: core_1.Flags.boolean({
|
|
205
|
+
description: 'After applying, reread every confirmed Task and report declared structured-field mismatches and read failures. This checks declarations, not whether Expectations are met. No repair or retry is performed by the readback.',
|
|
206
|
+
exclusive: ['verify', 'verify-spec', 'dry-run'],
|
|
207
|
+
}),
|
|
208
|
+
unassigned: core_1.Flags.boolean({ description: 'Explicitly clear assignees on every node, suppressing session/parent/Space defaults while retaining any declared executor intent. Does not start tasks.', exclusive: ['default-agent'] }),
|
|
191
209
|
'external-key-prefix': core_1.Flags.string({
|
|
192
210
|
description: 'Generate externalKey for nodes that omit one; enables idempotent re-runs. Defaults to a prefix derived from the file content (see --fresh)',
|
|
193
211
|
}),
|
|
@@ -214,6 +232,10 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
214
232
|
async run() {
|
|
215
233
|
this.requireAuth();
|
|
216
234
|
const { flags } = await this.parse(TasksCreateTree);
|
|
235
|
+
this.setJsonOperation({ command: 'tasks:create-tree', mode: flags['verify-spec'] || flags.verify ? 'verify' : flags['dry-run'] ? 'dry_run' : 'execute' });
|
|
236
|
+
const unassignmentError = (0, tasks_1.taskUnassignmentFlagError)(flags);
|
|
237
|
+
if (unassignmentError)
|
|
238
|
+
this.failWithCliError({ message: unassignmentError, code: 'TASK_UNASSIGNED_CONFLICT', exit: 2, retryable: false });
|
|
217
239
|
let input = {};
|
|
218
240
|
try {
|
|
219
241
|
input = await (0, prompt_1.readJsonBody)(flags['from-json']);
|
|
@@ -264,12 +286,42 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
264
286
|
const scopes = new Map();
|
|
265
287
|
for (const item of planned) {
|
|
266
288
|
try {
|
|
289
|
+
(0, tasks_1.applyExplicitTaskUnassignment)(item.payload, Boolean(flags.unassigned));
|
|
290
|
+
const parentSpace = item.parentKey ? plannedByKey.get(item.parentKey)?.payload.spaceId : undefined;
|
|
291
|
+
if (!item.payload.spaceId && typeof parentSpace === 'string')
|
|
292
|
+
item.payload.spaceId = parentSpace;
|
|
293
|
+
await this.resolveTaskResourceReferences(item.payload);
|
|
294
|
+
if (parentSpace && item.payload.spaceId && parentSpace !== item.payload.spaceId) {
|
|
295
|
+
throw new Error('The Task Space contradicts its planned parent Space; no tasks were written.');
|
|
296
|
+
}
|
|
267
297
|
scopes.set(item.key, await (0, tasks_1.resolveTaskCreateScope)(item.payload, { parentTaskCache, projectCache }));
|
|
268
298
|
}
|
|
269
299
|
catch (err) {
|
|
270
300
|
defaultAgentErrors.push(`${item.key}: ${err.message}`);
|
|
271
301
|
}
|
|
272
302
|
}
|
|
303
|
+
// Validate project references through the same scoped read as `projects show`.
|
|
304
|
+
// A supplied Space must not bypass project validation during a dry run.
|
|
305
|
+
const scopedProjects = new Map();
|
|
306
|
+
for (const item of planned) {
|
|
307
|
+
const { spaceId, projectId } = item.payload;
|
|
308
|
+
if (typeof spaceId !== 'string' || typeof projectId !== 'string')
|
|
309
|
+
continue;
|
|
310
|
+
const cacheKey = JSON.stringify([spaceId, projectId]);
|
|
311
|
+
try {
|
|
312
|
+
if (!scopedProjects.has(cacheKey)) {
|
|
313
|
+
scopedProjects.set(cacheKey, data_provider_1.dataService.getSpaceProject(spaceId, projectId));
|
|
314
|
+
}
|
|
315
|
+
const project = await scopedProjects.get(cacheKey);
|
|
316
|
+
if (!project || typeof project.id !== 'string')
|
|
317
|
+
throw new Error('Project lookup returned no canonical id');
|
|
318
|
+
item.payload.projectId = project.id;
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
const failure = (0, task_batch_1.describeApiFailure)(err);
|
|
322
|
+
defaultAgentErrors.push(`${item.key}: project '${projectId}' was not found or could not be read in space '${spaceId}': ${failure.message}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
273
325
|
// 2. Which nodes already exist? One bulk read, not one request per node.
|
|
274
326
|
const lookups = planned
|
|
275
327
|
.filter((item) => scopes.has(item.key) &&
|
|
@@ -299,7 +351,12 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
299
351
|
existingByKey.set(key, hit?.task ?? null);
|
|
300
352
|
}
|
|
301
353
|
}
|
|
302
|
-
if (flags.verify) {
|
|
354
|
+
if (flags.verify || flags['verify-spec']) {
|
|
355
|
+
for (const error of defaultAgentErrors) {
|
|
356
|
+
const item = planned.find((node) => error.startsWith(`${node.key}:`));
|
|
357
|
+
if (item)
|
|
358
|
+
unverifiable.push({ tempId: item.key, reason: error });
|
|
359
|
+
}
|
|
303
360
|
await this.verifyTree(planned, existingByKey, unverifiable, flags);
|
|
304
361
|
return;
|
|
305
362
|
}
|
|
@@ -355,7 +412,7 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
355
412
|
if (errors.length > 0) {
|
|
356
413
|
const result = { object: 'task_create_tree_validation', ok: false, errors, planned };
|
|
357
414
|
if (flags.json)
|
|
358
|
-
this.
|
|
415
|
+
this.printJsonOperation(result, { writeState: 'not_attempted' });
|
|
359
416
|
else
|
|
360
417
|
this.log(`Create-tree validation failed:\n- ${errors.join('\n- ')}`);
|
|
361
418
|
this.exit(1);
|
|
@@ -367,10 +424,12 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
367
424
|
// Say so before anything is written, not only inside a dry run (OSK-S-440 #9).
|
|
368
425
|
const agentAssignment = describeDefaultAgentAssignment(defaultAgentResolutions);
|
|
369
426
|
const noteworthyAssignment = agentAssignment ? [agentAssignment] : [];
|
|
427
|
+
const target = await this.assertWriteTarget(flags['expect-target'], { preview: flags['dry-run'] });
|
|
370
428
|
if (flags['dry-run']) {
|
|
371
429
|
const result = {
|
|
372
430
|
object: 'task_create_tree_dry_run',
|
|
373
431
|
ok: true,
|
|
432
|
+
target,
|
|
374
433
|
count: planned.length,
|
|
375
434
|
...(() => {
|
|
376
435
|
const dryWarnings = [
|
|
@@ -393,10 +452,11 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
393
452
|
externalKey: item.payload.externalKey,
|
|
394
453
|
action: plannedAction(existingByKey.get(item.key), Boolean(flags.resume)),
|
|
395
454
|
payload: item.payload,
|
|
455
|
+
assignmentPreview: (0, tasks_1.taskAssignmentPreview)(item.payload),
|
|
396
456
|
})),
|
|
397
457
|
};
|
|
398
458
|
if (flags.json)
|
|
399
|
-
this.
|
|
459
|
+
this.printJsonOperation(result);
|
|
400
460
|
else {
|
|
401
461
|
this.log(`Dry run passed. ${planned.length} task(s) would be created/upserted.`);
|
|
402
462
|
for (const item of planned) {
|
|
@@ -419,99 +479,160 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
419
479
|
if (agentAssignment && process.stderr.isTTY) {
|
|
420
480
|
process.stderr.write(`Warning: ${agentAssignment.hint}\n`);
|
|
421
481
|
}
|
|
422
|
-
//
|
|
423
|
-
//
|
|
424
|
-
const target = await this.assertWriteTarget(flags['expect-target']);
|
|
482
|
+
// Every preflight passed. Track confirmed and submitted work separately:
|
|
483
|
+
// a request can continue on the server after its client is interrupted.
|
|
425
484
|
const mapping = {};
|
|
426
485
|
const results = [];
|
|
427
486
|
const startedAt = Date.now();
|
|
428
487
|
let rounds = 0;
|
|
429
488
|
const next = this.nextCommand(flags);
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
mapping
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (flags.json) {
|
|
451
|
-
this.log(JSON.stringify({ ...partial, target }, null, 2));
|
|
452
|
-
process.exitCode = partial.failedAt.error.retryable ? 5 : 1;
|
|
453
|
-
this.exit(partial.failedAt.error.retryable ? 5 : 1);
|
|
489
|
+
const submitted = new Set();
|
|
490
|
+
const interrupt = (signal) => {
|
|
491
|
+
const confirmed = Object.keys(mapping).length;
|
|
492
|
+
const unknown = [...submitted].filter((key) => !mapping[key]).length;
|
|
493
|
+
const recovery = unkeyedNodes(planned).length === 0
|
|
494
|
+
? `Run ${next.replace(/ --resume$/, ' --verify')} to reconcile, then ${next} to continue.`
|
|
495
|
+
: 'Inspect the Space using the mapping before retrying: unkeyed nodes may be duplicated.';
|
|
496
|
+
// Signals can arrive while the network request is pending. Do not wait for
|
|
497
|
+
// it or claim it was cancelled: the server may still complete submitted rows.
|
|
498
|
+
try {
|
|
499
|
+
(0, node_fs_1.writeSync)(2, `Interrupted (${signal}). Confirmed ${confirmed} of ${planned.length}; ${unknown} submitted outcome(s) unknown. The server may still finish submitted writes. ${recovery}\n`);
|
|
500
|
+
if (!flags.json && confirmed > 0)
|
|
501
|
+
(0, node_fs_1.writeSync)(2, `Confirmed mapping: ${JSON.stringify(mapping)}\n`);
|
|
502
|
+
if (flags.json)
|
|
503
|
+
(0, node_fs_1.writeSync)(1, JSON.stringify((0, json_output_1.withCliOperation)({
|
|
504
|
+
object: 'task_create_tree_result', ok: false, interrupted: true, signal,
|
|
505
|
+
total: planned.length, count: confirmed, mapping: { ...mapping }, target,
|
|
506
|
+
summary: { confirmed, unknown, notAttempted: planned.length - confirmed - unknown },
|
|
507
|
+
recovery,
|
|
508
|
+
}, { command: 'tasks:create-tree', mode: 'execute', outcome: 'failed', writeState: 'unknown' }), null, 2) + '\n');
|
|
454
509
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
this.log(`- ${tempId} -> ${id}`);
|
|
458
|
-
this.log(partial.rerun);
|
|
459
|
-
if (partial.next)
|
|
460
|
-
this.log(`Next: ${partial.next}`);
|
|
461
|
-
if (failures) {
|
|
462
|
-
for (const row of failures) {
|
|
463
|
-
const detail = row.error;
|
|
464
|
-
this.log(`- ${String(row.tempId)}: ${String(row.outcome)} — ${detail.message}`);
|
|
465
|
-
}
|
|
466
|
-
this.exit(failure.retryable ? 5 : 1);
|
|
467
|
-
return;
|
|
510
|
+
finally {
|
|
511
|
+
process.exit(signal === 'SIGINT' ? 130 : 143);
|
|
468
512
|
}
|
|
469
|
-
this.handleApiError(err);
|
|
470
513
|
};
|
|
471
|
-
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
});
|
|
514
|
+
const onSigint = () => interrupt('SIGINT');
|
|
515
|
+
const onSigterm = () => interrupt('SIGTERM');
|
|
516
|
+
process.on('SIGINT', onSigint);
|
|
517
|
+
process.on('SIGTERM', onSigterm);
|
|
518
|
+
try {
|
|
519
|
+
// A half-applied tree reports the ids it did create; the only way back.
|
|
520
|
+
const reportPartial = (item, failure, err, failures) => {
|
|
521
|
+
if (failure.code === 'PROJECT_NOT_FOUND') {
|
|
522
|
+
failure = { ...failure, message: `Project '${String(item.payload.projectId)}' was not found in space '${String(item.payload.spaceId)}'. Correct --project or the node's projectId` };
|
|
480
523
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
524
|
+
const failureRows = failures ?? [{
|
|
525
|
+
tempId: item.key,
|
|
526
|
+
externalKey: item.payload.externalKey,
|
|
527
|
+
outcome: !failure.status || failure.status === 408 || failure.status >= 500 ? 'unknown' : 'failed',
|
|
528
|
+
error: failure,
|
|
529
|
+
}];
|
|
530
|
+
const accountedFor = new Set([...Object.keys(mapping), ...failureRows.map((row) => String(row.tempId))]);
|
|
531
|
+
for (const node of planned) {
|
|
532
|
+
if (accountedFor.has(node.key))
|
|
533
|
+
continue;
|
|
534
|
+
failureRows.push({
|
|
535
|
+
tempId: node.key,
|
|
536
|
+
externalKey: node.payload.externalKey,
|
|
537
|
+
outcome: 'not_attempted',
|
|
538
|
+
error: { message: 'Not attempted because an earlier node stopped the tree', retryable: true },
|
|
495
539
|
});
|
|
496
540
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
541
|
+
const partial = partialFailureResult({
|
|
542
|
+
results,
|
|
543
|
+
mapping,
|
|
544
|
+
total: planned.length,
|
|
545
|
+
prefix: keyPrefix,
|
|
546
|
+
keyed: unkeyedNodes(planned).length === 0,
|
|
547
|
+
warnings,
|
|
548
|
+
failures: failureRows,
|
|
549
|
+
next,
|
|
550
|
+
failedAt: {
|
|
551
|
+
tempId: item.key,
|
|
552
|
+
...(item.parentKey ? { parentTempId: item.parentKey } : {}),
|
|
553
|
+
title: item.payload.title,
|
|
554
|
+
error: failure,
|
|
555
|
+
},
|
|
556
|
+
});
|
|
557
|
+
if (flags.json) {
|
|
558
|
+
this.printJsonOperation({ ...partial, target }, { outcome: 'failed', writeState: partial.summary.unknown > 0 ? 'unknown' : 'confirmed' });
|
|
559
|
+
process.exitCode = partial.failedAt.error.retryable ? 5 : 1;
|
|
560
|
+
this.exit(partial.failedAt.error.retryable ? 5 : 1);
|
|
561
|
+
}
|
|
562
|
+
this.log(`Confirmed ${results.length} of ${planned.length} task(s); stopped at "${item.key}": ${failure.message}`);
|
|
563
|
+
for (const [tempId, id] of Object.entries(mapping))
|
|
564
|
+
this.log(`- ${tempId} -> ${id}`);
|
|
565
|
+
this.log(partial.rerun);
|
|
566
|
+
if (partial.next)
|
|
567
|
+
this.log(`Next: ${partial.next}`);
|
|
568
|
+
if (failures) {
|
|
569
|
+
for (const row of failures) {
|
|
570
|
+
const detail = row.error;
|
|
571
|
+
this.log(`- ${String(row.tempId)}: ${String(row.outcome)} — ${detail.message}`);
|
|
572
|
+
}
|
|
573
|
+
this.exit(failure.retryable ? 5 : 1);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
this.handleApiError(err);
|
|
577
|
+
};
|
|
578
|
+
// Blockers a node names by tempId, as the real ids the serial path needs.
|
|
579
|
+
const blockerIdsFor = (item) => {
|
|
580
|
+
const ids = [];
|
|
581
|
+
for (const blockerKey of item.blockerKeys ?? []) {
|
|
582
|
+
const id = mapping[blockerKey];
|
|
583
|
+
if (!id) {
|
|
584
|
+
this.error(`Blocker tempId "${blockerKey}" was not created before "${item.key}"`, {
|
|
585
|
+
exit: 1,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
ids.push(id);
|
|
589
|
+
}
|
|
590
|
+
return ids;
|
|
591
|
+
};
|
|
592
|
+
// The serial path: one request per node. Used for updates of existing keyed
|
|
593
|
+
// nodes, for every create against a server without the batch route, and for
|
|
594
|
+
// everything under --no-batch.
|
|
595
|
+
const applySerial = async (item) => {
|
|
596
|
+
const payload = { ...item.payload };
|
|
597
|
+
if (item.parentKey) {
|
|
598
|
+
payload.parentId = mapping[item.parentKey];
|
|
599
|
+
if (!payload.parentId) {
|
|
600
|
+
this.error(`Parent tempId "${item.parentKey}" was not created before "${item.key}"`, {
|
|
601
|
+
exit: 1,
|
|
513
602
|
});
|
|
514
603
|
}
|
|
604
|
+
}
|
|
605
|
+
const blockerIds = blockerIdsFor(item);
|
|
606
|
+
let action;
|
|
607
|
+
let task;
|
|
608
|
+
try {
|
|
609
|
+
submitted.add(item.key);
|
|
610
|
+
if (typeof payload.externalKey === 'string' && payload.externalKey.trim()) {
|
|
611
|
+
const existingTask = existingByKey.get(item.key) ?? null;
|
|
612
|
+
if (existingTask) {
|
|
613
|
+
action = 'updated';
|
|
614
|
+
const patch = (0, tasks_1.removeUndefinedFields)((0, tasks_1.createPatchFromCreatePayload)(payload));
|
|
615
|
+
// Adding is idempotent, so a re-run never duplicates or drops an edge.
|
|
616
|
+
if (blockerIds.length > 0)
|
|
617
|
+
patch.addBlockedByIds = blockerIds;
|
|
618
|
+
task = await data_provider_1.dataService.updateTask({
|
|
619
|
+
taskId: (0, tasks_1.taskId)(existingTask),
|
|
620
|
+
data: patch,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
action = 'created';
|
|
625
|
+
if (blockerIds.length > 0) {
|
|
626
|
+
payload.blockedByIds = [
|
|
627
|
+
...new Set([
|
|
628
|
+
...(payload.blockedByIds ?? []),
|
|
629
|
+
...blockerIds,
|
|
630
|
+
]),
|
|
631
|
+
];
|
|
632
|
+
}
|
|
633
|
+
task = await data_provider_1.dataService.createTask(payload);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
515
636
|
else {
|
|
516
637
|
action = 'created';
|
|
517
638
|
if (blockerIds.length > 0) {
|
|
@@ -525,147 +646,183 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
525
646
|
task = await data_provider_1.dataService.createTask(payload);
|
|
526
647
|
}
|
|
527
648
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
payload.blockedByIds = [
|
|
532
|
-
...new Set([
|
|
533
|
-
...(payload.blockedByIds ?? []),
|
|
534
|
-
...blockerIds,
|
|
535
|
-
]),
|
|
536
|
-
];
|
|
537
|
-
}
|
|
538
|
-
task = await data_provider_1.dataService.createTask(payload);
|
|
649
|
+
catch (err) {
|
|
650
|
+
reportPartial(item, (0, task_batch_1.describeApiFailure)(err), err);
|
|
651
|
+
return;
|
|
539
652
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
tempId: row.key,
|
|
590
|
-
parentTempId: node.parentKey,
|
|
591
|
-
id: row.id,
|
|
592
|
-
action: row.status === 'exists' ? 'existing' : 'created',
|
|
593
|
-
externalKey: row.externalKey ?? node.payload.externalKey,
|
|
594
|
-
title: node.payload.title,
|
|
595
|
-
task: {
|
|
653
|
+
const id = (0, tasks_1.taskId)(task);
|
|
654
|
+
mapping[item.key] = id;
|
|
655
|
+
results.push({
|
|
656
|
+
tempId: item.key,
|
|
657
|
+
parentTempId: item.parentKey,
|
|
658
|
+
id,
|
|
659
|
+
action,
|
|
660
|
+
externalKey: payload.externalKey,
|
|
661
|
+
title: task.title ?? payload.title,
|
|
662
|
+
task,
|
|
663
|
+
});
|
|
664
|
+
};
|
|
665
|
+
// A person watching sees the tree being built; anything capturing output
|
|
666
|
+
// sees nothing extra (the answer is the JSON / summary at the end).
|
|
667
|
+
const onProgress = (p) => {
|
|
668
|
+
submitted.clear();
|
|
669
|
+
for (const key of p.unknownKeys ?? [])
|
|
670
|
+
submitted.add(key);
|
|
671
|
+
if (process.stderr.isTTY) {
|
|
672
|
+
process.stderr.write(p.waiting
|
|
673
|
+
? `Waiting ${Math.max(1, Math.round(p.waiting.ms / 1000))}s before trying again (${p.waiting.reason}); ${p.confirmed} of ${p.total} confirmed.\n`
|
|
674
|
+
: `Confirmed ${p.confirmed} of ${p.total} (request ${p.round}, ${Math.round(p.elapsedMs / 1000)}s).\n`);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
// New nodes go to POST /api/tasks/batch, and the batch is driven until every
|
|
678
|
+
// one exists (createNodesViaBatch). `batchAvailable` flips off the first time
|
|
679
|
+
// the server answers 404/405, or under --no-batch, and every later node is serial.
|
|
680
|
+
let batchAvailable = !flags['no-batch'];
|
|
681
|
+
let pending = [];
|
|
682
|
+
const flushPending = async () => {
|
|
683
|
+
const nodes = pending;
|
|
684
|
+
pending = [];
|
|
685
|
+
if (nodes.length === 0)
|
|
686
|
+
return;
|
|
687
|
+
if (batchAvailable) {
|
|
688
|
+
const outcome = await (0, task_batch_1.createNodesViaBatch)(nodes.map((n) => ({
|
|
689
|
+
key: n.key,
|
|
690
|
+
parentKey: n.parentKey,
|
|
691
|
+
blockerKeys: n.blockerKeys,
|
|
692
|
+
payload: n.payload,
|
|
693
|
+
})), mapping, { onProgress, onSubmit: (nodes) => nodes.forEach((node) => submitted.add(node.key)) });
|
|
694
|
+
if (outcome.supported) {
|
|
695
|
+
rounds += outcome.rounds;
|
|
696
|
+
const byKey = new Map(nodes.map((n) => [n.key, n]));
|
|
697
|
+
for (const row of outcome.rows) {
|
|
698
|
+
const node = byKey.get(row.key);
|
|
699
|
+
results.push({
|
|
700
|
+
tempId: row.key,
|
|
701
|
+
parentTempId: node.parentKey,
|
|
596
702
|
id: row.id,
|
|
597
|
-
|
|
703
|
+
action: row.status === 'exists' ? 'existing' : 'created',
|
|
704
|
+
externalKey: row.externalKey ?? node.payload.externalKey,
|
|
598
705
|
title: node.payload.title,
|
|
599
|
-
|
|
600
|
-
|
|
706
|
+
task: {
|
|
707
|
+
id: row.id,
|
|
708
|
+
...(row.identifier ? { identifier: row.identifier } : {}),
|
|
709
|
+
title: node.payload.title,
|
|
710
|
+
},
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
const failure = outcome.failures.find((f) => !f.skipped) ?? outcome.failures[0];
|
|
714
|
+
if (failure) {
|
|
715
|
+
const node = byKey.get(failure.key);
|
|
716
|
+
const err = Object.assign(new Error(failure.error.message), {
|
|
717
|
+
...(failure.error.status ? { status: failure.error.status } : {}),
|
|
718
|
+
...(failure.error.code ? { code: failure.error.code } : {}),
|
|
719
|
+
});
|
|
720
|
+
reportPartial(node, failure.error, err, outcome.failures.map((f) => ({
|
|
721
|
+
tempId: f.key,
|
|
722
|
+
outcome: f.outcome ?? (f.skipped ? 'not_attempted' : 'failed'),
|
|
723
|
+
externalKey: f.externalKey ?? byKey.get(f.key)?.payload.externalKey,
|
|
724
|
+
error: f.error,
|
|
725
|
+
})));
|
|
726
|
+
}
|
|
727
|
+
return;
|
|
601
728
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
729
|
+
batchAvailable = false;
|
|
730
|
+
}
|
|
731
|
+
for (const node of nodes)
|
|
732
|
+
await applySerial(node);
|
|
733
|
+
};
|
|
734
|
+
for (const item of planned) {
|
|
735
|
+
const existingTask = existingByKey.get(item.key) ?? null;
|
|
736
|
+
if (existingTask) {
|
|
737
|
+
// An update must see its parent's id, and a later create its own parent's.
|
|
738
|
+
await flushPending();
|
|
739
|
+
if (flags.resume) {
|
|
740
|
+
const id = (0, tasks_1.taskId)(existingTask);
|
|
741
|
+
mapping[item.key] = id;
|
|
742
|
+
results.push({
|
|
743
|
+
tempId: item.key,
|
|
744
|
+
parentTempId: item.parentKey,
|
|
745
|
+
id,
|
|
746
|
+
action: 'existing',
|
|
747
|
+
externalKey: item.payload.externalKey,
|
|
748
|
+
title: existingTask.title ?? item.payload.title,
|
|
749
|
+
task: existingTask,
|
|
608
750
|
});
|
|
609
|
-
reportPartial(node, failure.error, err, outcome.failures.map((f) => ({
|
|
610
|
-
tempId: f.key,
|
|
611
|
-
outcome: f.outcome ?? (f.skipped ? 'not_attempted' : 'failed'),
|
|
612
|
-
externalKey: f.externalKey ?? byKey.get(f.key)?.payload.externalKey,
|
|
613
|
-
error: f.error,
|
|
614
|
-
})));
|
|
615
751
|
}
|
|
616
|
-
|
|
752
|
+
else
|
|
753
|
+
await applySerial(item);
|
|
617
754
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
for (const node of nodes)
|
|
621
|
-
await applySerial(node);
|
|
622
|
-
};
|
|
623
|
-
for (const item of planned) {
|
|
624
|
-
const existingTask = existingByKey.get(item.key) ?? null;
|
|
625
|
-
if (existingTask) {
|
|
626
|
-
// An update must see its parent's id, and a later create its own parent's.
|
|
627
|
-
await flushPending();
|
|
628
|
-
if (flags.resume) {
|
|
629
|
-
const id = (0, tasks_1.taskId)(existingTask);
|
|
630
|
-
mapping[item.key] = id;
|
|
631
|
-
results.push({
|
|
632
|
-
tempId: item.key,
|
|
633
|
-
parentTempId: item.parentKey,
|
|
634
|
-
id,
|
|
635
|
-
action: 'existing',
|
|
636
|
-
externalKey: item.payload.externalKey,
|
|
637
|
-
title: existingTask.title ?? item.payload.title,
|
|
638
|
-
task: existingTask,
|
|
639
|
-
});
|
|
755
|
+
else {
|
|
756
|
+
pending.push(item);
|
|
640
757
|
}
|
|
641
|
-
else
|
|
642
|
-
await applySerial(item);
|
|
643
758
|
}
|
|
644
|
-
|
|
645
|
-
|
|
759
|
+
await flushPending();
|
|
760
|
+
for (const result of results) {
|
|
761
|
+
result.url = (0, web_url_1.taskUrlFrom)(this.cliConfig.baseURL, result.task);
|
|
646
762
|
}
|
|
763
|
+
const verification = flags.readback
|
|
764
|
+
? await this.readbackSpecifications(planned, mapping)
|
|
765
|
+
: undefined;
|
|
766
|
+
const summary = {
|
|
767
|
+
object: 'task_create_tree_result',
|
|
768
|
+
ok: verification ? verification.ok : true,
|
|
769
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
770
|
+
count: results.length,
|
|
771
|
+
defaultAgents: defaultAgentResolutions,
|
|
772
|
+
target,
|
|
773
|
+
timing: { elapsedMs: Date.now() - startedAt, requests: rounds },
|
|
774
|
+
mapping,
|
|
775
|
+
results,
|
|
776
|
+
...(verification ? { verification } : {}),
|
|
777
|
+
};
|
|
778
|
+
if (flags.json) {
|
|
779
|
+
this.printJsonOperation(summary, { writeState: 'confirmed' });
|
|
780
|
+
if (verification && !verification.ok)
|
|
781
|
+
this.exit(1);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
this.log(`Created task tree (${results.length} task(s)).`);
|
|
785
|
+
for (const item of results) {
|
|
786
|
+
const task = item.task;
|
|
787
|
+
this.log(`- ${item.tempId}: ${item.action} ${(0, tasks_1.formatTaskLabel)(task)}`);
|
|
788
|
+
if (item.url)
|
|
789
|
+
this.log(` ${item.url}`);
|
|
790
|
+
}
|
|
791
|
+
if (verification)
|
|
792
|
+
this.printSpecificationSummary(verification);
|
|
793
|
+
if (verification && !verification.ok)
|
|
794
|
+
this.exit(1);
|
|
647
795
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
ok: true,
|
|
652
|
-
...(warnings.length > 0 ? { warnings } : {}),
|
|
653
|
-
count: results.length,
|
|
654
|
-
defaultAgents: defaultAgentResolutions,
|
|
655
|
-
target,
|
|
656
|
-
timing: { elapsedMs: Date.now() - startedAt, requests: rounds },
|
|
657
|
-
mapping,
|
|
658
|
-
results,
|
|
659
|
-
};
|
|
660
|
-
if (flags.json) {
|
|
661
|
-
this.log(JSON.stringify(summary, null, 2));
|
|
662
|
-
return;
|
|
796
|
+
finally {
|
|
797
|
+
process.removeListener('SIGINT', onSigint);
|
|
798
|
+
process.removeListener('SIGTERM', onSigterm);
|
|
663
799
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
800
|
+
}
|
|
801
|
+
async readbackSpecifications(planned, mapping) {
|
|
802
|
+
const inputs = planned.map(item => {
|
|
803
|
+
const expected = { ...item.payload };
|
|
804
|
+
if (item.parentKey)
|
|
805
|
+
expected.parentId = mapping[item.parentKey];
|
|
806
|
+
if (item.blockerKeys?.length)
|
|
807
|
+
expected.blockedByIds = [...new Set([
|
|
808
|
+
...(expected.blockedByIds ?? []),
|
|
809
|
+
...item.blockerKeys.map(key => mapping[key]),
|
|
810
|
+
])];
|
|
811
|
+
return { tempId: item.key, id: mapping[item.key], expected };
|
|
812
|
+
});
|
|
813
|
+
return (0, task_spec_verification_1.verifyTaskSpecifications)(inputs, id => data_provider_1.dataService.getTask(id, { enrich: false }));
|
|
814
|
+
}
|
|
815
|
+
printSpecificationSummary(verification) {
|
|
816
|
+
const { summary } = verification;
|
|
817
|
+
this.log(`Structured-field readback: ${summary.matched} match; ${summary.mismatched} differ; ${summary.unavailable} unavailable.`);
|
|
818
|
+
for (const row of verification.results) {
|
|
819
|
+
for (const mismatch of row.mismatches)
|
|
820
|
+
this.log(`- ${row.tempId}: ${mismatch.field} differs`);
|
|
821
|
+
if (row.error)
|
|
822
|
+
this.log(`- ${row.tempId}: cannot read — ${row.error}`);
|
|
668
823
|
}
|
|
824
|
+
if (summary.withUncheckedFields)
|
|
825
|
+
this.log('Some authored fields are explicitly unchecked; inspect verification.results[].uncheckedFields. No Expectation assessment was performed.');
|
|
669
826
|
}
|
|
670
827
|
/**
|
|
671
828
|
* `--verify`: which nodes of this tree exist, and which do not. Read-only by
|
|
@@ -692,6 +849,7 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
692
849
|
...(typeof task.identifier === 'string' ? { identifier: task.identifier } : {}),
|
|
693
850
|
externalKey: item.payload.externalKey,
|
|
694
851
|
title: task.title ?? item.payload.title,
|
|
852
|
+
url: (0, web_url_1.taskUrlFrom)(this.cliConfig.baseURL, task),
|
|
695
853
|
});
|
|
696
854
|
}
|
|
697
855
|
else {
|
|
@@ -703,7 +861,26 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
703
861
|
});
|
|
704
862
|
}
|
|
705
863
|
}
|
|
706
|
-
|
|
864
|
+
let verification;
|
|
865
|
+
if (flags['verify-spec']) {
|
|
866
|
+
const mapping = Object.fromEntries(existing.map(row => [String(row.tempId), String(row.id)]));
|
|
867
|
+
const checkable = [];
|
|
868
|
+
for (const item of planned) {
|
|
869
|
+
if (!mapping[item.key] || cannotCheck.has(item.key))
|
|
870
|
+
continue;
|
|
871
|
+
const unresolved = [item.parentKey, ...(item.blockerKeys ?? [])].filter(key => key && !mapping[key]);
|
|
872
|
+
if (unresolved.length) {
|
|
873
|
+
cannotCheck.set(item.key, `Cannot resolve related node(s): ${unresolved.join(', ')}`);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
// Resolve only explicitly authored names. Read-only verification must
|
|
877
|
+
// not re-derive who a current Space lead would assign today.
|
|
878
|
+
await this.resolveAssigneesInPayload(item.payload);
|
|
879
|
+
checkable.push(item);
|
|
880
|
+
}
|
|
881
|
+
verification = await this.readbackSpecifications(checkable, mapping);
|
|
882
|
+
}
|
|
883
|
+
const ok = missing.length === 0 && cannotCheck.size === 0 && (!verification || verification.ok);
|
|
707
884
|
const result = {
|
|
708
885
|
object: 'task_create_tree_verification',
|
|
709
886
|
ok,
|
|
@@ -716,11 +893,12 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
716
893
|
existing,
|
|
717
894
|
missing,
|
|
718
895
|
unverifiable: [...cannotCheck].map(([tempId, reason]) => ({ tempId, reason })),
|
|
896
|
+
...(verification ? { verification } : {}),
|
|
719
897
|
target: await this.describeWriteTarget(),
|
|
720
898
|
...(missing.length > 0 ? { next: this.nextCommand(flags) } : {}),
|
|
721
899
|
};
|
|
722
900
|
if (flags.json) {
|
|
723
|
-
this.
|
|
901
|
+
this.printJsonOperation(result);
|
|
724
902
|
}
|
|
725
903
|
else {
|
|
726
904
|
this.log(`${existing.length} of ${planned.length} node(s) exist; ${missing.length} missing` +
|
|
@@ -732,6 +910,8 @@ class TasksCreateTree extends base_command_1.BaseCommand {
|
|
|
732
910
|
this.log(`- cannot check: ${tempId} — ${reason}`);
|
|
733
911
|
if (result.next)
|
|
734
912
|
this.log(`Next: ${result.next}`);
|
|
913
|
+
if (verification)
|
|
914
|
+
this.printSpecificationSummary(verification);
|
|
735
915
|
}
|
|
736
916
|
if (!ok)
|
|
737
917
|
this.exit(1);
|