@astrosheep/keiyaku 4.6.8 → 4.6.9
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 +40 -14
- package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/opencode/index.js +1 -1
- package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/skills/keiyaku/SKILL.md +5 -6
- package/build/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/src/akuma/akuma-instance.d.ts +2 -0
- package/build/src/akuma/akuma-instance.js +10 -0
- package/build/src/akuma/akuma-observe.d.ts +33 -8
- package/build/src/akuma/akuma-observe.js +88 -64
- package/build/src/akuma/akuma-owner.d.ts +11 -2
- package/build/src/akuma/akuma-owner.js +45 -35
- package/build/src/akuma/akuma-selection-execution.js +9 -1
- package/build/src/akuma/akuma-stream.d.ts +22 -0
- package/build/src/akuma/akuma-stream.js +116 -0
- package/build/src/akuma/akuma-wait.d.ts +1 -40
- package/build/src/akuma/akuma-wait.js +23 -84
- package/build/src/akuma/akuma.d.ts +17 -11
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +7 -12
- package/build/src/akuma/allowed.js +13 -4
- package/build/src/akuma/body-supervisor.d.ts +5 -5
- package/build/src/akuma/body-supervisor.js +22 -20
- package/build/src/akuma/body.js +28 -1
- package/build/src/akuma/call-request.d.ts +12 -22
- package/build/src/akuma/heart/activity-schema.d.ts +12 -0
- package/build/src/akuma/heart/activity-schema.js +6 -0
- package/build/src/akuma/heart/index.d.ts +59 -2
- package/build/src/akuma/heart/index.js +87 -8
- package/build/src/akuma/heart/rows.js +5 -3
- package/build/src/akuma/heart/soul.d.ts +9 -0
- package/build/src/akuma/heart/soul.js +29 -0
- package/build/src/akuma/heart/storage.d.ts +15 -0
- package/build/src/akuma/heart/storage.js +55 -0
- package/build/src/akuma/heart/timeline.d.ts +7 -0
- package/build/src/akuma/heart/timeline.js +10 -0
- package/build/src/akuma/index.d.ts +1 -0
- package/build/src/akuma/projection.d.ts +25 -0
- package/build/src/akuma/projection.js +24 -7
- package/build/src/akuma/provider-recipe.d.ts +11 -0
- package/build/src/akuma/provider-recipe.js +23 -0
- package/build/src/akuma/provider.d.ts +25 -0
- package/build/src/akuma/provider.js +99 -7
- package/build/src/akuma/providers/acp/events.js +25 -2
- package/build/src/akuma/providers/claude/events.js +76 -10
- package/build/src/akuma/providers/claude/index.js +2 -5
- package/build/src/akuma/providers/codex-app-server/events.js +17 -2
- package/build/src/akuma/providers/codex-app-server/index.js +15 -9
- package/build/src/akuma/providers/decode.d.ts +8 -0
- package/build/src/akuma/providers/decode.js +21 -0
- package/build/src/akuma/providers/grok-build/index.js +10 -26
- package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
- package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
- package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
- package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
- package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
- package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
- package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
- package/build/src/akuma/providers/paseo/events.d.ts +8 -0
- package/build/src/akuma/providers/paseo/events.js +58 -11
- package/build/src/akuma/providers/paseo/index.js +11 -7
- package/build/src/akuma/providers/pi/events.d.ts +2 -0
- package/build/src/akuma/providers/pi/events.js +32 -24
- package/build/src/akuma/providers/pi/index.js +21 -35
- package/build/src/akuma/request-lifecycle.d.ts +1 -2
- package/build/src/akuma/request-lifecycle.js +2 -8
- package/build/src/akuma/request-rendezvous.js +38 -55
- package/build/src/akuma/request-serve.d.ts +1 -1
- package/build/src/akuma/request-serve.js +77 -113
- package/build/src/akuma/selection-observation.d.ts +57 -51
- package/build/src/akuma/selection-observation.js +3 -3
- package/build/src/akuma/turn-drive.d.ts +3 -0
- package/build/src/akuma/turn-drive.js +26 -5
- package/build/src/akuma-body.js +12 -22
- package/build/src/cli/akuma-caller.js +10 -0
- package/build/src/cli/commands/akuma-grammar.js +3 -4
- package/build/src/cli/commands/akuma.js +13 -51
- package/build/src/cli/commands/contract-grammar.d.ts +7 -6
- package/build/src/cli/commands/contract-grammar.js +27 -32
- package/build/src/cli/commands/contract-help.d.ts +16 -7
- package/build/src/cli/commands/contract-help.js +20 -11
- package/build/src/cli/commands/contract.js +11 -11
- package/build/src/cli/commands/debt-grammar.d.ts +19 -0
- package/build/src/cli/commands/debt-grammar.js +323 -0
- package/build/src/cli/commands/debt-query.d.ts +5 -0
- package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
- package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
- package/build/src/cli/commands/{task.js → debt.js} +83 -143
- package/build/src/cli/coordinates.d.ts +1 -1
- package/build/src/cli/coordinates.js +1 -1
- package/build/src/cli/parse.d.ts +4 -4
- package/build/src/cli/parse.js +17 -16
- package/build/src/cli/render/akuma-activity.d.ts +11 -83
- package/build/src/cli/render/akuma-activity.js +20 -382
- package/build/src/cli/render/catalog.d.ts +2 -2
- package/build/src/cli/render/catalog.js +5 -5
- package/build/src/cli/render/contract.js +2 -2
- package/build/src/cli/render/debt.d.ts +28 -0
- package/build/src/cli/render/{task.js → debt.js} +51 -112
- package/build/src/cli/render/kanshi.js +28 -28
- package/build/src/cli/render/marks.d.ts +5 -5
- package/build/src/cli/render/marks.js +4 -10
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/runtime.js +3 -3
- package/build/src/cli/scan.d.ts +1 -1
- package/build/src/cli/usage.d.ts +1 -1
- package/build/src/cli/usage.js +4 -4
- package/build/src/contract-worktree.js +3 -3
- package/build/src/debt/board.d.ts +160 -0
- package/build/src/{task → debt}/board.js +89 -89
- package/build/src/debt/catalog.d.ts +11 -0
- package/build/src/debt/catalog.js +59 -0
- package/build/src/{task → debt}/context.d.ts +1 -1
- package/build/src/{task → debt}/context.js +1 -1
- package/build/src/{task → debt}/created-observation.d.ts +6 -10
- package/build/src/{task → debt}/created-observation.js +7 -7
- package/build/src/debt/document.d.ts +37 -0
- package/build/src/{task → debt}/document.js +37 -37
- package/build/src/debt/identity.d.ts +21 -0
- package/build/src/{task → debt}/identity.js +35 -35
- package/build/src/debt/index.d.ts +111 -0
- package/build/src/debt/index.js +203 -0
- package/build/src/{task → debt}/input.d.ts +8 -8
- package/build/src/{task → debt}/input.js +21 -21
- package/build/src/debt/lifecycle-operations.d.ts +6 -0
- package/build/src/{task → debt}/lifecycle-operations.js +27 -31
- package/build/src/debt/mutation-result.d.ts +981 -0
- package/build/src/debt/mutation-result.js +109 -0
- package/build/src/debt/mutation.d.ts +424 -0
- package/build/src/debt/mutation.js +223 -0
- package/build/src/debt/operation-types.d.ts +71 -0
- package/build/src/debt/operations.d.ts +28 -0
- package/build/src/{task → debt}/operations.js +59 -60
- package/build/src/debt/query.d.ts +76 -0
- package/build/src/{task → debt}/query.js +55 -55
- package/build/src/{task → debt}/store.d.ts +13 -13
- package/build/src/{task → debt}/store.js +58 -49
- package/build/src/debt/view.d.ts +4 -0
- package/build/src/debt/view.js +7 -0
- package/build/src/identity/coordinates.d.ts +1 -1
- package/build/src/index.d.ts +13 -13
- package/build/src/index.js +9 -9
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +33 -33
- package/build/src/kanshi/report.d.ts +7 -7
- package/build/src/kanshi/select.js +4 -4
- package/build/src/library/akumas.d.ts +2 -3
- package/build/src/library/bind.d.ts +3 -3
- package/build/src/library/bind.js +5 -5
- package/build/src/library/contract-creation.js +5 -5
- package/build/src/library/contract-execution.js +4 -4
- package/build/src/library/contract-types.d.ts +2 -2
- package/build/src/library/input.d.ts +2 -2
- package/build/src/library/input.js +5 -5
- package/build/src/library/invocation.js +2 -2
- package/build/src/library/nuke.js +3 -3
- package/build/src/library/outcome.d.ts +126 -126
- package/build/src/library/outcome.js +3 -3
- package/build/src/library/selection.d.ts +1 -4
- package/build/src/library/selection.js +11 -62
- package/build/src/plugin/public.d.ts +5 -0
- package/build/src/plugin/runtime.js +3 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/fence.d.ts +3 -3
- package/build/src/settlement/fence.js +4 -4
- package/build/src/settlement/holder.d.ts +16 -16
- package/build/src/settlement/holder.js +69 -63
- package/build/src/settlement/settle.d.ts +5 -5
- package/build/src/settlement/settle.js +53 -53
- package/package.json +12 -6
- package/plugins/paseo/plugin/index.server.ts +17 -0
- package/plugins/paseo/plugin/paseo-plugin.json +4 -0
- package/plugins/paseo/plugin/server/attach.ts +52 -0
- package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
- package/plugins/paseo/plugin/server/message.ts +60 -0
- package/plugins/paseo/plugin/server/mirror.ts +193 -0
- package/plugins/paseo/plugin/server/model.ts +14 -0
- package/plugins/paseo/plugin/server/provider.ts +276 -0
- package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
- package/plugins/paseo/plugin/server/sdk.ts +289 -0
- package/plugins/paseo/plugin/server/stop.ts +26 -0
- package/plugins/paseo/plugin/server/transport.ts +35 -0
- package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
- package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
- package/plugins/paseo/plugin/tsconfig.json +6 -0
- package/skills/keiyaku/SKILL.md +5 -6
- package/skills/keiyaku-akuma/SKILL.md +1 -1
- package/skills/keiyaku-akuma/references/automation.md +8 -8
- package/skills/keiyaku-babysit/SKILL.md +1 -1
- package/skills/keiyaku-bind/SKILL.md +9 -9
- package/skills/keiyaku-debt/SKILL.md +91 -0
- package/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
- package/build/skills/keiyaku-task/SKILL.md +0 -104
- package/build/src/cli/commands/task-grammar.d.ts +0 -19
- package/build/src/cli/commands/task-grammar.js +0 -384
- package/build/src/cli/commands/task-query.d.ts +0 -5
- package/build/src/cli/render/task.d.ts +0 -39
- package/build/src/task/board.d.ts +0 -168
- package/build/src/task/catalog.d.ts +0 -11
- package/build/src/task/catalog.js +0 -59
- package/build/src/task/compose-language.d.ts +0 -57
- package/build/src/task/compose-language.js +0 -364
- package/build/src/task/compose-parser.d.ts +0 -32
- package/build/src/task/compose-parser.js +0 -180
- package/build/src/task/compose.d.ts +0 -16
- package/build/src/task/compose.js +0 -189
- package/build/src/task/document.d.ts +0 -39
- package/build/src/task/identity.d.ts +0 -21
- package/build/src/task/index.d.ts +0 -138
- package/build/src/task/index.js +0 -269
- package/build/src/task/lifecycle-operations.d.ts +0 -6
- package/build/src/task/mutation-result.d.ts +0 -1726
- package/build/src/task/mutation-result.js +0 -198
- package/build/src/task/mutation.d.ts +0 -590
- package/build/src/task/mutation.js +0 -262
- package/build/src/task/operation-types.d.ts +0 -71
- package/build/src/task/operations.d.ts +0 -28
- package/build/src/task/query.d.ts +0 -76
- package/build/src/task/view.d.ts +0 -4
- package/build/src/task/view.js +0 -7
- package/skills/keiyaku-task/SKILL.md +0 -104
- /package/build/src/{task → debt}/operation-types.js +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { World } from "../world.js";
|
|
2
|
+
import { requestBodyCommand } from "../akuma/request-rendezvous.js";
|
|
3
|
+
import { eraseRequestCommand, } from "../akuma/request-wire.js";
|
|
4
|
+
import { debtIdsSchema, debtNamespaceSchema } from "./identity.js";
|
|
5
|
+
import { debtNonblankTextSchema, debtStateSchema, debtPrioritySchema } from "./document.js";
|
|
6
|
+
import { debtBatchResultSchema, debtMutationIdSchema, debtMutationResultSchema, debtUpdateResultSchema, } from "./mutation-result.js";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export const DEBT_MUTATION_ACTIONS = Object.freeze([
|
|
9
|
+
"debt.add",
|
|
10
|
+
"debt.addDocument",
|
|
11
|
+
"debt.done",
|
|
12
|
+
"debt.drop",
|
|
13
|
+
"debt.update",
|
|
14
|
+
]);
|
|
15
|
+
const debtMutationActionSchema = z.enum(DEBT_MUTATION_ACTIONS);
|
|
16
|
+
const nonemptyDebtIdsSchema = debtIdsSchema.unwrap().min(1).readonly();
|
|
17
|
+
const addInputSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
title: debtNonblankTextSchema,
|
|
20
|
+
namespace: debtNamespaceSchema,
|
|
21
|
+
body: z.string().optional(),
|
|
22
|
+
note: z.string().optional(),
|
|
23
|
+
state: debtStateSchema.optional(),
|
|
24
|
+
priority: debtPrioritySchema.optional(),
|
|
25
|
+
needs: debtIdsSchema.optional(),
|
|
26
|
+
parent: debtMutationIdSchema.nullable().optional(),
|
|
27
|
+
supersedes: debtIdsSchema.optional(),
|
|
28
|
+
relates: debtIdsSchema.optional(),
|
|
29
|
+
})
|
|
30
|
+
.strict();
|
|
31
|
+
const updateInputSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
title: debtNonblankTextSchema.optional(),
|
|
34
|
+
body: z.string().optional(),
|
|
35
|
+
appendBody: z.string().optional(),
|
|
36
|
+
note: z.string().optional(),
|
|
37
|
+
priority: debtPrioritySchema.optional(),
|
|
38
|
+
needs: debtIdsSchema.optional(),
|
|
39
|
+
addNeeds: debtIdsSchema.optional(),
|
|
40
|
+
dropNeeds: debtIdsSchema.optional(),
|
|
41
|
+
parent: debtMutationIdSchema.nullable().optional(),
|
|
42
|
+
supersedes: debtIdsSchema.optional(),
|
|
43
|
+
addSupersedes: debtIdsSchema.optional(),
|
|
44
|
+
dropSupersedes: debtIdsSchema.optional(),
|
|
45
|
+
relates: debtIdsSchema.optional(),
|
|
46
|
+
addRelates: debtIdsSchema.optional(),
|
|
47
|
+
dropRelates: debtIdsSchema.optional(),
|
|
48
|
+
})
|
|
49
|
+
.strict()
|
|
50
|
+
.superRefine((input, context) => {
|
|
51
|
+
if (input.body !== undefined && input.appendBody !== undefined)
|
|
52
|
+
context.addIssue({ code: "custom", message: "body and appendBody are mutually exclusive" });
|
|
53
|
+
if (Object.values(input).every((value) => value === undefined))
|
|
54
|
+
context.addIssue({ code: "custom", message: "update requires at least one field change" });
|
|
55
|
+
});
|
|
56
|
+
const addRequestSchema = z
|
|
57
|
+
.object({ input: addInputSchema })
|
|
58
|
+
.strict()
|
|
59
|
+
.transform(({ input }) => ({ action: "debt.add", input }));
|
|
60
|
+
const addDocumentRequestSchema = z
|
|
61
|
+
.object({ input: z.object({ markdown: z.string(), namespace: debtNamespaceSchema }).strict() })
|
|
62
|
+
.strict()
|
|
63
|
+
.transform(({ input }) => ({ action: "debt.addDocument", input }));
|
|
64
|
+
const updateRequestSchema = z
|
|
65
|
+
.object({ id: debtMutationIdSchema, input: updateInputSchema })
|
|
66
|
+
.strict()
|
|
67
|
+
.transform((request) => ({ action: "debt.update", ...request }));
|
|
68
|
+
const terminalRequestSchema = (action) => z.union([
|
|
69
|
+
z
|
|
70
|
+
.object({ id: debtMutationIdSchema, note: z.string().optional() })
|
|
71
|
+
.strict()
|
|
72
|
+
.transform(({ id, note }) => ({ action, id, ...(note === undefined ? {} : { note }) })),
|
|
73
|
+
z
|
|
74
|
+
.object({ ids: nonemptyDebtIdsSchema, note: z.string().optional() })
|
|
75
|
+
.strict()
|
|
76
|
+
.transform(({ ids, note }) => ({ action, ids, ...(note === undefined ? {} : { note }) })),
|
|
77
|
+
]);
|
|
78
|
+
const debtRequestSchemas = {
|
|
79
|
+
"debt.add": addRequestSchema,
|
|
80
|
+
"debt.addDocument": addDocumentRequestSchema,
|
|
81
|
+
"debt.done": terminalRequestSchema("debt.done"),
|
|
82
|
+
"debt.drop": terminalRequestSchema("debt.drop"),
|
|
83
|
+
"debt.update": updateRequestSchema,
|
|
84
|
+
};
|
|
85
|
+
const worldPathSchema = z.string().min(1);
|
|
86
|
+
const debtBodyRequestSchema = z
|
|
87
|
+
.object({ world: worldPathSchema, request: z.union(Object.values(debtRequestSchemas)) })
|
|
88
|
+
.strict();
|
|
89
|
+
const debtMutationServiceSchema = z.object({ action: debtMutationActionSchema }).strict();
|
|
90
|
+
export const forwardedDebtReferenceSchema = z
|
|
91
|
+
.object({ kind: z.literal("served-reference"), action: debtMutationActionSchema })
|
|
92
|
+
.strict();
|
|
93
|
+
function decodeDebtBodyRequest(action, value) {
|
|
94
|
+
const parsed = debtBodyRequestSchema.extend({ request: debtRequestSchemas[action] }).safeParse(value);
|
|
95
|
+
return parsed.success ? parsed.data : null;
|
|
96
|
+
}
|
|
97
|
+
function decodeDebtService(action, value) {
|
|
98
|
+
const parsed = debtMutationServiceSchema.safeParse(value);
|
|
99
|
+
if (!parsed.success || parsed.data.action !== action)
|
|
100
|
+
throw new Error(`malformed stored Debt service evidence for ${action}`);
|
|
101
|
+
return parsed.data;
|
|
102
|
+
}
|
|
103
|
+
function decodeDebtReference(action, value) {
|
|
104
|
+
const parsed = forwardedDebtReferenceSchema.safeParse(value);
|
|
105
|
+
if (!parsed.success || parsed.data.action !== action)
|
|
106
|
+
throw new Error(`malformed Debt service reference for ${action}`);
|
|
107
|
+
return parsed.data;
|
|
108
|
+
}
|
|
109
|
+
/** Debt owns forwarded mutation payload, live result, and durable service evidence. */
|
|
110
|
+
export function debtMutationRequestProtocol(action, batch) {
|
|
111
|
+
return {
|
|
112
|
+
action,
|
|
113
|
+
encodeRequest: (input) => {
|
|
114
|
+
const { action: _action, ...request } = input.request;
|
|
115
|
+
return { world: input.world, request };
|
|
116
|
+
},
|
|
117
|
+
decodeRequest: (value) => decodeDebtBodyRequest(action, value),
|
|
118
|
+
encodeResult: (result) => result,
|
|
119
|
+
decodeResult: (result) => {
|
|
120
|
+
const schema = action === "debt.update"
|
|
121
|
+
? debtUpdateResultSchema
|
|
122
|
+
: batch === undefined
|
|
123
|
+
? z.union([debtMutationResultSchema, debtBatchResultSchema])
|
|
124
|
+
: batch
|
|
125
|
+
? debtBatchResultSchema
|
|
126
|
+
: debtMutationResultSchema;
|
|
127
|
+
const parsed = schema.safeParse(result);
|
|
128
|
+
if (!parsed.success)
|
|
129
|
+
throw new Error(`transport integrity: Debt ${action} returned an invalid live result`);
|
|
130
|
+
return parsed.data;
|
|
131
|
+
},
|
|
132
|
+
decodeReference: (reference) => decodeDebtReference(action, reference),
|
|
133
|
+
isPermitted: (allowed) => allowed.includes(action),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export function debtMutationRequestCommand(action, port) {
|
|
137
|
+
return {
|
|
138
|
+
completion: "service",
|
|
139
|
+
protocol: debtMutationRequestProtocol(action),
|
|
140
|
+
encodeService: (service) => service,
|
|
141
|
+
decodeService: (service) => decodeDebtService(action, service),
|
|
142
|
+
projectService: (service) => ({ kind: "served-reference", action: service.action }),
|
|
143
|
+
execute: async (request, facts) => {
|
|
144
|
+
const world = await World.prove(request.world);
|
|
145
|
+
const action = request.request.action;
|
|
146
|
+
let result;
|
|
147
|
+
switch (action) {
|
|
148
|
+
case "debt.add":
|
|
149
|
+
result = await port.add({
|
|
150
|
+
world,
|
|
151
|
+
options: addDebtOptions(request.request.input, facts.requester, facts.signal),
|
|
152
|
+
});
|
|
153
|
+
break;
|
|
154
|
+
case "debt.addDocument":
|
|
155
|
+
result = await port.addDocument({
|
|
156
|
+
world,
|
|
157
|
+
document: { ...request.request.input, actor: facts.requester, signal: facts.signal },
|
|
158
|
+
});
|
|
159
|
+
break;
|
|
160
|
+
case "debt.update":
|
|
161
|
+
result = await port.update({
|
|
162
|
+
world,
|
|
163
|
+
id: request.request.id,
|
|
164
|
+
options: updateDebtOptions(request.request.input, facts.signal),
|
|
165
|
+
});
|
|
166
|
+
break;
|
|
167
|
+
case "debt.done":
|
|
168
|
+
case "debt.drop": {
|
|
169
|
+
const verb = action.slice("debt.".length);
|
|
170
|
+
const note = "note" in request.request ? request.request.note : undefined;
|
|
171
|
+
result =
|
|
172
|
+
"ids" in request.request
|
|
173
|
+
? await port.batch({
|
|
174
|
+
world,
|
|
175
|
+
verb,
|
|
176
|
+
ids: request.request.ids,
|
|
177
|
+
...(note === undefined ? {} : { note }),
|
|
178
|
+
signal: facts.signal,
|
|
179
|
+
})
|
|
180
|
+
: await port.lifecycle({
|
|
181
|
+
world,
|
|
182
|
+
verb,
|
|
183
|
+
id: request.request.id,
|
|
184
|
+
...(note === undefined ? {} : { note }),
|
|
185
|
+
signal: facts.signal,
|
|
186
|
+
});
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { kind: "served", result, service: { action } };
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
export function debtMutationRequestCommands(port) {
|
|
195
|
+
return Object.fromEntries(DEBT_MUTATION_ACTIONS.map((action) => [action, eraseRequestCommand(debtMutationRequestCommand(action, port))]));
|
|
196
|
+
}
|
|
197
|
+
export async function requestForwardedDebt(input) {
|
|
198
|
+
const response = await requestBodyCommand({
|
|
199
|
+
directory: input.directory,
|
|
200
|
+
...(input.id === undefined ? {} : { id: input.id }),
|
|
201
|
+
command: debtMutationRequestProtocol(input.request.action, "ids" in input.request),
|
|
202
|
+
value: { world: input.world, request: input.request },
|
|
203
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
204
|
+
});
|
|
205
|
+
if (response.kind === "reference")
|
|
206
|
+
return response.reference;
|
|
207
|
+
return response.result;
|
|
208
|
+
}
|
|
209
|
+
/** Absent optional fields are omitted, never republished as an explicit undefined. */
|
|
210
|
+
function definedFields(fields, additions = {}) {
|
|
211
|
+
const selected = {};
|
|
212
|
+
for (const [key, value] of Object.entries({ ...fields, ...additions })) {
|
|
213
|
+
if (value !== undefined)
|
|
214
|
+
selected[key] = value;
|
|
215
|
+
}
|
|
216
|
+
return selected;
|
|
217
|
+
}
|
|
218
|
+
function addDebtOptions(input, actor, signal) {
|
|
219
|
+
return definedFields(input, { actor, signal });
|
|
220
|
+
}
|
|
221
|
+
function updateDebtOptions(input, signal) {
|
|
222
|
+
return definedFields(input, { signal });
|
|
223
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DebtPriority, DebtState } from "./document.js";
|
|
2
|
+
import type { DebtId } from "./identity.js";
|
|
3
|
+
import type { DebtCleanupFailure, DebtRefusal, DebtRetry, DebtView } from "./mutation-result.js";
|
|
4
|
+
export type { DebtView, DebtCleanupFailure, DebtRefusal, DebtRetry, DebtMutationResult, DebtUpdateResult, DebtBatchResult, } from "./mutation-result.js";
|
|
5
|
+
export type DebtOutcome<A> = Readonly<{
|
|
6
|
+
kind: "accepted";
|
|
7
|
+
value: A;
|
|
8
|
+
cleanup?: DebtCleanupFailure;
|
|
9
|
+
}> | Readonly<{
|
|
10
|
+
kind: "refused";
|
|
11
|
+
refusal: DebtRefusal;
|
|
12
|
+
}> | Readonly<{
|
|
13
|
+
kind: "retry";
|
|
14
|
+
reason: DebtRetry;
|
|
15
|
+
}>;
|
|
16
|
+
export type DebtLifecycleVerb = Extract<DebtRefusal, {
|
|
17
|
+
kind: "invalid-lifecycle-transition";
|
|
18
|
+
}>["verb"];
|
|
19
|
+
export type SettledDebtAction = "done";
|
|
20
|
+
export type SettledDebtResult = Readonly<{
|
|
21
|
+
kind: "changed";
|
|
22
|
+
debt: DebtView;
|
|
23
|
+
action: SettledDebtAction;
|
|
24
|
+
cleanup?: DebtCleanupFailure;
|
|
25
|
+
}> | Readonly<{
|
|
26
|
+
kind: "unchanged";
|
|
27
|
+
}> | Readonly<{
|
|
28
|
+
kind: "refused";
|
|
29
|
+
refusal: DebtRefusal;
|
|
30
|
+
}> | Readonly<{
|
|
31
|
+
kind: "retry";
|
|
32
|
+
reason: DebtRetry;
|
|
33
|
+
}>;
|
|
34
|
+
export type AddDebtInput = Readonly<{
|
|
35
|
+
title: string;
|
|
36
|
+
namespace?: readonly string[];
|
|
37
|
+
body?: string;
|
|
38
|
+
note?: string;
|
|
39
|
+
state?: DebtState;
|
|
40
|
+
priority?: DebtPriority;
|
|
41
|
+
needs?: readonly DebtId[];
|
|
42
|
+
parent?: DebtId | null;
|
|
43
|
+
supersedes?: readonly DebtId[];
|
|
44
|
+
relates?: readonly DebtId[];
|
|
45
|
+
actor?: string;
|
|
46
|
+
signal?: AbortSignal;
|
|
47
|
+
}>;
|
|
48
|
+
export type AddDebtDocumentInput = Readonly<{
|
|
49
|
+
markdown: string;
|
|
50
|
+
namespace?: readonly string[];
|
|
51
|
+
actor?: string;
|
|
52
|
+
signal?: AbortSignal;
|
|
53
|
+
}>;
|
|
54
|
+
export type UpdateDebtInput = Readonly<{
|
|
55
|
+
title?: string;
|
|
56
|
+
body?: string;
|
|
57
|
+
appendBody?: string;
|
|
58
|
+
note?: string;
|
|
59
|
+
priority?: DebtPriority;
|
|
60
|
+
needs?: readonly DebtId[];
|
|
61
|
+
addNeeds?: readonly DebtId[];
|
|
62
|
+
dropNeeds?: readonly DebtId[];
|
|
63
|
+
parent?: DebtId | null;
|
|
64
|
+
supersedes?: readonly DebtId[];
|
|
65
|
+
addSupersedes?: readonly DebtId[];
|
|
66
|
+
dropSupersedes?: readonly DebtId[];
|
|
67
|
+
relates?: readonly DebtId[];
|
|
68
|
+
addRelates?: readonly DebtId[];
|
|
69
|
+
dropRelates?: readonly DebtId[];
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
}>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type BlockedDebtRow, type DebtBoardObservation, type DebtDetailFacts, type DebtRow } from "./board.js";
|
|
2
|
+
import { type DebtId } from "./identity.js";
|
|
3
|
+
import type { WorldRoot } from "../world.js";
|
|
4
|
+
import { type DebtPage, type DebtQueryExpression, type DebtQueryRow, type DebtQuerySort } from "./query.js";
|
|
5
|
+
export { debtView } from "./view.js";
|
|
6
|
+
export type { AddDebtDocumentInput, AddDebtInput, DebtCleanupFailure, SettledDebtResult, DebtBatchResult, DebtMutationResult, DebtOutcome, DebtRefusal, DebtRetry, DebtUpdateResult, DebtView, UpdateDebtInput, } from "./operation-types.js";
|
|
7
|
+
import type { AddDebtDocumentInput, AddDebtInput, DebtMutationResult, DebtOutcome, DebtUpdateResult, UpdateDebtInput } from "./operation-types.js";
|
|
8
|
+
export declare function nukeDebt(world: WorldRoot, options?: Readonly<{
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
onRemoved?(count: number): void;
|
|
11
|
+
}>): Promise<number>;
|
|
12
|
+
export declare function addDebt(world: WorldRoot, input: AddDebtInput): Promise<DebtMutationResult>;
|
|
13
|
+
export declare function addDebtDocument(world: WorldRoot, input: AddDebtDocumentInput): Promise<DebtMutationResult>;
|
|
14
|
+
export declare function updateDebt(world: WorldRoot, id: DebtId, input: UpdateDebtInput): Promise<DebtUpdateResult>;
|
|
15
|
+
export { batchDebts, lifecycleDebt, settleDebt } from "./lifecycle-operations.js";
|
|
16
|
+
export declare function listDebts(world: WorldRoot, namespace: readonly string[] | undefined, selection: "active" | "closed" | "all", scope?: "namespace" | "world", limit?: number): Promise<DebtOutcome<DebtPage<DebtRow>>>;
|
|
17
|
+
export declare function readDebtDetail(world: WorldRoot, id: DebtId): Promise<DebtDetailFacts | null>;
|
|
18
|
+
export declare function readyDebts(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: DebtId, limit?: number): Promise<DebtOutcome<DebtPage<DebtRow>>>;
|
|
19
|
+
export declare function blockedDebts(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: DebtId, limit?: number): Promise<DebtOutcome<DebtPage<BlockedDebtRow>>>;
|
|
20
|
+
export declare function queryDebts(input: Readonly<{
|
|
21
|
+
world: WorldRoot;
|
|
22
|
+
namespace?: readonly string[];
|
|
23
|
+
expression: DebtQueryExpression;
|
|
24
|
+
scope?: "namespace" | "world";
|
|
25
|
+
sort?: DebtQuerySort;
|
|
26
|
+
limit?: number;
|
|
27
|
+
}>): Promise<DebtOutcome<DebtPage<DebtQueryRow>>>;
|
|
28
|
+
export declare function observeDebtBoard(world: WorldRoot): Promise<DebtBoardObservation>;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
|
|
2
2
|
import { documentDiff } from "../markdown/diff.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { allocateLocalId, deriveLocalStem,
|
|
6
|
-
import {
|
|
3
|
+
import { createDebtRelations, projectOwnedDetailFacts, projectDebtBoardObservation, relationProblem, projectBlocked, projectRows, occupiedLocalIds, } from "./board.js";
|
|
4
|
+
import { parseDebtCreationDocument, serializeDebtDocument, } from "./document.js";
|
|
5
|
+
import { allocateLocalId, deriveLocalStem, formatDebtId } from "./identity.js";
|
|
6
|
+
import { nukeDebtAuthority, readBoard, readDebtDocument, replaceAuthority, withDebtLocks } from "./store.js";
|
|
7
7
|
import { boundedListLimit, projectBoundedList } from "../bounded-list.js";
|
|
8
8
|
import { projectQuery, projectQueryRows, queryUnderTargets, underExpression, } from "./query.js";
|
|
9
|
-
import {
|
|
10
|
-
export {
|
|
11
|
-
export async function
|
|
12
|
-
const result = await
|
|
9
|
+
import { advanceDebtTimestamp, debtView } from "./view.js";
|
|
10
|
+
export { debtView } from "./view.js";
|
|
11
|
+
export async function nukeDebt(world, options) {
|
|
12
|
+
const result = await nukeDebtAuthority(world, options);
|
|
13
13
|
if (result === "busy")
|
|
14
|
-
throw new SqliteTransactionLockError("
|
|
14
|
+
throw new SqliteTransactionLockError("Debt reset lock contention", "timeout");
|
|
15
15
|
return result;
|
|
16
16
|
}
|
|
17
17
|
function refused(refusal) {
|
|
@@ -23,26 +23,25 @@ function retry(reason) {
|
|
|
23
23
|
function currentTimestamp() {
|
|
24
24
|
return new Date().toISOString();
|
|
25
25
|
}
|
|
26
|
-
/** Internal Task timestamp rule shared by ordinary mutations and compose. */
|
|
27
26
|
function addDocument(base, namespace, board, at, actor) {
|
|
28
27
|
const localId = allocateLocalId(deriveLocalStem(base.title), occupiedLocalIds(board, namespace));
|
|
29
28
|
return {
|
|
30
29
|
...base,
|
|
31
|
-
id:
|
|
30
|
+
id: formatDebtId({ namespace, localId }),
|
|
32
31
|
...(actor === undefined ? {} : { createdBy: actor }),
|
|
33
32
|
createdAt: at,
|
|
34
33
|
updatedAt: at,
|
|
35
34
|
};
|
|
36
35
|
}
|
|
37
36
|
function boardWith(board, document) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
return {
|
|
37
|
+
const debts = new Map(board.debts);
|
|
38
|
+
debts.set(document.id, document);
|
|
39
|
+
return { debts };
|
|
41
40
|
}
|
|
42
41
|
async function create(world, base, namespace, signal, actor) {
|
|
43
42
|
let result;
|
|
44
43
|
try {
|
|
45
|
-
result = await
|
|
44
|
+
result = await withDebtLocks({ world, allocation: true, ids: [], ...(signal === undefined ? {} : { signal }) }, async () => {
|
|
46
45
|
const snapshot = await readBoard(world), next = addDocument(base, namespace, snapshot.board, currentTimestamp(), actor);
|
|
47
46
|
const problem = relationProblem(boardWith(snapshot.board, next), null, next);
|
|
48
47
|
if (problem !== null)
|
|
@@ -51,22 +50,22 @@ async function create(world, base, namespace, signal, actor) {
|
|
|
51
50
|
world,
|
|
52
51
|
id: next.id,
|
|
53
52
|
expected: null,
|
|
54
|
-
next:
|
|
53
|
+
next: serializeDebtDocument(next),
|
|
55
54
|
});
|
|
56
55
|
return replaced === "replaced"
|
|
57
|
-
? { kind: "accepted", value:
|
|
56
|
+
? { kind: "accepted", value: debtView(next) }
|
|
58
57
|
: retry("concurrent-modification");
|
|
59
58
|
});
|
|
60
59
|
}
|
|
61
60
|
catch (error) {
|
|
62
61
|
if (error instanceof TypeError &&
|
|
63
|
-
/
|
|
62
|
+
/debt identity (?:cannot fit the physical filename budget|contains a Windows-reserved physical segment)/u.test(error.message))
|
|
64
63
|
return refused({ kind: "invalid-namespace-context", path: namespace.join("/") });
|
|
65
64
|
throw error;
|
|
66
65
|
}
|
|
67
66
|
return result === "busy" ? retry("busy") : result;
|
|
68
67
|
}
|
|
69
|
-
export async function
|
|
68
|
+
export async function addDebt(world, input) {
|
|
70
69
|
const namespace = input.namespace ?? [];
|
|
71
70
|
return create(world, {
|
|
72
71
|
title: input.title,
|
|
@@ -80,9 +79,9 @@ export async function addTask(world, input) {
|
|
|
80
79
|
relates: input.relates ?? [],
|
|
81
80
|
}, namespace, input.signal, input.actor);
|
|
82
81
|
}
|
|
83
|
-
export async function
|
|
82
|
+
export async function addDebtDocument(world, input) {
|
|
84
83
|
const namespace = input.namespace ?? [];
|
|
85
|
-
return create(world,
|
|
84
|
+
return create(world, parseDebtCreationDocument(input.markdown), namespace, input.signal, input.actor);
|
|
86
85
|
}
|
|
87
86
|
function listChange(current, replacement, additions, removals) {
|
|
88
87
|
const next = [...(replacement ?? current)];
|
|
@@ -92,9 +91,9 @@ function listChange(current, replacement, additions, removals) {
|
|
|
92
91
|
return next.filter((id) => !(removals ?? []).includes(id));
|
|
93
92
|
}
|
|
94
93
|
function relatedOwner(board, id, target) {
|
|
95
|
-
return board.
|
|
94
|
+
return board.debts.get(target)?.relates.includes(id) ? target : null;
|
|
96
95
|
}
|
|
97
|
-
function
|
|
96
|
+
function appendDebtBody(current, addition) {
|
|
98
97
|
if (current.length === 0 || addition.length === 0 || current.endsWith("\n") || addition.startsWith("\n")) {
|
|
99
98
|
return current + addition;
|
|
100
99
|
}
|
|
@@ -105,12 +104,12 @@ function updateDocument(board, current, input) {
|
|
|
105
104
|
if (!current.relates.includes(related)) {
|
|
106
105
|
const owner = relatedOwner(board, current.id, related);
|
|
107
106
|
if (owner !== null)
|
|
108
|
-
return { kind: "relation-owned-by-other",
|
|
107
|
+
return { kind: "relation-owned-by-other", debtId: current.id, related, declaringDebt: owner };
|
|
109
108
|
}
|
|
110
109
|
return {
|
|
111
110
|
...current,
|
|
112
111
|
...(input.title === undefined ? {} : { title: input.title }),
|
|
113
|
-
body: input.body ?? (input.appendBody === undefined ? current.body :
|
|
112
|
+
body: input.body ?? (input.appendBody === undefined ? current.body : appendDebtBody(current.body, input.appendBody)),
|
|
114
113
|
...(input.note === undefined ? {} : { note: input.note }),
|
|
115
114
|
...(input.priority === undefined ? {} : { priority: input.priority }),
|
|
116
115
|
needs: listChange(current.needs, input.needs, input.addNeeds, input.dropNeeds),
|
|
@@ -141,11 +140,11 @@ function updateFieldChanges(current, next, input) {
|
|
|
141
140
|
}
|
|
142
141
|
return changes;
|
|
143
142
|
}
|
|
144
|
-
export async function
|
|
145
|
-
const result = await
|
|
146
|
-
const snapshot = await readBoard(world), current = snapshot.board.
|
|
143
|
+
export async function updateDebt(world, id, input) {
|
|
144
|
+
const result = await withDebtLocks({ world, allocation: false, ids: [id], ...(input.signal === undefined ? {} : { signal: input.signal }) }, async () => {
|
|
145
|
+
const snapshot = await readBoard(world), current = snapshot.board.debts.get(id);
|
|
147
146
|
if (current === undefined)
|
|
148
|
-
return { kind: "refused", refusal: { kind: "
|
|
147
|
+
return { kind: "refused", refusal: { kind: "debt-missing", debtId: id } };
|
|
149
148
|
const candidate = updateDocument(snapshot.board, current, input);
|
|
150
149
|
if ("kind" in candidate)
|
|
151
150
|
return { kind: "refused", refusal: candidate };
|
|
@@ -154,13 +153,13 @@ export async function updateTask(world, id, input) {
|
|
|
154
153
|
return { kind: "refused", refusal: { kind: "invalid-graph", diagnostic: problem } };
|
|
155
154
|
const predecessor = snapshot.bytes.get(id);
|
|
156
155
|
const before = Buffer.from(predecessor).toString("utf8");
|
|
157
|
-
const changed = !Buffer.from(
|
|
156
|
+
const changed = !Buffer.from(serializeDebtDocument(candidate)).equals(Buffer.from(predecessor));
|
|
158
157
|
let next = candidate;
|
|
159
158
|
if (changed) {
|
|
160
159
|
const at = currentTimestamp();
|
|
161
|
-
next = { ...candidate, updatedAt:
|
|
160
|
+
next = { ...candidate, updatedAt: advanceDebtTimestamp(current.updatedAt, at) };
|
|
162
161
|
}
|
|
163
|
-
const afterBytes =
|
|
162
|
+
const afterBytes = serializeDebtDocument(next);
|
|
164
163
|
const after = Buffer.from(afterBytes).toString("utf8");
|
|
165
164
|
if (before !== after &&
|
|
166
165
|
(await replaceAuthority({ world, id, expected: predecessor, next: afterBytes })) !== "replaced") {
|
|
@@ -170,7 +169,7 @@ export async function updateTask(world, id, input) {
|
|
|
170
169
|
return {
|
|
171
170
|
kind: "accepted",
|
|
172
171
|
value: {
|
|
173
|
-
|
|
172
|
+
debt: debtView(next),
|
|
174
173
|
documentDiff: documentDiff(label, label, before, after),
|
|
175
174
|
changedFields: updateFieldChanges(current, next, input),
|
|
176
175
|
},
|
|
@@ -178,45 +177,45 @@ export async function updateTask(world, id, input) {
|
|
|
178
177
|
});
|
|
179
178
|
return result === "busy" ? { kind: "retry", reason: "busy" } : result;
|
|
180
179
|
}
|
|
181
|
-
export {
|
|
180
|
+
export { batchDebts, lifecycleDebt, settleDebt } from "./lifecycle-operations.js";
|
|
182
181
|
function readScope(namespace, scope) {
|
|
183
182
|
return scope === "world" ? null : (namespace ?? []);
|
|
184
183
|
}
|
|
185
|
-
export async function
|
|
184
|
+
export async function listDebts(world, namespace, selection, scope, limit) {
|
|
186
185
|
const selectedLimit = boundedListLimit(limit);
|
|
187
186
|
const selected = readScope(namespace, scope);
|
|
188
187
|
const board = (await readBoard(world)).board;
|
|
189
188
|
return {
|
|
190
189
|
kind: "accepted",
|
|
191
|
-
value: projectBoundedList(projectRows(board,
|
|
190
|
+
value: projectBoundedList(projectRows(board, createDebtRelations(board), selected, selection), selectedLimit),
|
|
192
191
|
};
|
|
193
192
|
}
|
|
194
|
-
export async function
|
|
195
|
-
const
|
|
196
|
-
if (
|
|
193
|
+
export async function readDebtDetail(world, id) {
|
|
194
|
+
const debt = await readDebtDocument(world, id);
|
|
195
|
+
if (debt === undefined)
|
|
197
196
|
return null;
|
|
198
|
-
const selected = new Map([[id,
|
|
197
|
+
const selected = new Map([[id, debt]]);
|
|
199
198
|
const references = [
|
|
200
|
-
...
|
|
201
|
-
...(
|
|
202
|
-
...
|
|
203
|
-
...
|
|
199
|
+
...debt.needs,
|
|
200
|
+
...(debt.parent === null ? [] : [debt.parent]),
|
|
201
|
+
...debt.supersedes,
|
|
202
|
+
...debt.relates,
|
|
204
203
|
];
|
|
205
204
|
for (const reference of references) {
|
|
206
205
|
if (selected.has(reference))
|
|
207
206
|
continue;
|
|
208
|
-
const document = await
|
|
207
|
+
const document = await readDebtDocument(world, reference);
|
|
209
208
|
if (document !== undefined)
|
|
210
209
|
selected.set(reference, document);
|
|
211
210
|
}
|
|
212
|
-
return projectOwnedDetailFacts({
|
|
211
|
+
return projectOwnedDetailFacts({ debts: selected }, id);
|
|
213
212
|
}
|
|
214
213
|
/** One board observation and predicate projection shared by the ready and blocked views. */
|
|
215
|
-
async function
|
|
214
|
+
async function readDebtQueryContext(input) {
|
|
216
215
|
const board = (await readBoard(input.world)).board;
|
|
217
|
-
if (input.parent !== undefined && !board.
|
|
218
|
-
return { kind: "refused", refusal: { kind: "
|
|
219
|
-
const relations =
|
|
216
|
+
if (input.parent !== undefined && !board.debts.has(input.parent))
|
|
217
|
+
return { kind: "refused", refusal: { kind: "debt-missing", debtId: input.parent } };
|
|
218
|
+
const relations = createDebtRelations(board);
|
|
220
219
|
const scope = readScope(input.namespace, input.scope);
|
|
221
220
|
const predicate = {
|
|
222
221
|
kind: "predicate",
|
|
@@ -236,15 +235,15 @@ async function readTaskQueryContext(input) {
|
|
|
236
235
|
},
|
|
237
236
|
};
|
|
238
237
|
}
|
|
239
|
-
export async function
|
|
240
|
-
const queried = await
|
|
238
|
+
export async function readyDebts(world, namespace, scope, parent, limit) {
|
|
239
|
+
const queried = await readDebtQueryContext({ world, field: "ready", namespace, scope, parent, limit });
|
|
241
240
|
if (queried.kind !== "accepted")
|
|
242
241
|
return queried;
|
|
243
242
|
const rows = queried.value.rows.map(({ parent: _parent, needs: _needs, blocks: _blocks, createdAt: _createdAt, ...row }) => row);
|
|
244
243
|
return { kind: "accepted", value: projectBoundedList(rows, queried.value.limit) };
|
|
245
244
|
}
|
|
246
|
-
export async function
|
|
247
|
-
const queried = await
|
|
245
|
+
export async function blockedDebts(world, namespace, scope, parent, limit) {
|
|
246
|
+
const queried = await readDebtQueryContext({ world, field: "blocked", namespace, scope, parent, limit });
|
|
248
247
|
if (queried.kind !== "accepted")
|
|
249
248
|
return queried;
|
|
250
249
|
const { board, scope: selected, relations, limit: selectedLimit, rows } = queried.value;
|
|
@@ -254,14 +253,14 @@ export async function blockedTasks(world, namespace, scope, parent, limit) {
|
|
|
254
253
|
value: projectBoundedList(projectBlocked(board, selected, relations).filter((row) => ids.has(row.id)), selectedLimit),
|
|
255
254
|
};
|
|
256
255
|
}
|
|
257
|
-
export async function
|
|
256
|
+
export async function queryDebts(input) {
|
|
258
257
|
const selectedLimit = boundedListLimit(input.limit);
|
|
259
258
|
const selected = readScope(input.namespace, input.scope);
|
|
260
259
|
const board = (await readBoard(input.world)).board;
|
|
261
|
-
const relations =
|
|
260
|
+
const relations = createDebtRelations(board);
|
|
262
261
|
for (const target of queryUnderTargets(input.expression))
|
|
263
|
-
if (!board.
|
|
264
|
-
return { kind: "refused", refusal: { kind: "
|
|
262
|
+
if (!board.debts.has(target)) {
|
|
263
|
+
return { kind: "refused", refusal: { kind: "debt-missing", debtId: target } };
|
|
265
264
|
}
|
|
266
265
|
return {
|
|
267
266
|
kind: "accepted",
|
|
@@ -273,6 +272,6 @@ export async function queryTasks(input) {
|
|
|
273
272
|
}),
|
|
274
273
|
};
|
|
275
274
|
}
|
|
276
|
-
export async function
|
|
277
|
-
return
|
|
275
|
+
export async function observeDebtBoard(world) {
|
|
276
|
+
return projectDebtBoardObservation((await readBoard(world)).board);
|
|
278
277
|
}
|