@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
package/build/src/kanshi/read.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { Tasks } from "../task/index.js";
|
|
1
|
+
import { Repo } from "../library/repo.js";
|
|
2
|
+
import { scopeForRepo } from "../library/repo.js";
|
|
3
|
+
import { observeTaskStatusRows } from "../task/operations.js";
|
|
5
4
|
import { Akuma } from "../akuma/index.js";
|
|
5
|
+
import { readAliases } from "../alias/index.js";
|
|
6
|
+
import { readDispatchesAt } from "../dispatch/index.js";
|
|
7
|
+
import { readTaskHolderProjectionAt } from "../settlement/holder.js";
|
|
8
|
+
import { readContractBoard } from "../protocol/read/status.js";
|
|
9
|
+
import { withGitDecodeChannel, withGitReadObservation } from "../git/read-observation.js";
|
|
10
|
+
import { readDocuments } from "../protocol/read/documents.js";
|
|
11
|
+
import { readRegionDeclarations, validateRegionPath } from "../library/region.js";
|
|
12
|
+
import { contractId } from "../core/facts/types.js";
|
|
13
|
+
import { selectRegion } from "./select.js";
|
|
6
14
|
function diagnostic(error) {
|
|
7
15
|
let source;
|
|
8
16
|
if (error instanceof Error)
|
|
@@ -20,81 +28,273 @@ function diagnostic(error) {
|
|
|
20
28
|
const line = source.replaceAll(/\s+/gu, " ").trim();
|
|
21
29
|
return line.length <= 240 ? line : `${line.slice(0, 239)}…`;
|
|
22
30
|
}
|
|
31
|
+
function record(value, label) {
|
|
32
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
33
|
+
throw new TypeError(`kanshi ${label} must be an object`);
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
function exactKeys(value, allowed, label) {
|
|
37
|
+
for (const key of Object.keys(value))
|
|
38
|
+
if (!allowed.includes(key))
|
|
39
|
+
throw new TypeError(`kanshi ${label} has unknown field: ${key}`);
|
|
40
|
+
}
|
|
41
|
+
function regionSelection(value) {
|
|
42
|
+
const selection = record(value, "region selection");
|
|
43
|
+
if (typeof selection.kind !== "string")
|
|
44
|
+
throw new TypeError("kanshi region selection kind must be a string");
|
|
45
|
+
if (selection.kind === "declarations") {
|
|
46
|
+
exactKeys(selection, ["kind"], "region selection");
|
|
47
|
+
return { kind: "declarations" };
|
|
48
|
+
}
|
|
49
|
+
if (selection.kind === "contract") {
|
|
50
|
+
exactKeys(selection, ["kind", "contract"], "region selection");
|
|
51
|
+
if (typeof selection.contract !== "string")
|
|
52
|
+
throw new TypeError("kanshi region contract must be a ContractId");
|
|
53
|
+
try {
|
|
54
|
+
return { kind: "contract", contract: contractId(selection.contract) };
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new TypeError("kanshi region contract must be a canonical ContractId");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (selection.kind === "overlap") {
|
|
61
|
+
exactKeys(selection, ["kind", "contract"], "region selection");
|
|
62
|
+
if (selection.contract === undefined)
|
|
63
|
+
return { kind: "overlap" };
|
|
64
|
+
if (typeof selection.contract !== "string")
|
|
65
|
+
throw new TypeError("kanshi region contract must be a ContractId");
|
|
66
|
+
try {
|
|
67
|
+
return { kind: "overlap", contract: contractId(selection.contract) };
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new TypeError("kanshi region contract must be a canonical ContractId");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (selection.kind === "path") {
|
|
74
|
+
exactKeys(selection, ["kind", "path"], "region selection");
|
|
75
|
+
try {
|
|
76
|
+
validateRegionPath(selection.path);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw new TypeError(error instanceof Error ? error.message : String(error));
|
|
80
|
+
}
|
|
81
|
+
return { kind: "path", path: selection.path };
|
|
82
|
+
}
|
|
83
|
+
throw new TypeError(`kanshi region selection kind is invalid: ${selection.kind}`);
|
|
84
|
+
}
|
|
23
85
|
function coordinate(input) {
|
|
24
|
-
if (input === undefined)
|
|
25
|
-
return process.cwd();
|
|
26
86
|
if (typeof input !== "object" || input === null || Array.isArray(input))
|
|
27
87
|
throw new TypeError("kanshi input must be an object");
|
|
28
88
|
for (const key of Object.keys(input))
|
|
29
|
-
if (key !== "
|
|
89
|
+
if (key !== "world" && key !== "repo" && key !== "region")
|
|
30
90
|
throw new TypeError(`kanshi input has unknown field: ${key}`);
|
|
31
|
-
if (input.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
91
|
+
if (input.world !== null && (typeof input.world !== "string" || input.world.trim().length === 0)) {
|
|
92
|
+
throw new TypeError("kanshi world must be a WorldRoot or null");
|
|
93
|
+
}
|
|
94
|
+
if (input.repo !== undefined && !(input.repo instanceof Repo))
|
|
95
|
+
throw new TypeError("kanshi repo must be a Repo");
|
|
96
|
+
return input.region === undefined ? input : { ...input, region: regionSelection(input.region) };
|
|
36
97
|
}
|
|
37
|
-
async function
|
|
98
|
+
async function readRegion(observation, selection) {
|
|
38
99
|
try {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return { repo, section: { kind: "present", value: await listKeiyaku({ repo }) } };
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
return { repo, section: { kind: "failed", failure: { message: diagnostic(error) } } };
|
|
45
|
-
}
|
|
100
|
+
const declarations = [...readRegionDeclarations(await readDocuments(observation))].sort((left, right) => left.contract.localeCompare(right.contract));
|
|
101
|
+
return { kind: "present", value: selectRegion({ declarations, selection }) };
|
|
46
102
|
}
|
|
47
103
|
catch (error) {
|
|
48
|
-
return {
|
|
49
|
-
|
|
50
|
-
|
|
104
|
+
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function readBranch(repo) {
|
|
108
|
+
if (repo === undefined)
|
|
109
|
+
return null;
|
|
110
|
+
try {
|
|
111
|
+
return await repo.currentBranch();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function readContracts(observation) {
|
|
118
|
+
try {
|
|
119
|
+
return { kind: "present", value: await readContractBoard(observation) };
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function readHolders(observation) {
|
|
126
|
+
try {
|
|
127
|
+
return { kind: "present", value: await readTaskHolderProjectionAt(observation) };
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function attachFleet(contracts, akuma) {
|
|
134
|
+
if (contracts.kind !== "present")
|
|
135
|
+
return contracts;
|
|
136
|
+
const attachments = new Map();
|
|
137
|
+
if (akuma.kind === "present") {
|
|
138
|
+
for (const row of akuma.value.rows) {
|
|
139
|
+
if (row.contract === undefined)
|
|
140
|
+
continue;
|
|
141
|
+
const current = attachments.get(row.contract.id) ?? [];
|
|
142
|
+
current.push({ id: row.id, aliases: row.aliases });
|
|
143
|
+
attachments.set(row.contract.id, current);
|
|
144
|
+
}
|
|
51
145
|
}
|
|
146
|
+
return {
|
|
147
|
+
kind: "present",
|
|
148
|
+
value: {
|
|
149
|
+
...contracts.value,
|
|
150
|
+
rows: contracts.value.rows.map((row) => ({ ...row, fleet: attachments.get(row.id) ?? [] })),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function decorateContracts(contracts, holders) {
|
|
155
|
+
if (contracts.kind !== "present")
|
|
156
|
+
return contracts;
|
|
157
|
+
return {
|
|
158
|
+
kind: "present",
|
|
159
|
+
value: {
|
|
160
|
+
...contracts.value,
|
|
161
|
+
rows: contracts.value.rows.map((row) => {
|
|
162
|
+
if (holders.kind === "failed")
|
|
163
|
+
return { ...row, holder: { kind: "unavailable" }, fleet: [] };
|
|
164
|
+
const holder = holders.kind === "present" ? holders.value.get(row.id) : undefined;
|
|
165
|
+
return {
|
|
166
|
+
...row,
|
|
167
|
+
fleet: [],
|
|
168
|
+
holder: holder?.disposition === "held"
|
|
169
|
+
? { kind: "held", taskId: holder.taskId }
|
|
170
|
+
: { kind: "none" },
|
|
171
|
+
};
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
};
|
|
52
175
|
}
|
|
53
|
-
function
|
|
176
|
+
function contractEndpointObserver(contracts) {
|
|
54
177
|
const dispositions = contracts.kind === "present"
|
|
55
178
|
? new Map(contracts.value.rows.map((row) => [row.id, row.disposition]))
|
|
56
179
|
: null;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
180
|
+
return (id) => dispositions === null ? "unavailable" : dispositions.get(id) ?? "missing";
|
|
181
|
+
}
|
|
182
|
+
function joinTasks(rows, holders, observeContract) {
|
|
183
|
+
const associations = new Map(holders.kind === "present"
|
|
184
|
+
? [...holders.value.values()]
|
|
185
|
+
.filter((holder) => holder.disposition === "held")
|
|
186
|
+
.map((holder) => [holder.taskId, holder.contractId])
|
|
187
|
+
: []);
|
|
60
188
|
return rows.map((row) => {
|
|
61
189
|
const contractId = associations.get(row.id);
|
|
62
190
|
if (contractId === undefined)
|
|
63
191
|
return row;
|
|
64
|
-
|
|
65
|
-
? "unavailable"
|
|
66
|
-
: dispositions?.get(contractId) ?? "missing";
|
|
67
|
-
return { ...row, contract: { id: contractId, observed } };
|
|
192
|
+
return { ...row, contract: { id: contractId, observed: observeContract(contractId) } };
|
|
68
193
|
});
|
|
69
194
|
}
|
|
70
|
-
async function readTasks(path,
|
|
195
|
+
async function readTasks(path, holders, observeContract) {
|
|
196
|
+
if (holders.kind === "failed")
|
|
197
|
+
return { kind: "failed", failure: holders.failure };
|
|
198
|
+
try {
|
|
199
|
+
return {
|
|
200
|
+
kind: "present",
|
|
201
|
+
value: { root: path, rows: joinTasks(await observeTaskStatusRows(path), holders, observeContract) },
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async function joinAkuma(path, observeContract, dispatches) {
|
|
71
209
|
try {
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
210
|
+
const source = await Akuma.of(path).list();
|
|
211
|
+
const aliases = await readAliases(path);
|
|
212
|
+
const aliasById = new Map();
|
|
213
|
+
for (const binding of aliases)
|
|
214
|
+
aliasById.set(binding.akuId, [...(aliasById.get(binding.akuId) ?? []), binding]);
|
|
215
|
+
const dispatchById = new Map(dispatches.map((dispatch) => [dispatch.akuId, dispatch]));
|
|
76
216
|
return {
|
|
77
217
|
kind: "present",
|
|
78
|
-
value: {
|
|
218
|
+
value: {
|
|
219
|
+
...source,
|
|
220
|
+
rows: source.rows.map((row) => {
|
|
221
|
+
const dispatch = dispatchById.get(row.id);
|
|
222
|
+
return {
|
|
223
|
+
...row,
|
|
224
|
+
aliases: (aliasById.get(row.id) ?? []).map((binding) => binding.alias),
|
|
225
|
+
...(dispatch === undefined ? {} : {
|
|
226
|
+
contract: {
|
|
227
|
+
id: dispatch.contractId,
|
|
228
|
+
observed: observeContract(dispatch.contractId),
|
|
229
|
+
},
|
|
230
|
+
}),
|
|
231
|
+
};
|
|
232
|
+
}),
|
|
233
|
+
},
|
|
79
234
|
};
|
|
80
235
|
}
|
|
81
236
|
catch (error) {
|
|
82
237
|
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
83
238
|
}
|
|
84
239
|
}
|
|
85
|
-
function
|
|
240
|
+
async function readDispatches(observation) {
|
|
86
241
|
try {
|
|
87
|
-
|
|
88
|
-
return { kind: "present", value: source };
|
|
242
|
+
return { kind: "present", value: await readDispatchesAt(observation) };
|
|
89
243
|
}
|
|
90
244
|
catch (error) {
|
|
91
245
|
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
92
246
|
}
|
|
93
247
|
}
|
|
94
248
|
export async function kanshi(input) {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
249
|
+
const observedAt = new Date().toISOString();
|
|
250
|
+
const { world, repo } = coordinate(input);
|
|
251
|
+
const branch = await readBranch(repo);
|
|
252
|
+
if (repo === undefined) {
|
|
253
|
+
const contracts = { kind: "absent" };
|
|
254
|
+
const holders = { kind: "absent" };
|
|
255
|
+
const observeContract = contractEndpointObserver(contracts);
|
|
256
|
+
const tasks = world === null ? { kind: "absent" } : await readTasks(world, holders, observeContract);
|
|
257
|
+
const akuma = world === null ? { kind: "absent" } : await joinAkuma(world, observeContract, []);
|
|
258
|
+
return { root: world, observedAt, branch, contracts, tasks, akuma, ...(input.region === undefined ? {} : { region: { kind: "absent" } }) };
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const repository = scopeForRepo(repo);
|
|
262
|
+
return await withGitDecodeChannel(repository, (channel) => withGitReadObservation(repository, channel, async (observation) => {
|
|
263
|
+
const [contractSection, holders, dispatches, region] = await Promise.all([
|
|
264
|
+
readContracts(observation),
|
|
265
|
+
readHolders(observation),
|
|
266
|
+
readDispatches(observation),
|
|
267
|
+
input.region === undefined ? Promise.resolve(undefined) : readRegion(observation, input.region),
|
|
268
|
+
]);
|
|
269
|
+
const contracts = decorateContracts(contractSection, holders);
|
|
270
|
+
const observeContract = contractEndpointObserver(contracts);
|
|
271
|
+
const tasks = world === null ? { kind: "absent" } : await readTasks(world, holders, observeContract);
|
|
272
|
+
const akuma = world === null
|
|
273
|
+
? { kind: "absent" }
|
|
274
|
+
: dispatches.kind === "failed"
|
|
275
|
+
? dispatches
|
|
276
|
+
: await joinAkuma(world, observeContract, dispatches.value);
|
|
277
|
+
return {
|
|
278
|
+
root: world,
|
|
279
|
+
observedAt,
|
|
280
|
+
branch,
|
|
281
|
+
contracts: attachFleet(contracts, akuma),
|
|
282
|
+
tasks,
|
|
283
|
+
akuma,
|
|
284
|
+
...(region === undefined ? {} : { region }),
|
|
285
|
+
};
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
const failure = { kind: "failed", failure: { message: diagnostic(error) } };
|
|
290
|
+
return {
|
|
291
|
+
root: world,
|
|
292
|
+
observedAt,
|
|
293
|
+
branch,
|
|
294
|
+
contracts: failure,
|
|
295
|
+
tasks: world === null ? { kind: "absent" } : failure,
|
|
296
|
+
akuma: world === null ? { kind: "absent" } : failure,
|
|
297
|
+
...(input.region === undefined ? {} : { region: failure }),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
100
300
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { ContractBoard, ContractDisposition } from "../
|
|
2
|
-
import type { TaskRow } from "../task/index.js";
|
|
1
|
+
import type { ContractBoard, ContractDisposition } from "../library/contract.js";
|
|
2
|
+
import type { TaskId, TaskRef, TaskRow } from "../task/index.js";
|
|
3
3
|
import type { AkumaList, AkumaListRow, UnbornAkumaListRow } from "../akuma/index.js";
|
|
4
|
+
import type { AkumaAlias } from "../identity/selector.js";
|
|
5
|
+
import type { WorldRoot } from "../world.js";
|
|
6
|
+
import type { ContractId } from "../library/contract.js";
|
|
4
7
|
export type Section<Value> = Readonly<{
|
|
5
8
|
kind: "present";
|
|
6
9
|
value: Value;
|
|
@@ -13,23 +16,95 @@ export type Section<Value> = Readonly<{
|
|
|
13
16
|
}>;
|
|
14
17
|
}>;
|
|
15
18
|
export type ContractEndpointObservation = ContractDisposition | "missing" | "unavailable";
|
|
19
|
+
export type ContractHolderObservation = Readonly<{
|
|
20
|
+
kind: "held";
|
|
21
|
+
taskId: TaskId;
|
|
22
|
+
}> | Readonly<{
|
|
23
|
+
kind: "none";
|
|
24
|
+
}> | Readonly<{
|
|
25
|
+
kind: "unavailable";
|
|
26
|
+
}>;
|
|
27
|
+
export type ContractFleetAttachment = Readonly<{
|
|
28
|
+
id: string;
|
|
29
|
+
aliases: readonly AkumaAlias[];
|
|
30
|
+
}>;
|
|
31
|
+
export type ContractKanshiRow = ContractBoard["rows"][number] & Readonly<{
|
|
32
|
+
holder: ContractHolderObservation;
|
|
33
|
+
fleet: readonly ContractFleetAttachment[];
|
|
34
|
+
}>;
|
|
35
|
+
export type ContractKanshiBoard = Omit<ContractBoard, "rows"> & Readonly<{
|
|
36
|
+
rows: readonly ContractKanshiRow[];
|
|
37
|
+
}>;
|
|
16
38
|
export type TaskKanshiRow = TaskRow & Readonly<{
|
|
17
39
|
contract?: Readonly<{
|
|
18
40
|
id: string;
|
|
19
41
|
observed: ContractEndpointObservation;
|
|
20
42
|
}>;
|
|
43
|
+
blockers?: readonly TaskRef[];
|
|
21
44
|
}>;
|
|
22
45
|
export type TaskKanshiWorld = Readonly<{
|
|
23
|
-
root:
|
|
46
|
+
root: WorldRoot;
|
|
24
47
|
rows: readonly TaskKanshiRow[];
|
|
25
48
|
}>;
|
|
26
|
-
export type AkumaKanshiRow = AkumaListRow | UnbornAkumaListRow
|
|
49
|
+
export type AkumaKanshiRow = (AkumaListRow | UnbornAkumaListRow) & Readonly<{
|
|
50
|
+
aliases: readonly AkumaAlias[];
|
|
51
|
+
contract?: Readonly<{
|
|
52
|
+
id: string;
|
|
53
|
+
observed: ContractEndpointObservation;
|
|
54
|
+
}>;
|
|
55
|
+
}>;
|
|
27
56
|
export type AkumaKanshiWorld = Omit<AkumaList, "rows"> & Readonly<{
|
|
28
57
|
rows: readonly AkumaKanshiRow[];
|
|
29
58
|
}>;
|
|
59
|
+
export type KanshiRegionSelection = Readonly<{
|
|
60
|
+
kind: "declarations";
|
|
61
|
+
}> | Readonly<{
|
|
62
|
+
kind: "contract";
|
|
63
|
+
contract: ContractId;
|
|
64
|
+
}> | Readonly<{
|
|
65
|
+
kind: "overlap";
|
|
66
|
+
contract?: ContractId;
|
|
67
|
+
}> | Readonly<{
|
|
68
|
+
kind: "path";
|
|
69
|
+
path: string;
|
|
70
|
+
}>;
|
|
71
|
+
export type RegionDeclaration = Readonly<{
|
|
72
|
+
contract: ContractId;
|
|
73
|
+
patterns: readonly string[];
|
|
74
|
+
}>;
|
|
75
|
+
export type RegionIntersection = Readonly<{
|
|
76
|
+
left: ContractId;
|
|
77
|
+
right: ContractId;
|
|
78
|
+
patterns: readonly Readonly<{
|
|
79
|
+
left: string;
|
|
80
|
+
right: string;
|
|
81
|
+
}>[];
|
|
82
|
+
}>;
|
|
83
|
+
export type RegionPathMatch = Readonly<{
|
|
84
|
+
contract: ContractId;
|
|
85
|
+
pattern: string;
|
|
86
|
+
}>;
|
|
87
|
+
export type RegionRead = Readonly<{
|
|
88
|
+
kind: "declarations";
|
|
89
|
+
declarations: readonly RegionDeclaration[];
|
|
90
|
+
}> | Readonly<{
|
|
91
|
+
kind: "contract";
|
|
92
|
+
declaration: RegionDeclaration;
|
|
93
|
+
}> | Readonly<{
|
|
94
|
+
kind: "overlap";
|
|
95
|
+
subject?: ContractId;
|
|
96
|
+
intersections: readonly RegionIntersection[];
|
|
97
|
+
}> | Readonly<{
|
|
98
|
+
kind: "path";
|
|
99
|
+
path: string;
|
|
100
|
+
matches: readonly RegionPathMatch[];
|
|
101
|
+
}>;
|
|
30
102
|
export type KanshiReport = Readonly<{
|
|
31
|
-
root:
|
|
32
|
-
|
|
103
|
+
root: WorldRoot | null;
|
|
104
|
+
observedAt: string;
|
|
105
|
+
branch: string | null;
|
|
106
|
+
contracts: Section<ContractKanshiBoard>;
|
|
33
107
|
tasks: Section<TaskKanshiWorld>;
|
|
34
108
|
akuma: Section<AkumaKanshiWorld>;
|
|
109
|
+
region?: Section<RegionRead>;
|
|
35
110
|
}>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { KanshiReport } from "./report.js";
|
|
2
|
+
import type { KanshiRegionSelection, RegionDeclaration, RegionRead } from "./report.js";
|
|
2
3
|
export type KanshiSelection = Readonly<{
|
|
3
4
|
contract: string;
|
|
4
5
|
}>;
|
|
@@ -6,3 +7,7 @@ export declare function selectKanshi(input: Readonly<{
|
|
|
6
7
|
report: KanshiReport;
|
|
7
8
|
contract: string;
|
|
8
9
|
}>): KanshiReport;
|
|
10
|
+
export declare function selectRegion(input: Readonly<{
|
|
11
|
+
declarations: readonly RegionDeclaration[];
|
|
12
|
+
selection: KanshiRegionSelection;
|
|
13
|
+
}>): RegionRead;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { regionIntersections, regionPathMatches } from "../library/region.js";
|
|
1
2
|
export function selectKanshi(input) {
|
|
2
3
|
const { report, contract } = input;
|
|
3
4
|
return {
|
|
@@ -13,9 +14,40 @@ export function selectKanshi(input) {
|
|
|
13
14
|
kind: "present",
|
|
14
15
|
value: {
|
|
15
16
|
...report.akuma.value,
|
|
16
|
-
rows:
|
|
17
|
+
rows: report.akuma.value.rows.filter((row) => row.contract?.id === contract),
|
|
17
18
|
},
|
|
18
19
|
}
|
|
19
20
|
: report.akuma,
|
|
20
21
|
};
|
|
21
22
|
}
|
|
23
|
+
export function selectRegion(input) {
|
|
24
|
+
const { declarations, selection } = input;
|
|
25
|
+
if (selection.kind === "declarations")
|
|
26
|
+
return { kind: "declarations", declarations };
|
|
27
|
+
if (selection.kind === "contract") {
|
|
28
|
+
const declaration = declarations.find((value) => value.contract === selection.contract);
|
|
29
|
+
if (declaration === undefined)
|
|
30
|
+
throw new Error(`active contract not found: ${selection.contract}`);
|
|
31
|
+
return { kind: "contract", declaration };
|
|
32
|
+
}
|
|
33
|
+
if (selection.kind === "path") {
|
|
34
|
+
const matches = declarations.flatMap((declaration) => regionPathMatches(declaration.patterns, selection.path).map((pattern) => ({ contract: declaration.contract, pattern })));
|
|
35
|
+
return { kind: "path", path: selection.path, matches };
|
|
36
|
+
}
|
|
37
|
+
const intersections = [];
|
|
38
|
+
for (let leftIndex = 0; leftIndex < declarations.length; leftIndex += 1) {
|
|
39
|
+
for (let rightIndex = leftIndex + 1; rightIndex < declarations.length; rightIndex += 1) {
|
|
40
|
+
const left = declarations[leftIndex];
|
|
41
|
+
const right = declarations[rightIndex];
|
|
42
|
+
if (selection.contract !== undefined && left.contract !== selection.contract && right.contract !== selection.contract)
|
|
43
|
+
continue;
|
|
44
|
+
const patterns = regionIntersections(left.patterns, right.patterns);
|
|
45
|
+
if (patterns.length > 0)
|
|
46
|
+
intersections.push({ left: left.contract, right: right.contract, patterns });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (selection.contract !== undefined && !declarations.some((value) => value.contract === selection.contract)) {
|
|
50
|
+
throw new Error(`active contract not found: ${selection.contract}`);
|
|
51
|
+
}
|
|
52
|
+
return { kind: "overlap", ...(selection.contract === undefined ? {} : { subject: selection.contract }), intersections };
|
|
53
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type AkuId } from "../akuma/identity.js";
|
|
2
|
+
import { type AkumaAlias, type AkumaGlob } from "../identity/selector.js";
|
|
3
|
+
import type { Settings } from "../settings.js";
|
|
4
|
+
import type { WorldRoot } from "../world.js";
|
|
5
|
+
import { type Repo } from "./repo.js";
|
|
6
|
+
export type DirectAkumaSelector = AkuId | AkumaAlias;
|
|
7
|
+
export type SetAkumaSelector = DirectAkumaSelector | AkumaGlob | `kei/${string}`;
|
|
8
|
+
export type AkumaAddressInput = Readonly<{
|
|
9
|
+
path: WorldRoot;
|
|
10
|
+
akuma: string;
|
|
11
|
+
settings?: Settings;
|
|
12
|
+
repo?: Repo;
|
|
13
|
+
}>;
|
|
14
|
+
export type AkumaSetAddressInput = Readonly<{
|
|
15
|
+
path: WorldRoot;
|
|
16
|
+
akuma: readonly string[];
|
|
17
|
+
settings?: Settings;
|
|
18
|
+
repo?: Repo;
|
|
19
|
+
}>;
|
|
20
|
+
export type AkumaWorldScopeRefusal = Readonly<{
|
|
21
|
+
kind: "akuma-not-in-world";
|
|
22
|
+
ids: readonly AkuId[];
|
|
23
|
+
world: WorldRoot;
|
|
24
|
+
}>;
|
|
25
|
+
export declare class AkumaWorldScopeError extends TypeError {
|
|
26
|
+
readonly refusal: AkumaWorldScopeRefusal;
|
|
27
|
+
constructor(refusal: AkumaWorldScopeRefusal);
|
|
28
|
+
}
|
|
29
|
+
export type NamedAddressContract = Readonly<{
|
|
30
|
+
id: string;
|
|
31
|
+
disposition: "active" | "terminal";
|
|
32
|
+
workspace: "worktree" | "here";
|
|
33
|
+
worktreePath: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
export type NamedAddress = Readonly<{
|
|
36
|
+
kind: "contract";
|
|
37
|
+
id: string;
|
|
38
|
+
}> | Readonly<{
|
|
39
|
+
kind: "akuma";
|
|
40
|
+
id: AkuId;
|
|
41
|
+
}>;
|
|
42
|
+
export type NamedAddressInput = Readonly<{
|
|
43
|
+
path: WorldRoot | null;
|
|
44
|
+
selector: string;
|
|
45
|
+
contracts: readonly NamedAddressContract[];
|
|
46
|
+
}>;
|
|
47
|
+
export declare function resolveNamedAddress(input: NamedAddressInput): Promise<NamedAddress>;
|
|
48
|
+
export declare function addressAkuma(input: AkumaAddressInput): Promise<Readonly<{
|
|
49
|
+
path: WorldRoot;
|
|
50
|
+
id: AkuId;
|
|
51
|
+
settings?: Settings;
|
|
52
|
+
}>>;
|
|
53
|
+
export declare function addressAkumaSet(input: AkumaSetAddressInput): Promise<Readonly<{
|
|
54
|
+
path: WorldRoot;
|
|
55
|
+
ids: readonly AkuId[];
|
|
56
|
+
settings?: Settings;
|
|
57
|
+
}>>;
|