@kya-os/cli 1.8.1 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent.d.ts +35 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +321 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/build.js +2 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/checkpoint-init.d.ts +1 -1
- package/dist/commands/checkpoint-init.d.ts.map +1 -1
- package/dist/commands/checkpoint-init.js +8 -41
- package/dist/commands/checkpoint-init.js.map +1 -1
- package/dist/commands/claim.js +2 -2
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/dco.d.ts +59 -0
- package/dist/commands/dco.d.ts.map +1 -1
- package/dist/commands/dco.js +280 -5
- package/dist/commands/dco.js.map +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -24
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.js +6 -6
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/identity.js +3 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/init-stages.d.ts +141 -0
- package/dist/commands/init-stages.d.ts.map +1 -0
- package/dist/commands/init-stages.js +684 -0
- package/dist/commands/init-stages.js.map +1 -0
- package/dist/commands/init.d.ts +46 -16
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +229 -279
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/orchestrator.d.ts +18 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +251 -0
- package/dist/commands/orchestrator.js.map +1 -0
- package/dist/commands/register.d.ts +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +35 -7
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/review.d.ts +48 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +220 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/rotate.js +4 -4
- package/dist/commands/rotate.js.map +1 -1
- package/dist/commands/score.d.ts +15 -0
- package/dist/commands/score.d.ts.map +1 -0
- package/dist/commands/score.js +471 -0
- package/dist/commands/score.js.map +1 -0
- package/dist/commands/start.js +3 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verify.js +6 -6
- package/dist/commands/verify.js.map +1 -1
- package/dist/dco.d.ts +4 -0
- package/dist/dco.d.ts.map +1 -0
- package/dist/dco.js +23 -0
- package/dist/dco.js.map +1 -0
- package/dist/index.js +52 -9
- package/dist/orchestrator/daemon.d.ts +137 -0
- package/dist/orchestrator/daemon.d.ts.map +1 -0
- package/dist/orchestrator/daemon.js +242 -0
- package/dist/orchestrator/daemon.js.map +1 -0
- package/dist/orchestrator/db/dispatches.d.ts +108 -0
- package/dist/orchestrator/db/dispatches.d.ts.map +1 -0
- package/dist/orchestrator/db/dispatches.js +122 -0
- package/dist/orchestrator/db/dispatches.js.map +1 -0
- package/dist/orchestrator/db/index.d.ts +50 -0
- package/dist/orchestrator/db/index.d.ts.map +1 -0
- package/dist/orchestrator/db/index.js +116 -0
- package/dist/orchestrator/db/index.js.map +1 -0
- package/dist/orchestrator/db/journal.d.ts +93 -0
- package/dist/orchestrator/db/journal.d.ts.map +1 -0
- package/dist/orchestrator/db/journal.js +91 -0
- package/dist/orchestrator/db/journal.js.map +1 -0
- package/dist/orchestrator/db/liveness.d.ts +97 -0
- package/dist/orchestrator/db/liveness.d.ts.map +1 -0
- package/dist/orchestrator/db/liveness.js +105 -0
- package/dist/orchestrator/db/liveness.js.map +1 -0
- package/dist/orchestrator/db/mission.d.ts +78 -0
- package/dist/orchestrator/db/mission.d.ts.map +1 -0
- package/dist/orchestrator/db/mission.js +99 -0
- package/dist/orchestrator/db/mission.js.map +1 -0
- package/dist/orchestrator/db/schema.d.ts +14 -0
- package/dist/orchestrator/db/schema.d.ts.map +1 -0
- package/dist/orchestrator/db/schema.js +169 -0
- package/dist/orchestrator/db/schema.js.map +1 -0
- package/dist/orchestrator/db/tickets.d.ts +147 -0
- package/dist/orchestrator/db/tickets.d.ts.map +1 -0
- package/dist/orchestrator/db/tickets.js +238 -0
- package/dist/orchestrator/db/tickets.js.map +1 -0
- package/dist/orchestrator/db/verdicts.d.ts +187 -0
- package/dist/orchestrator/db/verdicts.d.ts.map +1 -0
- package/dist/orchestrator/db/verdicts.js +197 -0
- package/dist/orchestrator/db/verdicts.js.map +1 -0
- package/dist/orchestrator/events.d.ts +69 -0
- package/dist/orchestrator/events.d.ts.map +1 -0
- package/dist/orchestrator/events.js +20 -0
- package/dist/orchestrator/events.js.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts +159 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.js +313 -0
- package/dist/orchestrator/github-credential-anchor-sender.js.map +1 -0
- package/dist/orchestrator/hub-dispatch.d.ts +120 -0
- package/dist/orchestrator/hub-dispatch.d.ts.map +1 -0
- package/dist/orchestrator/hub-dispatch.js +257 -0
- package/dist/orchestrator/hub-dispatch.js.map +1 -0
- package/dist/orchestrator/hub-observer.d.ts +201 -0
- package/dist/orchestrator/hub-observer.d.ts.map +1 -0
- package/dist/orchestrator/hub-observer.js +474 -0
- package/dist/orchestrator/hub-observer.js.map +1 -0
- package/dist/orchestrator/journal-writer.d.ts +80 -0
- package/dist/orchestrator/journal-writer.d.ts.map +1 -0
- package/dist/orchestrator/journal-writer.js +113 -0
- package/dist/orchestrator/journal-writer.js.map +1 -0
- package/dist/orchestrator/mcp/server.d.ts +136 -0
- package/dist/orchestrator/mcp/server.d.ts.map +1 -0
- package/dist/orchestrator/mcp/server.js +582 -0
- package/dist/orchestrator/mcp/server.js.map +1 -0
- package/dist/orchestrator/mcp/stdio.d.ts +22 -0
- package/dist/orchestrator/mcp/stdio.d.ts.map +1 -0
- package/dist/orchestrator/mcp/stdio.js +51 -0
- package/dist/orchestrator/mcp/stdio.js.map +1 -0
- package/dist/orchestrator/review.d.ts +131 -0
- package/dist/orchestrator/review.d.ts.map +1 -0
- package/dist/orchestrator/review.js +322 -0
- package/dist/orchestrator/review.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +71 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/components.d.ts +110 -0
- package/dist/tui/components.d.ts.map +1 -0
- package/dist/tui/components.js +118 -0
- package/dist/tui/components.js.map +1 -0
- package/dist/tui/index.d.ts +30 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +95 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/keymap.d.ts +33 -0
- package/dist/tui/keymap.d.ts.map +1 -0
- package/dist/tui/keymap.js +49 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/nav.d.ts +29 -0
- package/dist/tui/nav.d.ts.map +1 -0
- package/dist/tui/nav.js +39 -0
- package/dist/tui/nav.js.map +1 -0
- package/dist/tui/sanitize.d.ts +25 -0
- package/dist/tui/sanitize.d.ts.map +1 -0
- package/dist/tui/sanitize.js +36 -0
- package/dist/tui/sanitize.js.map +1 -0
- package/dist/tui/theme.d.ts +32 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +63 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/views/agents.d.ts +67 -0
- package/dist/tui/views/agents.d.ts.map +1 -0
- package/dist/tui/views/agents.js +231 -0
- package/dist/tui/views/agents.js.map +1 -0
- package/dist/tui/views/index.d.ts +93 -0
- package/dist/tui/views/index.d.ts.map +1 -0
- package/dist/tui/views/index.js +150 -0
- package/dist/tui/views/index.js.map +1 -0
- package/dist/tui/views/registry.d.ts +22 -0
- package/dist/tui/views/registry.d.ts.map +1 -0
- package/dist/tui/views/registry.js +110 -0
- package/dist/tui/views/registry.js.map +1 -0
- package/dist/utils/agent/backoff.d.ts +31 -0
- package/dist/utils/agent/backoff.d.ts.map +1 -0
- package/dist/utils/agent/backoff.js +51 -0
- package/dist/utils/agent/backoff.js.map +1 -0
- package/dist/utils/agent/markers.d.ts +87 -0
- package/dist/utils/agent/markers.d.ts.map +1 -0
- package/dist/utils/agent/markers.js +147 -0
- package/dist/utils/agent/markers.js.map +1 -0
- package/dist/utils/agent/review.d.ts +67 -0
- package/dist/utils/agent/review.d.ts.map +1 -0
- package/dist/utils/agent/review.js +305 -0
- package/dist/utils/agent/review.js.map +1 -0
- package/dist/utils/agent/spawn-agent.d.ts +117 -0
- package/dist/utils/agent/spawn-agent.d.ts.map +1 -0
- package/dist/utils/agent/spawn-agent.js +177 -0
- package/dist/utils/agent/spawn-agent.js.map +1 -0
- package/dist/utils/agent/task.d.ts +101 -0
- package/dist/utils/agent/task.d.ts.map +1 -0
- package/dist/utils/agent/task.js +357 -0
- package/dist/utils/agent/task.js.map +1 -0
- package/dist/utils/agent/verify.d.ts +47 -0
- package/dist/utils/agent/verify.d.ts.map +1 -0
- package/dist/utils/agent/verify.js +144 -0
- package/dist/utils/agent/verify.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +48 -0
- package/dist/utils/agent-detector.d.ts.map +1 -0
- package/dist/utils/agent-detector.js +74 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/agent-profile-stage.d.ts +70 -0
- package/dist/utils/agent-profile-stage.d.ts.map +1 -0
- package/dist/utils/agent-profile-stage.js +153 -0
- package/dist/utils/agent-profile-stage.js.map +1 -0
- package/dist/utils/agent-profiles.d.ts +27 -0
- package/dist/utils/agent-profiles.d.ts.map +1 -0
- package/dist/utils/agent-profiles.js +61 -0
- package/dist/utils/agent-profiles.js.map +1 -0
- package/dist/utils/checkpoint-api.d.ts +1 -1
- package/dist/utils/checkpoint-api.js +1 -1
- package/dist/utils/checkpoint-env.d.ts +1 -1
- package/dist/utils/checkpoint-env.js +2 -2
- package/dist/utils/checkpoint-env.js.map +1 -1
- package/dist/utils/checkpoint-scaffold.d.ts +1 -1
- package/dist/utils/checkpoint-scaffold.js +1 -1
- package/dist/utils/cli-kit/browser.d.ts +24 -0
- package/dist/utils/cli-kit/browser.d.ts.map +1 -0
- package/dist/utils/cli-kit/browser.js +58 -0
- package/dist/utils/cli-kit/browser.js.map +1 -0
- package/dist/utils/cli-kit/claim-polling.d.ts +18 -0
- package/dist/utils/cli-kit/claim-polling.d.ts.map +1 -0
- package/dist/utils/{claim-polling.js → cli-kit/claim-polling.js} +19 -26
- package/dist/utils/cli-kit/claim-polling.js.map +1 -0
- package/dist/utils/cli-kit/diagnostics.d.ts +9 -0
- package/dist/utils/cli-kit/diagnostics.d.ts.map +1 -0
- package/dist/utils/cli-kit/diagnostics.js +11 -0
- package/dist/utils/cli-kit/diagnostics.js.map +1 -0
- package/dist/utils/cli-kit/fs-safe.d.ts +14 -0
- package/dist/utils/cli-kit/fs-safe.d.ts.map +1 -0
- package/dist/utils/cli-kit/fs-safe.js +20 -0
- package/dist/utils/cli-kit/fs-safe.js.map +1 -0
- package/dist/utils/cli-kit/index.d.ts +15 -0
- package/dist/utils/cli-kit/index.d.ts.map +1 -0
- package/dist/utils/cli-kit/index.js +10 -0
- package/dist/utils/cli-kit/index.js.map +1 -0
- package/dist/utils/cli-kit/json-file.d.ts +21 -0
- package/dist/utils/cli-kit/json-file.d.ts.map +1 -0
- package/dist/utils/cli-kit/json-file.js +51 -0
- package/dist/utils/cli-kit/json-file.js.map +1 -0
- package/dist/utils/cli-kit/marker-block.d.ts +26 -0
- package/dist/utils/cli-kit/marker-block.d.ts.map +1 -0
- package/dist/utils/cli-kit/marker-block.js +61 -0
- package/dist/utils/cli-kit/marker-block.js.map +1 -0
- package/dist/utils/cli-kit/paths.d.ts +15 -0
- package/dist/utils/cli-kit/paths.d.ts.map +1 -0
- package/dist/utils/cli-kit/paths.js +21 -0
- package/dist/utils/cli-kit/paths.js.map +1 -0
- package/dist/utils/cli-kit/secure-storage.d.ts +14 -0
- package/dist/utils/cli-kit/secure-storage.d.ts.map +1 -0
- package/dist/utils/cli-kit/secure-storage.js +20 -0
- package/dist/utils/cli-kit/secure-storage.js.map +1 -0
- package/dist/utils/cli-kit/step-report.d.ts +16 -0
- package/dist/utils/cli-kit/step-report.d.ts.map +1 -0
- package/dist/utils/cli-kit/step-report.js +36 -0
- package/dist/utils/cli-kit/step-report.js.map +1 -0
- package/dist/utils/dco/agent-metadata.d.ts +1 -1
- package/dist/utils/dco/agent-metadata.js +1 -1
- package/dist/utils/dco/agent-metadata.js.map +1 -1
- package/dist/utils/dco/claude-config.d.ts +18 -14
- package/dist/utils/dco/claude-config.d.ts.map +1 -1
- package/dist/utils/dco/claude-config.js +31 -97
- package/dist/utils/dco/claude-config.js.map +1 -1
- package/dist/utils/dco/dispatch.d.ts +134 -0
- package/dist/utils/dco/dispatch.d.ts.map +1 -0
- package/dist/utils/dco/dispatch.js +399 -0
- package/dist/utils/dco/dispatch.js.map +1 -0
- package/dist/utils/dco/fix.d.ts +122 -0
- package/dist/utils/dco/fix.d.ts.map +1 -0
- package/dist/utils/dco/fix.js +560 -0
- package/dist/utils/dco/fix.js.map +1 -0
- package/dist/utils/dco/git-config.d.ts.map +1 -1
- package/dist/utils/dco/git-config.js +5 -3
- package/dist/utils/dco/git-config.js.map +1 -1
- package/dist/utils/dco/github.d.ts +101 -0
- package/dist/utils/dco/github.d.ts.map +1 -1
- package/dist/utils/dco/github.js +133 -0
- package/dist/utils/dco/github.js.map +1 -1
- package/dist/utils/dco/paths.d.ts +1 -8
- package/dist/utils/dco/paths.d.ts.map +1 -1
- package/dist/utils/dco/paths.js +3 -12
- package/dist/utils/dco/paths.js.map +1 -1
- package/dist/utils/dco/render.d.ts +1 -1
- package/dist/utils/dco/render.d.ts.map +1 -1
- package/dist/utils/dco/render.js +4 -21
- package/dist/utils/dco/render.js.map +1 -1
- package/dist/utils/dco/resolve-agent.d.ts +54 -0
- package/dist/utils/dco/resolve-agent.d.ts.map +1 -0
- package/dist/utils/dco/resolve-agent.js +164 -0
- package/dist/utils/dco/resolve-agent.js.map +1 -0
- package/dist/utils/dco/setup.d.ts +10 -7
- package/dist/utils/dco/setup.d.ts.map +1 -1
- package/dist/utils/dco/setup.js +264 -200
- package/dist/utils/dco/setup.js.map +1 -1
- package/dist/utils/dco/signing-key-writer.d.ts +40 -0
- package/dist/utils/dco/signing-key-writer.d.ts.map +1 -0
- package/dist/utils/dco/signing-key-writer.js +76 -0
- package/dist/utils/dco/signing-key-writer.js.map +1 -0
- package/dist/utils/dco/ssh-key.d.ts +50 -0
- package/dist/utils/dco/ssh-key.d.ts.map +1 -1
- package/dist/utils/dco/ssh-key.js +129 -8
- package/dist/utils/dco/ssh-key.js.map +1 -1
- package/dist/utils/dco/status.d.ts +1 -1
- package/dist/utils/dco/status.d.ts.map +1 -1
- package/dist/utils/dco/status.js +3 -3
- package/dist/utils/dco/status.js.map +1 -1
- package/dist/utils/dco/verify.d.ts +170 -0
- package/dist/utils/dco/verify.d.ts.map +1 -0
- package/dist/utils/dco/verify.js +550 -0
- package/dist/utils/dco/verify.js.map +1 -0
- package/dist/utils/dependency-installer.d.ts +37 -0
- package/dist/utils/dependency-installer.d.ts.map +1 -0
- package/dist/utils/dependency-installer.js +32 -0
- package/dist/utils/dependency-installer.js.map +1 -0
- package/dist/utils/github-credential-stage.d.ts +87 -0
- package/dist/utils/github-credential-stage.d.ts.map +1 -0
- package/dist/utils/github-credential-stage.js +168 -0
- package/dist/utils/github-credential-stage.js.map +1 -0
- package/dist/utils/github-credential.d.ts +160 -0
- package/dist/utils/github-credential.d.ts.map +1 -0
- package/dist/utils/github-credential.js +308 -0
- package/dist/utils/github-credential.js.map +1 -0
- package/dist/utils/gitignore.d.ts +17 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +40 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/hub-config.d.ts +21 -0
- package/dist/utils/hub-config.d.ts.map +1 -0
- package/dist/utils/hub-config.js +28 -0
- package/dist/utils/hub-config.js.map +1 -0
- package/dist/utils/identity-heal.d.ts +16 -0
- package/dist/utils/identity-heal.d.ts.map +1 -0
- package/dist/utils/identity-heal.js +37 -0
- package/dist/utils/identity-heal.js.map +1 -0
- package/dist/utils/init/pipeline.d.ts +74 -0
- package/dist/utils/init/pipeline.d.ts.map +1 -0
- package/dist/utils/init/pipeline.js +96 -0
- package/dist/utils/init/pipeline.js.map +1 -0
- package/dist/utils/poll.d.ts +15 -1
- package/dist/utils/poll.d.ts.map +1 -1
- package/dist/utils/poll.js +6 -3
- package/dist/utils/poll.js.map +1 -1
- package/dist/utils/register-agent-identity.d.ts +67 -0
- package/dist/utils/register-agent-identity.d.ts.map +1 -0
- package/dist/utils/register-agent-identity.js +34 -0
- package/dist/utils/register-agent-identity.js.map +1 -0
- package/dist/utils/review/did-web-key.d.ts +34 -0
- package/dist/utils/review/did-web-key.d.ts.map +1 -0
- package/dist/utils/review/did-web-key.js +104 -0
- package/dist/utils/review/did-web-key.js.map +1 -0
- package/dist/utils/review/load-registry.d.ts +33 -0
- package/dist/utils/review/load-registry.d.ts.map +1 -0
- package/dist/utils/review/load-registry.js +62 -0
- package/dist/utils/review/load-registry.js.map +1 -0
- package/dist/utils/review/verdict-verify.d.ts +43 -0
- package/dist/utils/review/verdict-verify.d.ts.map +1 -0
- package/dist/utils/review/verdict-verify.js +53 -0
- package/dist/utils/review/verdict-verify.js.map +1 -0
- package/dist/utils/review-registry-writer.d.ts +52 -0
- package/dist/utils/review-registry-writer.d.ts.map +1 -0
- package/dist/utils/review-registry-writer.js +79 -0
- package/dist/utils/review-registry-writer.js.map +1 -0
- package/dist/utils/should-install-dependency.d.ts +17 -0
- package/dist/utils/should-install-dependency.d.ts.map +1 -0
- package/dist/utils/should-install-dependency.js +25 -0
- package/dist/utils/should-install-dependency.js.map +1 -0
- package/dist/utils/tool-readiness.d.ts +57 -0
- package/dist/utils/tool-readiness.d.ts.map +1 -0
- package/dist/utils/tool-readiness.js +114 -0
- package/dist/utils/tool-readiness.js.map +1 -0
- package/dist/utils/which.d.ts +2 -0
- package/dist/utils/which.d.ts.map +1 -0
- package/dist/utils/which.js +22 -0
- package/dist/utils/which.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/package.json +19 -6
- package/dist/utils/claim-polling.d.ts +0 -21
- package/dist/utils/claim-polling.d.ts.map +0 -1
- package/dist/utils/claim-polling.js.map +0 -1
- package/dist/utils/dco/fs-safe.d.ts +0 -14
- package/dist/utils/dco/fs-safe.d.ts.map +0 -1
- package/dist/utils/dco/fs-safe.js +0 -20
- package/dist/utils/dco/fs-safe.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket store (ORC-W1 PR-1).
|
|
3
|
+
*
|
|
4
|
+
* The two load-bearing operations live here, and both encode their invariant
|
|
5
|
+
* in SQL rather than in a caller's discipline.
|
|
6
|
+
*
|
|
7
|
+
* @module orchestrator/db/tickets
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { type Ledger } from "./index.js";
|
|
11
|
+
export declare const TicketStatusSchema: z.ZodEnum<["open", "claimed", "in-progress", "in-review", "blocked", "ready", "closed"]>;
|
|
12
|
+
export type TicketStatus = z.infer<typeof TicketStatusSchema>;
|
|
13
|
+
/**
|
|
14
|
+
* The statuses `setTicketStatus` is allowed to write.
|
|
15
|
+
*
|
|
16
|
+
* `closed` and `claimed` each carry something a bare status write cannot -- a
|
|
17
|
+
* recorded reason, and a claimant set in the same statement -- so each has a
|
|
18
|
+
* dedicated function here and neither is reachable through the generic setter.
|
|
19
|
+
*
|
|
20
|
+
* Defined in the STORE and not at the MCP boundary, because the boundary is
|
|
21
|
+
* only one of the entrances. The daemon, the CLI and any consumer of the built
|
|
22
|
+
* package call these functions directly, and a rule that holds at one door is
|
|
23
|
+
* not an invariant, it is a convention with good manners.
|
|
24
|
+
*/
|
|
25
|
+
export declare const SettableTicketStatusSchema: z.ZodEnum<["open", "in-progress", "in-review", "blocked", "ready"]>;
|
|
26
|
+
export type SettableTicketStatus = z.infer<typeof SettableTicketStatusSchema>;
|
|
27
|
+
export declare const SETTABLE_TICKET_STATUSES: ["open", "in-progress", "in-review", "blocked", "ready"];
|
|
28
|
+
export declare const TicketSeveritySchema: z.ZodEnum<["blocking", "major", "minor", "nit"]>;
|
|
29
|
+
export type TicketSeverity = z.infer<typeof TicketSeveritySchema>;
|
|
30
|
+
export declare const TicketSourceSchema: z.ZodEnum<["linear", "log_scan", "review_finding", "manual"]>;
|
|
31
|
+
export type TicketSource = z.infer<typeof TicketSourceSchema>;
|
|
32
|
+
/**
|
|
33
|
+
* Shape of a `tickets` row.
|
|
34
|
+
*
|
|
35
|
+
* Rows are parsed rather than cast. better-sqlite3's `.get()` is typed `any`,
|
|
36
|
+
* so `as Ticket` would not merely be an unchecked assumption, it would switch
|
|
37
|
+
* off checking for everything downstream of it — the repo bans exactly that.
|
|
38
|
+
* Parsing also means a schema drift (a migration that renames a column, a
|
|
39
|
+
* hand-edited ledger) fails loudly at the read instead of surfacing as
|
|
40
|
+
* `undefined` three layers away.
|
|
41
|
+
*/
|
|
42
|
+
export declare const TicketRowSchema: z.ZodObject<{
|
|
43
|
+
id: z.ZodString;
|
|
44
|
+
linear_id: z.ZodNullable<z.ZodString>;
|
|
45
|
+
title: z.ZodString;
|
|
46
|
+
body: z.ZodNullable<z.ZodString>;
|
|
47
|
+
status: z.ZodEnum<["open", "claimed", "in-progress", "in-review", "blocked", "ready", "closed"]>;
|
|
48
|
+
severity: z.ZodNullable<z.ZodEnum<["blocking", "major", "minor", "nit"]>>;
|
|
49
|
+
source: z.ZodEnum<["linear", "log_scan", "review_finding", "manual"]>;
|
|
50
|
+
claimed_by: z.ZodNullable<z.ZodString>;
|
|
51
|
+
claimed_at: z.ZodNullable<z.ZodString>;
|
|
52
|
+
closed_reason: z.ZodNullable<z.ZodString>;
|
|
53
|
+
superseded_by: z.ZodNullable<z.ZodString>;
|
|
54
|
+
created_at: z.ZodString;
|
|
55
|
+
updated_at: z.ZodString;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
id: string;
|
|
58
|
+
status: "open" | "closed" | "ready" | "claimed" | "in-progress" | "in-review" | "blocked";
|
|
59
|
+
body: string | null;
|
|
60
|
+
source: "linear" | "log_scan" | "review_finding" | "manual";
|
|
61
|
+
linear_id: string | null;
|
|
62
|
+
title: string;
|
|
63
|
+
severity: "blocking" | "major" | "minor" | "nit" | null;
|
|
64
|
+
claimed_by: string | null;
|
|
65
|
+
claimed_at: string | null;
|
|
66
|
+
closed_reason: string | null;
|
|
67
|
+
superseded_by: string | null;
|
|
68
|
+
created_at: string;
|
|
69
|
+
updated_at: string;
|
|
70
|
+
}, {
|
|
71
|
+
id: string;
|
|
72
|
+
status: "open" | "closed" | "ready" | "claimed" | "in-progress" | "in-review" | "blocked";
|
|
73
|
+
body: string | null;
|
|
74
|
+
source: "linear" | "log_scan" | "review_finding" | "manual";
|
|
75
|
+
linear_id: string | null;
|
|
76
|
+
title: string;
|
|
77
|
+
severity: "blocking" | "major" | "minor" | "nit" | null;
|
|
78
|
+
claimed_by: string | null;
|
|
79
|
+
claimed_at: string | null;
|
|
80
|
+
closed_reason: string | null;
|
|
81
|
+
superseded_by: string | null;
|
|
82
|
+
created_at: string;
|
|
83
|
+
updated_at: string;
|
|
84
|
+
}>;
|
|
85
|
+
export type Ticket = z.infer<typeof TicketRowSchema>;
|
|
86
|
+
export interface CreateTicketInput {
|
|
87
|
+
title: string;
|
|
88
|
+
source: TicketSource;
|
|
89
|
+
body?: string;
|
|
90
|
+
severity?: TicketSeverity;
|
|
91
|
+
linearId?: string;
|
|
92
|
+
id?: string;
|
|
93
|
+
}
|
|
94
|
+
/** Insert a ticket in the `open` state. */
|
|
95
|
+
export declare function createTicket(db: Ledger, input: CreateTicketInput): Ticket;
|
|
96
|
+
export declare function getTicket(db: Ledger, id: string): Ticket | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Claim the oldest open ticket, atomically.
|
|
99
|
+
*
|
|
100
|
+
* The claim and the mark are ONE statement. A read-then-write pair here is a
|
|
101
|
+
* review-blocking defect, not a style preference: two orchestrator ticks, or
|
|
102
|
+
* two orchestrators pointed at one ledger, would both read the same open
|
|
103
|
+
* ticket and both staff it, producing two workers on one ticket in two
|
|
104
|
+
* checkouts. With a single UPDATE the losing caller changes zero rows and
|
|
105
|
+
* moves on.
|
|
106
|
+
*
|
|
107
|
+
* Returns null when nothing was claimable, which is an ordinary outcome and
|
|
108
|
+
* never an error.
|
|
109
|
+
*/
|
|
110
|
+
export declare function claimNextTicket(db: Ledger, workerDid: string): Ticket | null;
|
|
111
|
+
/**
|
|
112
|
+
* Close a ticket by marking it, never by deleting it.
|
|
113
|
+
*
|
|
114
|
+
* There is deliberately no delete path anywhere in this package. Once a row is
|
|
115
|
+
* gone, a bad autonomous close and a clean backlog look identical, and the
|
|
116
|
+
* evidence needed to tell them apart went with it.
|
|
117
|
+
*/
|
|
118
|
+
export declare function closeTicket(db: Ledger, id: string, reason: string, supersededBy?: string): Ticket;
|
|
119
|
+
/**
|
|
120
|
+
* Move a ticket to one of the statuses a plain status write can express.
|
|
121
|
+
*
|
|
122
|
+
* `closed` and `claimed` are refused: see `SettableTicketStatusSchema`. The
|
|
123
|
+
* check is made at RUNTIME and not left to the parameter type, because the
|
|
124
|
+
* callers it guards are the ones TypeScript never sees -- JavaScript consumers
|
|
125
|
+
* of the built package, and anything arriving through an `unknown`. A type
|
|
126
|
+
* cannot stop a caller that was never type-checked.
|
|
127
|
+
*/
|
|
128
|
+
export declare function setTicketStatus(db: Ledger, id: string, status: SettableTicketStatus): Ticket;
|
|
129
|
+
/**
|
|
130
|
+
* Read tickets, optionally filtered, optionally capped.
|
|
131
|
+
*
|
|
132
|
+
* The cap is applied HERE, to the newest rows, not by the caller slicing an
|
|
133
|
+
* oldest-first list. Tickets soft-close and are never deleted, so closed
|
|
134
|
+
* history accumulates at the front of `created_at` order: capping afterwards
|
|
135
|
+
* meant that once the ledger outgrew the cap, an unfiltered read could be
|
|
136
|
+
* entirely closed rows with every open ticket invisible behind them. The
|
|
137
|
+
* journal and dispatch readers already ordered newest-first; this one was the
|
|
138
|
+
* outlier.
|
|
139
|
+
*
|
|
140
|
+
* The window is taken newest-first and then handed back oldest-first, so the
|
|
141
|
+
* result reads in the natural direction while still being the recent end of the
|
|
142
|
+
* ledger. `id` breaks ties because `created_at` alone is not unique -- two
|
|
143
|
+
* tickets made in the same millisecond would otherwise order arbitrarily, and
|
|
144
|
+
* an arbitrary order at the cap boundary decides which row is visible at all.
|
|
145
|
+
*/
|
|
146
|
+
export declare function listTickets(db: Ledger, status?: TicketStatus, limit?: number): Ticket[];
|
|
147
|
+
//# sourceMappingURL=tickets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/db/tickets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,kBAAkB,0FAQ7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,qEAAoD,CAAC;AAC5F,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,eAAO,MAAM,wBAAwB,0DAAqC,CAAC;AAgB3E,eAAO,MAAM,oBAAoB,kDAAgD,CAAC;AAClF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB,+DAA6D,CAAC;AAC7F,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAc1B,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAQrD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiBzE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB5E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CA4CR;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqC5F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBvF"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket store (ORC-W1 PR-1).
|
|
3
|
+
*
|
|
4
|
+
* The two load-bearing operations live here, and both encode their invariant
|
|
5
|
+
* in SQL rather than in a caller's discipline.
|
|
6
|
+
*
|
|
7
|
+
* @module orchestrator/db/tickets
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { rowCap } from "./index.js";
|
|
12
|
+
export const TicketStatusSchema = z.enum([
|
|
13
|
+
"open",
|
|
14
|
+
"claimed",
|
|
15
|
+
"in-progress",
|
|
16
|
+
"in-review",
|
|
17
|
+
"blocked",
|
|
18
|
+
"ready",
|
|
19
|
+
"closed",
|
|
20
|
+
]);
|
|
21
|
+
/**
|
|
22
|
+
* The statuses `setTicketStatus` is allowed to write.
|
|
23
|
+
*
|
|
24
|
+
* `closed` and `claimed` each carry something a bare status write cannot -- a
|
|
25
|
+
* recorded reason, and a claimant set in the same statement -- so each has a
|
|
26
|
+
* dedicated function here and neither is reachable through the generic setter.
|
|
27
|
+
*
|
|
28
|
+
* Defined in the STORE and not at the MCP boundary, because the boundary is
|
|
29
|
+
* only one of the entrances. The daemon, the CLI and any consumer of the built
|
|
30
|
+
* package call these functions directly, and a rule that holds at one door is
|
|
31
|
+
* not an invariant, it is a convention with good manners.
|
|
32
|
+
*/
|
|
33
|
+
export const SettableTicketStatusSchema = TicketStatusSchema.exclude(["closed", "claimed"]);
|
|
34
|
+
export const SETTABLE_TICKET_STATUSES = SettableTicketStatusSchema.options;
|
|
35
|
+
/**
|
|
36
|
+
* Why each excluded status is excluded, so a refusal names its replacement
|
|
37
|
+
* rather than just saying no.
|
|
38
|
+
*
|
|
39
|
+
* Null-prototyped, so a lookup answers for its OWN keys only. As a plain object
|
|
40
|
+
* literal every inherited name resolved -- `toString`, `constructor`,
|
|
41
|
+
* `__proto__` -- and `?? fallback` never fired, so a caller could steer the
|
|
42
|
+
* refusal into printing a native function body instead of the settable list.
|
|
43
|
+
*/
|
|
44
|
+
const UNSETTABLE_STATUS_REASON = Object.assign(Object.create(null), {
|
|
45
|
+
closed: "closing must record a reason, use closeTicket",
|
|
46
|
+
claimed: "claiming must set a claimant in the same statement, use claimNextTicket",
|
|
47
|
+
});
|
|
48
|
+
export const TicketSeveritySchema = z.enum(["blocking", "major", "minor", "nit"]);
|
|
49
|
+
export const TicketSourceSchema = z.enum(["linear", "log_scan", "review_finding", "manual"]);
|
|
50
|
+
/**
|
|
51
|
+
* Shape of a `tickets` row.
|
|
52
|
+
*
|
|
53
|
+
* Rows are parsed rather than cast. better-sqlite3's `.get()` is typed `any`,
|
|
54
|
+
* so `as Ticket` would not merely be an unchecked assumption, it would switch
|
|
55
|
+
* off checking for everything downstream of it — the repo bans exactly that.
|
|
56
|
+
* Parsing also means a schema drift (a migration that renames a column, a
|
|
57
|
+
* hand-edited ledger) fails loudly at the read instead of surfacing as
|
|
58
|
+
* `undefined` three layers away.
|
|
59
|
+
*/
|
|
60
|
+
export const TicketRowSchema = z.object({
|
|
61
|
+
id: z.string(),
|
|
62
|
+
linear_id: z.string().nullable(),
|
|
63
|
+
title: z.string(),
|
|
64
|
+
body: z.string().nullable(),
|
|
65
|
+
status: TicketStatusSchema,
|
|
66
|
+
severity: TicketSeveritySchema.nullable(),
|
|
67
|
+
source: TicketSourceSchema,
|
|
68
|
+
claimed_by: z.string().nullable(),
|
|
69
|
+
claimed_at: z.string().nullable(),
|
|
70
|
+
closed_reason: z.string().nullable(),
|
|
71
|
+
superseded_by: z.string().nullable(),
|
|
72
|
+
created_at: z.string(),
|
|
73
|
+
updated_at: z.string(),
|
|
74
|
+
});
|
|
75
|
+
/** Parse one row, or undefined when the query matched nothing. */
|
|
76
|
+
function parseRow(row) {
|
|
77
|
+
if (row === undefined || row === null)
|
|
78
|
+
return undefined;
|
|
79
|
+
return TicketRowSchema.parse(row);
|
|
80
|
+
}
|
|
81
|
+
/** Insert a ticket in the `open` state. */
|
|
82
|
+
export function createTicket(db, input) {
|
|
83
|
+
const now = new Date().toISOString();
|
|
84
|
+
const id = input.id ?? randomUUID();
|
|
85
|
+
db.prepare(`INSERT INTO tickets (id, linear_id, title, body, status, severity, source, created_at, updated_at)
|
|
86
|
+
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?)`).run(id, input.linearId ?? null, input.title, input.body ?? null, input.severity ?? null, input.source, now, now);
|
|
87
|
+
return getTicket(db, id);
|
|
88
|
+
}
|
|
89
|
+
export function getTicket(db, id) {
|
|
90
|
+
return parseRow(db.prepare(`SELECT * FROM tickets WHERE id = ?`).get(id));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Claim the oldest open ticket, atomically.
|
|
94
|
+
*
|
|
95
|
+
* The claim and the mark are ONE statement. A read-then-write pair here is a
|
|
96
|
+
* review-blocking defect, not a style preference: two orchestrator ticks, or
|
|
97
|
+
* two orchestrators pointed at one ledger, would both read the same open
|
|
98
|
+
* ticket and both staff it, producing two workers on one ticket in two
|
|
99
|
+
* checkouts. With a single UPDATE the losing caller changes zero rows and
|
|
100
|
+
* moves on.
|
|
101
|
+
*
|
|
102
|
+
* Returns null when nothing was claimable, which is an ordinary outcome and
|
|
103
|
+
* never an error.
|
|
104
|
+
*/
|
|
105
|
+
export function claimNextTicket(db, workerDid) {
|
|
106
|
+
const now = new Date().toISOString();
|
|
107
|
+
const row = db
|
|
108
|
+
.prepare(`UPDATE tickets
|
|
109
|
+
SET status = 'claimed', claimed_by = ?, claimed_at = ?, updated_at = ?
|
|
110
|
+
WHERE id = (
|
|
111
|
+
SELECT id FROM tickets
|
|
112
|
+
WHERE status = 'open'
|
|
113
|
+
ORDER BY created_at, id
|
|
114
|
+
LIMIT 1
|
|
115
|
+
)
|
|
116
|
+
RETURNING *`)
|
|
117
|
+
.get(workerDid, now, now);
|
|
118
|
+
return parseRow(row) ?? null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Close a ticket by marking it, never by deleting it.
|
|
122
|
+
*
|
|
123
|
+
* There is deliberately no delete path anywhere in this package. Once a row is
|
|
124
|
+
* gone, a bad autonomous close and a clean backlog look identical, and the
|
|
125
|
+
* evidence needed to tell them apart went with it.
|
|
126
|
+
*/
|
|
127
|
+
export function closeTicket(db, id, reason, supersededBy) {
|
|
128
|
+
// Enforced here and not only at the tool, for the reason the whole module
|
|
129
|
+
// exists: "nothing is ever deleted" buys an audit trail only if the surviving
|
|
130
|
+
// row says WHY it closed, and a blank reason produces the unexplained closed
|
|
131
|
+
// row permanently, since a second close is refused.
|
|
132
|
+
if (reason.trim() === "") {
|
|
133
|
+
throw new Error(`orchestrator: closing ticket ${id} needs a non-empty reason`);
|
|
134
|
+
}
|
|
135
|
+
const info = db
|
|
136
|
+
.prepare(`UPDATE tickets
|
|
137
|
+
SET status = 'closed',
|
|
138
|
+
closed_reason = ?,
|
|
139
|
+
superseded_by = ?,
|
|
140
|
+
updated_at = ?,
|
|
141
|
+
-- Closing LEAVES claimed, so it releases the claim too. The rule
|
|
142
|
+
-- lived only in setTicketStatus, so a closed row kept naming a
|
|
143
|
+
-- live worker and answered "who holds this" in flat contradiction
|
|
144
|
+
-- of its own status. In the same statement, so the release cannot
|
|
145
|
+
-- be separated from the close by a failure between them.
|
|
146
|
+
-- If a third writer ever leaves claimed, move this to a trigger
|
|
147
|
+
-- rather than writing the rule a third time.
|
|
148
|
+
claimed_by = NULL,
|
|
149
|
+
claimed_at = NULL
|
|
150
|
+
WHERE id = ?
|
|
151
|
+
AND status <> 'closed'`)
|
|
152
|
+
.run(reason, supersededBy ?? null, new Date().toISOString(), id);
|
|
153
|
+
if (info.changes === 0) {
|
|
154
|
+
const existing = getTicket(db, id);
|
|
155
|
+
if (existing === undefined) {
|
|
156
|
+
throw new Error(`orchestrator: cannot close unknown ticket ${id}`);
|
|
157
|
+
}
|
|
158
|
+
// Closing twice used to overwrite the original reason and NULL out
|
|
159
|
+
// superseded_by, which reduces "soft, auditable close" to one mutable
|
|
160
|
+
// column: the record of WHY something closed is the point of not deleting
|
|
161
|
+
// it, and a second close silently replaces that record.
|
|
162
|
+
throw new Error(`orchestrator: ticket ${id} is already closed (${existing.closed_reason ?? "no reason recorded"})`);
|
|
163
|
+
}
|
|
164
|
+
return getTicket(db, id);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Move a ticket to one of the statuses a plain status write can express.
|
|
168
|
+
*
|
|
169
|
+
* `closed` and `claimed` are refused: see `SettableTicketStatusSchema`. The
|
|
170
|
+
* check is made at RUNTIME and not left to the parameter type, because the
|
|
171
|
+
* callers it guards are the ones TypeScript never sees -- JavaScript consumers
|
|
172
|
+
* of the built package, and anything arriving through an `unknown`. A type
|
|
173
|
+
* cannot stop a caller that was never type-checked.
|
|
174
|
+
*/
|
|
175
|
+
export function setTicketStatus(db, id, status) {
|
|
176
|
+
if (!SettableTicketStatusSchema.safeParse(status).success) {
|
|
177
|
+
const because = UNSETTABLE_STATUS_REASON[status] ??
|
|
178
|
+
`settable statuses are ${SETTABLE_TICKET_STATUSES.join(", ")}`;
|
|
179
|
+
throw new Error(`orchestrator: setTicketStatus cannot set '${status}'; ${because}`);
|
|
180
|
+
}
|
|
181
|
+
const info = db
|
|
182
|
+
.prepare(`UPDATE tickets
|
|
183
|
+
SET status = ?,
|
|
184
|
+
updated_at = ?,
|
|
185
|
+
-- Any transition AWAY from claimed releases the claim, in the same
|
|
186
|
+
-- statement so the release cannot be separated from the status
|
|
187
|
+
-- change by a failure between them. Unconditional because the
|
|
188
|
+
-- guard above makes 'claimed' unreachable here: every status this
|
|
189
|
+
-- statement can write is a status that leaves it.
|
|
190
|
+
claimed_by = NULL,
|
|
191
|
+
claimed_at = NULL
|
|
192
|
+
WHERE id = ?
|
|
193
|
+
AND status <> 'closed'`)
|
|
194
|
+
.run(status, new Date().toISOString(), id);
|
|
195
|
+
if (info.changes === 0) {
|
|
196
|
+
// Distinguish the two ways to change nothing, because they mean opposite
|
|
197
|
+
// things to a caller: one is a bad id, the other is a refused transition.
|
|
198
|
+
const existing = getTicket(db, id);
|
|
199
|
+
if (existing === undefined) {
|
|
200
|
+
throw new Error(`orchestrator: cannot update unknown ticket ${id}`);
|
|
201
|
+
}
|
|
202
|
+
throw new Error(`orchestrator: ticket ${id} is closed; reopening is a human decision, not a status write`);
|
|
203
|
+
}
|
|
204
|
+
return getTicket(db, id);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Read tickets, optionally filtered, optionally capped.
|
|
208
|
+
*
|
|
209
|
+
* The cap is applied HERE, to the newest rows, not by the caller slicing an
|
|
210
|
+
* oldest-first list. Tickets soft-close and are never deleted, so closed
|
|
211
|
+
* history accumulates at the front of `created_at` order: capping afterwards
|
|
212
|
+
* meant that once the ledger outgrew the cap, an unfiltered read could be
|
|
213
|
+
* entirely closed rows with every open ticket invisible behind them. The
|
|
214
|
+
* journal and dispatch readers already ordered newest-first; this one was the
|
|
215
|
+
* outlier.
|
|
216
|
+
*
|
|
217
|
+
* The window is taken newest-first and then handed back oldest-first, so the
|
|
218
|
+
* result reads in the natural direction while still being the recent end of the
|
|
219
|
+
* ledger. `id` breaks ties because `created_at` alone is not unique -- two
|
|
220
|
+
* tickets made in the same millisecond would otherwise order arbitrarily, and
|
|
221
|
+
* an arbitrary order at the cap boundary decides which row is visible at all.
|
|
222
|
+
*/
|
|
223
|
+
export function listTickets(db, status, limit) {
|
|
224
|
+
const cap = rowCap(limit);
|
|
225
|
+
const rows = status
|
|
226
|
+
? db
|
|
227
|
+
.prepare(`SELECT * FROM (
|
|
228
|
+
SELECT * FROM tickets WHERE status = ? ORDER BY created_at DESC, id DESC LIMIT ?
|
|
229
|
+
) ORDER BY created_at, id`)
|
|
230
|
+
.all(status, cap)
|
|
231
|
+
: db
|
|
232
|
+
.prepare(`SELECT * FROM (
|
|
233
|
+
SELECT * FROM tickets ORDER BY created_at DESC, id DESC LIMIT ?
|
|
234
|
+
) ORDER BY created_at, id`)
|
|
235
|
+
.all(cap);
|
|
236
|
+
return z.array(TicketRowSchema).parse(rows);
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=tickets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../../src/orchestrator/db/tickets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verdict and quorum store.
|
|
3
|
+
*
|
|
4
|
+
* The point of this module is that both writes are idempotent by NATURAL key,
|
|
5
|
+
* not by a hash of the event that produced them:
|
|
6
|
+
*
|
|
7
|
+
* - a verdict is unique per (repo, pr, head_sha, reviewer_did)
|
|
8
|
+
* - quorum is unique per (repo, pr, head_sha)
|
|
9
|
+
*
|
|
10
|
+
* Those keys are what the review protocol already means, so "have we processed
|
|
11
|
+
* this?" is answered by asking whether the row exists. The previous approach
|
|
12
|
+
* derived a content hash of the hub event and stored a synthetic marker beside
|
|
13
|
+
* the ticket, which needed its own scoping, its own lookup path, and its own
|
|
14
|
+
* durability guarantees -- three review findings' worth of them. A UNIQUE
|
|
15
|
+
* constraint the schema already declared does the same job and cannot expire,
|
|
16
|
+
* collide across tickets, or be looked for in the wrong window.
|
|
17
|
+
*
|
|
18
|
+
* `verdicts` was in the schema from the start with exactly this shape and no
|
|
19
|
+
* reader; this is that reader.
|
|
20
|
+
*
|
|
21
|
+
* @module cli/orchestrator/db/verdicts
|
|
22
|
+
*/
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
import type { Ledger } from "./index.js";
|
|
25
|
+
export declare const VerdictKindSchema: z.ZodEnum<["approve", "request-changes", "comment"]>;
|
|
26
|
+
export type VerdictKind = z.infer<typeof VerdictKindSchema>;
|
|
27
|
+
export declare const VerdictRowSchema: z.ZodObject<{
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
ticket_id: z.ZodNullable<z.ZodString>;
|
|
30
|
+
repo: z.ZodString;
|
|
31
|
+
pr_number: z.ZodNumber;
|
|
32
|
+
head_sha: z.ZodString;
|
|
33
|
+
reviewer_did: z.ZodString;
|
|
34
|
+
verdict: z.ZodEnum<["approve", "request-changes", "comment"]>;
|
|
35
|
+
findings: z.ZodNullable<z.ZodString>;
|
|
36
|
+
counted: z.ZodNumber;
|
|
37
|
+
received_at: z.ZodString;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
id: string;
|
|
40
|
+
repo: string;
|
|
41
|
+
ticket_id: string | null;
|
|
42
|
+
pr_number: number;
|
|
43
|
+
head_sha: string;
|
|
44
|
+
reviewer_did: string;
|
|
45
|
+
verdict: "comment" | "approve" | "request-changes";
|
|
46
|
+
findings: string | null;
|
|
47
|
+
counted: number;
|
|
48
|
+
received_at: string;
|
|
49
|
+
}, {
|
|
50
|
+
id: string;
|
|
51
|
+
repo: string;
|
|
52
|
+
ticket_id: string | null;
|
|
53
|
+
pr_number: number;
|
|
54
|
+
head_sha: string;
|
|
55
|
+
reviewer_did: string;
|
|
56
|
+
verdict: "comment" | "approve" | "request-changes";
|
|
57
|
+
findings: string | null;
|
|
58
|
+
counted: number;
|
|
59
|
+
received_at: string;
|
|
60
|
+
}>;
|
|
61
|
+
export type VerdictRow = z.infer<typeof VerdictRowSchema>;
|
|
62
|
+
export interface RecordVerdictInput {
|
|
63
|
+
ticketId: string | null;
|
|
64
|
+
repo: string;
|
|
65
|
+
prNumber: number;
|
|
66
|
+
headSha: string;
|
|
67
|
+
reviewerDid: string;
|
|
68
|
+
verdict: VerdictKind;
|
|
69
|
+
/** The hub's own validity flag; false means it failed verdict validation. */
|
|
70
|
+
counted: boolean;
|
|
71
|
+
findings?: unknown;
|
|
72
|
+
/**
|
|
73
|
+
* PROTOCOL time -- the hub event's own timestamp -- not the wall clock at
|
|
74
|
+
* insert. Head ranking is derived from these, and consecutive better-sqlite3
|
|
75
|
+
* inserts land in the same millisecond, so a wall-clock stamp made ties the
|
|
76
|
+
* normal case on a cold-start replay and handed the decision to a lexicographic
|
|
77
|
+
* SHA comparison. Protocol time is the order things actually happened in, which
|
|
78
|
+
* is the order the ranking is trying to recover.
|
|
79
|
+
*/
|
|
80
|
+
observedAt: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Record one reviewer's verdict on one head SHA.
|
|
84
|
+
*
|
|
85
|
+
* Returns true when something CHANGED: the verdict is new, or the same reviewer
|
|
86
|
+
* revised it on the same head. False means this exact verdict was already
|
|
87
|
+
* recorded, which is a replay, a re-delivered event, or a boot reconcile of a
|
|
88
|
+
* window already processed.
|
|
89
|
+
*
|
|
90
|
+
* `received_at` is NEVER rewritten on conflict: it is the FIRST sighting of this
|
|
91
|
+
* head, which head ranking depends on, and letting a late revision move it
|
|
92
|
+
* contradicted the very function that reads it. A revision updates the verdict,
|
|
93
|
+
* not when the head was first seen.
|
|
94
|
+
*
|
|
95
|
+
* The mind-change case is why this is an upsert rather than INSERT OR IGNORE.
|
|
96
|
+
* The hub explicitly permits a reviewer to follow an approval with
|
|
97
|
+
* request-changes on the SAME head and emits a second review_verdict for it. On
|
|
98
|
+
* a plain OR IGNORE that second verdict is dropped as "already handled" and the
|
|
99
|
+
* ticket never goes back to in-progress -- a reviewer withdrawing approval would
|
|
100
|
+
* be silently overruled by a uniqueness constraint.
|
|
101
|
+
*
|
|
102
|
+
* The guarded UPDATE is what keeps false meaning "nothing to do": re-delivering
|
|
103
|
+
* an identical verdict fails the WHERE, changes no rows, and reports false.
|
|
104
|
+
* `findings` is part of that comparison so a revision that only changes its
|
|
105
|
+
* reasons is still stored -- otherwise the recorded findings silently went stale
|
|
106
|
+
* while the verdict itself looked current.
|
|
107
|
+
*
|
|
108
|
+
* The id is a readable composite of the natural key rather than a hash, so a row
|
|
109
|
+
* can be found by hand in a debugging session.
|
|
110
|
+
*/
|
|
111
|
+
export declare function recordVerdict(db: Ledger, input: RecordVerdictInput): boolean;
|
|
112
|
+
export interface RecordQuorumInput {
|
|
113
|
+
ticketId: string | null;
|
|
114
|
+
repo: string;
|
|
115
|
+
prNumber: number;
|
|
116
|
+
headSha: string;
|
|
117
|
+
quorumN?: number;
|
|
118
|
+
/** Protocol time, for the same reason as {@link RecordVerdictInput.observedAt}. */
|
|
119
|
+
observedAt: number;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Record that the hub declared quorum on one head SHA.
|
|
123
|
+
*
|
|
124
|
+
* Returns true when it was new. Quorum is stored rather than recomputed because
|
|
125
|
+
* the hub owns verdict validation, and a second implementation of the threshold
|
|
126
|
+
* here could disagree with the one that actually gated the decision.
|
|
127
|
+
*/
|
|
128
|
+
export declare function recordQuorum(db: Ledger, input: RecordQuorumInput): boolean;
|
|
129
|
+
/** Every verdict on one PR head, newest first. */
|
|
130
|
+
export declare function listVerdictsForPr(db: Ledger, repo: string, prNumber: number, headSha?: string): VerdictRow[];
|
|
131
|
+
/** Has the hub already declared quorum on this head? */
|
|
132
|
+
export declare function quorumReached(db: Ledger, repo: string, prNumber: number, headSha: string): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* The most recently seen head SHA for a pull request.
|
|
135
|
+
*
|
|
136
|
+
* Which revision the ledger currently believes is live. A push invalidates every
|
|
137
|
+
* prior verdict (the review protocol's settled rule), so status has to be derived
|
|
138
|
+
* from the newest head rather than from whichever head the event in hand names --
|
|
139
|
+
* otherwise a late or replayed quorum for superseded code moves current work.
|
|
140
|
+
* `counted: false` marks a stale VERDICT; quorum has no such flag.
|
|
141
|
+
*
|
|
142
|
+
* Ranked by when each head was FIRST seen, not when it was last touched. This is
|
|
143
|
+
* the whole correctness of the function. Ranking by last-touched let any newly
|
|
144
|
+
* recorded row for an older SHA promote it to "latest" -- including an uncounted
|
|
145
|
+
* stale verdict kept purely as evidence. Historical quorum on that superseded
|
|
146
|
+
* head would then clear a live objection on the real one, defeating the
|
|
147
|
+
* uncounted guard this derivation depends on. A head's first sighting cannot be
|
|
148
|
+
* moved by a late arrival, because the upsert never rewrites `received_at`.
|
|
149
|
+
*
|
|
150
|
+
* "When" is PROTOCOL time -- the hub event's own timestamp, carried in on
|
|
151
|
+
* `observedAt` -- not the wall clock at insert. Insert time made this a coin
|
|
152
|
+
* flip in the one case that matters most: on a cold start, `reconcileReviewState`
|
|
153
|
+
* replays the window fast enough that consecutive better-sqlite3 inserts land in
|
|
154
|
+
* the same millisecond, so every head tied and the winner fell to the SHA
|
|
155
|
+
* tiebreak. Half the time that elected the OLD head, derived a historical quorum
|
|
156
|
+
* against it, and moved a ticket to `ready` straight past a live counted
|
|
157
|
+
* request-changes on the new one.
|
|
158
|
+
*
|
|
159
|
+
* Ties still break on head_sha, for genuinely simultaneous protocol timestamps:
|
|
160
|
+
* an arbitrary-but-stable answer beats a fresh coin flip per query, and truly
|
|
161
|
+
* simultaneous revisions are ambiguous under any rule.
|
|
162
|
+
*/
|
|
163
|
+
export declare function latestHeadForPr(db: Ledger, repo: string, prNumber: number): string | undefined;
|
|
164
|
+
/**
|
|
165
|
+
* The same ranking as {@link latestHeadForPr}, blind to uncounted verdicts.
|
|
166
|
+
*
|
|
167
|
+
* `latestHeadForPr` deliberately ranks EVERY verdict, counted or not -- a
|
|
168
|
+
* verdict naming a stale or malformed SHA still proves the hub saw that SHA,
|
|
169
|
+
* which is what that function's contract promises. But "a SHA was mentioned"
|
|
170
|
+
* and "a SHA was genuinely reviewed" are different questions, and DERIVING
|
|
171
|
+
* status needs the second one: a verdict the hub itself flagged invalid must
|
|
172
|
+
* not be able to outrank a real counted verdict or quorum recorded on a
|
|
173
|
+
* different head just because it happened to arrive with a later protocol
|
|
174
|
+
* timestamp. Left unfiltered, that lets review noise on a throwaway SHA
|
|
175
|
+
* occlude a real objection sitting under the head that actually matters --
|
|
176
|
+
* the ticket keeps whatever status the occluded head implied, forever,
|
|
177
|
+
* because nothing ever asks about that head again.
|
|
178
|
+
*
|
|
179
|
+
* Quorum rows carry no `counted` column and are never filtered here, the same
|
|
180
|
+
* way {@link latestHeadForPr} treats them: the hub is the sole authority for
|
|
181
|
+
* quorum, so a recorded quorum is trusted unconditionally.
|
|
182
|
+
*
|
|
183
|
+
* Returns undefined when no head has ANY trusted evidence yet -- distinct
|
|
184
|
+
* from "no evidence at all," which only {@link latestHeadForPr} can answer.
|
|
185
|
+
*/
|
|
186
|
+
export declare function latestTrustedHeadForPr(db: Ledger, repo: string, prNumber: number): string | undefined;
|
|
187
|
+
//# sourceMappingURL=verdicts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdicts.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/db/verdicts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,eAAO,MAAM,iBAAiB,sDAAoD,CAAC;AACnF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CA6B5E;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAe1E;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,UAAU,EAAE,CAcd;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAMT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAe9F;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAerG"}
|