@astrosheep/keiyaku 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +67 -13
- package/build/src/akuma/provider.js +172 -105
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +52 -14
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -3
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { lstat, mkdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { replaceFileDurably } from "../coordination/durable-file.js";
|
|
3
|
+
import { repairDerivedFile, replaceFileDurably } from "../coordination/durable-file.js";
|
|
4
4
|
import { normalizeIdentityStem } from "../identity/normalize.js";
|
|
5
5
|
function directory(root) { return join(root, ".keiyaku", "namespace"); }
|
|
6
6
|
function currentPath(root) { return join(directory(root), "current"); }
|
|
@@ -10,13 +10,13 @@ function validNamespaceSegments(value) {
|
|
|
10
10
|
&& segment.length > 0 && normalizeIdentityStem({ source: segment }) === segment
|
|
11
11
|
&& !segment.includes("/") && segment !== "." && segment !== "..");
|
|
12
12
|
}
|
|
13
|
-
export function readNamespaceContext(root) {
|
|
13
|
+
export async function readNamespaceContext(root) {
|
|
14
14
|
let bytes;
|
|
15
15
|
try {
|
|
16
|
-
const path = currentPath(root), stat =
|
|
16
|
+
const path = currentPath(root), stat = await lstat(path);
|
|
17
17
|
if (!stat.isFile() || stat.isSymbolicLink())
|
|
18
18
|
return "malformed";
|
|
19
|
-
bytes =
|
|
19
|
+
bytes = await readFile(path, "utf8");
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
22
|
if (error.code === "ENOENT")
|
|
@@ -29,28 +29,23 @@ export function readNamespaceContext(root) {
|
|
|
29
29
|
const segments = content === "" ? [] : content.split("/");
|
|
30
30
|
return validNamespaceSegments(segments) ? segments : "malformed";
|
|
31
31
|
}
|
|
32
|
-
export function installNamespaceContext(root, segments) {
|
|
32
|
+
export async function installNamespaceContext(root, segments) {
|
|
33
33
|
if (!validNamespaceSegments(segments))
|
|
34
34
|
throw new TypeError("namespace must contain normalized segments");
|
|
35
35
|
const parent = directory(root);
|
|
36
|
-
|
|
37
|
-
installIgnore(root);
|
|
38
|
-
replaceFileDurably(currentPath(root), `${segments.join("/")}\n`);
|
|
36
|
+
await mkdir(parent, { recursive: true });
|
|
37
|
+
await installIgnore(root);
|
|
38
|
+
await replaceFileDurably(currentPath(root), `${segments.join("/")}\n`);
|
|
39
39
|
}
|
|
40
|
-
function installIgnore(root) {
|
|
41
|
-
|
|
42
|
-
const stat = lstatSync(ignore, { throwIfNoEntry: false });
|
|
43
|
-
if (stat !== undefined && (!stat.isFile() || stat.isSymbolicLink()))
|
|
44
|
-
throw new Error(`namespace ignore is not a regular file: ${ignore}`);
|
|
45
|
-
if (stat === undefined || readFileSync(ignore, "utf8") !== "*\n")
|
|
46
|
-
replaceFileDurably(ignore, "*\n");
|
|
40
|
+
async function installIgnore(root) {
|
|
41
|
+
await repairDerivedFile(ignorePath(root), "*\n");
|
|
47
42
|
}
|
|
48
|
-
export function repairNamespaceContext(root, segments) {
|
|
49
|
-
const current = readNamespaceContext(root);
|
|
43
|
+
export async function repairNamespaceContext(root, segments) {
|
|
44
|
+
const current = await readNamespaceContext(root);
|
|
50
45
|
if (Array.isArray(current)) {
|
|
51
|
-
installIgnore(root);
|
|
46
|
+
await installIgnore(root);
|
|
52
47
|
return "kept";
|
|
53
48
|
}
|
|
54
|
-
installNamespaceContext(root, segments);
|
|
49
|
+
await installNamespaceContext(root, segments);
|
|
55
50
|
return "installed";
|
|
56
51
|
}
|
|
@@ -11,11 +11,12 @@ export type TaskDocument = Readonly<{
|
|
|
11
11
|
supersedes: readonly TaskId[];
|
|
12
12
|
relates: readonly TaskId[];
|
|
13
13
|
note: string;
|
|
14
|
+
createdBy?: string;
|
|
14
15
|
createdAt: string;
|
|
15
16
|
updatedAt: string;
|
|
16
17
|
body: string;
|
|
17
18
|
}>;
|
|
18
|
-
export type TaskCreationDocument = Omit<TaskDocument, "id" | "createdAt" | "updatedAt">;
|
|
19
|
+
export type TaskCreationDocument = Omit<TaskDocument, "id" | "createdBy" | "createdAt" | "updatedAt">;
|
|
19
20
|
export declare class TaskAuthorityCorruptionError extends Error {
|
|
20
21
|
constructor(message: string, options?: ErrorOptions);
|
|
21
22
|
}
|
|
@@ -4,7 +4,8 @@ export class TaskAuthorityCorruptionError extends Error {
|
|
|
4
4
|
constructor(message, options) { super(message, options); this.name = "TaskAuthorityCorruptionError"; }
|
|
5
5
|
}
|
|
6
6
|
const STATES = new Set(["open", "in_progress", "on_hold", "done", "drop"]);
|
|
7
|
-
const
|
|
7
|
+
const REQUIRED_STORED_KEYS = ["id", "title", "state", "priority", "needs", "parent", "supersedes", "relates", "note", "createdAt", "updatedAt"];
|
|
8
|
+
const STORED_KEYS = [...REQUIRED_STORED_KEYS, "createdBy"];
|
|
8
9
|
const CREATION_KEYS = ["title", "state", "priority", "needs", "parent", "supersedes", "relates", "note"];
|
|
9
10
|
function frontMatter(markdown, fail) {
|
|
10
11
|
if (!markdown.startsWith("---\n"))
|
|
@@ -73,6 +74,11 @@ function taskIds(value, field, fail) {
|
|
|
73
74
|
function nullableTaskId(value, field, fail) {
|
|
74
75
|
return value === null ? null : taskId(value, field, fail);
|
|
75
76
|
}
|
|
77
|
+
function createdBy(value, fail) {
|
|
78
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
79
|
+
fail("createdBy must be a nonblank string");
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
76
82
|
function fields(value, body, fail) {
|
|
77
83
|
return {
|
|
78
84
|
title: title(value.title, fail),
|
|
@@ -88,14 +94,17 @@ function fields(value, body, fail) {
|
|
|
88
94
|
export function parseTaskDocument(bytes, expected) {
|
|
89
95
|
const fail = (message, cause) => { throw new TaskAuthorityCorruptionError(message, cause === undefined ? {} : { cause }); };
|
|
90
96
|
const { value, body } = frontMatter(Buffer.from(bytes).toString("utf8"), fail);
|
|
91
|
-
closed(value, STORED_KEYS,
|
|
97
|
+
closed(value, STORED_KEYS, REQUIRED_STORED_KEYS, fail);
|
|
92
98
|
const id = taskId(value.id, "id", fail);
|
|
93
99
|
if (id !== formatTaskId(expected))
|
|
94
100
|
fail(`task document ID ${id} does not match its authority path`);
|
|
95
101
|
const createdAt = timestamp(value.createdAt, "createdAt", fail), updatedAt = timestamp(value.updatedAt, "updatedAt", fail);
|
|
96
102
|
if (Date.parse(updatedAt) < Date.parse(createdAt))
|
|
97
103
|
fail("updatedAt must not precede createdAt");
|
|
98
|
-
return {
|
|
104
|
+
return {
|
|
105
|
+
id, state: state(value.state, fail), createdAt, updatedAt, ...fields(value, body, fail),
|
|
106
|
+
...(Object.hasOwn(value, "createdBy") ? { createdBy: createdBy(value.createdBy, fail) } : {}),
|
|
107
|
+
};
|
|
99
108
|
}
|
|
100
109
|
export function parseTaskCreationDocument(markdown) {
|
|
101
110
|
const fail = (message) => { throw new TypeError(message); };
|
|
@@ -111,8 +120,9 @@ export function serializeTaskDocument(document) {
|
|
|
111
120
|
const value = {
|
|
112
121
|
id: document.id, title: document.title, state: document.state, priority: document.priority,
|
|
113
122
|
needs: [...document.needs], parent: document.parent, supersedes: [...document.supersedes],
|
|
114
|
-
relates: [...document.relates], note: document.note,
|
|
115
|
-
|
|
123
|
+
relates: [...document.relates], note: document.note,
|
|
124
|
+
...(document.createdBy === undefined ? {} : { createdBy: document.createdBy }),
|
|
125
|
+
createdAt: document.createdAt, updatedAt: document.updatedAt,
|
|
116
126
|
};
|
|
117
127
|
return Buffer.from(`---\n${stringify(value, { lineWidth: 0 })}---\n${document.body}`);
|
|
118
128
|
}
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { WorldRoot } from "../world.js";
|
|
2
|
+
export type { WorldRoot } from "../world.js";
|
|
3
|
+
import { type BlockedTaskRow, type TaskDetailFacts, type TaskDoctorIssue, type TaskRef, type TaskRow, type TaskTreeNode } from "./board.js";
|
|
2
4
|
import { type TaskCompositionResult } from "./compose.js";
|
|
3
5
|
import { TaskAuthorityCorruptionError, type TaskPriority, type TaskState } from "./document.js";
|
|
4
6
|
import { type TaskId } from "./identity.js";
|
|
5
7
|
import { type AddTaskDocumentInput, type AddTaskInput, type TaskBatchResult, type TaskMutationResult, type TaskOutcome, type TaskRefusal, type TaskRetry, type TaskUpdateResult, type TaskView, type UpdateTaskInput } from "./operations.js";
|
|
6
|
-
import { type
|
|
8
|
+
import { type TaskPage, type TaskQueryExpression, type TaskQueryPredicate, type TaskQueryRow, type TaskQuerySort } from "./query.js";
|
|
7
9
|
export type TaskDetail = Omit<TaskDetailFacts, "task"> & Readonly<{
|
|
8
10
|
task: TaskView;
|
|
9
11
|
}>;
|
|
10
|
-
export type TaskList = TaskOutcome<
|
|
11
|
-
export type BlockedTaskList = TaskOutcome<
|
|
12
|
+
export type TaskList = TaskOutcome<TaskPage<TaskRow>>;
|
|
13
|
+
export type BlockedTaskList = TaskOutcome<TaskPage<BlockedTaskRow>>;
|
|
14
|
+
export type TaskQueryResult = TaskOutcome<TaskPage<TaskQueryRow>>;
|
|
12
15
|
export type TaskNamespaceResult = TaskOutcome<readonly string[]>;
|
|
13
16
|
export type TaskDoctorReport = Readonly<{
|
|
14
17
|
issues: readonly TaskDoctorIssue[];
|
|
15
18
|
}>;
|
|
16
|
-
export type
|
|
17
|
-
export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskUpdateResult, TaskView, UpdateTaskInput };
|
|
19
|
+
export type TaskDecompositionTree = TaskOutcome<TaskTreeNode>;
|
|
20
|
+
export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort };
|
|
18
21
|
export { TaskAuthorityCorruptionError };
|
|
19
22
|
declare class TaskHandle {
|
|
20
23
|
readonly id: TaskId;
|
|
21
24
|
private readonly world;
|
|
22
|
-
constructor(id: TaskId, world:
|
|
25
|
+
constructor(id: TaskId, world: WorldRoot);
|
|
23
26
|
read(): Promise<TaskDetail | null>;
|
|
24
|
-
tree(
|
|
25
|
-
full?: boolean;
|
|
26
|
-
}>): Promise<TaskDependencyTree>;
|
|
27
|
+
tree(): Promise<TaskDecompositionTree>;
|
|
27
28
|
update(input: UpdateTaskInput): Promise<TaskUpdateResult>;
|
|
28
29
|
private lifecycle;
|
|
29
30
|
start(input?: {
|
|
@@ -39,6 +40,7 @@ declare class TaskHandle {
|
|
|
39
40
|
signal?: AbortSignal;
|
|
40
41
|
}): Promise<TaskMutationResult>;
|
|
41
42
|
done(input?: {
|
|
43
|
+
note?: string;
|
|
42
44
|
signal?: AbortSignal;
|
|
43
45
|
}): Promise<TaskMutationResult>;
|
|
44
46
|
drop(input?: {
|
|
@@ -48,9 +50,9 @@ declare class TaskHandle {
|
|
|
48
50
|
}
|
|
49
51
|
export type Task = TaskHandle;
|
|
50
52
|
declare class TasksHandle {
|
|
51
|
-
readonly root: string;
|
|
52
53
|
private readonly world;
|
|
53
|
-
|
|
54
|
+
readonly root: WorldRoot;
|
|
55
|
+
constructor(world: WorldRoot);
|
|
54
56
|
namespace(): Promise<TaskNamespaceResult>;
|
|
55
57
|
setNamespace(input: Readonly<{
|
|
56
58
|
namespace: readonly string[];
|
|
@@ -63,13 +65,24 @@ declare class TasksHandle {
|
|
|
63
65
|
list(input?: Readonly<{
|
|
64
66
|
selection?: "active" | "closed" | "all";
|
|
65
67
|
scope?: "namespace" | "world";
|
|
68
|
+
limit?: number;
|
|
66
69
|
}>): Promise<TaskList>;
|
|
67
70
|
ready(input?: Readonly<{
|
|
68
71
|
scope?: "namespace" | "world";
|
|
72
|
+
parent?: string;
|
|
73
|
+
limit?: number;
|
|
69
74
|
}>): Promise<TaskList>;
|
|
70
75
|
blocked(input?: Readonly<{
|
|
71
76
|
scope?: "namespace" | "world";
|
|
77
|
+
parent?: string;
|
|
78
|
+
limit?: number;
|
|
72
79
|
}>): Promise<BlockedTaskList>;
|
|
80
|
+
query(input?: Readonly<{
|
|
81
|
+
where?: TaskQueryExpression;
|
|
82
|
+
scope?: "namespace" | "world";
|
|
83
|
+
sort?: TaskQuerySort;
|
|
84
|
+
limit?: number;
|
|
85
|
+
}>): Promise<TaskQueryResult>;
|
|
73
86
|
doctor(): Promise<TaskDoctorReport>;
|
|
74
87
|
batch(input: Readonly<{
|
|
75
88
|
verb: "done" | "drop" | "hold";
|
|
@@ -79,12 +92,11 @@ declare class TasksHandle {
|
|
|
79
92
|
}>): Promise<TaskBatchResult>;
|
|
80
93
|
compose(input: Readonly<{
|
|
81
94
|
markdown: string;
|
|
95
|
+
actor?: string;
|
|
82
96
|
signal?: AbortSignal;
|
|
83
97
|
}>): Promise<TaskCompositionResult>;
|
|
84
98
|
}
|
|
85
99
|
export type Tasks = TasksHandle;
|
|
86
100
|
export declare const Tasks: Readonly<{
|
|
87
|
-
|
|
88
|
-
path?: string;
|
|
89
|
-
}>): Tasks;
|
|
101
|
+
of(root: WorldRoot): Tasks;
|
|
90
102
|
}>;
|
package/build/src/task/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { resolveContextRoot } from "../context-root.js";
|
|
2
1
|
import { buildTree, diagnoseBoard, projectDetailFacts } from "./board.js";
|
|
3
2
|
import { composeTasks } from "./compose.js";
|
|
4
3
|
import { TaskAuthorityCorruptionError } from "./document.js";
|
|
5
4
|
import { isTaskSegment, parseTaskId } from "./identity.js";
|
|
6
|
-
import { addTask, addTaskDocument, batchTasks, blockedTasks, currentNamespace, lifecycleTask, listTasks, readyTasks, setCurrentNamespace, taskView, updateTask, } from "./operations.js";
|
|
5
|
+
import { addTask, addTaskDocument, batchTasks, blockedTasks, currentNamespace, lifecycleTask, listTasks, queryTasks, readyTasks, setCurrentNamespace, taskView, updateTask, } from "./operations.js";
|
|
7
6
|
import { readBoard } from "./store.js";
|
|
7
|
+
import { isValidTaskLimit, normalizeTaskQuery, MAX_TASK_LIMIT, DEFAULT_TASK_LIMIT } from "./query.js";
|
|
8
8
|
export { TaskAuthorityCorruptionError };
|
|
9
9
|
function record(value, label) {
|
|
10
10
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
@@ -49,9 +49,26 @@ function namespace(value) {
|
|
|
49
49
|
function text(value, label) { if (value === undefined)
|
|
50
50
|
return undefined; if (typeof value !== "string")
|
|
51
51
|
throw new TypeError(`${label} must be a string`); return value; }
|
|
52
|
+
function actor(value) {
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
56
|
+
throw new TypeError("actor must be a nonblank string");
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
52
59
|
function priority(value) { if (value === undefined)
|
|
53
60
|
return undefined; if (!Number.isInteger(value) || typeof value !== "number" || value < 0 || value > 3)
|
|
54
61
|
throw new TypeError("priority must be 0..3"); return value; }
|
|
62
|
+
function limit(value) { if (value === undefined)
|
|
63
|
+
return undefined; if (typeof value !== "number" || !isValidTaskLimit(value))
|
|
64
|
+
throw new TypeError(`limit must be an integer from 1 to ${MAX_TASK_LIMIT}`); return value; }
|
|
65
|
+
function sort(value) {
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
return undefined;
|
|
68
|
+
if (value !== "priority" && value !== "created" && value !== "updated" && value !== "id")
|
|
69
|
+
throw new TypeError("sort is invalid");
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
55
72
|
function state(value) {
|
|
56
73
|
if (value === undefined)
|
|
57
74
|
return undefined;
|
|
@@ -62,17 +79,18 @@ function state(value) {
|
|
|
62
79
|
function nullableId(value) { return value === undefined || value === null ? value : id(value); }
|
|
63
80
|
function addInput(input) {
|
|
64
81
|
const v = record(input, "add input");
|
|
65
|
-
closed(v, ["title", "namespace", "body", "note", "state", "priority", "needs", "parent", "supersedes", "relates", "signal"], "add input");
|
|
82
|
+
closed(v, ["title", "namespace", "body", "note", "state", "priority", "needs", "parent", "supersedes", "relates", "actor", "signal"], "add input");
|
|
66
83
|
const title = text(v.title, "title");
|
|
67
84
|
if (title === undefined || title.trim() === "")
|
|
68
85
|
throw new TypeError("title is required");
|
|
69
86
|
const ns = namespace(v.namespace), body = text(v.body, "body"), note = text(v.note, "note"), initialState = state(v.state), pri = priority(v.priority);
|
|
70
87
|
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);
|
|
88
|
+
const createdBy = actor(v.actor), abort = signal(v.signal);
|
|
72
89
|
return { title, ...(ns === undefined ? {} : { namespace: ns }), ...(body === undefined ? {} : { body }), ...(note === undefined ? {} : { note }),
|
|
73
90
|
...(initialState === undefined ? {} : { state: initialState }), ...(pri === undefined ? {} : { priority: pri }),
|
|
74
91
|
...(needs === undefined ? {} : { needs }), ...(parent === undefined ? {} : { parent }),
|
|
75
92
|
...(supersedes === undefined ? {} : { supersedes }), ...(relates === undefined ? {} : { relates }),
|
|
93
|
+
...(createdBy === undefined ? {} : { actor: createdBy }),
|
|
76
94
|
...(abort === undefined ? {} : { signal: abort }) };
|
|
77
95
|
}
|
|
78
96
|
function updateInput(input) {
|
|
@@ -121,22 +139,20 @@ class TaskHandle {
|
|
|
121
139
|
this.world = world;
|
|
122
140
|
}
|
|
123
141
|
async read() {
|
|
124
|
-
const facts = projectDetailFacts(readBoard(this.world).board, this.id);
|
|
142
|
+
const facts = projectDetailFacts((await readBoard(this.world)).board, this.id);
|
|
125
143
|
return facts === null ? null : { ...facts, task: taskView(facts.task) };
|
|
126
144
|
}
|
|
127
|
-
async tree(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
throw new TypeError("full must be a boolean");
|
|
132
|
-
const node = buildTree(readBoard(this.world).board, this.id, value.full ?? false);
|
|
145
|
+
async tree() {
|
|
146
|
+
if (arguments.length > 0)
|
|
147
|
+
throw new TypeError("tree accepts no input");
|
|
148
|
+
const node = buildTree((await readBoard(this.world)).board, this.id);
|
|
133
149
|
return node === null ? { kind: "refused", refusal: { kind: "task-missing", taskId: this.id } } : { kind: "accepted", value: node };
|
|
134
150
|
}
|
|
135
151
|
update(input) { return updateTask(this.world, this.id, updateInput(input)); }
|
|
136
152
|
lifecycle(verb, input) {
|
|
137
153
|
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;
|
|
154
|
+
closed(value, verb === "drop" || verb === "done" ? ["note", "signal"] : ["signal"], `${verb} input`);
|
|
155
|
+
const note = verb === "drop" || verb === "done" ? text(value.note, "note") : undefined;
|
|
140
156
|
return lifecycleTask(this.world, this.id, verb, signal(value.signal), note);
|
|
141
157
|
}
|
|
142
158
|
start(input) { return this.lifecycle("start", input); }
|
|
@@ -147,33 +163,39 @@ class TaskHandle {
|
|
|
147
163
|
drop(input) { return this.lifecycle("drop", input); }
|
|
148
164
|
}
|
|
149
165
|
class TasksHandle {
|
|
150
|
-
root;
|
|
151
166
|
world;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
this.world =
|
|
155
|
-
this.root =
|
|
167
|
+
root;
|
|
168
|
+
constructor(world) {
|
|
169
|
+
this.world = world;
|
|
170
|
+
this.root = world;
|
|
156
171
|
}
|
|
157
|
-
async namespace() { const value = currentNamespace(this.world); return "kind" in value ? { kind: "refused", refusal: value } : { kind: "accepted", value }; }
|
|
172
|
+
async namespace() { const value = await currentNamespace(this.world); return "kind" in value ? { kind: "refused", refusal: value } : { kind: "accepted", value }; }
|
|
158
173
|
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); }
|
|
174
|
+
throw new TypeError("namespace is required"); await setCurrentNamespace(this.world, ns); }
|
|
160
175
|
task(input) { const v = record(input, "task input"); closed(v, ["id"], "task input"); return new TaskHandle(id(v.id), this.world); }
|
|
161
176
|
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")
|
|
177
|
+
addDocument(input) { const v = record(input, "addDocument input"); closed(v, ["markdown", "namespace", "actor", "signal"], "addDocument input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
|
|
178
|
+
throw new TypeError("markdown is required"); const ns = namespace(v.namespace), createdBy = actor(v.actor), abort = signal(v.signal); return addTaskDocument(this.world, { markdown, ...(ns === undefined ? {} : { namespace: ns }), ...(createdBy === undefined ? {} : { actor: createdBy }), ...(abort === undefined ? {} : { signal: abort }) }); }
|
|
179
|
+
async list(input = {}) { const v = record(input, "list input"); closed(v, ["selection", "scope", "limit"], "list input"); if (v.selection !== undefined && v.selection !== "active" && v.selection !== "closed" && v.selection !== "all")
|
|
165
180
|
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
|
|
181
|
+
throw new TypeError("scope must be namespace or world"); return listTasks(this.world, v.selection ?? "active", v.scope, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
|
|
182
|
+
async ready(input = {}) { const v = record(input, "ready input"); closed(v, ["scope", "parent", "limit"], "ready input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
183
|
+
throw new TypeError("scope must be namespace or world"); const parent = v.parent === undefined ? undefined : id(v.parent); return readyTasks(this.world, v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
|
|
184
|
+
async blocked(input = {}) { const v = record(input, "blocked input"); closed(v, ["scope", "parent", "limit"], "blocked input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
185
|
+
throw new TypeError("scope must be namespace or world"); const parent = v.parent === undefined ? undefined : id(v.parent); return blockedTasks(this.world, v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
|
|
186
|
+
async query(input = {}) { const v = record(input, "query input"); closed(v, ["where", "scope", "sort", "limit"], "query input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
187
|
+
throw new TypeError("scope must be namespace or world"); const expression = v.where === undefined ? { kind: "and", terms: [{ kind: "predicate", predicate: { field: "state", operator: "!=", value: "done" } }, { kind: "predicate", predicate: { field: "state", operator: "!=", value: "drop" } }] } : normalizeTaskQuery(v.where); return queryTasks(this.world, expression, v.scope, sort(v.sort) ?? "priority", limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
|
|
188
|
+
async doctor() { return { issues: diagnoseBoard((await readBoard(this.world)).board) }; }
|
|
172
189
|
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)); }
|
|
190
|
+
throw new TypeError("batch verb is invalid"); const note = text(v.note, "note"); if (note !== undefined && verb !== "done" && verb !== "drop")
|
|
191
|
+
throw new TypeError("batch note is valid only for done or drop"); return batchTasks(this.world, verb, taskIds(v.ids, "ids") ?? [], signal(v.signal), note); }
|
|
192
|
+
compose(input) { const v = record(input, "compose input"); closed(v, ["markdown", "actor", "signal"], "compose input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
|
|
193
|
+
throw new TypeError("markdown is required"); return composeTasks(this.world, markdown, signal(v.signal), actor(v.actor)); }
|
|
177
194
|
}
|
|
178
|
-
export const Tasks = Object.freeze({
|
|
179
|
-
|
|
195
|
+
export const Tasks = Object.freeze({
|
|
196
|
+
of(root) {
|
|
197
|
+
if (typeof root !== "string")
|
|
198
|
+
throw new TypeError("Tasks.of root must be a WorldRoot");
|
|
199
|
+
return new TasksHandle(root);
|
|
200
|
+
},
|
|
201
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type BlockedTaskRow, type TaskRow } from "./board.js";
|
|
2
2
|
import { type TaskDocument, type TaskPriority, type TaskState } from "./document.js";
|
|
3
3
|
import { type TaskId } from "./identity.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { WorldRoot } from "../world.js";
|
|
5
|
+
import { type TaskPage, type TaskQueryExpression, type TaskQueryRow, type TaskQuerySort } from "./query.js";
|
|
5
6
|
export type TaskView = Readonly<TaskDocument & {
|
|
6
7
|
namespace: readonly string[];
|
|
7
8
|
}>;
|
|
@@ -51,7 +52,7 @@ export type TaskBatchResult = Readonly<{
|
|
|
51
52
|
outcome: TaskMutationResult;
|
|
52
53
|
}>[];
|
|
53
54
|
}>;
|
|
54
|
-
export type SettledTaskAction = "done"
|
|
55
|
+
export type SettledTaskAction = "done";
|
|
55
56
|
export type SettledTaskResult = Readonly<{
|
|
56
57
|
kind: "changed";
|
|
57
58
|
task: TaskView;
|
|
@@ -76,11 +77,13 @@ export type AddTaskInput = Readonly<{
|
|
|
76
77
|
parent?: TaskId | null;
|
|
77
78
|
supersedes?: readonly TaskId[];
|
|
78
79
|
relates?: readonly TaskId[];
|
|
80
|
+
actor?: string;
|
|
79
81
|
signal?: AbortSignal;
|
|
80
82
|
}>;
|
|
81
83
|
export type AddTaskDocumentInput = Readonly<{
|
|
82
84
|
markdown: string;
|
|
83
85
|
namespace?: readonly string[];
|
|
86
|
+
actor?: string;
|
|
84
87
|
signal?: AbortSignal;
|
|
85
88
|
}>;
|
|
86
89
|
export type UpdateTaskInput = Readonly<{
|
|
@@ -102,14 +105,36 @@ export type UpdateTaskInput = Readonly<{
|
|
|
102
105
|
signal?: AbortSignal;
|
|
103
106
|
}>;
|
|
104
107
|
export declare function taskView(document: TaskDocument): TaskView;
|
|
105
|
-
export declare function addTask(world:
|
|
106
|
-
export declare function addTaskDocument(world:
|
|
107
|
-
export declare function updateTask(world:
|
|
108
|
-
export declare function lifecycleTask(world:
|
|
109
|
-
export declare function batchTasks(world:
|
|
110
|
-
export declare function settleTask(world:
|
|
111
|
-
export declare function listTasks(world:
|
|
112
|
-
export declare function readyTasks(world:
|
|
113
|
-
export declare function blockedTasks(world:
|
|
114
|
-
export declare function
|
|
115
|
-
|
|
108
|
+
export declare function addTask(world: WorldRoot, input: AddTaskInput): Promise<TaskMutationResult>;
|
|
109
|
+
export declare function addTaskDocument(world: WorldRoot, input: AddTaskDocumentInput): Promise<TaskMutationResult>;
|
|
110
|
+
export declare function updateTask(world: WorldRoot, id: TaskId, input: UpdateTaskInput): Promise<TaskUpdateResult>;
|
|
111
|
+
export declare function lifecycleTask(world: WorldRoot, id: TaskId, verb: TaskLifecycleVerb, signal?: AbortSignal, note?: string): Promise<TaskMutationResult>;
|
|
112
|
+
export declare function batchTasks(world: WorldRoot, verb: "done" | "drop" | "hold", ids: readonly TaskId[], signal?: AbortSignal, note?: string): Promise<TaskBatchResult>;
|
|
113
|
+
export declare function settleTask(world: WorldRoot, id: TaskId): Promise<SettledTaskResult>;
|
|
114
|
+
export declare function listTasks(world: WorldRoot, selection: "active" | "closed" | "all", scope?: "namespace" | "world", limit?: number): Promise<TaskOutcome<TaskPage<TaskRow>>>;
|
|
115
|
+
export declare function readyTasks(world: WorldRoot, scope?: "namespace" | "world", parent?: TaskId, limit?: number): Promise<TaskOutcome<TaskPage<TaskRow>>>;
|
|
116
|
+
export declare function blockedTasks(world: WorldRoot, scope?: "namespace" | "world", parent?: TaskId, limit?: number): Promise<TaskOutcome<TaskPage<BlockedTaskRow>>>;
|
|
117
|
+
export declare function queryTasks(world: WorldRoot, expression: TaskQueryExpression, scope?: "namespace" | "world", sort?: TaskQuerySort, limit?: number): Promise<TaskOutcome<TaskPage<TaskQueryRow>>>;
|
|
118
|
+
/** Internal composite observation from one complete Task board read. */
|
|
119
|
+
export declare function observeTaskStatusRows(world: WorldRoot): Promise<(Readonly<{
|
|
120
|
+
id: TaskId;
|
|
121
|
+
title: string;
|
|
122
|
+
state: TaskState;
|
|
123
|
+
priority: TaskPriority;
|
|
124
|
+
disposition: import("./board.js").TaskDisposition;
|
|
125
|
+
}> | {
|
|
126
|
+
blockers: readonly Readonly<{
|
|
127
|
+
id: TaskId;
|
|
128
|
+
title: string | null;
|
|
129
|
+
state: TaskState | "missing";
|
|
130
|
+
}>[];
|
|
131
|
+
id: TaskId;
|
|
132
|
+
title: string;
|
|
133
|
+
state: TaskState;
|
|
134
|
+
priority: TaskPriority;
|
|
135
|
+
disposition: import("./board.js").TaskDisposition;
|
|
136
|
+
})[]>;
|
|
137
|
+
/** Internal identity catalog from one complete Task board read. */
|
|
138
|
+
export declare function observeTaskCatalogRows(world: WorldRoot): Promise<readonly TaskRow[]>;
|
|
139
|
+
export declare function setCurrentNamespace(world: WorldRoot, namespace: readonly string[]): Promise<void>;
|
|
140
|
+
export declare function currentNamespace(world: WorldRoot): Promise<readonly string[] | TaskRefusal>;
|