@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,203 @@
|
|
|
1
|
+
import { executionChannel, localExecutionContext } from "../akuma/requests.js";
|
|
2
|
+
import { requestForwardedDebt, } from "./mutation.js";
|
|
3
|
+
import { buildTree, createDebtRelations, diagnoseBoard, } from "./board.js";
|
|
4
|
+
import { DebtAuthorityCorruptionError } from "./document.js";
|
|
5
|
+
import { addDebt, addDebtDocument, batchDebts, blockedDebts, lifecycleDebt, listDebts, queryDebts, readDebtDetail, readyDebts, debtView, updateDebt, } from "./operations.js";
|
|
6
|
+
import { boundedListLimit } from "../bounded-list.js";
|
|
7
|
+
import { readBoard } from "./store.js";
|
|
8
|
+
import { actor, addInput, closed, namespace, record, signal, sort, debtId as id, debtIds, text, updateInput, } from "./input.js";
|
|
9
|
+
import { normalizeDebtQuery, debtQuerySelection, DEBT_RELATION_PREDICATE_FIELDS, } from "./query.js";
|
|
10
|
+
export { DebtAuthorityCorruptionError, DEBT_RELATION_PREDICATE_FIELDS };
|
|
11
|
+
export { observeRecentDebtStatus } from "./catalog.js";
|
|
12
|
+
export { boundedListLimit as debtRowViewLimit } from "../bounded-list.js";
|
|
13
|
+
function debtRoute(execution) {
|
|
14
|
+
const channel = executionChannel(execution);
|
|
15
|
+
return channel.kind === "body-request" ? { kind: "forwarded", directory: channel.directory } : { kind: "local" };
|
|
16
|
+
}
|
|
17
|
+
function forwardDebt(directory, world, request, signal) {
|
|
18
|
+
return requestForwardedDebt({
|
|
19
|
+
directory,
|
|
20
|
+
world,
|
|
21
|
+
request,
|
|
22
|
+
...(signal === undefined ? {} : { signal }),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** The single lifecycle request shapes, keyed once by verb instead of switched per handle. */
|
|
26
|
+
const SINGLE_LIFECYCLE = {
|
|
27
|
+
done: (id, note) => ({ action: "debt.done", id, ...(note === undefined ? {} : { note }) }),
|
|
28
|
+
drop: (id, note) => ({ action: "debt.drop", id, ...(note === undefined ? {} : { note }) }),
|
|
29
|
+
};
|
|
30
|
+
/** The batch lifecycle request shapes for the same verbs. */
|
|
31
|
+
const BATCH_LIFECYCLE = {
|
|
32
|
+
done: (ids, note) => ({ action: "debt.done", ids, ...(note === undefined ? {} : { note }) }),
|
|
33
|
+
drop: (ids, note) => ({ action: "debt.drop", ids, ...(note === undefined ? {} : { note }) }),
|
|
34
|
+
};
|
|
35
|
+
function debtOperations(world, route) {
|
|
36
|
+
if (route.kind === "forwarded") {
|
|
37
|
+
const { directory } = route;
|
|
38
|
+
return {
|
|
39
|
+
add: (values) => {
|
|
40
|
+
const { actor: _actor, signal, namespace: selected, ...request } = values;
|
|
41
|
+
return forwardDebt(directory, world, { action: "debt.add", input: { ...request, namespace: selected ?? [] } }, signal);
|
|
42
|
+
},
|
|
43
|
+
addDocument: (values) => forwardDebt(directory, world, { action: "debt.addDocument", input: { markdown: values.markdown, namespace: values.namespace ?? [] } }, values.signal),
|
|
44
|
+
update: (id, values) => {
|
|
45
|
+
const { signal, ...request } = values;
|
|
46
|
+
return forwardDebt(directory, world, { action: "debt.update", id, input: request }, signal);
|
|
47
|
+
},
|
|
48
|
+
lifecycle: (id, verb, note, signal) => forwardDebt(directory, world, SINGLE_LIFECYCLE[verb](id, note), signal),
|
|
49
|
+
batch: (verb, ids, note, signal) => forwardDebt(directory, world, BATCH_LIFECYCLE[verb](ids, note), signal),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
add: (values) => addDebt(world, values),
|
|
54
|
+
addDocument: (values) => addDebtDocument(world, values),
|
|
55
|
+
update: (id, values) => updateDebt(world, id, values),
|
|
56
|
+
lifecycle: (id, verb, note, signal) => lifecycleDebt(world, id, verb, signal, note),
|
|
57
|
+
batch: (verb, ids, note, signal) => batchDebts(world, verb, ids, signal, note),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
class DebtHandle {
|
|
61
|
+
id;
|
|
62
|
+
world;
|
|
63
|
+
operations;
|
|
64
|
+
constructor(id, world, operations) {
|
|
65
|
+
this.id = id;
|
|
66
|
+
this.world = world;
|
|
67
|
+
this.operations = operations;
|
|
68
|
+
}
|
|
69
|
+
async read() {
|
|
70
|
+
const facts = await readDebtDetail(this.world, this.id);
|
|
71
|
+
return facts === null ? null : { ...facts, debt: debtView(facts.debt) };
|
|
72
|
+
}
|
|
73
|
+
async tree() {
|
|
74
|
+
if (arguments.length > 0)
|
|
75
|
+
throw new TypeError("tree accepts no input");
|
|
76
|
+
const board = (await readBoard(this.world)).board;
|
|
77
|
+
const node = buildTree(board, this.id, createDebtRelations(board));
|
|
78
|
+
return node === null
|
|
79
|
+
? { kind: "refused", refusal: { kind: "debt-missing", debtId: this.id } }
|
|
80
|
+
: { kind: "accepted", value: node };
|
|
81
|
+
}
|
|
82
|
+
update(input) {
|
|
83
|
+
return this.operations.update(this.id, updateInput(input));
|
|
84
|
+
}
|
|
85
|
+
lifecycle(verb, input) {
|
|
86
|
+
const value = record(input ?? {}, `${verb} input`);
|
|
87
|
+
closed(value, ["note", "signal"], `${verb} input`);
|
|
88
|
+
const note = text(value.note, "note");
|
|
89
|
+
return this.operations.lifecycle(this.id, verb, note, signal(value.signal));
|
|
90
|
+
}
|
|
91
|
+
done(input) {
|
|
92
|
+
return this.lifecycle("done", input);
|
|
93
|
+
}
|
|
94
|
+
drop(input) {
|
|
95
|
+
return this.lifecycle("drop", input);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
class DebtsHandle {
|
|
99
|
+
world;
|
|
100
|
+
root;
|
|
101
|
+
operations;
|
|
102
|
+
constructor(world, execution) {
|
|
103
|
+
this.world = world;
|
|
104
|
+
this.root = world;
|
|
105
|
+
this.operations = debtOperations(world, debtRoute(execution));
|
|
106
|
+
}
|
|
107
|
+
debt(input) {
|
|
108
|
+
const v = record(input, "debt input");
|
|
109
|
+
closed(v, ["id"], "debt input");
|
|
110
|
+
return new DebtHandle(id(v.id), this.world, this.operations);
|
|
111
|
+
}
|
|
112
|
+
add(input) {
|
|
113
|
+
return this.operations.add(addInput(input));
|
|
114
|
+
}
|
|
115
|
+
addDocument(input) {
|
|
116
|
+
const v = record(input, "addDocument input");
|
|
117
|
+
closed(v, ["markdown", "namespace", "actor", "signal"], "addDocument input");
|
|
118
|
+
const markdown = text(v.markdown, "markdown");
|
|
119
|
+
if (markdown === undefined)
|
|
120
|
+
throw new TypeError("markdown is required");
|
|
121
|
+
const ns = namespace(v.namespace), createdBy = actor(v.actor), abort = signal(v.signal);
|
|
122
|
+
return this.operations.addDocument({
|
|
123
|
+
markdown,
|
|
124
|
+
...(ns === undefined ? {} : { namespace: ns }),
|
|
125
|
+
...(createdBy === undefined ? {} : { actor: createdBy }),
|
|
126
|
+
...(abort === undefined ? {} : { signal: abort }),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async list(input = {}) {
|
|
130
|
+
const v = record(input, "list input");
|
|
131
|
+
closed(v, ["selection", "scope", "namespace", "limit"], "list input");
|
|
132
|
+
if (v.selection !== undefined && v.selection !== "active" && v.selection !== "closed" && v.selection !== "all")
|
|
133
|
+
throw new TypeError("selection must be active, closed, or all");
|
|
134
|
+
if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
135
|
+
throw new TypeError("scope must be namespace or world");
|
|
136
|
+
const selectedLimit = boundedListLimit(v.limit);
|
|
137
|
+
return listDebts(this.world, namespace(v.namespace), v.selection ?? "active", v.scope, selectedLimit);
|
|
138
|
+
}
|
|
139
|
+
async ready(input = {}) {
|
|
140
|
+
const v = record(input, "ready input");
|
|
141
|
+
closed(v, ["scope", "namespace", "parent", "limit"], "ready input");
|
|
142
|
+
if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
143
|
+
throw new TypeError("scope must be namespace or world");
|
|
144
|
+
const parent = v.parent === undefined ? undefined : id(v.parent);
|
|
145
|
+
const selectedLimit = boundedListLimit(v.limit);
|
|
146
|
+
return readyDebts(this.world, namespace(v.namespace), v.scope, parent, selectedLimit);
|
|
147
|
+
}
|
|
148
|
+
async blocked(input = {}) {
|
|
149
|
+
const v = record(input, "blocked input");
|
|
150
|
+
closed(v, ["scope", "namespace", "parent", "limit"], "blocked input");
|
|
151
|
+
if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
152
|
+
throw new TypeError("scope must be namespace or world");
|
|
153
|
+
const parent = v.parent === undefined ? undefined : id(v.parent);
|
|
154
|
+
const selectedLimit = boundedListLimit(v.limit);
|
|
155
|
+
return blockedDebts(this.world, namespace(v.namespace), v.scope, parent, selectedLimit);
|
|
156
|
+
}
|
|
157
|
+
async query(input = {}) {
|
|
158
|
+
const v = record(input, "query input");
|
|
159
|
+
closed(v, ["where", "scope", "namespace", "sort", "limit"], "query input");
|
|
160
|
+
if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
|
|
161
|
+
throw new TypeError("scope must be namespace or world");
|
|
162
|
+
const expression = v.where === undefined ? debtQuerySelection() : normalizeDebtQuery(v.where);
|
|
163
|
+
const selected = namespace(v.namespace);
|
|
164
|
+
const selectedLimit = boundedListLimit(v.limit);
|
|
165
|
+
return queryDebts({
|
|
166
|
+
world: this.world,
|
|
167
|
+
...(selected === undefined ? {} : { namespace: selected }),
|
|
168
|
+
expression,
|
|
169
|
+
...(v.scope === undefined ? {} : { scope: v.scope }),
|
|
170
|
+
sort: sort(v.sort) ?? "priority",
|
|
171
|
+
limit: selectedLimit,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
async doctor() {
|
|
175
|
+
return { issues: diagnoseBoard((await readBoard(this.world)).board) };
|
|
176
|
+
}
|
|
177
|
+
batch(input) {
|
|
178
|
+
const v = record(input, "batch input");
|
|
179
|
+
closed(v, ["verb", "ids", "note", "signal"], "batch input");
|
|
180
|
+
const verb = v.verb;
|
|
181
|
+
if (verb !== "done" && verb !== "drop")
|
|
182
|
+
throw new TypeError("batch verb is invalid");
|
|
183
|
+
const ids = debtIds(v.ids, "ids");
|
|
184
|
+
if (ids === undefined || ids.length === 0)
|
|
185
|
+
throw new TypeError("ids requires at least one DebtId");
|
|
186
|
+
const note = text(v.note, "note");
|
|
187
|
+
return this.operations.batch(verb, ids, note, signal(v.signal));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The one Debts composition. Public `of` fixes local execution; CLI and Body pass their captured
|
|
192
|
+
* internal channel through `debtsWithExecution` instead of a second constructor.
|
|
193
|
+
*/
|
|
194
|
+
export function debtsWithExecution(world, execution) {
|
|
195
|
+
if (typeof world !== "string")
|
|
196
|
+
throw new TypeError("Debts.of world must be a WorldRoot");
|
|
197
|
+
return new DebtsHandle(world, execution);
|
|
198
|
+
}
|
|
199
|
+
export const Debts = Object.freeze({
|
|
200
|
+
of(world) {
|
|
201
|
+
return debtsWithExecution(world, localExecutionContext());
|
|
202
|
+
},
|
|
203
|
+
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import { type DebtId } from "./identity.js";
|
|
2
|
+
import type { AddDebtInput, UpdateDebtInput } from "./operations.js";
|
|
3
|
+
import type { DebtQuerySort } from "./query.js";
|
|
4
4
|
export declare function record(value: unknown, label: string): Record<string, unknown>;
|
|
5
5
|
export declare function closed(value: Record<string, unknown>, allowed: readonly string[], label: string): void;
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function debtId(value: unknown): DebtId;
|
|
7
7
|
export declare function signal(value: unknown): AbortSignal | undefined;
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function debtIds(value: unknown, label: string): readonly DebtId[] | undefined;
|
|
9
9
|
export declare function namespace(value: unknown): readonly string[] | undefined;
|
|
10
10
|
export declare function text(value: unknown, label: string): string | undefined;
|
|
11
11
|
export declare function actor(value: unknown): string | undefined;
|
|
12
|
-
export declare function sort(value: unknown):
|
|
13
|
-
export declare function addInput(input: unknown):
|
|
14
|
-
export declare function updateInput(input: unknown):
|
|
12
|
+
export declare function sort(value: unknown): DebtQuerySort | undefined;
|
|
13
|
+
export declare function addInput(input: unknown): AddDebtInput;
|
|
14
|
+
export declare function updateInput(input: unknown): UpdateDebtInput;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDebtSegment, parseDebtId } from "./identity.js";
|
|
2
2
|
export function record(value, label) {
|
|
3
3
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4
4
|
throw new TypeError(`${label} must be an object`);
|
|
@@ -11,10 +11,10 @@ export function closed(value, allowed, label) {
|
|
|
11
11
|
throw new TypeError(`${label} has unknown field: ${key}`);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
export function
|
|
14
|
+
export function debtId(value) {
|
|
15
15
|
if (typeof value !== "string")
|
|
16
|
-
throw new TypeError("
|
|
17
|
-
|
|
16
|
+
throw new TypeError("debt ID must be a string");
|
|
17
|
+
parseDebtId(value);
|
|
18
18
|
return value;
|
|
19
19
|
}
|
|
20
20
|
export function signal(value) {
|
|
@@ -32,8 +32,8 @@ function strings(value, label) {
|
|
|
32
32
|
}
|
|
33
33
|
return value;
|
|
34
34
|
}
|
|
35
|
-
export function
|
|
36
|
-
const values = strings(value, label)?.map(
|
|
35
|
+
export function debtIds(value, label) {
|
|
36
|
+
const values = strings(value, label)?.map(debtId);
|
|
37
37
|
if (values !== undefined && new Set(values).size !== values.length) {
|
|
38
38
|
throw new TypeError(`${label} must not contain duplicates`);
|
|
39
39
|
}
|
|
@@ -43,7 +43,7 @@ export function namespace(value) {
|
|
|
43
43
|
const values = strings(value, "namespace");
|
|
44
44
|
if (values === undefined)
|
|
45
45
|
return undefined;
|
|
46
|
-
if (!values.every(
|
|
46
|
+
if (!values.every(isDebtSegment))
|
|
47
47
|
throw new TypeError("namespace must contain canonical segments");
|
|
48
48
|
return values;
|
|
49
49
|
}
|
|
@@ -81,13 +81,13 @@ export function sort(value) {
|
|
|
81
81
|
function state(value) {
|
|
82
82
|
if (value === undefined)
|
|
83
83
|
return undefined;
|
|
84
|
-
if (value !== "open" && value !== "
|
|
84
|
+
if (value !== "open" && value !== "done" && value !== "drop") {
|
|
85
85
|
throw new TypeError("state is invalid");
|
|
86
86
|
}
|
|
87
87
|
return value;
|
|
88
88
|
}
|
|
89
89
|
function nullableId(value) {
|
|
90
|
-
return value === undefined || value === null ? value :
|
|
90
|
+
return value === undefined || value === null ? value : debtId(value);
|
|
91
91
|
}
|
|
92
92
|
export function addInput(input) {
|
|
93
93
|
const value = record(input, "add input");
|
|
@@ -113,10 +113,10 @@ export function addInput(input) {
|
|
|
113
113
|
const note = text(value.note, "note");
|
|
114
114
|
const initialState = state(value.state);
|
|
115
115
|
const selectedPriority = priority(value.priority);
|
|
116
|
-
const needs =
|
|
116
|
+
const needs = debtIds(value.needs, "needs");
|
|
117
117
|
const parent = nullableId(value.parent);
|
|
118
|
-
const supersedes =
|
|
119
|
-
const relates =
|
|
118
|
+
const supersedes = debtIds(value.supersedes, "supersedes");
|
|
119
|
+
const relates = debtIds(value.relates, "relates");
|
|
120
120
|
const createdBy = actor(value.actor);
|
|
121
121
|
const abort = signal(value.signal);
|
|
122
122
|
return {
|
|
@@ -177,15 +177,15 @@ export function updateInput(input) {
|
|
|
177
177
|
if (selectedPriority !== undefined)
|
|
178
178
|
result.priority = selectedPriority;
|
|
179
179
|
for (const [key, ids] of [
|
|
180
|
-
["needs",
|
|
181
|
-
["addNeeds",
|
|
182
|
-
["dropNeeds",
|
|
183
|
-
["supersedes",
|
|
184
|
-
["addSupersedes",
|
|
185
|
-
["dropSupersedes",
|
|
186
|
-
["relates",
|
|
187
|
-
["addRelates",
|
|
188
|
-
["dropRelates",
|
|
180
|
+
["needs", debtIds(value.needs, "needs")],
|
|
181
|
+
["addNeeds", debtIds(value.addNeeds, "addNeeds")],
|
|
182
|
+
["dropNeeds", debtIds(value.dropNeeds, "dropNeeds")],
|
|
183
|
+
["supersedes", debtIds(value.supersedes, "supersedes")],
|
|
184
|
+
["addSupersedes", debtIds(value.addSupersedes, "addSupersedes")],
|
|
185
|
+
["dropSupersedes", debtIds(value.dropSupersedes, "dropSupersedes")],
|
|
186
|
+
["relates", debtIds(value.relates, "relates")],
|
|
187
|
+
["addRelates", debtIds(value.addRelates, "addRelates")],
|
|
188
|
+
["dropRelates", debtIds(value.dropRelates, "dropRelates")],
|
|
189
189
|
])
|
|
190
190
|
if (ids !== undefined)
|
|
191
191
|
result[key] = ids;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type SettledDebtResult, type DebtBatchResult, type DebtLifecycleVerb, type DebtMutationResult } from "./operation-types.js";
|
|
2
|
+
import type { DebtId } from "./identity.js";
|
|
3
|
+
import type { WorldRoot } from "../world.js";
|
|
4
|
+
export declare function lifecycleDebt(world: WorldRoot, id: DebtId, verb: DebtLifecycleVerb, signal?: AbortSignal, note?: string): Promise<DebtMutationResult>;
|
|
5
|
+
export declare function batchDebts(world: WorldRoot, verb: DebtLifecycleVerb, ids: readonly DebtId[], signal?: AbortSignal, note?: string): Promise<DebtBatchResult>;
|
|
6
|
+
export declare function settleDebt(world: WorldRoot, id: DebtId): Promise<SettledDebtResult>;
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { authorityBytesMatch, readBoard, replaceAuthority,
|
|
3
|
-
import {
|
|
1
|
+
import { serializeDebtDocument } from "./document.js";
|
|
2
|
+
import { authorityBytesMatch, readBoard, replaceAuthority, withDebtLocks } from "./store.js";
|
|
3
|
+
import { advanceDebtTimestamp, debtView } from "./view.js";
|
|
4
4
|
const TRANSITIONS = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
hold: { open: "on_hold", in_progress: "on_hold" },
|
|
8
|
-
resume: { on_hold: "open" },
|
|
9
|
-
done: { open: "done", in_progress: "done", on_hold: "done" },
|
|
10
|
-
drop: { open: "drop", in_progress: "drop", on_hold: "drop" },
|
|
5
|
+
done: { open: "done" },
|
|
6
|
+
drop: { open: "drop" },
|
|
11
7
|
};
|
|
12
|
-
function
|
|
8
|
+
function currentDebtBoard(board, bytes) {
|
|
13
9
|
return { board, bytes: new Map(bytes) };
|
|
14
10
|
}
|
|
15
11
|
function retry(reason) {
|
|
@@ -17,26 +13,26 @@ function retry(reason) {
|
|
|
17
13
|
}
|
|
18
14
|
async function transitionLifecycle(world, id, verb, currentBoard, options = {}) {
|
|
19
15
|
const { note, freshness = "none" } = options;
|
|
20
|
-
const current = currentBoard.board.
|
|
16
|
+
const current = currentBoard.board.debts.get(id);
|
|
21
17
|
if (current === undefined) {
|
|
22
18
|
return freshness === "batch" && !(await authorityBytesMatch(world, id, null))
|
|
23
19
|
? retry("concurrent-modification")
|
|
24
|
-
: { kind: "refused", refusal: { kind: "
|
|
20
|
+
: { kind: "refused", refusal: { kind: "debt-missing", debtId: id } };
|
|
25
21
|
}
|
|
26
22
|
const state = TRANSITIONS[verb][current.state];
|
|
27
23
|
if (state === undefined) {
|
|
28
24
|
return freshness === "batch" && !(await authorityBytesMatch(world, id, currentBoard.bytes.get(id)))
|
|
29
25
|
? retry("concurrent-modification")
|
|
30
|
-
: { kind: "refused", refusal: { kind: "invalid-lifecycle-transition",
|
|
26
|
+
: { kind: "refused", refusal: { kind: "invalid-lifecycle-transition", debtId: id, state: current.state, verb } };
|
|
31
27
|
}
|
|
32
28
|
const at = new Date().toISOString();
|
|
33
29
|
const next = {
|
|
34
30
|
...current,
|
|
35
31
|
state,
|
|
36
32
|
...(note === undefined ? {} : { note }),
|
|
37
|
-
updatedAt:
|
|
33
|
+
updatedAt: advanceDebtTimestamp(current.updatedAt, at),
|
|
38
34
|
};
|
|
39
|
-
const bytes =
|
|
35
|
+
const bytes = serializeDebtDocument(next);
|
|
40
36
|
if ((await replaceAuthority({
|
|
41
37
|
world,
|
|
42
38
|
id,
|
|
@@ -46,31 +42,31 @@ async function transitionLifecycle(world, id, verb, currentBoard, options = {})
|
|
|
46
42
|
return retry("concurrent-modification");
|
|
47
43
|
}
|
|
48
44
|
currentBoard.board = {
|
|
49
|
-
|
|
45
|
+
debts: new Map(currentBoard.board.debts).set(id, next),
|
|
50
46
|
};
|
|
51
47
|
currentBoard.bytes.set(id, bytes);
|
|
52
|
-
return { kind: "accepted", value:
|
|
48
|
+
return { kind: "accepted", value: debtView(next) };
|
|
53
49
|
}
|
|
54
50
|
async function lifecycleFromCurrentBoard(world, id, verb, currentBoard, options = {}) {
|
|
55
51
|
const { signal, note } = options;
|
|
56
|
-
const result = await
|
|
52
|
+
const result = await withDebtLocks({ world, allocation: false, ids: [id], ...(signal === undefined ? {} : { signal }) }, async () => transitionLifecycle(world, id, verb, currentBoard, {
|
|
57
53
|
freshness: "batch",
|
|
58
54
|
...(note === undefined ? {} : { note }),
|
|
59
55
|
}));
|
|
60
56
|
return result === "busy" ? retry("busy") : result;
|
|
61
57
|
}
|
|
62
|
-
export async function
|
|
63
|
-
const result = await
|
|
58
|
+
export async function lifecycleDebt(world, id, verb, signal, note) {
|
|
59
|
+
const result = await withDebtLocks({ world, allocation: false, ids: [id], ...(signal === undefined ? {} : { signal }) }, async () => {
|
|
64
60
|
const snapshot = await readBoard(world);
|
|
65
61
|
const options = note === undefined ? {} : { note };
|
|
66
|
-
return transitionLifecycle(world, id, verb,
|
|
62
|
+
return transitionLifecycle(world, id, verb, currentDebtBoard(snapshot.board, snapshot.bytes), options);
|
|
67
63
|
});
|
|
68
64
|
return result === "busy" ? retry("busy") : result;
|
|
69
65
|
}
|
|
70
|
-
export async function
|
|
66
|
+
export async function batchDebts(world, verb, ids, signal, note) {
|
|
71
67
|
signal?.throwIfAborted();
|
|
72
68
|
const snapshot = await readBoard(world);
|
|
73
|
-
const currentBoard =
|
|
69
|
+
const currentBoard = currentDebtBoard(snapshot.board, snapshot.bytes);
|
|
74
70
|
const items = [];
|
|
75
71
|
for (const id of ids) {
|
|
76
72
|
signal?.throwIfAborted();
|
|
@@ -84,32 +80,32 @@ export async function batchTasks(world, verb, ids, signal, note) {
|
|
|
84
80
|
}
|
|
85
81
|
return { items };
|
|
86
82
|
}
|
|
87
|
-
export async function
|
|
88
|
-
const result = await
|
|
89
|
-
const snapshot = await readBoard(world), current = snapshot.board.
|
|
83
|
+
export async function settleDebt(world, id) {
|
|
84
|
+
const result = await withDebtLocks({ world, allocation: false, ids: [id] }, async () => {
|
|
85
|
+
const snapshot = await readBoard(world), current = snapshot.board.debts.get(id);
|
|
90
86
|
if (current === undefined)
|
|
91
|
-
return { kind: "refused", refusal: { kind: "
|
|
87
|
+
return { kind: "refused", refusal: { kind: "debt-missing", debtId: id } };
|
|
92
88
|
if (current.state === "done")
|
|
93
89
|
return { kind: "unchanged" };
|
|
94
90
|
if (current.state === "drop") {
|
|
95
91
|
return {
|
|
96
92
|
kind: "refused",
|
|
97
|
-
refusal: { kind: "invalid-lifecycle-transition",
|
|
93
|
+
refusal: { kind: "invalid-lifecycle-transition", debtId: id, state: current.state, verb: "done" },
|
|
98
94
|
};
|
|
99
95
|
}
|
|
100
96
|
const next = {
|
|
101
97
|
...current,
|
|
102
98
|
state: "done",
|
|
103
|
-
updatedAt:
|
|
99
|
+
updatedAt: advanceDebtTimestamp(current.updatedAt, new Date().toISOString()),
|
|
104
100
|
};
|
|
105
101
|
const replaced = await replaceAuthority({
|
|
106
102
|
world,
|
|
107
103
|
id,
|
|
108
104
|
expected: snapshot.bytes.get(id),
|
|
109
|
-
next:
|
|
105
|
+
next: serializeDebtDocument(next),
|
|
110
106
|
});
|
|
111
107
|
return replaced === "replaced"
|
|
112
|
-
? { kind: "changed",
|
|
108
|
+
? { kind: "changed", debt: debtView(next), action: "done" }
|
|
113
109
|
: { kind: "retry", reason: "concurrent-modification" };
|
|
114
110
|
});
|
|
115
111
|
return result === "busy" ? { kind: "retry", reason: "busy" } : result;
|