@humwick/server 0.130.0 → 0.130.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/docs/guides/tools-administration.md +6 -1
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +58 -0
- package/docs/openapi.json +414 -1
- package/package.json +8 -17
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
- package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
- package/public/assets/fleet-C7jQWbw2.js +2 -0
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
- package/public/assets/index-CRHep3M9.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
- package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
- package/public/assets/projects-Br2Bd2h1.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
- package/public/assets/provider-display-DsuWMvVL.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
- package/public/assets/run-card-CpKqRbhg.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
- package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
- package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
- package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
- package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
- package/public/assets/use-project-list-59LheVP7.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
- package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/provider-setup.ts +34 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +18 -23
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/scripts/cd-config.ts +24 -3
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +7 -76
- package/src/bus.ts +19 -20
- package/src/cd-deploy-notify.ts +30 -2
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/root-missing.ts +2 -7
- package/src/ci/transition-notify.ts +7 -39
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +8 -2
- package/src/commands-db.ts +10 -6
- package/src/commands-write.ts +8 -0
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +13 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-lifecycle-write-ops.ts +1 -0
- package/src/db/agent-meta.ts +2 -2
- package/src/db/agent-ownership-write-ops.ts +4 -0
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +58 -7
- package/src/db/agents-write-ops.ts +28 -5
- package/src/db/agents.ts +81 -54
- package/src/db/artifacts-write-ops.ts +8 -3
- package/src/db/bus-outbox-write-ops.ts +1 -0
- package/src/db/channels-write-ops.ts +4 -0
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/claude-api-budget-ops.ts +5 -5
- package/src/db/claude-app-oauth.ts +4 -4
- package/src/db/codex-reset-consumes-write-ops.ts +3 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/commands-write-ops.ts +21 -0
- package/src/db/config-store-write-ops.ts +9 -2
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +9 -0
- package/src/db/continuations.ts +2 -2
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/delivery-write-ops.ts +5 -0
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts-write-ops.ts +14 -0
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-write-ops.ts +4 -0
- package/src/db/inbox.ts +0 -14
- package/src/db/index.ts +2 -0
- package/src/db/insights-write-ops.ts +1 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +20 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +7 -8
- package/src/db/long-running-work.ts +2 -2
- package/src/db/macos-privacy.ts +1 -1
- package/src/db/main-connection-writes.ts +23 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-reads-write-ops.ts +3 -0
- package/src/db/message-write-ops.ts +4 -0
- package/src/db/migrations.ts +7 -15
- package/src/db/orchestrators-async.ts +7 -3
- package/src/db/orchestrators-write-ops.ts +7 -1
- package/src/db/orchestrators.ts +21 -77
- package/src/db/pairs.ts +1 -13
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/prompt-versions-ops.ts +1 -0
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-catalog-write-ops.ts +4 -4
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-flap-messages-write-ops.ts +1 -0
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/provider-quota-lease-write-ops.ts +1 -0
- package/src/db/provider-quota-write-ops.ts +2 -0
- package/src/db/provisioning-write-ops.ts +9 -8
- package/src/db/read-op-marshaling-fixtures.ts +5 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/routing-policy.ts +3 -4
- package/src/db/schema.ts +9 -3
- package/src/db/secrets-broker-write-ops.ts +5 -5
- package/src/db/secrets-vault-write.ts +7 -7
- package/src/db/services-write-ops.ts +3 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-tree-cleanup.ts +3 -0
- package/src/db/stats-async.ts +4 -3
- package/src/db/task-entity.ts +23 -2
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-spawn-delegation.ts +1 -1
- package/src/db/teams-write-ops.ts +4 -4
- package/src/db/timer-cutover-write-ops.ts +7 -0
- package/src/db/timer-ingress-write-ops.ts +9 -0
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/timer-operator-write-ops.ts +14 -0
- package/src/db/timer-transfer-write-ops.ts +4 -0
- package/src/db/timer-write-ops.ts +14 -0
- package/src/db/token-db-write-ops.ts +21 -0
- package/src/db/token-standing.ts +15 -11
- package/src/db/user-settings-write-ops.ts +1 -0
- package/src/db/vault-backup.ts +2 -2
- package/src/db/vault-expiry.ts +2 -2
- package/src/db/vault-health.ts +3 -3
- package/src/db/vault-token-ops.ts +8 -8
- package/src/db/web-tool-call-ops.ts +3 -3
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/write-ops.ts +15 -1
- package/src/db/writer-fault-seam.ts +5 -2
- package/src/db/writer-gateway.ts +21 -12
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/host/disk-alert.ts +121 -0
- package/src/lifecycle-manager.ts +3 -2
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/critical-job-watchdog.ts +16 -17
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +3 -2
- package/src/maintenance/scheduler.ts +84 -128
- package/src/maintenance/stalled-delivery-pager.ts +6 -5
- package/src/maintenance/workspaces.ts +1 -1
- package/src/managed-policy.ts +31 -27
- package/src/mcp/index.ts +5 -2
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +4 -4
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/tool-groups.ts +1 -1
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-host-tools.ts +1 -1
- package/src/mcp-issue-ref-tools.ts +12 -11
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-profile-trust-tools.ts +4 -4
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-workflow-tools.ts +10 -3
- package/src/notification-types.ts +2 -1
- package/src/operator-alarm.ts +26 -11
- package/src/package-pack.ts +42 -39
- package/src/project-instructions.ts +4 -0
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/recipe-runner.ts +2 -2
- package/src/repo-config-source.ts +10 -4
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +6 -6
- package/src/routes/commands-listing.ts +4 -0
- package/src/routes/commands.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/host-resource-control.ts +4 -1
- package/src/routes/index.ts +10 -1
- package/src/routes/integrations.ts +24 -50
- package/src/routes/issue-refs.ts +7 -7
- package/src/routes/orchestrator-bootstrap.ts +3 -3
- package/src/routes/orchestrator-host-registration.ts +2 -2
- package/src/routes/orchestrator-host-utilization.ts +3 -1
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +4 -4
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +2 -2
- package/src/routes/provider-config.ts +9 -8
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/settings.ts +5 -5
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +5 -5
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/tokens.ts +12 -5
- package/src/routes/workflows.ts +20 -5
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +4 -2
- package/src/runtime-tokens.ts +50 -9
- package/src/security.ts +13 -20
- package/src/server-background.ts +1 -1
- package/src/server.ts +5 -2
- package/src/services/host-utilization.ts +23 -0
- package/src/services/idle-epics.ts +5 -6
- package/src/services/issue-lifecycle.ts +57 -61
- package/src/services/issue-refs.ts +9 -13
- package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
- package/src/services/kernel-timers-ingress.ts +1 -1
- package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
- package/src/services/landed-ancestry.ts +19 -3
- package/src/services/memory-areas.ts +15 -51
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-wake-digest.ts +1 -0
- package/src/services/profile-trust.ts +4 -3
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/restart-spawn.ts +61 -49
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +5 -1
- package/src/services/spawn-agent.ts +13 -2
- package/src/services/spawn-chain-inspector.ts +6 -13
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-tree-cleanup.ts +2 -2
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-state-reconcile.ts +6 -14
- package/src/services/team-templates.ts +9 -8
- package/src/services/transient-agent-reaper.ts +3 -1
- package/src/services/workflow-auto-start.ts +25 -13
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-deferred-cleanup.ts +4 -2
- package/src/services/workflow-effect-driver.ts +2 -0
- package/src/services/workflow-effects.ts +18 -11
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-reconcile.ts +13 -11
- package/src/services/workflow-run-view.ts +2 -0
- package/src/services/workflow-runs.ts +29 -13
- package/src/services/workflow-supervisor-state.ts +5 -0
- package/src/services/workflow-supervisor.ts +7 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +1 -1
- package/src/spawn-targets.ts +1 -1
- package/src/startup-context-injection.ts +1 -0
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward.ts +7 -6
- package/src/task-dispatch-live.ts +1 -1
- package/src/task-dispatcher.ts +1 -1
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/workspace-command-settle.ts +2 -1
- package/src/workspace-steward-wake.ts +2 -2
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -47
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -46
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/fleet-BL4UXS_k.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BK0WV6hF.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/routing-model-aliases.ts +0 -21
|
@@ -77,13 +77,20 @@ export function spawnDelegationState(agentId: string, launchProfile?: string) {
|
|
|
77
77
|
participating: Boolean((ancestors?.length !== 1 || launchProfile === "sub-coordinator")
|
|
78
78
|
&& (grant || ownTeam?.parentTeamId || (rootTeam && hasPrivateTeams(rootTeam.id)))), enabled: grant?.enabled === true,
|
|
79
79
|
grant, projectId: ancestors && ancestors.length > 1 ? delegatedProjectId(agentId) ?? projectIdForAgent(agent) : rootTeam?.projectId,
|
|
80
|
-
displaced: (ancestors ?? [agentId])
|
|
81
|
-
const ancestor = getAgent(id);
|
|
82
|
-
return isDisplacedSeat(id, ancestor?.teamId ?? seatTeam(id)?.id);
|
|
83
|
-
}),
|
|
80
|
+
displaced: displacedThroughDelegation(ancestors ?? [agentId]),
|
|
84
81
|
};
|
|
85
82
|
}
|
|
86
83
|
|
|
84
|
+
/** The agent's own seat was claimed, or that of an ancestor it reaches only through delegated launches. An
|
|
85
|
+
* ordinary child is inherited by the claimant and keeps its standing (#3773). */
|
|
86
|
+
function displacedThroughDelegation(ancestors: readonly string[]): boolean {
|
|
87
|
+
for (const id of ancestors) {
|
|
88
|
+
if (isDisplacedSeat(id, getAgent(id)?.teamId ?? seatTeam(id)?.id)) return true;
|
|
89
|
+
if (!delegatedLaunch(id)) return false;
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
87
94
|
/** Ordinary tokens avoid ancestry reads; private-team linkage survives grant removal. */
|
|
88
95
|
export function participatesInSpawnDelegation(agentId: string): boolean {
|
|
89
96
|
return Boolean(getDb().query(`WITH RECURSIVE lineage(id, depth) AS (
|
|
@@ -35,12 +35,14 @@ export const SPAWN_TREE_CLEANUP_READ_OPS = {
|
|
|
35
35
|
|
|
36
36
|
export const SPAWN_TREE_CLEANUP_WRITE_OPS = {
|
|
37
37
|
"spawnTree.markTransferred": {
|
|
38
|
+
offLoop: true,
|
|
38
39
|
idempotent: true,
|
|
39
40
|
fn: ({ id }: { id: string }): void => {
|
|
40
41
|
getDb().query("UPDATE spawn_tree_stops SET cleanup_effect_id = id WHERE id = ?").run(id);
|
|
41
42
|
},
|
|
42
43
|
},
|
|
43
44
|
"spawnTree.stopGoneCallers": {
|
|
45
|
+
offLoop: true,
|
|
44
46
|
idempotent: true,
|
|
45
47
|
fn: (_args: undefined, ctx: { now: number }): void => {
|
|
46
48
|
const rows = getDb().query(`WITH launches AS MATERIALIZED (
|
|
@@ -70,6 +72,7 @@ export const SPAWN_TREE_CLEANUP_WRITE_OPS = {
|
|
|
70
72
|
},
|
|
71
73
|
},
|
|
72
74
|
"spawnTree.prepareCleanup": {
|
|
75
|
+
offLoop: true,
|
|
73
76
|
idempotent: true,
|
|
74
77
|
fn: ({ agentId }: { agentId: string }, ctx: { now: number }): void => {
|
|
75
78
|
const ids = spawnTreeParentIds(agentId).filter(id => delegatedLaunch(id));
|
package/src/db/stats-async.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mainConnectionWrites } from "./main-connection-writes";
|
|
1
|
+
import { mainConnectionBootWrites, mainConnectionWrites } from "./main-connection-writes";
|
|
2
2
|
import { allWriterOps } from "./write-ops";
|
|
3
3
|
import { assertMainThreadState } from "./main-thread-state";
|
|
4
4
|
// Async reader-pool facades for DB-only stats. Health is a deliberate documented deferral: its
|
|
@@ -105,7 +105,7 @@ async function probeDatabaseLiveness(): Promise<HealthCheck> {
|
|
|
105
105
|
* `readerBackend`/`writerBackend` plus reader-pool depth/in-flight/shed counts unconditionally (the
|
|
106
106
|
* in-process backend's zeroed pool numbers ARE the "report that plainly" answer, not a special case).
|
|
107
107
|
*/
|
|
108
|
-
function buildDbGatewayCheck(stats: DbGatewayStats): HealthCheck {
|
|
108
|
+
export function buildDbGatewayCheck(stats: DbGatewayStats): HealthCheck {
|
|
109
109
|
const reader = stats.reader;
|
|
110
110
|
const readerActive = reader.backend !== "uninitialized";
|
|
111
111
|
const wedged = stats.writer.wedged;
|
|
@@ -119,7 +119,7 @@ function buildDbGatewayCheck(stats: DbGatewayStats): HealthCheck {
|
|
|
119
119
|
`reader=${stats.readerBackend}`,
|
|
120
120
|
`onLoopOps=${specs.length - offLoop}; writerThreadOps=${offLoop}`,
|
|
121
121
|
`mainConnectionWrites1h=${JSON.stringify(writes)}`,
|
|
122
|
-
...(wedged ? [
|
|
122
|
+
...(wedged ? [`writer wedged: op ${wedged.op} running ${Math.round(wedged.runningMs / 1000)}s`] : []),
|
|
123
123
|
...(shedCount > 0 ? [`${shedCount} reader shed(s)`] : []),
|
|
124
124
|
].join("; ");
|
|
125
125
|
return {
|
|
@@ -131,6 +131,7 @@ function buildDbGatewayCheck(stats: DbGatewayStats): HealthCheck {
|
|
|
131
131
|
onLoopOps: specs.length - offLoop,
|
|
132
132
|
writerThreadOps: offLoop,
|
|
133
133
|
mainConnectionWrites1h: Object.values(writes).reduce((sum, count) => sum + count, 0),
|
|
134
|
+
mainConnectionBootWrites: mainConnectionBootWrites(),
|
|
134
135
|
writerQueued: stats.writer.queued,
|
|
135
136
|
writerBusy: stats.writer.busy,
|
|
136
137
|
writerHighWater: stats.writer.highWater,
|
package/src/db/task-entity.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
type TaskStatus,
|
|
38
38
|
} from "../types";
|
|
39
39
|
import { parseJson } from "../utils";
|
|
40
|
+
import { repoRelativePath } from "@humwick/sdk/spawn-policy";
|
|
40
41
|
import { cleanEnum, cleanStringArray, optionalEnum } from "../validation";
|
|
41
42
|
import { getDb, writeTransaction, ValidationError } from "./connection.ts";
|
|
42
43
|
import { ownerForNewTask } from "./task-owner.ts";
|
|
@@ -108,6 +109,16 @@ function cleanTags(value: unknown, field = "tags"): string[] | undefined {
|
|
|
108
109
|
return cleanStringArray(value, field, { itemMax: 60, maxItems: 30 });
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
/** #3736 — repo-relative, normalized; a path that leaves the repo is refused. Stored null when empty. */
|
|
113
|
+
function taskPathsColumn(value: unknown): string | null {
|
|
114
|
+
const paths = (cleanStringArray(value, "paths", { itemMax: 300, maxItems: 50 }) ?? []).map((path, i) => {
|
|
115
|
+
const rel = repoRelativePath(path);
|
|
116
|
+
if (rel === undefined) throw new ValidationError(`paths[${i}] must be a repo-relative path inside the repo`);
|
|
117
|
+
return rel;
|
|
118
|
+
});
|
|
119
|
+
return paths.length ? JSON.stringify([...new Set(paths)]) : null;
|
|
120
|
+
}
|
|
121
|
+
|
|
111
122
|
// #1535 WS3 — backlog lifecycle state. Optional (like priority): absent stays undefined so a
|
|
112
123
|
// non-backlog task's column is NULL; a present-but-invalid value throws rather than silently
|
|
113
124
|
// dropping. The backlog→promoted flip is a distinct writer (setTaskBacklogState in db/backlog.ts).
|
|
@@ -196,6 +207,7 @@ export interface CreateDeliverableTaskInput {
|
|
|
196
207
|
complexity?: TaskComplexity;
|
|
197
208
|
context?: string;
|
|
198
209
|
terminalStage?: Task["terminalStage"];
|
|
210
|
+
onDeploy?: string;
|
|
199
211
|
doneWhen?: string; branch?: string;
|
|
200
212
|
teamId?: string;
|
|
201
213
|
projectId?: string;
|
|
@@ -206,6 +218,7 @@ export interface CreateDeliverableTaskInput {
|
|
|
206
218
|
latestSteer?: string;
|
|
207
219
|
dispatch?: TaskDispatch;
|
|
208
220
|
tags?: string[];
|
|
221
|
+
paths?: string[];
|
|
209
222
|
priority?: TaskPriority;
|
|
210
223
|
/** #1535 WS3 — seed the task directly into the backlog (`backlog`) so it shows up in the
|
|
211
224
|
* prioritized backlog query until promoted. Absent ⇒ not backlog-managed. */
|
|
@@ -225,6 +238,7 @@ export function createDeliverableTaskBody(input: CreateDeliverableTaskInput, now
|
|
|
225
238
|
const intent = requireText(input.intent, "intent", 1_000_000);
|
|
226
239
|
const dispatch = cleanTaskDispatch(input.dispatch);
|
|
227
240
|
const complexity = cleanTaskComplexity(input.complexity ?? dispatch?.complexity, "complexity") ?? DEFAULT_TASK_COMPLEXITY;
|
|
241
|
+
const onDeploy = optionalText(input.onDeploy, "onDeploy", 500);
|
|
228
242
|
const context = optionalText(input.context, "context", 1_000_000);
|
|
229
243
|
const branch = optionalText(input.branch, "branch", 500);
|
|
230
244
|
const taskProject = cleanTaskProject(input);
|
|
@@ -237,8 +251,8 @@ export function createDeliverableTaskBody(input: CreateDeliverableTaskInput, now
|
|
|
237
251
|
INSERT INTO tasks (
|
|
238
252
|
source, title, body, severity, status, target, occurrence_count, metadata,
|
|
239
253
|
created_at, updated_at, last_seen_at,
|
|
240
|
-
kind, intent, complexity, context, latest_steer, deliverable_stage, done_when, branch, team_id, project_id, repo, created_by, dispatch, tags, priority, backlog_state, owner
|
|
241
|
-
) VALUES (?, ?, ?, 'info', 'open', ?, 1, '{}', ?, ?, ?, '${DELIVERABLE_TASK_KIND}', ?, ?, ?, ?, 'none', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
254
|
+
kind, intent, complexity, context, latest_steer, deliverable_stage, done_when, branch, team_id, project_id, repo, created_by, dispatch, tags, paths, priority, backlog_state, owner, on_deploy
|
|
255
|
+
) VALUES (?, ?, ?, 'info', 'open', ?, 1, '{}', ?, ?, ?, '${DELIVERABLE_TASK_KIND}', ?, ?, ?, ?, 'none', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
242
256
|
`).run(
|
|
243
257
|
optionalText(input.source, "source", 200) ?? "coordinator",
|
|
244
258
|
title,
|
|
@@ -254,9 +268,11 @@ export function createDeliverableTaskBody(input: CreateDeliverableTaskInput, now
|
|
|
254
268
|
createdBy,
|
|
255
269
|
dispatch ? JSON.stringify(dispatch) : null,
|
|
256
270
|
tags.length ? JSON.stringify(tags) : null,
|
|
271
|
+
taskPathsColumn(input.paths),
|
|
257
272
|
priority ?? null,
|
|
258
273
|
backlogState ?? null,
|
|
259
274
|
ownerForNewTask(createdBy, teamId),
|
|
275
|
+
onDeploy ?? null,
|
|
260
276
|
);
|
|
261
277
|
const id = Number(result.lastInsertRowid);
|
|
262
278
|
if (input.terminalStage) getDb().query("UPDATE tasks SET terminal_stage = ? WHERE id = ?").run(input.terminalStage, id);
|
|
@@ -282,6 +298,7 @@ export interface UpdateDeliverableTaskInput {
|
|
|
282
298
|
complexity?: TaskComplexity;
|
|
283
299
|
context?: string;
|
|
284
300
|
latestSteer?: string;
|
|
301
|
+
onDeploy?: string;
|
|
285
302
|
doneWhen?: string;
|
|
286
303
|
dispatch?: TaskDispatch;
|
|
287
304
|
teamId?: string;
|
|
@@ -290,6 +307,8 @@ export interface UpdateDeliverableTaskInput {
|
|
|
290
307
|
actor?: string;
|
|
291
308
|
/** Absent ⇒ untouched. `[]` (or `null`) ⇒ clear all tags. */
|
|
292
309
|
tags?: string[] | null;
|
|
310
|
+
/** Absent ⇒ untouched. `[]` (or `null`) ⇒ clear all paths. */
|
|
311
|
+
paths?: string[] | null;
|
|
293
312
|
/** Absent ⇒ untouched. `null` ⇒ clear (priority has no default, unlike complexity). */
|
|
294
313
|
priority?: TaskPriority | null;
|
|
295
314
|
}
|
|
@@ -309,6 +328,7 @@ export function updateDeliverableTaskBody(id: number, input: UpdateDeliverableTa
|
|
|
309
328
|
if (input.complexity !== undefined) push("complexity", cleanTaskComplexity(input.complexity) ?? null);
|
|
310
329
|
if (input.context !== undefined) push("context", optionalText(input.context, "context", 1_000_000) ?? null);
|
|
311
330
|
if (input.latestSteer !== undefined) push("latest_steer", optionalText(input.latestSteer, "latestSteer", 1_000_000) ?? null);
|
|
331
|
+
if (input.onDeploy !== undefined) push("on_deploy", optionalText(input.onDeploy, "onDeploy", 500) ?? null);
|
|
312
332
|
if (input.doneWhen !== undefined) push("done_when", optionalText(input.doneWhen, "doneWhen", 1_000_000) ?? null);
|
|
313
333
|
if (input.teamId !== undefined) push("team_id", optionalText(input.teamId, "teamId", 200) ?? null);
|
|
314
334
|
if (input.projectId !== undefined || input.repo !== undefined) {
|
|
@@ -321,6 +341,7 @@ export function updateDeliverableTaskBody(id: number, input: UpdateDeliverableTa
|
|
|
321
341
|
const tags = input.tags === null ? [] : (cleanTags(input.tags) ?? []);
|
|
322
342
|
push("tags", tags.length ? JSON.stringify(tags) : null);
|
|
323
343
|
}
|
|
344
|
+
if (input.paths !== undefined) push("paths", taskPathsColumn(input.paths ?? []));
|
|
324
345
|
if (input.terminalStage !== undefined) push("terminal_stage", input.terminalStage === null ? null : cleanTaskTerminalStage(input.terminalStage));
|
|
325
346
|
if (input.priority !== undefined) push("priority", input.priority === null ? null : requireTaskPriority(input.priority));
|
|
326
347
|
if (sets.length > 0) {
|
package/src/db/task-list.ts
CHANGED
|
@@ -41,7 +41,8 @@ function buildDeliverableTasksWhere(filter: ListDeliverableTasksFilter): { claus
|
|
|
41
41
|
}
|
|
42
42
|
if (filter.staleOwnerGone) conditions.push(STALE_TASK_OWNER_SQL);
|
|
43
43
|
if (filter.status) { conditions.push("status = ?"); params.push(filter.status); }
|
|
44
|
-
if (filter.deliverableStage)
|
|
44
|
+
if (filter.deliverableStage === "awaiting-deploy") conditions.push("deliverable_stage IN ('landed-on-main', 'deploying')");
|
|
45
|
+
else if (filter.deliverableStage) { conditions.push("deliverable_stage = ?"); params.push(filter.deliverableStage); }
|
|
45
46
|
if (filter.teamId) { conditions.push("team_id = ?"); params.push(filter.teamId); }
|
|
46
47
|
if (filter.createdBy) { conditions.push("created_by = ?"); params.push(filter.createdBy); }
|
|
47
48
|
if (filter.ownerAgentId) { conditions.push("owner_agent_id = ?"); params.push(filter.ownerAgentId); }
|
|
@@ -87,6 +88,7 @@ function taskListItem(task: Task): TaskListItem {
|
|
|
87
88
|
status: task.status,
|
|
88
89
|
kind: task.kind,
|
|
89
90
|
...(task.validationItems ? { validationItems: task.validationItems } : {}),
|
|
91
|
+
...(task.onDeploy ? { onDeploy: task.onDeploy } : {}),
|
|
90
92
|
...(task.terminalStage ? { terminalStage: task.terminalStage } : {}),
|
|
91
93
|
...(task.completedAt ? { completedAt: task.completedAt } : {}),
|
|
92
94
|
...(task.staleOwnerGone ? { staleOwnerGone: true } : {}),
|
package/src/db/tasks.ts
CHANGED
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
import { taskVisibilitySql, type ViewerScope } from "./viewer-scope";
|
|
2
|
-
import {
|
|
3
|
-
import { isRecord, stringValue, isMechanicalMessageKind } from "@humwick/sdk";
|
|
4
|
-
import { ORCHESTRATOR_PROTOCOL_VERSION, VERSION } from "../config.ts";
|
|
5
|
-
import { parseJson } from "../utils";
|
|
6
|
-
import { isLiveIsolatedWorkspace } from "../workspace-phase";
|
|
7
|
-
import {
|
|
8
|
-
CONTRACT_REQUIREMENTS,
|
|
9
|
-
contractCompatibility,
|
|
10
|
-
parseRuntimeCapabilities,
|
|
11
|
-
parseRuntimeContracts,
|
|
12
|
-
parseRuntimePackage,
|
|
13
|
-
type RuntimeContracts,
|
|
14
|
-
} from "../contracts";
|
|
15
|
-
import { STALE_TTL_MS, DAY_MS, CLAIM_LEASE_MS, POOL_CLAIM_LEASE_MS, WORKSPACE_MERGE_LEASE_MS } from "../config";
|
|
16
|
-
import { matchAgents } from "../agent-ref";
|
|
2
|
+
import { CLAIM_LEASE_MS } from "../config";
|
|
17
3
|
import { getAgent, validateAgentSession } from "./agents.ts";
|
|
18
4
|
import { messageTaskClosed } from "./claim-sql.ts";
|
|
19
5
|
import { ClaimError, getDb, writeTransaction } from "./connection.ts";
|
|
@@ -51,7 +37,6 @@ export function taskMessageBody(task: Pick<Task, "id" | "source" | "severity" |
|
|
|
51
37
|
return lines.join("\n");
|
|
52
38
|
}
|
|
53
39
|
|
|
54
|
-
|
|
55
40
|
export function getTask(id: number): Task | null {
|
|
56
41
|
const row = getDb().query(`${TASK_SELECT} WHERE id = ?`).get(id) as any;
|
|
57
42
|
return row ? rowToTask(row) : null;
|
|
@@ -85,7 +70,6 @@ export function listTasks(filter?: { viewer?: ViewerScope | null; status?: strin
|
|
|
85
70
|
return (getDb().query(`${TASK_SELECT} ${where} ORDER BY updated_at DESC LIMIT ?`).all(...params) as any[]).map(rowToTask);
|
|
86
71
|
}
|
|
87
72
|
|
|
88
|
-
|
|
89
73
|
/** Deliverable stages meaning the work already left the worker's hands (#2036): a Task sitting in
|
|
90
74
|
* `in_progress` while its land gate runs is not a stalled worker. Excluded IN SQL, not after the
|
|
91
75
|
* fact — these rows carry the OLDEST claims, so a post-LIMIT filter would let them consume the
|
|
@@ -45,5 +45,5 @@ export function setTeamSpawnDelegationBody(args: SetTeamDelegationArgs, now: num
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export const TEAM_SPAWN_DELEGATION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = {
|
|
48
|
-
"teams.spawnDelegation.set": { idempotent: true, fn: (args: SetTeamDelegationArgs, ctx) => setTeamSpawnDelegationBody(args, ctx.now) },
|
|
48
|
+
"teams.spawnDelegation.set": { offLoop: true, idempotent: true, fn: (args: SetTeamDelegationArgs, ctx) => setTeamSpawnDelegationBody(args, ctx.now) },
|
|
49
49
|
};
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
11
11
|
|
|
12
12
|
export const TEAMS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
13
|
-
"teams.zeroMembers.set": { idempotent: true, fn: (a: { teamId: string; ts: number }) => setTeamZeroMembersSince(a.teamId, a.ts) },
|
|
14
|
-
"teams.zeroMembers.clear": { idempotent: true, fn: (a: { teamId: string }, ctx) => clearTeamZeroMembersSince(a.teamId, ctx.now) },
|
|
15
|
-
"teams.brief.set": { idempotent: true, fn: (a: Parameters<typeof setTeamBrief>[0], ctx) => setTeamBrief(a, ctx.now) },
|
|
16
|
-
"teams.dissolve": { idempotent: false, fn: (a: { teamId: string; input?: Parameters<typeof dissolveTeam>[1] }, ctx) => dissolveTeam(a.teamId, a.input, ctx.now) },
|
|
13
|
+
"teams.zeroMembers.set": { offLoop: true, idempotent: true, fn: (a: { teamId: string; ts: number }) => setTeamZeroMembersSince(a.teamId, a.ts) },
|
|
14
|
+
"teams.zeroMembers.clear": { offLoop: true, idempotent: true, fn: (a: { teamId: string }, ctx) => clearTeamZeroMembersSince(a.teamId, ctx.now) },
|
|
15
|
+
"teams.brief.set": { offLoop: true, idempotent: true, fn: (a: Parameters<typeof setTeamBrief>[0], ctx) => setTeamBrief(a, ctx.now) },
|
|
16
|
+
"teams.dissolve": { offLoop: true, idempotent: false, fn: (a: { teamId: string; input?: Parameters<typeof dissolveTeam>[1] }, ctx) => dissolveTeam(a.teamId, a.input, ctx.now) },
|
|
17
17
|
});
|
|
@@ -242,6 +242,7 @@ function rebaseBootstrapEpoch(args: {
|
|
|
242
242
|
|
|
243
243
|
export const TIMER_CUTOVER_WRITE_OPS = {
|
|
244
244
|
"timers.cutover.releaseInterruptedTransfer": {
|
|
245
|
+
offLoop: true,
|
|
245
246
|
idempotent: true,
|
|
246
247
|
fn: (args: { now?: number } | undefined, ctx: WriterOpContext) =>
|
|
247
248
|
releaseInterruptedCutoverTransfer(args?.now ?? ctx.now),
|
|
@@ -249,26 +250,32 @@ export const TIMER_CUTOVER_WRITE_OPS = {
|
|
|
249
250
|
// A kernel batch has already durably changed timer state by the time these run. Never shed the
|
|
250
251
|
// resume cursor/journal acknowledgement or a restart will repeat a committed side effect.
|
|
251
252
|
"timers.cutoverOperation.commitBackfillBatch": {
|
|
253
|
+
offLoop: true,
|
|
252
254
|
idempotent: false,
|
|
253
255
|
fn: (args: Parameters<typeof commitBackfillBatch>[0]) => commitBackfillBatch(args),
|
|
254
256
|
},
|
|
255
257
|
"timers.cutoverOperation.commitBootstrapBatch": {
|
|
258
|
+
offLoop: true,
|
|
256
259
|
idempotent: false,
|
|
257
260
|
fn: (args: Parameters<typeof commitBootstrapBatch>[0]) => commitBootstrapBatch(args),
|
|
258
261
|
},
|
|
259
262
|
"timers.cutoverOperation.commitTransferBatch": {
|
|
263
|
+
offLoop: true,
|
|
260
264
|
idempotent: false,
|
|
261
265
|
fn: (args: Parameters<typeof commitTransferBatch>[0]) => commitTransferBatch(args),
|
|
262
266
|
},
|
|
263
267
|
"timers.cutoverOperation.appendJournal": {
|
|
268
|
+
offLoop: true,
|
|
264
269
|
idempotent: false,
|
|
265
270
|
fn: (args: Parameters<typeof appendOperationJournal>[0]) => appendOperationJournal(args),
|
|
266
271
|
},
|
|
267
272
|
"timers.cutoverOperation.complete": {
|
|
273
|
+
offLoop: true,
|
|
268
274
|
idempotent: false,
|
|
269
275
|
fn: (args: Parameters<typeof completeOperation>[0]) => completeOperation(args),
|
|
270
276
|
},
|
|
271
277
|
"timers.cutoverOperation.rebaseBootstrapEpoch": {
|
|
278
|
+
offLoop: true,
|
|
272
279
|
idempotent: false,
|
|
273
280
|
fn: (args: Parameters<typeof rebaseBootstrapEpoch>[0]) => rebaseBootstrapEpoch(args),
|
|
274
281
|
},
|
|
@@ -78,12 +78,15 @@ export interface AcceptTimerIngressBootstrapOpArgs {
|
|
|
78
78
|
|
|
79
79
|
export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
80
80
|
"timerIngress.acceptCreate": {
|
|
81
|
+
offLoop: true,
|
|
81
82
|
idempotent: true,
|
|
82
83
|
fn: (args: AcceptTimerIngressCreateOpArgs) =>
|
|
83
84
|
acceptTimerIngressCreateInTx({ source: args.source, storedKey: args.storedKey, at: args.at }),
|
|
84
85
|
},
|
|
85
86
|
|
|
86
87
|
"timerIngress.acceptCancel": {
|
|
88
|
+
|
|
89
|
+
offLoop: true,
|
|
87
90
|
idempotent: true,
|
|
88
91
|
fn: (args: AcceptTimerIngressCancelOpArgs) =>
|
|
89
92
|
acceptTimerIngressCancelInTx({
|
|
@@ -95,6 +98,8 @@ export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = O
|
|
|
95
98
|
},
|
|
96
99
|
|
|
97
100
|
"timerIngress.acceptBootstrapCreate": {
|
|
101
|
+
|
|
102
|
+
offLoop: true,
|
|
98
103
|
idempotent: true,
|
|
99
104
|
fn: (args: AcceptTimerIngressBootstrapOpArgs) =>
|
|
100
105
|
acceptTimerIngressBootstrapCreateInTx({
|
|
@@ -107,6 +112,7 @@ export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = O
|
|
|
107
112
|
|
|
108
113
|
/** Collapse one unsettled intent to `terminal` (supersede / tombstone / malformed quarantine). */
|
|
109
114
|
"timerIngress.settleTerminal": {
|
|
115
|
+
offLoop: true,
|
|
110
116
|
idempotent: true,
|
|
111
117
|
fn: (args: { seq: number; reason: TimerIngressTerminalReason; error?: string; ownerId: string; at: number }) =>
|
|
112
118
|
settleTimerIngressTerminal({
|
|
@@ -120,6 +126,7 @@ export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = O
|
|
|
120
126
|
|
|
121
127
|
/** CAS-claim an intent for apply (state + lease). Returns false when another applier holds it. */
|
|
122
128
|
"timerIngress.claim": {
|
|
129
|
+
offLoop: true,
|
|
123
130
|
idempotent: true,
|
|
124
131
|
fn: (args: { seq: number; ownerId: string; leaseMs: number; at: number }) =>
|
|
125
132
|
claimTimerIngressIntent({ seq: args.seq, ownerId: args.ownerId, leaseMs: args.leaseMs, at: args.at }),
|
|
@@ -127,6 +134,7 @@ export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = O
|
|
|
127
134
|
|
|
128
135
|
/** Settle a successfully applied intent and advance the terminal-inclusive watermark. */
|
|
129
136
|
"timerIngress.settleApplied": {
|
|
137
|
+
offLoop: true,
|
|
130
138
|
idempotent: true,
|
|
131
139
|
fn: (args: { seq: number; ownerId: string; at: number }) => {
|
|
132
140
|
settleTimerIngressApplied({ seq: args.seq, ownerId: args.ownerId, at: args.at });
|
|
@@ -136,6 +144,7 @@ export const TIMER_INGRESS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = O
|
|
|
136
144
|
|
|
137
145
|
/** Drop our lease after a failed apply so the next pass retries immediately, keeping the error. */
|
|
138
146
|
"timerIngress.releaseAfterFailure": {
|
|
147
|
+
offLoop: true,
|
|
139
148
|
idempotent: true,
|
|
140
149
|
fn: (args: { seq: number; error: string; ownerId: string }) => {
|
|
141
150
|
releaseTimerIngressLeaseAfterFailure({ seq: args.seq, error: args.error, ownerId: args.ownerId });
|
package/src/db/timer-ingress.ts
CHANGED
|
@@ -104,13 +104,18 @@ function rowToIntent(row: IntentDbRow): TimerIngressIntentRow {
|
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
const installedOn = new WeakSet<object>();
|
|
108
|
+
|
|
107
109
|
/** Idempotent, crash-safe schema install (one transaction; re-running over existing data is a
|
|
108
110
|
* no-op). Bootstrap DDL — it runs ONCE at startup as its own committed statement, never lazily
|
|
109
111
|
* inside an op, so a rolled-back op can never undo the schema it ran against (§4 allowlist). */
|
|
110
112
|
export function installTimerIngressSchema(
|
|
111
|
-
options: { requestKeyMigrationFaults?: TimerIngressRequestKeyMigrationFaults } = {},
|
|
113
|
+
options: { requestKeyMigrationFaults?: TimerIngressRequestKeyMigrationFaults; ifNotInstalled?: boolean } = {},
|
|
112
114
|
): void {
|
|
113
115
|
const db = getDb();
|
|
116
|
+
// #1870 S7: `startServer` installs it before bind (the boot exception); `createTimerIngress` passes
|
|
117
|
+
// `ifNotInstalled` so its later call runs no DDL on the main connection. Explicit calls always install.
|
|
118
|
+
if (options.ifNotInstalled && installedOn.has(db)) return;
|
|
114
119
|
db.transaction(() => {
|
|
115
120
|
// AUTOINCREMENT is deliberate: `seq` must be monotone and NEVER reused (the watermark's meaning
|
|
116
121
|
// depends on it — and it doubles as the per-timer apply FENCE), even if settled rows are pruned.
|
|
@@ -165,6 +170,7 @@ export function installTimerIngressSchema(
|
|
|
165
170
|
db.run("INSERT OR IGNORE INTO timer_ingress_watermark (id, applied_seq, updated_at) VALUES (1, 0, 0)");
|
|
166
171
|
options.requestKeyMigrationFaults?.beforeCommit?.();
|
|
167
172
|
}).immediate();
|
|
173
|
+
installedOn.add(db);
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
// ── Reads ───────────────────────────────────────────────────────────────────────────────────────
|
|
@@ -39,14 +39,17 @@ import {
|
|
|
39
39
|
export const TIMER_OPERATOR_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
40
40
|
// --- Dedup-by-construction: idempotent, no key required. ------------------------------------------
|
|
41
41
|
"timerOperator.acceptCommand": {
|
|
42
|
+
offLoop: true,
|
|
42
43
|
idempotent: true,
|
|
43
44
|
fn: (args: AcceptAuditedCommandArgs, ctx: WriterOpContext) => acceptAuditedCommandBody(args, ctx.now),
|
|
44
45
|
},
|
|
45
46
|
"timerOperator.ensureOperation": {
|
|
47
|
+
offLoop: true,
|
|
46
48
|
idempotent: true,
|
|
47
49
|
fn: (args: Omit<EnsureOperationArgs, "now">, ctx: WriterOpContext) => ensureOperationBody({ ...args, now: ctx.now }),
|
|
48
50
|
},
|
|
49
51
|
"timerOperator.resetTerminal": {
|
|
52
|
+
offLoop: true,
|
|
50
53
|
// An occupied terminal slot deletes a row; replaying its body with `acceptAlreadyCleared: false`
|
|
51
54
|
// throws. The facade therefore supplies a durable request-scoped key for retry replay.
|
|
52
55
|
idempotent: false,
|
|
@@ -54,48 +57,59 @@ export const TIMER_OPERATOR_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> =
|
|
|
54
57
|
resetTerminalOperationBody(args.requestId, args.acceptAlreadyCleared),
|
|
55
58
|
},
|
|
56
59
|
"timerOperator.finishAbort": {
|
|
60
|
+
offLoop: true,
|
|
57
61
|
idempotent: true,
|
|
58
62
|
fn: (_args: Record<string, never> | undefined, ctx: WriterOpContext) => finishAbortBody(ctx.now),
|
|
59
63
|
},
|
|
60
64
|
"timerOperator.pinTransferLeg": {
|
|
65
|
+
offLoop: true,
|
|
61
66
|
idempotent: true,
|
|
62
67
|
fn: (args: Omit<PinTransferLegArgs, "now">, ctx: WriterOpContext) => pinTransferLegBody({ ...args, now: ctx.now }),
|
|
63
68
|
},
|
|
64
69
|
"timerOperator.finishTransfer": {
|
|
70
|
+
offLoop: true,
|
|
65
71
|
idempotent: true,
|
|
66
72
|
fn: (args: Omit<FinishTransferArgs, "now">, ctx: WriterOpContext) => finishTransferBody({ ...args, now: ctx.now }),
|
|
67
73
|
},
|
|
68
74
|
|
|
69
75
|
// --- No in-body dedup guard: idempotent false, facade supplies a per-call key. --------------------
|
|
70
76
|
"timerOperator.claimOperation": {
|
|
77
|
+
offLoop: true,
|
|
71
78
|
idempotent: false,
|
|
72
79
|
fn: (args: Omit<ClaimOperationArgs, "now">, ctx: WriterOpContext) => claimOperationBody({ ...args, now: ctx.now }),
|
|
73
80
|
},
|
|
74
81
|
"timerOperator.commitBackfillBatch": {
|
|
82
|
+
offLoop: true,
|
|
75
83
|
idempotent: false,
|
|
76
84
|
fn: (args: Omit<CommitBackfillBatchArgs, "at">, ctx: WriterOpContext) => commitBackfillBatchBody({ ...args, at: ctx.now }),
|
|
77
85
|
},
|
|
78
86
|
"timerOperator.epochRebase": {
|
|
87
|
+
offLoop: true,
|
|
79
88
|
idempotent: false,
|
|
80
89
|
fn: (args: Omit<EpochRebaseArgs, "at">, ctx: WriterOpContext) => epochRebaseBody({ ...args, at: ctx.now }),
|
|
81
90
|
},
|
|
82
91
|
"timerOperator.commitBootstrapBatch": {
|
|
92
|
+
offLoop: true,
|
|
83
93
|
idempotent: false,
|
|
84
94
|
fn: (args: Omit<CommitBootstrapBatchArgs, "at">, ctx: WriterOpContext) => commitBootstrapBatchBody({ ...args, at: ctx.now }),
|
|
85
95
|
},
|
|
86
96
|
"timerOperator.completeStage9": {
|
|
97
|
+
offLoop: true,
|
|
87
98
|
idempotent: false,
|
|
88
99
|
fn: (args: Omit<CompleteStage9Args, "at">, ctx: WriterOpContext) => completeStage9Body({ ...args, at: ctx.now }),
|
|
89
100
|
},
|
|
90
101
|
"timerOperator.beginAbort": {
|
|
102
|
+
offLoop: true,
|
|
91
103
|
idempotent: false,
|
|
92
104
|
fn: (args: Omit<BeginAbortArgs, "now">, ctx: WriterOpContext) => beginAbortBody({ ...args, now: ctx.now }),
|
|
93
105
|
},
|
|
94
106
|
"timerOperator.recordG1Transfer": {
|
|
107
|
+
offLoop: true,
|
|
95
108
|
idempotent: false,
|
|
96
109
|
fn: (args: Omit<RecordG1TransferArgs, "now">, ctx: WriterOpContext) => recordG1TransferBody({ ...args, now: ctx.now }),
|
|
97
110
|
},
|
|
98
111
|
"timerOperator.commitTransferBatch": {
|
|
112
|
+
offLoop: true,
|
|
99
113
|
idempotent: false,
|
|
100
114
|
fn: (args: Omit<CommitTransferBatchArgs, "at">, ctx: WriterOpContext) => commitTransferBatchBody({ ...args, at: ctx.now }),
|
|
101
115
|
},
|
|
@@ -21,18 +21,22 @@ function withNow(args: TransferArgs, ctx: WriterOpContext): TimerMessageTransfer
|
|
|
21
21
|
* the same durable journal row or is refused; it cannot move ownership twice. */
|
|
22
22
|
export const TIMER_TRANSFER_WRITE_OPS = {
|
|
23
23
|
"timers.transfer.prepareForward": {
|
|
24
|
+
offLoop: true,
|
|
24
25
|
idempotent: true,
|
|
25
26
|
fn: (args: TransferArgs, ctx: WriterOpContext) => prepareForwardTimerMessageTransfer(withNow(args, ctx)),
|
|
26
27
|
},
|
|
27
28
|
"timers.transfer.prepareReverse": {
|
|
29
|
+
offLoop: true,
|
|
28
30
|
idempotent: true,
|
|
29
31
|
fn: (args: TransferArgs, ctx: WriterOpContext) => prepareReverseTimerMessageTransfer(withNow(args, ctx)),
|
|
30
32
|
},
|
|
31
33
|
"timers.transfer.commitForward": {
|
|
34
|
+
offLoop: true,
|
|
32
35
|
idempotent: true,
|
|
33
36
|
fn: (args: TransferArgs, ctx: WriterOpContext) => commitForwardTimerMessageTransfer(withNow(args, ctx)),
|
|
34
37
|
},
|
|
35
38
|
"timers.transfer.commitReverse": {
|
|
39
|
+
offLoop: true,
|
|
36
40
|
idempotent: true,
|
|
37
41
|
fn: (args: TransferArgs, ctx: WriterOpContext) => commitReverseTimerMessageTransfer(withNow(args, ctx)),
|
|
38
42
|
},
|
|
@@ -136,6 +136,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
136
136
|
* `row.id` as that key: it is unique per logical create by construction and stable across a retry.
|
|
137
137
|
*/
|
|
138
138
|
"timers.create": {
|
|
139
|
+
offLoop: true,
|
|
139
140
|
idempotent: false,
|
|
140
141
|
fn: (args: CreateTimerOpArgs, ctx: WriterOpContext) =>
|
|
141
142
|
insertScheduledTimerWithinQuota(args.row, args.caps, ctx.now, QUOTA_FAULTS, args.route ?? "direct"),
|
|
@@ -143,6 +144,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
143
144
|
|
|
144
145
|
/** CAS claim of a due timer. Re-applying either re-wins the same lease or returns null — idempotent. */
|
|
145
146
|
"timers.claim": {
|
|
147
|
+
offLoop: true,
|
|
146
148
|
idempotent: true,
|
|
147
149
|
fn: (args: ClaimTimerOpArgs, ctx: WriterOpContext) =>
|
|
148
150
|
claimScheduledTimer(args.id, args.owner, args.now ?? ctx.now, args.leaseMs),
|
|
@@ -155,6 +157,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
155
157
|
* matching replay writes the identical row.
|
|
156
158
|
*/
|
|
157
159
|
"timers.completeRun": {
|
|
160
|
+
offLoop: true,
|
|
158
161
|
idempotent: true,
|
|
159
162
|
fn: (args: CompleteTimerRunOpArgs, ctx: WriterOpContext) =>
|
|
160
163
|
completeScheduledTimerRun({ timer: args.timer, messageId: args.messageId, now: args.now ?? ctx.now }),
|
|
@@ -162,6 +165,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
162
165
|
|
|
163
166
|
/** Same claim-predicate shape as `completeRun`, so a replay is a no-op — idempotent. */
|
|
164
167
|
"timers.recordFailure": {
|
|
168
|
+
offLoop: true,
|
|
165
169
|
idempotent: true,
|
|
166
170
|
fn: (args: RecordTimerFailureOpArgs, ctx: WriterOpContext) =>
|
|
167
171
|
recordScheduledTimerFailure({
|
|
@@ -175,6 +179,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
175
179
|
|
|
176
180
|
/** `WHERE enabled = 1` makes the second cancel a no-op that returns the same row — idempotent. */
|
|
177
181
|
"timers.cancel": {
|
|
182
|
+
offLoop: true,
|
|
178
183
|
idempotent: true,
|
|
179
184
|
fn: (args: { id: string; route?: TimerMessageMutationRoute }) =>
|
|
180
185
|
cancelScheduledTimer(args.id, args.route ?? "direct"),
|
|
@@ -182,6 +187,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
182
187
|
|
|
183
188
|
/** Unconditional UPDATE to a fixed end state — re-applying reaches the same state. */
|
|
184
189
|
"timers.disable": {
|
|
190
|
+
offLoop: true,
|
|
185
191
|
idempotent: true,
|
|
186
192
|
fn: (args: { id: string; reason: string }) => disableScheduledTimer(args.id, args.reason),
|
|
187
193
|
},
|
|
@@ -189,6 +195,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
189
195
|
/** UPDATE to a caller-supplied absolute `nextRunAt` — replaying writes the same instant, so it is
|
|
190
196
|
* the same end state. Idempotent. */
|
|
191
197
|
"timers.deferRun": {
|
|
198
|
+
offLoop: true,
|
|
192
199
|
idempotent: true,
|
|
193
200
|
fn: (args: { id: string; nextRunAt: number }) => deferScheduledTimerRun(args.id, args.nextRunAt),
|
|
194
201
|
},
|
|
@@ -196,6 +203,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
196
203
|
/** Read-modify-write of the command JSON, folded into the op. Writing the same commandId twice is
|
|
197
204
|
* the same end state — idempotent. */
|
|
198
205
|
"timers.setCommandId": {
|
|
206
|
+
offLoop: true,
|
|
199
207
|
idempotent: true,
|
|
200
208
|
fn: (args: { timerId: string; commandId: string }) => setScheduledTimerCommandId(args.timerId, args.commandId),
|
|
201
209
|
},
|
|
@@ -203,6 +211,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
203
211
|
/** Read-modify-write merge of a command patch, folded into the op. Re-merging the same patch onto
|
|
204
212
|
* the already-merged row is the same end state — idempotent. */
|
|
205
213
|
"timers.updateCommand": {
|
|
214
|
+
offLoop: true,
|
|
206
215
|
idempotent: true,
|
|
207
216
|
fn: (args: UpdateTimerCommandOpArgs) => updateScheduledTimerCommand(args.timerId, args.patch),
|
|
208
217
|
},
|
|
@@ -214,6 +223,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
214
223
|
* decide the same run twice.
|
|
215
224
|
*/
|
|
216
225
|
"timers.decideFire": {
|
|
226
|
+
offLoop: true,
|
|
217
227
|
idempotent: true,
|
|
218
228
|
fn: (args: { input: Omit<DecideLegacyTimerMessageFireInput, "now">; now?: number }, ctx: WriterOpContext) =>
|
|
219
229
|
decideLegacyTimerMessageFire({ ...args.input, now: args.now ?? ctx.now }, FIRE_DECISION_FAULTS),
|
|
@@ -221,6 +231,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
221
231
|
|
|
222
232
|
/** Returns `already-sent` on replay rather than re-marking — idempotent. */
|
|
223
233
|
"timers.markFireSent": {
|
|
234
|
+
offLoop: true,
|
|
224
235
|
idempotent: true,
|
|
225
236
|
fn: (args: { timerId: string; run: number; messageId: number }, ctx: WriterOpContext) =>
|
|
226
237
|
markTimerMessageFireSent(args.timerId, args.run, args.messageId, ctx.now),
|
|
@@ -232,6 +243,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
232
243
|
* therefore requires a key; the facade passes one derived from the failing attempt.
|
|
233
244
|
*/
|
|
234
245
|
"timers.recordFireSendFailure": {
|
|
246
|
+
offLoop: true,
|
|
235
247
|
idempotent: false,
|
|
236
248
|
fn: (args: RecordFireSendFailureOpArgs, ctx: WriterOpContext) =>
|
|
237
249
|
recordTimerMessageFireSendFailure({
|
|
@@ -246,6 +258,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
246
258
|
|
|
247
259
|
/** DELETE of a transient failure record — re-applying deletes nothing. Idempotent. */
|
|
248
260
|
"timers.clearFireSendFailure": {
|
|
261
|
+
offLoop: true,
|
|
249
262
|
idempotent: true,
|
|
250
263
|
fn: (args: { timerId: string; run: number }) => {
|
|
251
264
|
clearTimerMessageFireSendFailure(args.timerId, args.run);
|
|
@@ -255,6 +268,7 @@ export const TIMER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
255
268
|
|
|
256
269
|
/** Monotone fence advance (`applied_fence < fence` guard) — re-applying is a no-op. Idempotent. */
|
|
257
270
|
"timers.markAuthorityApplied": {
|
|
271
|
+
offLoop: true,
|
|
258
272
|
idempotent: true,
|
|
259
273
|
fn: (args: { timerId: string; fence: number }, ctx: WriterOpContext) => {
|
|
260
274
|
markLegacyMessageAuthorityApplied(args.timerId, args.fence, ctx.now);
|