@astrosheep/keiyaku 2.9.13 → 4.0.0
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 +10 -130
- package/build/integrations/marketplace/.agents/plugins/marketplace.json +12 -0
- package/build/integrations/marketplace/.claude-plugin/marketplace.json +5 -0
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +7 -0
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +18 -0
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +16 -0
- package/build/integrations/marketplace/plugins/keiyaku/package.json +8 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +34 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +50 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +62 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +72 -0
- package/build/src/akuma/activity.d.ts +66 -0
- package/build/src/akuma/activity.js +139 -0
- package/build/src/akuma/akuma.d.ts +116 -0
- package/build/src/akuma/akuma.js +382 -0
- package/build/src/akuma/archetype.d.ts +31 -0
- package/build/src/akuma/archetype.js +188 -0
- package/build/src/akuma/body.d.ts +20 -0
- package/build/src/akuma/body.js +305 -0
- package/build/src/akuma/heart/facts.d.ts +150 -0
- package/build/src/akuma/heart/facts.js +9 -0
- package/build/src/akuma/heart/index.d.ts +78 -0
- package/build/src/akuma/heart/index.js +361 -0
- package/build/src/akuma/heart/rows.d.ts +189 -0
- package/build/src/akuma/heart/rows.js +319 -0
- package/build/src/akuma/heart/schema.d.ts +5 -0
- package/build/src/akuma/heart/schema.js +113 -0
- package/build/src/akuma/identity.d.ts +46 -0
- package/build/src/akuma/identity.js +89 -0
- package/build/src/akuma/index.d.ts +7 -0
- package/build/src/akuma/index.js +3 -0
- package/build/src/akuma/provider.d.ts +123 -0
- package/build/src/akuma/provider.js +235 -0
- package/build/src/akuma/providers/claude.d.ts +84 -0
- package/build/src/akuma/providers/claude.js +305 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +110 -0
- package/build/src/akuma/providers/codex-app-server/events.js +337 -0
- package/build/src/akuma/providers/codex-app-server/index.d.ts +27 -0
- package/build/src/akuma/providers/codex-app-server/index.js +162 -0
- package/build/src/akuma/providers/index.d.ts +4 -0
- package/build/src/akuma/providers/index.js +71 -0
- package/build/src/akuma/publication.d.ts +10 -0
- package/build/src/akuma/publication.js +107 -0
- package/build/src/akuma/requests.d.ts +46 -0
- package/build/src/akuma/requests.js +388 -0
- package/build/src/alias/index.d.ts +17 -0
- package/build/src/alias/index.js +104 -0
- package/build/src/body/amend.d.ts +2 -0
- package/build/src/body/amend.js +289 -0
- package/build/src/body/arc.d.ts +2 -0
- package/build/src/body/arc.js +54 -0
- package/build/src/body/decode.d.ts +4 -0
- package/build/src/body/decode.js +146 -0
- package/build/src/body/keys.d.ts +4 -0
- package/build/src/body/keys.js +11 -0
- package/build/src/body/region.d.ts +6 -0
- package/build/src/body/region.js +139 -0
- package/build/src/body/render.d.ts +4 -0
- package/build/src/body/render.js +73 -0
- package/build/src/body/shape.d.ts +29 -0
- package/build/src/body/shape.js +16 -0
- package/build/src/body/types.d.ts +28 -0
- package/build/src/body/verification.d.ts +7 -0
- package/build/src/body/verification.js +25 -0
- package/build/src/cli/accepted.d.ts +16 -0
- package/build/src/cli/accepted.js +65 -0
- package/build/src/cli/actor.d.ts +8 -0
- package/build/src/cli/actor.js +11 -0
- package/build/src/cli/commands/akuma-invoke.d.ts +53 -0
- package/build/src/cli/commands/akuma-invoke.js +68 -0
- package/build/src/cli/commands/akuma.d.ts +42 -0
- package/build/src/cli/commands/akuma.js +224 -0
- package/build/src/cli/commands/amend.d.ts +13 -0
- package/build/src/cli/commands/amend.js +13 -0
- package/build/src/cli/commands/bind.d.ts +12 -0
- package/build/src/cli/commands/bind.js +17 -0
- package/build/src/cli/commands/install.d.ts +25 -0
- package/build/src/cli/commands/install.js +103 -0
- package/build/src/cli/commands/task-invoke.d.ts +9 -0
- package/build/src/cli/commands/task-invoke.js +92 -0
- package/build/src/cli/commands/task.d.ts +16 -0
- package/build/src/cli/commands/task.js +144 -0
- package/build/src/cli/index.d.ts +2 -0
- package/build/src/cli/index.js +3 -0
- package/build/src/cli/invoke.d.ts +17 -0
- package/build/src/cli/invoke.js +265 -0
- package/build/src/cli/main.d.ts +1 -0
- package/build/src/cli/main.js +79 -0
- package/build/src/cli/parse.d.ts +210 -0
- package/build/src/cli/parse.js +375 -0
- package/build/src/cli/render/akuma-tool.d.ts +11 -0
- package/build/src/cli/render/akuma-tool.js +68 -0
- package/build/src/cli/render/akuma.d.ts +6 -0
- package/build/src/cli/render/akuma.js +254 -0
- package/build/src/cli/render/board.d.ts +2 -0
- package/build/src/cli/render/board.js +4 -0
- package/build/src/cli/render/contract.d.ts +4 -0
- package/build/src/cli/render/contract.js +69 -0
- package/build/src/cli/render/kanshi.d.ts +3 -0
- package/build/src/cli/render/kanshi.js +204 -0
- package/build/src/cli/render/refusal.d.ts +2 -0
- package/build/src/cli/render/refusal.js +4 -0
- package/build/src/cli/render/settings.d.ts +3 -0
- package/build/src/cli/render/settings.js +30 -0
- package/build/src/cli/render/task.d.ts +6 -0
- package/build/src/cli/render/task.js +105 -0
- package/build/src/cli/render/terminal.d.ts +10 -0
- package/build/src/cli/render/terminal.js +76 -0
- package/build/src/cli/render/text.d.ts +3 -0
- package/build/src/cli/render/text.js +15 -0
- package/build/src/cli/result.d.ts +55 -0
- package/build/src/cli/selectors.d.ts +9 -0
- package/build/src/cli/selectors.js +66 -0
- package/build/src/cli/usage.d.ts +6 -0
- package/build/src/cli/usage.js +19 -0
- package/build/src/context-root.d.ts +4 -0
- package/build/src/context-root.js +15 -0
- package/build/src/coordination/durable-file.d.ts +1 -0
- package/build/src/coordination/durable-file.js +36 -0
- package/build/src/coordination/sqlite-transaction-lock.d.ts +14 -0
- package/build/src/coordination/sqlite-transaction-lock.js +119 -0
- package/build/src/core/decide.d.ts +45 -0
- package/build/src/core/facts/codec.d.ts +3 -0
- package/build/src/core/facts/codec.js +258 -0
- package/build/src/core/facts/eligibility.d.ts +16 -0
- package/build/src/core/facts/eligibility.js +75 -0
- package/build/src/core/facts/errors.d.ts +3 -0
- package/build/src/core/facts/errors.js +6 -0
- package/build/src/core/facts/fold.d.ts +2 -0
- package/build/src/core/facts/fold.js +97 -0
- package/build/src/core/facts/gate.d.ts +24 -0
- package/build/src/core/facts/gate.js +52 -0
- package/build/src/core/facts/observation.d.ts +12 -0
- package/build/src/core/facts/observation.js +23 -0
- package/build/src/core/facts/offer.d.ts +21 -0
- package/build/src/core/facts/types.d.ts +130 -0
- package/build/src/core/facts/types.js +66 -0
- package/build/src/core/subject.d.ts +21 -0
- package/build/src/core/subject.js +89 -0
- package/build/src/core/verbs/abandon.d.ts +13 -0
- package/build/src/core/verbs/abandon.js +17 -0
- package/build/src/core/verbs/amend.d.ts +14 -0
- package/build/src/core/verbs/amend.js +56 -0
- package/build/src/core/verbs/arc.d.ts +13 -0
- package/build/src/core/verbs/arc.js +25 -0
- package/build/src/core/verbs/attestation.d.ts +13 -0
- package/build/src/core/verbs/attestation.js +21 -0
- package/build/src/core/verbs/bind.d.ts +13 -0
- package/build/src/core/verbs/bind.js +40 -0
- package/build/src/core/verbs/deliver.d.ts +13 -0
- package/build/src/core/verbs/deliver.js +26 -0
- package/build/src/core/verbs/placement.d.ts +13 -0
- package/build/src/core/verbs/placement.js +42 -0
- package/build/src/dispatch/index.d.ts +31 -0
- package/build/src/dispatch/index.js +159 -0
- package/build/src/git/admission.d.ts +18 -0
- package/build/src/git/admission.js +116 -0
- package/build/src/git/delivery.d.ts +20 -0
- package/build/src/git/delivery.js +109 -0
- package/build/src/git/hooks.d.ts +34 -0
- package/build/src/git/hooks.js +258 -0
- package/build/src/git/identity.d.ts +13 -0
- package/build/src/git/identity.js +28 -0
- package/build/src/git/observe.d.ts +38 -0
- package/build/src/git/observe.js +227 -0
- package/build/src/git/reconcile.d.ts +49 -0
- package/build/src/git/reconcile.js +223 -0
- package/build/src/git/repository.d.ts +80 -0
- package/build/src/git/repository.js +456 -0
- package/build/src/git/tree.d.ts +34 -0
- package/build/src/git/tree.js +112 -0
- package/build/src/git/verification.d.ts +14 -0
- package/build/src/git/verification.js +56 -0
- package/build/src/identity/coordinates.d.ts +9 -0
- package/build/src/identity/coordinates.js +20 -0
- package/build/src/identity/normalize.d.ts +8 -0
- package/build/src/identity/normalize.js +45 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +7 -0
- package/build/src/index.d.ts +4 -0
- package/build/src/index.js +2 -0
- package/build/src/kanshi/index.d.ts +5 -0
- package/build/src/kanshi/index.js +2 -0
- package/build/src/kanshi/read.d.ts +5 -0
- package/build/src/kanshi/read.js +100 -0
- package/build/src/kanshi/report.d.ts +35 -0
- package/build/src/kanshi/select.d.ts +8 -0
- package/build/src/kanshi/select.js +21 -0
- package/build/src/library/akuma-creation.d.ts +79 -0
- package/build/src/library/akuma-creation.js +151 -0
- package/build/src/library/configuration.d.ts +26 -0
- package/build/src/library/configuration.js +100 -0
- package/build/src/library/contract.d.ts +145 -0
- package/build/src/library/contract.js +325 -0
- package/build/src/library/input.d.ts +13 -0
- package/build/src/library/input.js +82 -0
- package/build/src/library/keiyaku.d.ts +28 -0
- package/build/src/library/keiyaku.js +16 -0
- package/build/src/library/region.d.ts +17 -0
- package/build/src/library/region.js +30 -0
- package/build/src/library/repo.d.ts +33 -0
- package/build/src/library/repo.js +61 -0
- package/build/src/markdown/diff.d.ts +1 -0
- package/build/src/markdown/diff.js +4 -0
- package/build/src/markdown/lex.d.ts +3 -0
- package/build/src/markdown/lex.js +221 -0
- package/build/src/markdown/parse.d.ts +2 -0
- package/build/src/markdown/parse.js +221 -0
- package/build/src/markdown/query.d.ts +21 -0
- package/build/src/markdown/query.js +51 -0
- package/build/src/markdown/types.d.ts +118 -0
- package/build/src/markdown/types.js +6 -0
- package/build/src/protocol/attempt.d.ts +36 -0
- package/build/src/protocol/attempt.js +119 -0
- package/build/src/protocol/bind.d.ts +25 -0
- package/build/src/protocol/bind.js +62 -0
- package/build/src/protocol/intent.d.ts +52 -0
- package/build/src/protocol/intent.js +129 -0
- package/build/src/protocol/operations.d.ts +140 -0
- package/build/src/protocol/operations.js +373 -0
- package/build/src/protocol/outcome.d.ts +18 -0
- package/build/src/protocol/outcome.js +15 -0
- package/build/src/protocol/read/audit.d.ts +25 -0
- package/build/src/protocol/read/audit.js +39 -0
- package/build/src/protocol/read/documents.d.ts +8 -0
- package/build/src/protocol/read/documents.js +16 -0
- package/build/src/protocol/read/status.d.ts +38 -0
- package/build/src/protocol/read/status.js +47 -0
- package/build/src/protocol/run.d.ts +39 -0
- package/build/src/protocol/run.js +36 -0
- package/build/src/runtime/proc/line-rpc.d.ts +37 -0
- package/build/src/runtime/proc/line-rpc.js +124 -0
- package/build/src/runtime/proc/run.d.ts +54 -0
- package/build/src/runtime/proc/run.js +200 -0
- package/build/src/settings.d.ts +45 -0
- package/build/src/settings.js +99 -0
- package/build/src/settlement/holder.d.ts +15 -0
- package/build/src/settlement/holder.js +113 -0
- package/build/src/settlement/settle.d.ts +36 -0
- package/build/src/settlement/settle.js +91 -0
- package/build/src/task/board.d.ts +65 -0
- package/build/src/task/board.js +155 -0
- package/build/src/task/compose.d.ts +25 -0
- package/build/src/task/compose.js +232 -0
- package/build/src/task/context.d.ts +4 -0
- package/build/src/task/context.js +56 -0
- package/build/src/task/document.d.ts +24 -0
- package/build/src/task/document.js +118 -0
- package/build/src/task/identity.d.ts +12 -0
- package/build/src/task/identity.js +47 -0
- package/build/src/task/index.d.ts +90 -0
- package/build/src/task/index.js +179 -0
- package/build/src/task/operations.d.ts +115 -0
- package/build/src/task/operations.js +194 -0
- package/build/src/task/store.d.ts +22 -0
- package/build/src/task/store.js +114 -0
- package/build/src/verification/declaration.d.ts +22 -0
- package/build/src/verification/declaration.js +14 -0
- package/build/src/verification/producer.d.ts +23 -0
- package/build/src/verification/producer.js +54 -0
- package/package.json +62 -44
- package/build/.tsbuildinfo +0 -1
- package/build/agents/call-terms.js +0 -32
- package/build/agents/harness/activity-values.js +0 -70
- package/build/agents/harness/control-types.js +0 -18
- package/build/agents/harness/event-channel.js +0 -213
- package/build/agents/harness/event-persistence.js +0 -220
- package/build/agents/harness/events.js +0 -48
- package/build/agents/harness/execution-handle.js +0 -172
- package/build/agents/harness/index.js +0 -11
- package/build/agents/harness/outcome-error.js +0 -81
- package/build/agents/harness/outcome.js +0 -220
- package/build/agents/harness/projection.js +0 -369
- package/build/agents/harness/provider-adapter.js +0 -58
- package/build/agents/harness/router.js +0 -30
- package/build/agents/harness/runtime.js +0 -85
- package/build/agents/harness/session.js +0 -15
- package/build/agents/launch-snapshot/model.js +0 -127
- package/build/agents/launch-snapshot/parse-helpers.js +0 -114
- package/build/agents/launch-snapshot/resolve.js +0 -46
- package/build/agents/opencode-sdk.js +0 -159
- package/build/agents/providers/claude-agent-sdk/adapter.js +0 -396
- package/build/agents/providers/claude-agent-sdk/events.js +0 -218
- package/build/agents/providers/claude-agent-sdk/registration.js +0 -225
- package/build/agents/providers/claude-agent-sdk/session-schema.js +0 -2
- package/build/agents/providers/claude-agent-sdk/session.js +0 -172
- package/build/agents/providers/codex-app-server/adapter.js +0 -387
- package/build/agents/providers/codex-app-server/events.js +0 -492
- package/build/agents/providers/codex-app-server/identity.js +0 -1
- package/build/agents/providers/codex-app-server/policy.js +0 -29
- package/build/agents/providers/codex-app-server/registration.js +0 -259
- package/build/agents/providers/codex-app-server/session-schema.js +0 -6
- package/build/agents/providers/codex-app-server/session.js +0 -273
- package/build/agents/providers/event-type-tail.js +0 -16
- package/build/agents/providers/opencode-sdk/adapter.js +0 -402
- package/build/agents/providers/opencode-sdk/events.js +0 -380
- package/build/agents/providers/opencode-sdk/registration.js +0 -146
- package/build/agents/providers/opencode-sdk/session-schema.js +0 -2
- package/build/agents/providers/opencode-sdk/session.js +0 -187
- package/build/agents/providers/pi/adapter.js +0 -285
- package/build/agents/providers/pi/checkpoint.js +0 -49
- package/build/agents/providers/pi/events.js +0 -285
- package/build/agents/providers/pi/registration.js +0 -160
- package/build/agents/providers/pi/session-schema.js +0 -6
- package/build/agents/providers/registration.js +0 -7
- package/build/agents/providers/registry.js +0 -76
- package/build/agents/selector.js +0 -120
- package/build/agents/session.js +0 -29
- package/build/agents/string-tail-buffer.js +0 -44
- package/build/agents/types.js +0 -30
- package/build/artifact-directories.js +0 -22
- package/build/cli/commands/akuma/akuma/handler.js +0 -5
- package/build/cli/commands/akuma/akuma/meta.js +0 -17
- package/build/cli/commands/akuma/catalog.js +0 -10
- package/build/cli/commands/akuma/list/handler.js +0 -15
- package/build/cli/commands/akuma/list/meta-list.js +0 -12
- package/build/cli/commands/akuma/list/meta-ls.js +0 -9
- package/build/cli/commands/akuma/show/handler.js +0 -27
- package/build/cli/commands/akuma/show/meta.js +0 -8
- package/build/cli/commands/akuma.js +0 -186
- package/build/cli/commands/contract/amend/handler.js +0 -17
- package/build/cli/commands/contract/amend/meta.js +0 -13
- package/build/cli/commands/contract/arc/handler.js +0 -16
- package/build/cli/commands/contract/arc/meta.js +0 -28
- package/build/cli/commands/contract/audit/handler.js +0 -42
- package/build/cli/commands/contract/audit/meta.js +0 -17
- package/build/cli/commands/contract/bind/handler.js +0 -39
- package/build/cli/commands/contract/bind/meta.js +0 -96
- package/build/cli/commands/contract/catalog.js +0 -18
- package/build/cli/commands/contract/forfeit/handler.js +0 -17
- package/build/cli/commands/contract/forfeit/meta.js +0 -12
- package/build/cli/commands/contract/log/handler.js +0 -12
- package/build/cli/commands/contract/log/meta.js +0 -12
- package/build/cli/commands/contract/petition/handler.js +0 -64
- package/build/cli/commands/contract/petition/meta.js +0 -23
- package/build/cli/commands/contract/renew/handler.js +0 -65
- package/build/cli/commands/contract/renew/meta.js +0 -19
- package/build/cli/commands/metadata.js +0 -68
- package/build/cli/commands/projection/call/handler.js +0 -43
- package/build/cli/commands/projection/call/meta.js +0 -12
- package/build/cli/commands/projection/catalog.js +0 -16
- package/build/cli/commands/projection/fork/handler.js +0 -61
- package/build/cli/commands/projection/fork/meta.js +0 -12
- package/build/cli/commands/projection/history/handler.js +0 -65
- package/build/cli/commands/projection/history/meta.js +0 -9
- package/build/cli/commands/projection/kill/handler.js +0 -20
- package/build/cli/commands/projection/kill/meta.js +0 -11
- package/build/cli/commands/projection/shared.js +0 -27
- package/build/cli/commands/projection/status/handler.js +0 -42
- package/build/cli/commands/projection/status/meta.js +0 -20
- package/build/cli/commands/projection/tell/handler.js +0 -32
- package/build/cli/commands/projection/tell/meta.js +0 -12
- package/build/cli/commands/projection/wait/handler.js +0 -80
- package/build/cli/commands/projection/wait/meta.js +0 -16
- package/build/cli/commands/registry.js +0 -48
- package/build/cli/commands/shared.js +0 -74
- package/build/cli/commands/skills/catalog.js +0 -6
- package/build/cli/commands/skills/install/handler.js +0 -7
- package/build/cli/commands/skills/install/meta.js +0 -9
- package/build/cli/commands/skills/skills/handler.js +0 -4
- package/build/cli/commands/skills/skills/meta.js +0 -10
- package/build/cli/commands/system/catalog.js +0 -10
- package/build/cli/commands/system/completion/handler.js +0 -10
- package/build/cli/commands/system/completion/meta.js +0 -9
- package/build/cli/commands/system/dump-env/handler.js +0 -3
- package/build/cli/commands/system/dump-env/meta.js +0 -10
- package/build/cli/commands/system/guide/handler.js +0 -4
- package/build/cli/commands/system/guide/meta.js +0 -9
- package/build/cli/commands/task/add/handler.js +0 -38
- package/build/cli/commands/task/add/meta.js +0 -31
- package/build/cli/commands/task/catalog.js +0 -32
- package/build/cli/commands/task/compose/handler.js +0 -18
- package/build/cli/commands/task/compose/meta.js +0 -10
- package/build/cli/commands/task/doctor/handler.js +0 -3
- package/build/cli/commands/task/doctor/meta.js +0 -8
- package/build/cli/commands/task/done/handler.js +0 -10
- package/build/cli/commands/task/done/meta.js +0 -8
- package/build/cli/commands/task/drop/handler.js +0 -8
- package/build/cli/commands/task/drop/meta.js +0 -11
- package/build/cli/commands/task/hold/handler.js +0 -3
- package/build/cli/commands/task/hold/meta.js +0 -8
- package/build/cli/commands/task/log/handler.js +0 -12
- package/build/cli/commands/task/log/meta.js +0 -8
- package/build/cli/commands/task/ls/handler.js +0 -17
- package/build/cli/commands/task/ls/meta.js +0 -8
- package/build/cli/commands/task/note/handler.js +0 -6
- package/build/cli/commands/task/note/meta.js +0 -11
- package/build/cli/commands/task/resume/handler.js +0 -3
- package/build/cli/commands/task/resume/meta.js +0 -8
- package/build/cli/commands/task/shared.js +0 -181
- package/build/cli/commands/task/show/handler.js +0 -13
- package/build/cli/commands/task/show/meta.js +0 -8
- package/build/cli/commands/task/start/handler.js +0 -3
- package/build/cli/commands/task/start/meta.js +0 -8
- package/build/cli/commands/task/stop/handler.js +0 -10
- package/build/cli/commands/task/stop/meta.js +0 -8
- package/build/cli/commands/task/task/handler.js +0 -5
- package/build/cli/commands/task/task/meta.js +0 -11
- package/build/cli/commands/task/update/handler.js +0 -21
- package/build/cli/commands/task/update/meta.js +0 -12
- package/build/cli/commands/verification/handler.js +0 -43
- package/build/cli/commands/verification/meta.js +0 -13
- package/build/cli/completion.js +0 -91
- package/build/cli/draft-artifact.js +0 -50
- package/build/cli/flags.js +0 -321
- package/build/cli/help.js +0 -99
- package/build/cli/index.js +0 -333
- package/build/cli/missing-subcommand.js +0 -7
- package/build/cli/output-stream-error-policy.js +0 -31
- package/build/cli/parse-flags.js +0 -301
- package/build/cli/parse-metadata.js +0 -132
- package/build/cli/parse-selectors.js +0 -83
- package/build/cli/parse.js +0 -250
- package/build/cli/projection-address.js +0 -105
- package/build/cli/render/address.js +0 -101
- package/build/cli/render/amendment-warning.js +0 -8
- package/build/cli/render/arc.js +0 -88
- package/build/cli/render/audit.js +0 -440
- package/build/cli/render/call.js +0 -70
- package/build/cli/render/compact-text.js +0 -3
- package/build/cli/render/errors.js +0 -101
- package/build/cli/render/format.js +0 -226
- package/build/cli/render/kanshi.js +0 -300
- package/build/cli/render/kill.js +0 -9
- package/build/cli/render/lifecycle.js +0 -56
- package/build/cli/render/line-width.js +0 -103
- package/build/cli/render/misc.js +0 -84
- package/build/cli/render/path-prefix-compaction.js +0 -131
- package/build/cli/render/petition.js +0 -85
- package/build/cli/render/projection-activity.js +0 -332
- package/build/cli/render/projection-history.js +0 -77
- package/build/cli/render/response-style.js +0 -27
- package/build/cli/render/shared.js +0 -232
- package/build/cli/render/skills.js +0 -10
- package/build/cli/render/status-indicator.js +0 -47
- package/build/cli/render/status.js +0 -243
- package/build/cli/render/success-response.js +0 -95
- package/build/cli/render/task.js +0 -175
- package/build/cli/render/tell.js +0 -11
- package/build/cli/render/terminal-failure.js +0 -65
- package/build/cli/render/tool-command-normalization.js +0 -137
- package/build/cli/render/tool-ledger-rollup.js +0 -74
- package/build/cli/render/tool-presentation.js +0 -98
- package/build/cli/render/types.js +0 -2
- package/build/cli/render/verification.js +0 -23
- package/build/cli/render/wait.js +0 -343
- package/build/cli/skills-install.js +0 -348
- package/build/cli/subagent-guard.js +0 -25
- package/build/cli/types.js +0 -2
- package/build/config/akuma-loader.js +0 -240
- package/build/config/env-keys.js +0 -57
- package/build/config/env.js +0 -304
- package/build/config/provider-policy-ownership.js +0 -10
- package/build/config/settings/disease.js +0 -33
- package/build/config/settings/knobs.js +0 -14
- package/build/config/settings/loader.js +0 -275
- package/build/config/settings/provider-instance-fields.js +0 -51
- package/build/config/settings/schema.js +0 -113
- package/build/core/address-carrier.js +0 -89
- package/build/core/addressing.js +0 -407
- package/build/core/amend.js +0 -321
- package/build/core/amendment-criteria.js +0 -17
- package/build/core/amendment-warning.js +0 -10
- package/build/core/arc.js +0 -293
- package/build/core/atomic-publish.js +0 -64
- package/build/core/audit/candidate.js +0 -141
- package/build/core/audit/coordinates.js +0 -230
- package/build/core/audit/evidence.js +0 -156
- package/build/core/audit/facade.js +0 -65
- package/build/core/audit/readiness.js +0 -4
- package/build/core/audit/report.js +0 -38
- package/build/core/audit.js +0 -1
- package/build/core/bind-reconciliation.js +0 -409
- package/build/core/bind-workspace.js +0 -115
- package/build/core/bind.js +0 -503
- package/build/core/call/call.js +0 -235
- package/build/core/call/context.js +0 -210
- package/build/core/call/execution.js +0 -255
- package/build/core/call/prompt.js +0 -27
- package/build/core/call/reference.js +0 -24
- package/build/core/call-persist.js +0 -76
- package/build/core/command-markdown.js +0 -45
- package/build/core/context.js +0 -104
- package/build/core/contract-carrier-runtime.js +0 -512
- package/build/core/contract-carrier.js +0 -353
- package/build/core/contract-view.js +0 -319
- package/build/core/contract.js +0 -19
- package/build/core/derived-replay.js +0 -340
- package/build/core/draft.js +0 -400
- package/build/core/execution-coordinate.js +0 -46
- package/build/core/execution-pact.js +0 -126
- package/build/core/forfeit.js +0 -132
- package/build/core/hints.js +0 -34
- package/build/core/identifier-slug.js +0 -116
- package/build/core/ids.js +0 -90
- package/build/core/lifecycle-history.js +0 -48
- package/build/core/lifecycle-recovery.js +0 -122
- package/build/core/lifecycle-runner.js +0 -377
- package/build/core/log.js +0 -50
- package/build/core/markdown/lex.js +0 -274
- package/build/core/markdown/parser.js +0 -260
- package/build/core/markdown/render.js +0 -68
- package/build/core/markdown/sections.js +0 -80
- package/build/core/markdown/titles.js +0 -9
- package/build/core/markdown/types.js +0 -6
- package/build/core/outcome-base.js +0 -185
- package/build/core/places.js +0 -175
- package/build/core/projection/akuma-name.js +0 -43
- package/build/core/projection/generation/database.js +0 -473
- package/build/core/projection/generation/identity.js +0 -84
- package/build/core/projection/generation/ledger.js +0 -91
- package/build/core/projection/generation/model.js +0 -261
- package/build/core/projection/generation/projection-generation-continuation.js +0 -84
- package/build/core/projection/generation/projection-generation-doorbell.js +0 -88
- package/build/core/projection/generation/projection-generation-execution.js +0 -241
- package/build/core/projection/generation/projection-generation-identity.js +0 -21
- package/build/core/projection/generation/projection-generation-launcher.js +0 -154
- package/build/core/projection/generation/projection-generation-process.js +0 -47
- package/build/core/projection/generation/projection-generation-runner.js +0 -489
- package/build/core/projection/generation/projection-generation-runtime.js +0 -46
- package/build/core/projection/generation/protocol.js +0 -68
- package/build/core/projection/generation/store.js +0 -108
- package/build/core/projection/generation/transitions.js +0 -463
- package/build/core/projection/heart.js +0 -9
- package/build/core/projection/index.js +0 -28
- package/build/core/projection/projection-activity.js +0 -273
- package/build/core/projection/projection-alias.js +0 -131
- package/build/core/projection/projection-coordinate.js +0 -61
- package/build/core/projection/projection-core.js +0 -127
- package/build/core/projection/projection-execution-observer.js +0 -270
- package/build/core/projection/projection-history.js +0 -474
- package/build/core/projection/projection-identity.js +0 -11
- package/build/core/projection/projection-kill.js +0 -112
- package/build/core/projection/projection-life-observer.js +0 -101
- package/build/core/projection/projection-mint.js +0 -170
- package/build/core/projection/projection-status-observation.js +0 -434
- package/build/core/projection/projection-status.js +0 -442
- package/build/core/projection/projection-terminal-failure.js +0 -111
- package/build/core/projection/projection-wait.js +0 -337
- package/build/core/projection/projection-wake.js +0 -298
- package/build/core/projection/tell/launch-store.js +0 -244
- package/build/core/projection/tell/model.js +0 -98
- package/build/core/projection/tell/store.js +0 -245
- package/build/core/provider-loader-ports.js +0 -4
- package/build/core/registry.js +0 -100
- package/build/core/renew-build.js +0 -554
- package/build/core/renew-plan.js +0 -264
- package/build/core/renew-rewrite.js +0 -118
- package/build/core/renew.js +0 -345
- package/build/core/repository-ledger/accepted-fold-read.js +0 -22
- package/build/core/repository-ledger/accepted-tail.js +0 -116
- package/build/core/repository-ledger/admission.js +0 -38
- package/build/core/repository-ledger/authoritative-transaction.js +0 -1
- package/build/core/repository-ledger/claim-evidence.js +0 -147
- package/build/core/repository-ledger/codec.js +0 -303
- package/build/core/repository-ledger/current-state-store.js +0 -968
- package/build/core/repository-ledger/fold-repository.js +0 -374
- package/build/core/repository-ledger/fold.js +0 -248
- package/build/core/repository-ledger/git-object-store.js +0 -243
- package/build/core/repository-ledger/history-read.js +0 -15
- package/build/core/repository-ledger/identity.js +0 -60
- package/build/core/repository-ledger/incremental-read.js +0 -153
- package/build/core/repository-ledger/index.js +0 -15
- package/build/core/repository-ledger/inventory-plan.js +0 -75
- package/build/core/repository-ledger/inventory.js +0 -310
- package/build/core/repository-ledger/publication-admission.js +0 -125
- package/build/core/repository-ledger/publication.js +0 -353
- package/build/core/repository-ledger/read-model.js +0 -517
- package/build/core/repository-ledger/transaction-membership.js +0 -78
- package/build/core/repository-ledger/traversal.js +0 -404
- package/build/core/repository-ledger/write-transaction.js +0 -346
- package/build/core/response-artifact-catalog-sqlite.js +0 -112
- package/build/core/response-artifact-catalog.js +0 -7
- package/build/core/response-artifact-id.js +0 -5
- package/build/core/run-control/connection-bound-close.js +0 -41
- package/build/core/run-control/detached-lease-bootstrap.js +0 -208
- package/build/core/run-control/detached-process.js +0 -14
- package/build/core/run-control/index.js +0 -6
- package/build/core/run-control/process-tree.js +0 -139
- package/build/core/run-control/runner-lease.js +0 -172
- package/build/core/run-control/sqlite-process-lifetime-lock.js +0 -174
- package/build/core/scope.js +0 -416
- package/build/core/seal.js +0 -364
- package/build/core/settlement/claim-delivery.js +0 -82
- package/build/core/settlement/claim.js +0 -258
- package/build/core/settlement/index.js +0 -19
- package/build/core/settlement/petition-claim-gates.js +0 -247
- package/build/core/settlement/petition-forfeit.js +0 -46
- package/build/core/settlement/petition-head-guard.js +0 -12
- package/build/core/settlement/petition-io.js +0 -1
- package/build/core/settlement/petition-preview.js +0 -125
- package/build/core/settlement/petition-window.js +0 -50
- package/build/core/settlement/petition.js +0 -315
- package/build/core/settlement/queue-read-model.js +0 -120
- package/build/core/settlement/queue-seat-allocation.js +0 -65
- package/build/core/settlement/queue.js +0 -6
- package/build/core/settlement/settlement.js +0 -385
- package/build/core/settlement/verdict.js +0 -126
- package/build/core/settlement/verification.js +0 -554
- package/build/core/status/board.js +0 -455
- package/build/core/status/drift.js +0 -113
- package/build/core/status/lifecycle.js +0 -11
- package/build/core/stored-agent-event.js +0 -129
- package/build/core/structured-query.js +0 -23
- package/build/core/target-ref.js +0 -10
- package/build/core/task/board.js +0 -248
- package/build/core/task/commands.js +0 -401
- package/build/core/task/compose.js +0 -328
- package/build/core/task/coordinate.js +0 -56
- package/build/core/task/document.js +0 -273
- package/build/core/task/index.js +0 -16
- package/build/core/task/model.js +0 -8
- package/build/core/task/query.js +0 -204
- package/build/core/task/settlement-git.js +0 -423
- package/build/core/task/settlement-policy.js +0 -137
- package/build/core/task/source-board.js +0 -104
- package/build/core/task/source-model.js +0 -1
- package/build/core/task/task-bind-preparation.js +0 -243
- package/build/core/task/task-contract.js +0 -371
- package/build/core/task/task-doctor.js +0 -14
- package/build/core/task/task-file-transaction.js +0 -171
- package/build/core/task/task-git-actor.js +0 -33
- package/build/core/task/task-git-runtime.js +0 -97
- package/build/core/task/task-git-store.js +0 -400
- package/build/core/task/task-repository.js +0 -1
- package/build/core/task/task-store-repository.js +0 -97
- package/build/core/task/task-store.js +0 -1
- package/build/core/task/task-worktree.js +0 -25
- package/build/core/task/task.js +0 -7
- package/build/core/task/tree.js +0 -37
- package/build/core/task/validation.js +0 -48
- package/build/core/transcripts.js +0 -485
- package/build/core/validation.js +0 -17
- package/build/core/verification-declaration.js +0 -95
- package/build/core/worktree-bootstrap.js +0 -195
- package/build/core/worktree-path.js +0 -371
- package/build/errno.js +0 -3
- package/build/flow-error.js +0 -191
- package/build/fs/durability.js +0 -27
- package/build/fs/path-coordinate.js +0 -16
- package/build/generated/version.js +0 -3
- package/build/git/branches.js +0 -84
- package/build/git/commits.js +0 -151
- package/build/git/core.js +0 -86
- package/build/git/diff/parsers.js +0 -181
- package/build/git/diff/pathspec.js +0 -3
- package/build/git/diff/preview.js +0 -38
- package/build/git/diff/read.js +0 -105
- package/build/git/diff/structured.js +0 -127
- package/build/git/diff/types.js +0 -1
- package/build/git/path-coordinate.js +0 -17
- package/build/git/process.js +0 -229
- package/build/git/refs.js +0 -250
- package/build/git/staging.js +0 -79
- package/build/git/streaming-batch.js +0 -354
- package/build/git/worktree.js +0 -175
- package/build/index.js +0 -67
- package/build/keiyaku-constants.js +0 -2
- package/build/keiyaku.js +0 -30
- package/build/telemetry/debug-log.js +0 -40
- package/build/telemetry/logger.js +0 -48
- package/skills/keiyaku/SKILL.md +0 -46
- package/skills/keiyaku-akuma/SKILL.md +0 -97
- package/skills/keiyaku-task/SKILL.md +0 -118
- package/skills/keiyaku-workflow/SKILL.md +0 -191
- /package/build/{agents/launch-snapshot → src/body}/types.js +0 -0
- /package/build/{agents/providers/claude-agent-sdk/terms.js → src/cli/result.js} +0 -0
- /package/build/{agents/providers/codex-app-server/terms.js → src/core/decide.js} +0 -0
- /package/build/{agents/providers/opencode-sdk/terms.js → src/core/facts/offer.js} +0 -0
- /package/build/{agents/providers/pi/terms.js → src/kanshi/report.js} +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { resolveContextRoot } from "../context-root.js";
|
|
2
|
+
import { buildTree, diagnoseBoard, projectDetailFacts } from "./board.js";
|
|
3
|
+
import { composeTasks } from "./compose.js";
|
|
4
|
+
import { TaskAuthorityCorruptionError } from "./document.js";
|
|
5
|
+
import { isTaskSegment, parseTaskId } from "./identity.js";
|
|
6
|
+
import { addTask, addTaskDocument, batchTasks, blockedTasks, currentNamespace, lifecycleTask, listTasks, readyTasks, setCurrentNamespace, taskView, updateTask, } from "./operations.js";
|
|
7
|
+
import { readBoard } from "./store.js";
|
|
8
|
+
export { TaskAuthorityCorruptionError };
|
|
9
|
+
function record(value, label) {
|
|
10
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
11
|
+
throw new TypeError(`${label} must be an object`);
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function closed(value, allowed, label) {
|
|
15
|
+
for (const key of Object.keys(value))
|
|
16
|
+
if (!allowed.includes(key))
|
|
17
|
+
throw new TypeError(`${label} has unknown field: ${key}`);
|
|
18
|
+
}
|
|
19
|
+
function id(value) { if (typeof value !== "string")
|
|
20
|
+
throw new TypeError("task ID must be a string"); parseTaskId(value); return value; }
|
|
21
|
+
function signal(value) {
|
|
22
|
+
if (value === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (!(value instanceof AbortSignal))
|
|
25
|
+
throw new TypeError("signal must be an AbortSignal");
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function strings(value, label) {
|
|
29
|
+
if (value === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (!Array.isArray(value) || !value.every((item) => typeof item === "string"))
|
|
32
|
+
throw new TypeError(`${label} must be an array of strings`);
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function taskIds(value, label) {
|
|
36
|
+
const values = strings(value, label)?.map(id);
|
|
37
|
+
if (values !== undefined && new Set(values).size !== values.length)
|
|
38
|
+
throw new TypeError(`${label} must not contain duplicates`);
|
|
39
|
+
return values;
|
|
40
|
+
}
|
|
41
|
+
function namespace(value) {
|
|
42
|
+
const values = strings(value, "namespace");
|
|
43
|
+
if (values === undefined)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (!values.every(isTaskSegment))
|
|
46
|
+
throw new TypeError("namespace must contain canonical segments");
|
|
47
|
+
return values;
|
|
48
|
+
}
|
|
49
|
+
function text(value, label) { if (value === undefined)
|
|
50
|
+
return undefined; if (typeof value !== "string")
|
|
51
|
+
throw new TypeError(`${label} must be a string`); return value; }
|
|
52
|
+
function priority(value) { if (value === undefined)
|
|
53
|
+
return undefined; if (!Number.isInteger(value) || typeof value !== "number" || value < 0 || value > 3)
|
|
54
|
+
throw new TypeError("priority must be 0..3"); return value; }
|
|
55
|
+
function state(value) {
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (value !== "open" && value !== "in_progress" && value !== "on_hold" && value !== "done" && value !== "drop")
|
|
59
|
+
throw new TypeError("state is invalid");
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function nullableId(value) { return value === undefined || value === null ? value : id(value); }
|
|
63
|
+
function addInput(input) {
|
|
64
|
+
const v = record(input, "add input");
|
|
65
|
+
closed(v, ["title", "namespace", "body", "note", "state", "priority", "needs", "parent", "supersedes", "relates", "signal"], "add input");
|
|
66
|
+
const title = text(v.title, "title");
|
|
67
|
+
if (title === undefined || title.trim() === "")
|
|
68
|
+
throw new TypeError("title is required");
|
|
69
|
+
const ns = namespace(v.namespace), body = text(v.body, "body"), note = text(v.note, "note"), initialState = state(v.state), pri = priority(v.priority);
|
|
70
|
+
const needs = taskIds(v.needs, "needs"), parent = nullableId(v.parent), supersedes = taskIds(v.supersedes, "supersedes"), relates = taskIds(v.relates, "relates");
|
|
71
|
+
const abort = signal(v.signal);
|
|
72
|
+
return { title, ...(ns === undefined ? {} : { namespace: ns }), ...(body === undefined ? {} : { body }), ...(note === undefined ? {} : { note }),
|
|
73
|
+
...(initialState === undefined ? {} : { state: initialState }), ...(pri === undefined ? {} : { priority: pri }),
|
|
74
|
+
...(needs === undefined ? {} : { needs }), ...(parent === undefined ? {} : { parent }),
|
|
75
|
+
...(supersedes === undefined ? {} : { supersedes }), ...(relates === undefined ? {} : { relates }),
|
|
76
|
+
...(abort === undefined ? {} : { signal: abort }) };
|
|
77
|
+
}
|
|
78
|
+
function updateInput(input) {
|
|
79
|
+
const v = record(input, "update input");
|
|
80
|
+
closed(v, ["title", "body", "appendBody", "note", "priority", "needs", "addNeeds", "dropNeeds", "parent", "supersedes", "addSupersedes", "dropSupersedes", "relates", "addRelates", "dropRelates", "signal"], "update input");
|
|
81
|
+
if (v.body !== undefined && v.appendBody !== undefined)
|
|
82
|
+
throw new TypeError("body and appendBody are mutually exclusive");
|
|
83
|
+
const result = {};
|
|
84
|
+
const title = text(v.title, "title");
|
|
85
|
+
if (title !== undefined) {
|
|
86
|
+
if (title.trim().length === 0)
|
|
87
|
+
throw new TypeError("title must be nonblank");
|
|
88
|
+
result.title = title;
|
|
89
|
+
}
|
|
90
|
+
const body = text(v.body, "body");
|
|
91
|
+
if (body !== undefined)
|
|
92
|
+
result.body = body;
|
|
93
|
+
const appendBody = text(v.appendBody, "appendBody");
|
|
94
|
+
if (appendBody !== undefined)
|
|
95
|
+
result.appendBody = appendBody;
|
|
96
|
+
const note = text(v.note, "note");
|
|
97
|
+
if (note !== undefined)
|
|
98
|
+
result.note = note;
|
|
99
|
+
const pri = priority(v.priority);
|
|
100
|
+
if (pri !== undefined)
|
|
101
|
+
result.priority = pri;
|
|
102
|
+
for (const [key, value] of [["needs", taskIds(v.needs, "needs")], ["addNeeds", taskIds(v.addNeeds, "addNeeds")], ["dropNeeds", taskIds(v.dropNeeds, "dropNeeds")], ["supersedes", taskIds(v.supersedes, "supersedes")], ["addSupersedes", taskIds(v.addSupersedes, "addSupersedes")], ["dropSupersedes", taskIds(v.dropSupersedes, "dropSupersedes")], ["relates", taskIds(v.relates, "relates")], ["addRelates", taskIds(v.addRelates, "addRelates")], ["dropRelates", taskIds(v.dropRelates, "dropRelates")]])
|
|
103
|
+
if (value !== undefined)
|
|
104
|
+
result[key] = value;
|
|
105
|
+
const parent = nullableId(v.parent);
|
|
106
|
+
if (parent !== undefined)
|
|
107
|
+
result.parent = parent;
|
|
108
|
+
const abort = signal(v.signal);
|
|
109
|
+
if (abort !== undefined)
|
|
110
|
+
result.signal = abort;
|
|
111
|
+
const update = result;
|
|
112
|
+
if (Object.keys(result).filter((key) => key !== "signal").length === 0)
|
|
113
|
+
throw new TypeError("update requires at least one field change");
|
|
114
|
+
return update;
|
|
115
|
+
}
|
|
116
|
+
class TaskHandle {
|
|
117
|
+
id;
|
|
118
|
+
world;
|
|
119
|
+
constructor(id, world) {
|
|
120
|
+
this.id = id;
|
|
121
|
+
this.world = world;
|
|
122
|
+
}
|
|
123
|
+
async read() {
|
|
124
|
+
const facts = projectDetailFacts(readBoard(this.world).board, this.id);
|
|
125
|
+
return facts === null ? null : { ...facts, task: taskView(facts.task) };
|
|
126
|
+
}
|
|
127
|
+
async tree(input) {
|
|
128
|
+
const value = record(input ?? {}, "tree input");
|
|
129
|
+
closed(value, ["full"], "tree input");
|
|
130
|
+
if (value.full !== undefined && typeof value.full !== "boolean")
|
|
131
|
+
throw new TypeError("full must be a boolean");
|
|
132
|
+
const node = buildTree(readBoard(this.world).board, this.id, value.full ?? false);
|
|
133
|
+
return node === null ? { kind: "refused", refusal: { kind: "task-missing", taskId: this.id } } : { kind: "accepted", value: node };
|
|
134
|
+
}
|
|
135
|
+
update(input) { return updateTask(this.world, this.id, updateInput(input)); }
|
|
136
|
+
lifecycle(verb, input) {
|
|
137
|
+
const value = record(input ?? {}, `${verb} input`);
|
|
138
|
+
closed(value, verb === "drop" ? ["note", "signal"] : ["signal"], `${verb} input`);
|
|
139
|
+
const note = verb === "drop" ? text(value.note, "note") : undefined;
|
|
140
|
+
return lifecycleTask(this.world, this.id, verb, signal(value.signal), note);
|
|
141
|
+
}
|
|
142
|
+
start(input) { return this.lifecycle("start", input); }
|
|
143
|
+
stop(input) { return this.lifecycle("stop", input); }
|
|
144
|
+
hold(input) { return this.lifecycle("hold", input); }
|
|
145
|
+
resume(input) { return this.lifecycle("resume", input); }
|
|
146
|
+
done(input) { return this.lifecycle("done", input); }
|
|
147
|
+
drop(input) { return this.lifecycle("drop", input); }
|
|
148
|
+
}
|
|
149
|
+
class TasksHandle {
|
|
150
|
+
root;
|
|
151
|
+
world;
|
|
152
|
+
constructor(path) {
|
|
153
|
+
const root = resolveContextRoot({ from: path ?? process.cwd(), marker: ".keiyaku" });
|
|
154
|
+
this.world = { root };
|
|
155
|
+
this.root = root;
|
|
156
|
+
}
|
|
157
|
+
async namespace() { const value = currentNamespace(this.world); return "kind" in value ? { kind: "refused", refusal: value } : { kind: "accepted", value }; }
|
|
158
|
+
async setNamespace(input) { const v = record(input, "setNamespace input"); closed(v, ["namespace"], "setNamespace input"); const ns = namespace(v.namespace); if (ns === undefined)
|
|
159
|
+
throw new TypeError("namespace is required"); setCurrentNamespace(this.world, ns); }
|
|
160
|
+
task(input) { const v = record(input, "task input"); closed(v, ["id"], "task input"); return new TaskHandle(id(v.id), this.world); }
|
|
161
|
+
add(input) { return addTask(this.world, addInput(input)); }
|
|
162
|
+
addDocument(input) { const v = record(input, "addDocument input"); closed(v, ["markdown", "namespace", "signal"], "addDocument input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
|
|
163
|
+
throw new TypeError("markdown is required"); const ns = namespace(v.namespace), abort = signal(v.signal); return addTaskDocument(this.world, { markdown, ...(ns === undefined ? {} : { namespace: ns }), ...(abort === undefined ? {} : { signal: abort }) }); }
|
|
164
|
+
async list(input = {}) { const v = record(input, "list input"); closed(v, ["selection", "scope"], "list input"); if (v.selection !== undefined && v.selection !== "active" && v.selection !== "closed" && v.selection !== "all")
|
|
165
|
+
throw new TypeError("selection must be active, closed, or all"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
166
|
+
throw new TypeError("scope must be namespace or world"); return listTasks(this.world, v.selection ?? "active", v.scope); }
|
|
167
|
+
async ready(input = {}) { const v = record(input, "ready input"); closed(v, ["scope"], "ready input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
168
|
+
throw new TypeError("scope must be namespace or world"); return readyTasks(this.world, v.scope); }
|
|
169
|
+
async blocked(input = {}) { const v = record(input, "blocked input"); closed(v, ["scope"], "blocked input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
170
|
+
throw new TypeError("scope must be namespace or world"); return blockedTasks(this.world, v.scope); }
|
|
171
|
+
async doctor() { return { issues: diagnoseBoard(readBoard(this.world).board) }; }
|
|
172
|
+
batch(input) { const v = record(input, "batch input"); closed(v, ["verb", "ids", "note", "signal"], "batch input"); const verb = v.verb; if (verb !== "done" && verb !== "drop" && verb !== "hold")
|
|
173
|
+
throw new TypeError("batch verb is invalid"); const note = text(v.note, "note"); if (note !== undefined && verb !== "drop")
|
|
174
|
+
throw new TypeError("batch note is valid only for drop"); return batchTasks(this.world, verb, taskIds(v.ids, "ids") ?? [], signal(v.signal), note); }
|
|
175
|
+
compose(input) { const v = record(input, "compose input"); closed(v, ["markdown", "signal"], "compose input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
|
|
176
|
+
throw new TypeError("markdown is required"); return composeTasks(this.world, markdown, signal(v.signal)); }
|
|
177
|
+
}
|
|
178
|
+
export const Tasks = Object.freeze({ at(input) { if (input === undefined)
|
|
179
|
+
return new TasksHandle(); const value = record(input, "Tasks.at input"); closed(value, ["path"], "Tasks.at input"); return new TasksHandle(text(value.path, "path")); } });
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { type BlockedTaskRow, type TaskRow } from "./board.js";
|
|
2
|
+
import { type TaskDocument, type TaskPriority, type TaskState } from "./document.js";
|
|
3
|
+
import { type TaskId } from "./identity.js";
|
|
4
|
+
import { type TaskWorld } from "./store.js";
|
|
5
|
+
export type TaskView = Readonly<TaskDocument & {
|
|
6
|
+
namespace: readonly string[];
|
|
7
|
+
}>;
|
|
8
|
+
export type TaskRefusal = Readonly<{
|
|
9
|
+
kind: "task-missing";
|
|
10
|
+
taskId: TaskId;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
kind: "invalid-lifecycle-transition";
|
|
13
|
+
taskId: TaskId;
|
|
14
|
+
state: TaskState;
|
|
15
|
+
verb: TaskLifecycleVerb;
|
|
16
|
+
}> | Readonly<{
|
|
17
|
+
kind: "invalid-graph";
|
|
18
|
+
diagnostic: string;
|
|
19
|
+
}> | Readonly<{
|
|
20
|
+
kind: "invalid-namespace-context";
|
|
21
|
+
path: string;
|
|
22
|
+
}> | Readonly<{
|
|
23
|
+
kind: "relation-owned-by-other";
|
|
24
|
+
taskId: TaskId;
|
|
25
|
+
related: TaskId;
|
|
26
|
+
declaringTask: TaskId;
|
|
27
|
+
}> | Readonly<{
|
|
28
|
+
kind: "invalid-composition";
|
|
29
|
+
diagnostic: string;
|
|
30
|
+
}>;
|
|
31
|
+
export type TaskRetry = "busy" | "concurrent-modification";
|
|
32
|
+
export type TaskOutcome<A> = Readonly<{
|
|
33
|
+
kind: "accepted";
|
|
34
|
+
value: A;
|
|
35
|
+
}> | Readonly<{
|
|
36
|
+
kind: "refused";
|
|
37
|
+
refusal: TaskRefusal;
|
|
38
|
+
}> | Readonly<{
|
|
39
|
+
kind: "retry";
|
|
40
|
+
reason: TaskRetry;
|
|
41
|
+
}>;
|
|
42
|
+
export type TaskMutationResult = TaskOutcome<TaskView>;
|
|
43
|
+
export type TaskUpdateResult = TaskOutcome<Readonly<{
|
|
44
|
+
task: TaskView;
|
|
45
|
+
documentDiff: string;
|
|
46
|
+
}>>;
|
|
47
|
+
export type TaskLifecycleVerb = "start" | "stop" | "hold" | "resume" | "done" | "drop";
|
|
48
|
+
export type TaskBatchResult = Readonly<{
|
|
49
|
+
items: readonly Readonly<{
|
|
50
|
+
id: TaskId;
|
|
51
|
+
outcome: TaskMutationResult;
|
|
52
|
+
}>[];
|
|
53
|
+
}>;
|
|
54
|
+
export type SettledTaskAction = "done" | "reopened";
|
|
55
|
+
export type SettledTaskResult = Readonly<{
|
|
56
|
+
kind: "changed";
|
|
57
|
+
task: TaskView;
|
|
58
|
+
action: SettledTaskAction;
|
|
59
|
+
}> | Readonly<{
|
|
60
|
+
kind: "unchanged";
|
|
61
|
+
}> | Readonly<{
|
|
62
|
+
kind: "refused";
|
|
63
|
+
refusal: TaskRefusal;
|
|
64
|
+
}> | Readonly<{
|
|
65
|
+
kind: "retry";
|
|
66
|
+
reason: TaskRetry;
|
|
67
|
+
}>;
|
|
68
|
+
export type AddTaskInput = Readonly<{
|
|
69
|
+
title: string;
|
|
70
|
+
namespace?: readonly string[];
|
|
71
|
+
body?: string;
|
|
72
|
+
note?: string;
|
|
73
|
+
state?: TaskState;
|
|
74
|
+
priority?: TaskPriority;
|
|
75
|
+
needs?: readonly TaskId[];
|
|
76
|
+
parent?: TaskId | null;
|
|
77
|
+
supersedes?: readonly TaskId[];
|
|
78
|
+
relates?: readonly TaskId[];
|
|
79
|
+
signal?: AbortSignal;
|
|
80
|
+
}>;
|
|
81
|
+
export type AddTaskDocumentInput = Readonly<{
|
|
82
|
+
markdown: string;
|
|
83
|
+
namespace?: readonly string[];
|
|
84
|
+
signal?: AbortSignal;
|
|
85
|
+
}>;
|
|
86
|
+
export type UpdateTaskInput = Readonly<{
|
|
87
|
+
title?: string;
|
|
88
|
+
body?: string;
|
|
89
|
+
appendBody?: string;
|
|
90
|
+
note?: string;
|
|
91
|
+
priority?: TaskPriority;
|
|
92
|
+
needs?: readonly TaskId[];
|
|
93
|
+
addNeeds?: readonly TaskId[];
|
|
94
|
+
dropNeeds?: readonly TaskId[];
|
|
95
|
+
parent?: TaskId | null;
|
|
96
|
+
supersedes?: readonly TaskId[];
|
|
97
|
+
addSupersedes?: readonly TaskId[];
|
|
98
|
+
dropSupersedes?: readonly TaskId[];
|
|
99
|
+
relates?: readonly TaskId[];
|
|
100
|
+
addRelates?: readonly TaskId[];
|
|
101
|
+
dropRelates?: readonly TaskId[];
|
|
102
|
+
signal?: AbortSignal;
|
|
103
|
+
}>;
|
|
104
|
+
export declare function taskView(document: TaskDocument): TaskView;
|
|
105
|
+
export declare function addTask(world: TaskWorld, input: AddTaskInput): Promise<TaskMutationResult>;
|
|
106
|
+
export declare function addTaskDocument(world: TaskWorld, input: AddTaskDocumentInput): Promise<TaskMutationResult>;
|
|
107
|
+
export declare function updateTask(world: TaskWorld, id: TaskId, input: UpdateTaskInput): Promise<TaskUpdateResult>;
|
|
108
|
+
export declare function lifecycleTask(world: TaskWorld, id: TaskId, verb: TaskLifecycleVerb, signal?: AbortSignal, note?: string): Promise<TaskMutationResult>;
|
|
109
|
+
export declare function batchTasks(world: TaskWorld, verb: "done" | "drop" | "hold", ids: readonly TaskId[], signal?: AbortSignal, note?: string): Promise<TaskBatchResult>;
|
|
110
|
+
export declare function settleTask(world: TaskWorld, id: TaskId, desired: "done" | "open-from-done"): Promise<SettledTaskResult>;
|
|
111
|
+
export declare function listTasks(world: TaskWorld, selection: "active" | "closed" | "all", scope?: "namespace" | "world"): TaskOutcome<readonly TaskRow[]>;
|
|
112
|
+
export declare function readyTasks(world: TaskWorld, scope?: "namespace" | "world"): TaskOutcome<readonly TaskRow[]>;
|
|
113
|
+
export declare function blockedTasks(world: TaskWorld, scope?: "namespace" | "world"): TaskOutcome<readonly BlockedTaskRow[]>;
|
|
114
|
+
export declare function setCurrentNamespace(world: TaskWorld, namespace: readonly string[]): void;
|
|
115
|
+
export declare function currentNamespace(world: TaskWorld): readonly string[] | TaskRefusal;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { documentDiff } from "../markdown/diff.js";
|
|
2
|
+
import { installNamespaceContext, readNamespaceContext } from "./context.js";
|
|
3
|
+
import { relationProblem, projectBlocked, projectReady, projectRows } from "./board.js";
|
|
4
|
+
import { parseTaskCreationDocument, serializeTaskDocument } from "./document.js";
|
|
5
|
+
import { allocateLocalId, deriveLocalStem, formatTaskId, parseTaskId, sameNamespace } from "./identity.js";
|
|
6
|
+
import { authorityPath, readBoard, replaceAuthority, withTaskLocks, } from "./store.js";
|
|
7
|
+
export function taskView(document) {
|
|
8
|
+
return { ...document, namespace: parseTaskId(document.id).namespace };
|
|
9
|
+
}
|
|
10
|
+
function refused(refusal) { return { kind: "refused", refusal }; }
|
|
11
|
+
function retry(reason) { return { kind: "retry", reason }; }
|
|
12
|
+
function context(world, explicit) {
|
|
13
|
+
if (explicit !== undefined)
|
|
14
|
+
return explicit;
|
|
15
|
+
const current = readNamespaceContext(world.root);
|
|
16
|
+
return current === "malformed" ? { kind: "invalid-namespace-context", path: `${world.root}/.keiyaku/namespace/current` }
|
|
17
|
+
: current === "absent" ? [] : current;
|
|
18
|
+
}
|
|
19
|
+
function occupied(board, namespace) {
|
|
20
|
+
return new Set([...board.tasks.values()].flatMap((task) => {
|
|
21
|
+
const coordinate = parseTaskId(task.id);
|
|
22
|
+
return sameNamespace(coordinate.namespace, namespace) ? [coordinate.localId] : [];
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
function currentTimestamp() { return new Date().toISOString(); }
|
|
26
|
+
function advancedTimestamp(previous) {
|
|
27
|
+
const current = currentTimestamp();
|
|
28
|
+
return current > previous ? current : new Date(Date.parse(previous) + 1).toISOString();
|
|
29
|
+
}
|
|
30
|
+
function addDocument(base, namespace, board, at) {
|
|
31
|
+
const localId = allocateLocalId(deriveLocalStem(base.title), occupied(board, namespace));
|
|
32
|
+
return { ...base, id: formatTaskId({ namespace, localId }), createdAt: at, updatedAt: at };
|
|
33
|
+
}
|
|
34
|
+
function boardWith(board, document) {
|
|
35
|
+
const tasks = new Map(board.tasks);
|
|
36
|
+
tasks.set(document.id, document);
|
|
37
|
+
return { tasks };
|
|
38
|
+
}
|
|
39
|
+
async function create(world, base, namespace, signal) {
|
|
40
|
+
const result = await withTaskLocks({ world, allocation: true, ids: [], ...(signal === undefined ? {} : { signal }) }, async () => {
|
|
41
|
+
const snapshot = readBoard(world), next = addDocument(base, namespace, snapshot.board, currentTimestamp());
|
|
42
|
+
const problem = relationProblem(boardWith(snapshot.board, next), null, next);
|
|
43
|
+
if (problem !== null)
|
|
44
|
+
return refused({ kind: "invalid-graph", diagnostic: problem });
|
|
45
|
+
const replaced = replaceAuthority({ path: authorityPath(world, next.id), expected: null, next: serializeTaskDocument(next) });
|
|
46
|
+
return replaced === "replaced" ? { kind: "accepted", value: taskView(next) } : retry("concurrent-modification");
|
|
47
|
+
});
|
|
48
|
+
return result === "busy" ? retry("busy") : result;
|
|
49
|
+
}
|
|
50
|
+
export async function addTask(world, input) {
|
|
51
|
+
const namespace = context(world, input.namespace);
|
|
52
|
+
if (!Array.isArray(namespace))
|
|
53
|
+
return refused(namespace);
|
|
54
|
+
return create(world, {
|
|
55
|
+
title: input.title, body: input.body ?? "", note: input.note ?? "", state: input.state ?? "open", priority: input.priority ?? 2, needs: input.needs ?? [], parent: input.parent ?? null,
|
|
56
|
+
supersedes: input.supersedes ?? [], relates: input.relates ?? [],
|
|
57
|
+
}, namespace, input.signal);
|
|
58
|
+
}
|
|
59
|
+
export async function addTaskDocument(world, input) {
|
|
60
|
+
const namespace = context(world, input.namespace);
|
|
61
|
+
if (!Array.isArray(namespace))
|
|
62
|
+
return refused(namespace);
|
|
63
|
+
return create(world, parseTaskCreationDocument(input.markdown), namespace, input.signal);
|
|
64
|
+
}
|
|
65
|
+
function listChange(current, replacement, additions, removals) {
|
|
66
|
+
const next = [...(replacement ?? current)];
|
|
67
|
+
for (const id of additions ?? [])
|
|
68
|
+
if (!next.includes(id))
|
|
69
|
+
next.push(id);
|
|
70
|
+
return next.filter((id) => !(removals ?? []).includes(id));
|
|
71
|
+
}
|
|
72
|
+
function relatedOwner(board, id, target) {
|
|
73
|
+
return board.tasks.get(target)?.relates.includes(id) ? target : null;
|
|
74
|
+
}
|
|
75
|
+
function updateDocument(board, current, input) {
|
|
76
|
+
for (const related of input.dropRelates ?? [])
|
|
77
|
+
if (!current.relates.includes(related)) {
|
|
78
|
+
const owner = relatedOwner(board, current.id, related);
|
|
79
|
+
if (owner !== null)
|
|
80
|
+
return { kind: "relation-owned-by-other", taskId: current.id, related, declaringTask: owner };
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...current,
|
|
84
|
+
...(input.title === undefined ? {} : { title: input.title }),
|
|
85
|
+
body: input.body ?? (input.appendBody === undefined ? current.body : current.body + input.appendBody),
|
|
86
|
+
...(input.note === undefined ? {} : { note: input.note }),
|
|
87
|
+
...(input.priority === undefined ? {} : { priority: input.priority }),
|
|
88
|
+
needs: listChange(current.needs, input.needs, input.addNeeds, input.dropNeeds),
|
|
89
|
+
...(input.parent === undefined ? {} : { parent: input.parent }),
|
|
90
|
+
supersedes: listChange(current.supersedes, input.supersedes, input.addSupersedes, input.dropSupersedes),
|
|
91
|
+
relates: listChange(current.relates, input.relates, input.addRelates, input.dropRelates),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export async function updateTask(world, id, input) {
|
|
95
|
+
const result = await withTaskLocks({ world, allocation: false, ids: [id], ...(input.signal === undefined ? {} : { signal: input.signal }) }, async () => {
|
|
96
|
+
const snapshot = readBoard(world), current = snapshot.board.tasks.get(id);
|
|
97
|
+
if (current === undefined)
|
|
98
|
+
return { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
|
|
99
|
+
const candidate = updateDocument(snapshot.board, current, input);
|
|
100
|
+
if ("kind" in candidate)
|
|
101
|
+
return { kind: "refused", refusal: candidate };
|
|
102
|
+
const problem = relationProblem(boardWith(snapshot.board, candidate), current, candidate);
|
|
103
|
+
if (problem !== null)
|
|
104
|
+
return { kind: "refused", refusal: { kind: "invalid-graph", diagnostic: problem } };
|
|
105
|
+
const predecessor = snapshot.bytes.get(id), before = Buffer.from(predecessor).toString("utf8");
|
|
106
|
+
const changed = !Buffer.from(serializeTaskDocument(candidate)).equals(Buffer.from(predecessor));
|
|
107
|
+
const next = changed ? { ...candidate, updatedAt: advancedTimestamp(current.updatedAt) } : candidate;
|
|
108
|
+
const afterBytes = serializeTaskDocument(next), after = Buffer.from(afterBytes).toString("utf8");
|
|
109
|
+
if (before !== after && replaceAuthority({ path: authorityPath(world, id), expected: predecessor, next: afterBytes }) !== "replaced")
|
|
110
|
+
return { kind: "retry", reason: "concurrent-modification" };
|
|
111
|
+
const label = `${id}.md`;
|
|
112
|
+
return { kind: "accepted", value: { task: taskView(next), documentDiff: documentDiff(label, label, before, after) } };
|
|
113
|
+
});
|
|
114
|
+
return result === "busy" ? { kind: "retry", reason: "busy" } : result;
|
|
115
|
+
}
|
|
116
|
+
const TRANSITIONS = {
|
|
117
|
+
start: { open: "in_progress" }, stop: { in_progress: "open" }, hold: { open: "on_hold", in_progress: "on_hold" },
|
|
118
|
+
resume: { on_hold: "open" }, done: { open: "done", in_progress: "done", on_hold: "done" },
|
|
119
|
+
drop: { open: "drop", in_progress: "drop", on_hold: "drop" },
|
|
120
|
+
};
|
|
121
|
+
export async function lifecycleTask(world, id, verb, signal, note) {
|
|
122
|
+
const result = await withTaskLocks({ world, allocation: false, ids: [id], ...(signal === undefined ? {} : { signal }) }, async () => {
|
|
123
|
+
const snapshot = readBoard(world), current = snapshot.board.tasks.get(id);
|
|
124
|
+
if (current === undefined)
|
|
125
|
+
return refused({ kind: "task-missing", taskId: id });
|
|
126
|
+
const state = TRANSITIONS[verb][current.state];
|
|
127
|
+
if (state === undefined)
|
|
128
|
+
return refused({ kind: "invalid-lifecycle-transition", taskId: id, state: current.state, verb });
|
|
129
|
+
const next = { ...current, state, ...(note === undefined ? {} : { note }), updatedAt: advancedTimestamp(current.updatedAt) };
|
|
130
|
+
const bytes = serializeTaskDocument(next);
|
|
131
|
+
return replaceAuthority({ path: authorityPath(world, id), expected: snapshot.bytes.get(id), next: bytes }) === "replaced"
|
|
132
|
+
? { kind: "accepted", value: taskView(next) } : retry("concurrent-modification");
|
|
133
|
+
});
|
|
134
|
+
return result === "busy" ? retry("busy") : result;
|
|
135
|
+
}
|
|
136
|
+
export async function batchTasks(world, verb, ids, signal, note) {
|
|
137
|
+
const items = [];
|
|
138
|
+
for (const id of ids) {
|
|
139
|
+
signal?.throwIfAborted();
|
|
140
|
+
items.push({ id, outcome: await lifecycleTask(world, id, verb, signal, note) });
|
|
141
|
+
}
|
|
142
|
+
return { items };
|
|
143
|
+
}
|
|
144
|
+
export async function settleTask(world, id, desired) {
|
|
145
|
+
const result = await withTaskLocks({ world, allocation: false, ids: [id] }, async () => {
|
|
146
|
+
const snapshot = readBoard(world), current = snapshot.board.tasks.get(id);
|
|
147
|
+
if (current === undefined)
|
|
148
|
+
return { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
|
|
149
|
+
if (desired === "done") {
|
|
150
|
+
if (current.state === "done")
|
|
151
|
+
return { kind: "unchanged" };
|
|
152
|
+
if (current.state === "drop") {
|
|
153
|
+
return { kind: "refused", refusal: { kind: "invalid-lifecycle-transition", taskId: id, state: current.state, verb: "done" } };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else if (current.state !== "done")
|
|
157
|
+
return { kind: "unchanged" };
|
|
158
|
+
const state = desired === "done" ? "done" : "open";
|
|
159
|
+
const next = { ...current, state, updatedAt: advancedTimestamp(current.updatedAt) };
|
|
160
|
+
const replaced = replaceAuthority({ path: authorityPath(world, id), expected: snapshot.bytes.get(id), next: serializeTaskDocument(next) });
|
|
161
|
+
return replaced === "replaced"
|
|
162
|
+
? { kind: "changed", task: taskView(next), action: desired === "done" ? "done" : "reopened" }
|
|
163
|
+
: { kind: "retry", reason: "concurrent-modification" };
|
|
164
|
+
});
|
|
165
|
+
return result === "busy" ? { kind: "retry", reason: "busy" } : result;
|
|
166
|
+
}
|
|
167
|
+
function readScope(world, scope) {
|
|
168
|
+
if (scope === "world")
|
|
169
|
+
return null;
|
|
170
|
+
return context(world);
|
|
171
|
+
}
|
|
172
|
+
export function listTasks(world, selection, scope) {
|
|
173
|
+
const selected = readScope(world, scope);
|
|
174
|
+
if (selected !== null && !Array.isArray(selected))
|
|
175
|
+
return { kind: "refused", refusal: selected };
|
|
176
|
+
return { kind: "accepted", value: projectRows(readBoard(world).board, selected, selection) };
|
|
177
|
+
}
|
|
178
|
+
export function readyTasks(world, scope) {
|
|
179
|
+
const selected = readScope(world, scope);
|
|
180
|
+
if (selected !== null && !Array.isArray(selected))
|
|
181
|
+
return { kind: "refused", refusal: selected };
|
|
182
|
+
return { kind: "accepted", value: projectReady(readBoard(world).board, selected) };
|
|
183
|
+
}
|
|
184
|
+
export function blockedTasks(world, scope) {
|
|
185
|
+
const selected = readScope(world, scope);
|
|
186
|
+
if (selected !== null && !Array.isArray(selected))
|
|
187
|
+
return { kind: "refused", refusal: selected };
|
|
188
|
+
return { kind: "accepted", value: projectBlocked(readBoard(world).board, selected) };
|
|
189
|
+
}
|
|
190
|
+
export function setCurrentNamespace(world, namespace) { installNamespaceContext(world.root, namespace); }
|
|
191
|
+
export function currentNamespace(world) {
|
|
192
|
+
const selected = context(world);
|
|
193
|
+
return selected;
|
|
194
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type TaskId } from "./identity.js";
|
|
2
|
+
import type { TaskBoard } from "./board.js";
|
|
3
|
+
export type TaskWorld = Readonly<{
|
|
4
|
+
root: string;
|
|
5
|
+
}>;
|
|
6
|
+
export type BoardSnapshot = Readonly<{
|
|
7
|
+
board: TaskBoard;
|
|
8
|
+
bytes: ReadonlyMap<TaskId, Uint8Array>;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function readBoard(world: TaskWorld): BoardSnapshot;
|
|
11
|
+
export declare function replaceAuthority(input: Readonly<{
|
|
12
|
+
path: string;
|
|
13
|
+
expected: Uint8Array | null;
|
|
14
|
+
next: Uint8Array;
|
|
15
|
+
}>): "replaced" | "concurrent-modification";
|
|
16
|
+
export declare function withTaskLocks<T>(input: Readonly<{
|
|
17
|
+
world: TaskWorld;
|
|
18
|
+
allocation: boolean;
|
|
19
|
+
ids: readonly TaskId[];
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}>, action: () => Promise<T>): Promise<T | "busy">;
|
|
22
|
+
export declare function authorityPath(world: TaskWorld, id: TaskId): string;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { closeSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { dirname, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { acquireSqliteTransactionLock, SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
|
|
5
|
+
import { parseTaskDocument } from "./document.js";
|
|
6
|
+
import { formatTaskId, parseTaskId, taskAuthorityPath } from "./identity.js";
|
|
7
|
+
function tasksDirectory(world) { return resolve(world.root, ".keiyaku", "tasks"); }
|
|
8
|
+
function authorityFiles(directory) {
|
|
9
|
+
if (!existsSync(directory))
|
|
10
|
+
return [];
|
|
11
|
+
const files = [];
|
|
12
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
13
|
+
const path = resolve(directory, entry.name);
|
|
14
|
+
if (entry.isDirectory())
|
|
15
|
+
files.push(...authorityFiles(path));
|
|
16
|
+
else if (entry.isFile() && entry.name.endsWith(".md"))
|
|
17
|
+
files.push(path);
|
|
18
|
+
else
|
|
19
|
+
throw new Error(`unexpected Task authority entry: ${path}`);
|
|
20
|
+
}
|
|
21
|
+
return files.sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)));
|
|
22
|
+
}
|
|
23
|
+
function coordinateFromPath(tasksDirectory, path) {
|
|
24
|
+
const local = relative(tasksDirectory, path);
|
|
25
|
+
if (local.startsWith("..") || resolve(tasksDirectory, local) !== path || !local.endsWith(".md"))
|
|
26
|
+
throw new Error(`invalid Task authority path: ${path}`);
|
|
27
|
+
return parseTaskId(`task/${local.slice(0, -3).split(sep).join("/")}`);
|
|
28
|
+
}
|
|
29
|
+
export function readBoard(world) {
|
|
30
|
+
const directory = tasksDirectory(world);
|
|
31
|
+
const tasks = new Map(), bytes = new Map();
|
|
32
|
+
for (const path of authorityFiles(directory)) {
|
|
33
|
+
const stat = lstatSync(path);
|
|
34
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
35
|
+
throw new Error(`Task authority is not a regular file: ${path}`);
|
|
36
|
+
const coordinate = coordinateFromPath(directory, path);
|
|
37
|
+
const id = formatTaskId(coordinate);
|
|
38
|
+
const source = readFileSync(path);
|
|
39
|
+
tasks.set(id, parseTaskDocument(source, coordinate));
|
|
40
|
+
bytes.set(id, source);
|
|
41
|
+
}
|
|
42
|
+
return { board: { tasks }, bytes };
|
|
43
|
+
}
|
|
44
|
+
function equal(left, right) {
|
|
45
|
+
return left === null || right === null ? left === right : Buffer.from(left).equals(Buffer.from(right));
|
|
46
|
+
}
|
|
47
|
+
function currentBytes(path) {
|
|
48
|
+
try {
|
|
49
|
+
return readFileSync(path);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error.code === "ENOENT")
|
|
53
|
+
return null;
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function replaceAuthority(input) {
|
|
58
|
+
const parent = dirname(input.path);
|
|
59
|
+
mkdirSync(parent, { recursive: true });
|
|
60
|
+
const temporary = resolve(parent, `.tmp-${randomBytes(8).toString("hex")}`);
|
|
61
|
+
let descriptor;
|
|
62
|
+
try {
|
|
63
|
+
descriptor = openSync(temporary, "wx", 0o600);
|
|
64
|
+
writeFileSync(descriptor, input.next);
|
|
65
|
+
fsyncSync(descriptor);
|
|
66
|
+
closeSync(descriptor);
|
|
67
|
+
descriptor = undefined;
|
|
68
|
+
if (!equal(currentBytes(input.path), input.expected))
|
|
69
|
+
return "concurrent-modification";
|
|
70
|
+
renameSync(temporary, input.path);
|
|
71
|
+
const directoryDescriptor = openSync(parent, "r");
|
|
72
|
+
try {
|
|
73
|
+
fsyncSync(directoryDescriptor);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
closeSync(directoryDescriptor);
|
|
77
|
+
}
|
|
78
|
+
return "replaced";
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
if (descriptor !== undefined)
|
|
82
|
+
closeSync(descriptor);
|
|
83
|
+
try {
|
|
84
|
+
unlinkSync(temporary);
|
|
85
|
+
}
|
|
86
|
+
catch { /* renamed or best effort */ }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function lockPath(world, id) {
|
|
90
|
+
const coordinate = parseTaskId(id);
|
|
91
|
+
return resolve(world.root, ".keiyaku", "locks", "task", ...coordinate.namespace, `${coordinate.localId}.sqlite`);
|
|
92
|
+
}
|
|
93
|
+
export async function withTaskLocks(input, action) {
|
|
94
|
+
const paths = [
|
|
95
|
+
...(input.allocation ? [resolve(input.world.root, ".keiyaku", "locks", "task-allocation.sqlite")] : []),
|
|
96
|
+
...[...new Set(input.ids)].sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b))).map((id) => lockPath(input.world, id)),
|
|
97
|
+
];
|
|
98
|
+
const held = [];
|
|
99
|
+
try {
|
|
100
|
+
for (const path of paths)
|
|
101
|
+
held.push(await acquireSqliteTransactionLock({ path, mode: "immediate", timeoutMs: 3_000, ...(input.signal === undefined ? {} : { signal: input.signal }) }));
|
|
102
|
+
return await action();
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (error instanceof SqliteTransactionLockError && error.reason === "timeout")
|
|
106
|
+
return "busy";
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
for (const lock of held.reverse())
|
|
111
|
+
lock.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function authorityPath(world, id) { return taskAuthorityPath(tasksDirectory(world), parseTaskId(id)); }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Preparation } from "../core/decide.js";
|
|
2
|
+
import { type ContractId, type DocumentSegmentKey, type Gate } from "../core/facts/types.js";
|
|
3
|
+
export type VerificationExecutor = "bash" | "zsh" | "pwsh";
|
|
4
|
+
export type VerificationDeclaration = Readonly<{
|
|
5
|
+
readonly executor: VerificationExecutor;
|
|
6
|
+
readonly script: string;
|
|
7
|
+
}>;
|
|
8
|
+
export type VerificationDefinition = Readonly<{
|
|
9
|
+
readonly segment: DocumentSegmentKey;
|
|
10
|
+
readonly declarations: readonly VerificationDeclaration[];
|
|
11
|
+
}>;
|
|
12
|
+
export type VerificationDeclarationRefusal = Readonly<{
|
|
13
|
+
kind: "verification-declaration-invalid";
|
|
14
|
+
contractId?: ContractId;
|
|
15
|
+
}>;
|
|
16
|
+
export type VerificationDeclarationPreparation = Preparation<VerificationDefinition | null, VerificationDeclarationRefusal>;
|
|
17
|
+
export declare const VERIFIED: Gate;
|
|
18
|
+
export declare function prepareVerificationDeclaration(input: Readonly<{
|
|
19
|
+
gates: readonly Gate[];
|
|
20
|
+
definition: VerificationDefinition | null;
|
|
21
|
+
contractId?: ContractId;
|
|
22
|
+
}>): VerificationDeclarationPreparation;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { gate } from "../core/facts/types.js";
|
|
2
|
+
export const VERIFIED = gate("verified");
|
|
3
|
+
export function prepareVerificationDeclaration(input) {
|
|
4
|
+
if (input.definition !== null || !input.gates.includes(VERIFIED)) {
|
|
5
|
+
return { kind: "prepared", data: input.definition };
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
kind: "refused",
|
|
9
|
+
refusal: {
|
|
10
|
+
kind: "verification-declaration-invalid",
|
|
11
|
+
...(input.contractId === undefined ? {} : { contractId: input.contractId }),
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|