@astrosheep/keiyaku 4.0.4 → 4.0.6
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/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +24 -4
- package/build/src/akuma/akuma.d.ts +2 -1
- package/build/src/akuma/akuma.js +27 -9
- package/build/src/akuma/allowed.d.ts +1 -1
- package/build/src/akuma/allowed.js +3 -10
- package/build/src/akuma/archetype.d.ts +3 -1
- package/build/src/akuma/archetype.js +11 -6
- package/build/src/akuma/body-turn.d.ts +64 -0
- package/build/src/akuma/body-turn.js +449 -0
- package/build/src/akuma/body.d.ts +4 -5
- package/build/src/akuma/body.js +9 -414
- package/build/src/akuma/heart/facts.d.ts +37 -9
- package/build/src/akuma/heart/facts.js +3 -1
- package/build/src/akuma/heart/index.d.ts +4 -13
- package/build/src/akuma/heart/index.js +14 -135
- package/build/src/akuma/heart/request-authority.d.ts +12 -0
- package/build/src/akuma/heart/request-authority.js +119 -0
- package/build/src/akuma/heart/request-rows.d.ts +16 -0
- package/build/src/akuma/heart/request-rows.js +88 -0
- package/build/src/akuma/heart/rows.d.ts +1 -28
- package/build/src/akuma/heart/rows.js +4 -138
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +11 -3
- package/build/src/akuma/heart/soul.js +0 -36
- package/build/src/akuma/heart/timeline.d.ts +1 -0
- package/build/src/akuma/heart/timeline.js +19 -0
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/nuke.d.ts +2 -0
- package/build/src/akuma/nuke.js +152 -0
- package/build/src/akuma/provider-recipe.js +1 -11
- package/build/src/akuma/provider.d.ts +4 -7
- package/build/src/akuma/providers/acp/config.d.ts +8 -0
- package/build/src/akuma/providers/acp/config.js +37 -0
- package/build/src/akuma/providers/acp/core.js +12 -2
- package/build/src/akuma/providers/acp/index.d.ts +1 -8
- package/build/src/akuma/providers/acp/index.js +2 -38
- package/build/src/akuma/providers/claude/index.d.ts +0 -4
- package/build/src/akuma/providers/claude/index.js +12 -3
- package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
- package/build/src/akuma/providers/codex-app-server/index.js +5 -2
- package/build/src/akuma/providers/grok-build/index.js +1 -2
- package/build/src/akuma/providers/index.d.ts +3 -2
- package/build/src/akuma/providers/index.js +36 -36
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
- package/build/src/akuma/providers/opencode-sdk/index.js +14 -4
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +2 -2
- package/build/src/akuma/providers/opencode-sdk/session.js +2 -2
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +29 -6
- package/build/src/akuma/request-serve.d.ts +88 -0
- package/build/src/akuma/request-serve.js +484 -0
- package/build/src/akuma/request-wire.d.ts +125 -0
- package/build/src/akuma/request-wire.js +383 -0
- package/build/src/akuma/requests.d.ts +28 -94
- package/build/src/akuma/requests.js +52 -562
- package/build/src/akuma-body.d.ts +7 -0
- package/build/src/akuma-body.js +69 -2
- package/build/src/alias/index.d.ts +1 -0
- package/build/src/alias/index.js +34 -1
- package/build/src/body/arc.js +4 -29
- package/build/src/body/decode.js +5 -39
- package/build/src/body/envelope.d.ts +7 -0
- package/build/src/body/envelope.js +37 -0
- package/build/src/cli/accepted.js +21 -9
- package/build/src/cli/commands/akuma-invoke.js +1 -0
- package/build/src/cli/commands/akuma.d.ts +1 -0
- package/build/src/cli/commands/akuma.js +13 -10
- package/build/src/cli/commands/contract.d.ts +28 -17
- package/build/src/cli/commands/contract.js +23 -17
- package/build/src/cli/commands/install.d.ts +2 -2
- package/build/src/cli/commands/install.js +6 -6
- package/build/src/cli/commands/nuke.d.ts +10 -0
- package/build/src/cli/commands/nuke.js +20 -0
- package/build/src/cli/commands/task-invoke.d.ts +15 -0
- package/build/src/cli/commands/task-invoke.js +144 -24
- package/build/src/cli/commands/task-query.d.ts +2 -2
- package/build/src/cli/commands/task-query.js +1 -2
- package/build/src/cli/commands/task.js +22 -22
- package/build/src/cli/coordinates.d.ts +6 -2
- package/build/src/cli/coordinates.js +12 -56
- package/build/src/cli/invoke.d.ts +5 -4
- package/build/src/cli/invoke.js +112 -58
- package/build/src/cli/main.d.ts +0 -2
- package/build/src/cli/main.js +4 -140
- package/build/src/cli/parse.d.ts +17 -4
- package/build/src/cli/parse.js +93 -15
- package/build/src/cli/render/akuma.js +111 -53
- package/build/src/cli/render/audit.js +2 -6
- package/build/src/cli/render/contract.js +61 -20
- package/build/src/cli/render/kanshi.js +15 -5
- package/build/src/cli/render/nuke.d.ts +3 -0
- package/build/src/cli/render/nuke.js +8 -0
- package/build/src/cli/render/receipt.js +28 -1
- package/build/src/cli/render/refusal.d.ts +2 -1
- package/build/src/cli/render/refusal.js +31 -0
- package/build/src/cli/render/terminal.d.ts +0 -2
- package/build/src/cli/render/terminal.js +0 -29
- package/build/src/cli/render/text.js +6 -1
- package/build/src/cli/result.d.ts +36 -9
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +140 -0
- package/build/src/cli/usage.d.ts +0 -2
- package/build/src/cli/usage.js +0 -4
- package/build/src/contract-worktree.d.ts +29 -14
- package/build/src/contract-worktree.js +131 -70
- package/build/src/core/facts/codec.js +9 -0
- package/build/src/core/facts/fold.js +13 -1
- package/build/src/core/facts/types.d.ts +8 -1
- package/build/src/core/subject.js +4 -3
- package/build/src/core/verbs/placement.d.ts +9 -1
- package/build/src/core/verbs/placement.js +24 -6
- package/build/src/core/verbs/reintegrate.d.ts +13 -0
- package/build/src/core/verbs/reintegrate.js +24 -0
- package/build/src/dispatch/index.d.ts +1 -1
- package/build/src/git/admission.d.ts +2 -1
- package/build/src/git/hooks.d.ts +2 -0
- package/build/src/git/hooks.js +34 -1
- package/build/src/git/integration.d.ts +9 -2
- package/build/src/git/integration.js +92 -1
- package/build/src/git/nuke.d.ts +2 -0
- package/build/src/git/nuke.js +97 -0
- package/build/src/git/observe.d.ts +2 -1
- package/build/src/git/observe.js +6 -5
- package/build/src/git/process.d.ts +28 -0
- package/build/src/git/process.js +94 -0
- package/build/src/git/read-observation.d.ts +2 -1
- package/build/src/git/read-observation.js +3 -2
- package/build/src/git/reconcile.d.ts +4 -1
- package/build/src/git/reconcile.js +42 -8
- package/build/src/git/repository.d.ts +2 -29
- package/build/src/git/repository.js +7 -118
- package/build/src/git/scratch.d.ts +1 -1
- package/build/src/git/scratch.js +1 -1
- package/build/src/git/target-placement.d.ts +3 -2
- package/build/src/git/target-placement.js +15 -14
- package/build/src/git/tender.d.ts +2 -1
- package/build/src/git/tender.js +4 -3
- package/build/src/git/terminal-seal.d.ts +2 -2
- package/build/src/git/terminal-seal.js +3 -6
- package/build/src/git/workspace.d.ts +4 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/index.d.ts +1 -2
- package/build/src/index.js +1 -1
- package/build/src/kanshi/read.js +5 -1
- package/build/src/library/address.js +7 -1
- package/build/src/library/akuma-creation.d.ts +1 -0
- package/build/src/library/akuma-creation.js +8 -1
- package/build/src/library/audit.d.ts +3 -1
- package/build/src/library/audit.js +2 -1
- package/build/src/library/bind.d.ts +2 -1
- package/build/src/library/bind.js +1 -1
- package/build/src/library/configuration.d.ts +1 -1
- package/build/src/library/configuration.js +52 -18
- package/build/src/library/contract.d.ts +59 -4
- package/build/src/library/contract.js +195 -34
- package/build/src/library/delivery.d.ts +4 -2
- package/build/src/library/fleet.d.ts +27 -7
- package/build/src/library/fleet.js +79 -39
- package/build/src/library/input.d.ts +0 -1
- package/build/src/library/input.js +0 -5
- package/build/src/library/keiyaku.d.ts +6 -2
- package/build/src/library/keiyaku.js +2 -0
- package/build/src/library/mutation.d.ts +3 -1
- package/build/src/library/mutation.js +3 -0
- package/build/src/library/nuke.d.ts +14 -0
- package/build/src/library/nuke.js +54 -0
- package/build/src/library/reconcile.d.ts +2 -1
- package/build/src/library/reconcile.js +8 -3
- package/build/src/library/refusal.d.ts +10 -1
- package/build/src/library/region.d.ts +1 -1
- package/build/src/library/repo.d.ts +4 -1
- package/build/src/library/repo.js +10 -4
- package/build/src/protocol/abandon.d.ts +9 -0
- package/build/src/protocol/abandon.js +15 -0
- package/build/src/protocol/amend.d.ts +16 -0
- package/build/src/protocol/amend.js +77 -0
- package/build/src/protocol/arc.d.ts +6 -0
- package/build/src/protocol/arc.js +12 -0
- package/build/src/protocol/attempt.d.ts +2 -1
- package/build/src/protocol/audit.d.ts +53 -0
- package/build/src/protocol/audit.js +147 -0
- package/build/src/protocol/bind.d.ts +1 -1
- package/build/src/protocol/completion.d.ts +42 -0
- package/build/src/protocol/completion.js +183 -0
- package/build/src/protocol/deliver.d.ts +49 -0
- package/build/src/protocol/deliver.js +261 -0
- package/build/src/protocol/intent.d.ts +2 -1
- package/build/src/protocol/intent.js +8 -2
- package/build/src/protocol/operations.d.ts +93 -202
- package/build/src/protocol/operations.js +23 -642
- package/build/src/protocol/placement.d.ts +12 -13
- package/build/src/protocol/placement.js +8 -19
- package/build/src/protocol/read/status.d.ts +17 -5
- package/build/src/protocol/read/status.js +57 -13
- package/build/src/protocol/reconcile.d.ts +35 -0
- package/build/src/protocol/reconcile.js +41 -0
- package/build/src/protocol/reintegrate.d.ts +31 -0
- package/build/src/protocol/reintegrate.js +74 -0
- package/build/src/protocol/review.d.ts +34 -0
- package/build/src/protocol/review.js +156 -0
- package/build/src/protocol/run.d.ts +1 -1
- package/build/src/runtime/proc/run.js +9 -5
- package/build/src/settlement/fence.d.ts +3 -1
- package/build/src/settlement/fence.js +24 -0
- package/build/src/settlement/holder.d.ts +1 -1
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +1 -2
- package/build/src/task/board.d.ts +0 -1
- package/build/src/task/board.js +0 -3
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +13 -11
- package/build/src/task/context.d.ts +14 -2
- package/build/src/task/context.js +30 -7
- package/build/src/task/index.d.ts +7 -6
- package/build/src/task/index.js +17 -145
- package/build/src/task/input.d.ts +18 -0
- package/build/src/task/input.js +189 -0
- package/build/src/task/mutation.d.ts +44 -0
- package/build/src/task/mutation.js +93 -0
- package/build/src/task/operations.d.ts +14 -6
- package/build/src/task/operations.js +57 -57
- package/build/src/task/store.d.ts +1 -0
- package/build/src/task/store.js +91 -3
- package/build/src/verification/execution.d.ts +1 -1
- package/build/src/workspace-place.d.ts +3 -4
- package/build/src/workspace-place.js +26 -15
- package/package.json +3 -3
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
export const
|
|
2
|
-
"
|
|
3
|
-
" ## Replace: Design",
|
|
4
|
-
"
|
|
1
|
+
export const AMEND_OPERATIONS_HELP = [
|
|
2
|
+
"stdin operations (H2 sections only, no H1):",
|
|
3
|
+
" ## Replace: Context|Objective|Design|Region|Criteria|Verification|<extension>",
|
|
4
|
+
" ## Append: Context|Objective|Design|Criteria|<extension>",
|
|
5
|
+
" ## Add: Criteria|<new-extension-title>",
|
|
6
|
+
" ## Update: Criterion <existing-title>|<existing-extension-title>",
|
|
7
|
+
" ## Remove: Criterion <existing-title>|<existing-extension-title>",
|
|
8
|
+
"",
|
|
9
|
+
"full operation grammar: docs/document.md, Amend Operations",
|
|
5
10
|
].join("\n");
|
|
6
11
|
export const CONTRACT_COMMAND_SPECS = {
|
|
7
|
-
bind: { positional: "none", stdin: "required", flags: { actor: "value", task: "value", target: "value", here: "boolean", after: "repeat-value", gates: "value", json: "boolean" }, usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name
|
|
8
|
-
amend: { positional: "optional", stdin: "optional", flags: { actor: "value", after: "repeat-value", "clear-after": "boolean", gates: "value", json: "boolean" }, usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name
|
|
9
|
-
deliver: { positional: "optional", stdin: "none", flags: { actor: "value", message: "value", "include-dirty": "boolean", json: "boolean" }, usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--actor <actor>]
|
|
10
|
-
review: { positional: "optional", stdin: "optional", flags: { actor: "value", satisfied: "boolean", unsatisfied: "boolean", summary: "value", json: "boolean" }, usage: "review [<contract>|@<contract>] (--satisfied | --unsatisfied) (--summary <text> | -) [--actor <actor>]
|
|
11
|
-
arc: { positional: "optional", stdin: "required", flags: { actor: "value", json: "boolean" }, usage: "arc [<contract>|@<contract>] [--actor <actor>]
|
|
12
|
-
abandon: { positional: "optional", stdin: "none", flags: { actor: "value", note: "value", json: "boolean" }, usage: "abandon [<contract>|@<contract>] [--note <text>] [--actor <actor>]
|
|
13
|
-
status: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "status [<contract>|@name|<aku/...>]
|
|
14
|
-
show: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "show [<contract>|@<contract>]
|
|
15
|
-
ls: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "ls task/
|
|
16
|
-
audit: { positional: "optional", stdin: "none", flags: { "include-dirty": "boolean", diff: "boolean", actor: "value", json: "boolean" }, usage: "audit [<contract>|@<contract>] [--include-dirty] [--diff] [--actor <actor>]
|
|
17
|
-
reconcile: { positional: "optional", stdin: "none", flags: { "retry-hooks": "boolean", json: "boolean" }, usage: "reconcile [<contract>|@<contract>] [--retry-hooks]
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
bind: { positional: "none", stdin: "required", flags: { actor: "value", task: "value", target: "value", here: "boolean", after: "repeat-value", gates: "raw-value", json: "boolean" }, usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name,...>] [--actor <actor>] -", purpose: "Create one Contract from stdin Markdown." },
|
|
13
|
+
amend: { positional: "optional", stdin: "optional", flags: { actor: "value", after: "repeat-value", "clear-after": "boolean", gates: "raw-value", json: "boolean" }, usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name,...>] [--actor <actor>] [-]", purpose: "Amend one Contract's document operations or structured terms." },
|
|
14
|
+
deliver: { positional: "optional", stdin: "none", flags: { actor: "value", message: "value", "include-dirty": "boolean", "materialize-conflict": "boolean", json: "boolean" }, usage: "deliver [<contract>|@<contract>] [--message <text>] [--include-dirty] [--materialize-conflict] [--actor <actor>]", purpose: "Deliver one Contract candidate." },
|
|
15
|
+
review: { positional: "optional", stdin: "optional", flags: { actor: "value", satisfied: "boolean", unsatisfied: "boolean", summary: "value", json: "boolean" }, usage: "review [<contract>|@<contract>] (--satisfied | --unsatisfied) (--summary <text> | -) [--actor <actor>]", purpose: "Record one review verdict." },
|
|
16
|
+
arc: { positional: "optional", stdin: "required", flags: { actor: "value", json: "boolean" }, usage: "arc [<contract>|@<contract>] [--actor <actor>] -", purpose: "Record stdin arc Markdown for one Contract." },
|
|
17
|
+
abandon: { positional: "optional", stdin: "none", flags: { actor: "value", note: "value", json: "boolean" }, usage: "abandon [<contract>|@<contract>] [--note <text>] [--actor <actor>]", purpose: "Abandon one Contract with an optional note." },
|
|
18
|
+
status: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "status [<contract>|@name|<aku/...>]", purpose: "Read the world status board or one Contract projection." },
|
|
19
|
+
show: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "show [<contract>|@<contract>]", purpose: "Read one Contract guidance projection." },
|
|
20
|
+
ls: { positional: "optional", stdin: "none", flags: { json: "boolean" }, usage: "ls task[/]\n keiyaku ls kei[/]\n keiyaku ls aku[/]\n keiyaku ls aku/<akuma>[/]\n keiyaku ls \"aku/*/*\"", purpose: "List one identity directory." },
|
|
21
|
+
audit: { positional: "optional", stdin: "none", flags: { "include-dirty": "boolean", diff: "boolean", actor: "value", json: "boolean" }, usage: "audit [<contract>|@<contract>] [--include-dirty] [--diff] [--actor <actor>]", purpose: "Ask what candidate preparation, Verification, and target placement would do." },
|
|
22
|
+
reconcile: { positional: "optional", stdin: "none", flags: { "retry-hooks": "boolean", json: "boolean" }, usage: "reconcile [<contract>|@<contract>] [--retry-hooks]", purpose: "Reconcile one Contract or the invocation world." },
|
|
23
|
+
nuke: { positional: "none", stdin: "none", flags: { confirm: "value", json: "boolean" }, usage: "nuke [--confirm <WorldRoot>]", purpose: "Remove Keiyaku-owned data from one confirmed World." },
|
|
24
|
+
settings: { positional: "none", stdin: "none", flags: { json: "boolean" }, usage: "settings", purpose: "Read user and project Settings resources." },
|
|
25
|
+
region: { positional: "optional", stdin: "none", flags: { overlap: "boolean", path: "value", json: "boolean" }, usage: "region [<contract>] [--overlap]\n region --path <repo-relative-path>", purpose: "Read active declared Contract Regions." },
|
|
20
26
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ProcessInput, ProcessOutcome } from "../../runtime/proc/run.js";
|
|
2
2
|
export declare const HARNESS_NAMES: readonly ["codex", "claude", "opencode", "pi"];
|
|
3
3
|
export type HarnessName = typeof HARNESS_NAMES[number];
|
|
4
4
|
export type ParsedInstallCommand = Readonly<{
|
|
@@ -16,7 +16,7 @@ export type InstallInvocationResult = Readonly<{
|
|
|
16
16
|
results: readonly HarnessInstallResult[];
|
|
17
17
|
}>;
|
|
18
18
|
export type InstallRunner = (input: ProcessInput) => Promise<ProcessOutcome>;
|
|
19
|
-
export declare const INSTALL_USAGE = "install <codex|claude|opencode|pi
|
|
19
|
+
export declare const INSTALL_USAGE = "install <codex|claude|opencode|pi>\n install --all";
|
|
20
20
|
export declare function parseInstallCommand(argv: readonly string[]): ParsedInstallCommand;
|
|
21
21
|
export declare function renderInstallHelp(): string;
|
|
22
22
|
export declare function installAssetsRoot(): string;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { dirname, resolve } from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import {
|
|
4
|
-
import { CliUsageError, usageLine, withJsonAutomationHelp } from "../usage.js";
|
|
3
|
+
import { CliUsageError, usageLine } from "../usage.js";
|
|
5
4
|
export const HARNESS_NAMES = ["codex", "claude", "opencode", "pi"];
|
|
6
|
-
export const INSTALL_USAGE = "install <codex|claude|opencode|pi
|
|
5
|
+
export const INSTALL_USAGE = "install <codex|claude|opencode|pi>\n install --all";
|
|
7
6
|
function isHarness(value) {
|
|
8
7
|
return value !== undefined && HARNESS_NAMES.includes(value);
|
|
9
8
|
}
|
|
@@ -43,7 +42,7 @@ export function parseInstallCommand(argv) {
|
|
|
43
42
|
};
|
|
44
43
|
}
|
|
45
44
|
export function renderInstallHelp() {
|
|
46
|
-
return
|
|
45
|
+
return `Install the Keiyaku skills into one or more agent harnesses.\n\n${usageLine(INSTALL_USAGE)}`;
|
|
47
46
|
}
|
|
48
47
|
const INSTALL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
49
48
|
const ASSET_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../../integrations/marketplace");
|
|
@@ -80,12 +79,13 @@ function diagnostic(argv, outcome) {
|
|
|
80
79
|
export function installAssetsRoot() {
|
|
81
80
|
return ASSET_ROOT;
|
|
82
81
|
}
|
|
83
|
-
export async function installHarnesses(harnesses, environment, runner
|
|
82
|
+
export async function installHarnesses(harnesses, environment, runner) {
|
|
83
|
+
const run = runner ?? (await import("../../runtime/proc/run.js")).runCrossPlatformProcess;
|
|
84
84
|
const results = [];
|
|
85
85
|
for (const harness of harnesses) {
|
|
86
86
|
let failure;
|
|
87
87
|
for (const argv of recipes(harness)) {
|
|
88
|
-
const detail = diagnostic(argv, await
|
|
88
|
+
const detail = diagnostic(argv, await run({ argv, env: environment, timeoutMs: INSTALL_TIMEOUT_MS }));
|
|
89
89
|
if (detail.length > 0) {
|
|
90
90
|
failure = detail;
|
|
91
91
|
break;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type NukeResult } from "../../index.js";
|
|
2
|
+
import type { WorldRoot } from "../../world.js";
|
|
3
|
+
import { type ParsedCommand } from "../parse.js";
|
|
4
|
+
import type { InvocationResult } from "../result.js";
|
|
5
|
+
export declare function invokeNuke(command: Extract<ParsedCommand, {
|
|
6
|
+
command: "nuke";
|
|
7
|
+
}>, world: WorldRoot | null): Promise<Readonly<{
|
|
8
|
+
kind: "nuke";
|
|
9
|
+
result: NukeResult;
|
|
10
|
+
}> | InvocationResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Keiyaku, KeiyakuRefused } from "../../index.js";
|
|
2
|
+
import { CliUsageError } from "../parse.js";
|
|
3
|
+
export async function invokeNuke(command, world) {
|
|
4
|
+
if (world === null)
|
|
5
|
+
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
6
|
+
try {
|
|
7
|
+
return {
|
|
8
|
+
kind: "nuke",
|
|
9
|
+
result: await Keiyaku.nuke({
|
|
10
|
+
world,
|
|
11
|
+
...(command.confirm === undefined ? {} : { confirm: command.confirm }),
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (error instanceof KeiyakuRefused)
|
|
17
|
+
return { kind: "refused", verb: "nuke", refusal: error.refusal };
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -16,9 +16,24 @@ export type TaskWorldObservation = Readonly<{
|
|
|
16
16
|
}>;
|
|
17
17
|
type TaskInput = Readonly<{
|
|
18
18
|
world: WorldRoot | null;
|
|
19
|
+
context: Readonly<{
|
|
20
|
+
directory: string;
|
|
21
|
+
boundary: string;
|
|
22
|
+
}>;
|
|
19
23
|
establish(): Promise<WorldRoot>;
|
|
20
24
|
readStdin(): Promise<string>;
|
|
21
25
|
actor?: string;
|
|
22
26
|
}>;
|
|
27
|
+
export declare function invokeTaskFromEdge(input: Readonly<{
|
|
28
|
+
parsed: ParsedTaskCommand;
|
|
29
|
+
world: WorldRoot | null;
|
|
30
|
+
context: Readonly<{
|
|
31
|
+
directory: string;
|
|
32
|
+
boundary: string;
|
|
33
|
+
}>;
|
|
34
|
+
establish: () => Promise<WorldRoot>;
|
|
35
|
+
readStdin: () => Promise<string>;
|
|
36
|
+
actor: string | undefined;
|
|
37
|
+
}>): Promise<TaskInvocationResult>;
|
|
23
38
|
export declare function invokeTask(command: ParsedTaskCommand, input: TaskInput): Promise<TaskInvocationResult>;
|
|
24
39
|
export {};
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { Tasks, } from "../../task/index.js";
|
|
2
|
+
import { injectedBodyRequests, requestBodyTask } from "../../akuma/requests.js";
|
|
3
|
+
import { decodeTaskMutationRequest } from "../../task/mutation.js";
|
|
4
|
+
import { resolveTaskNamespaceContext, writeTaskNamespaceContext } from "../../task/context.js";
|
|
5
|
+
import { CliUsageError } from "../usage.js";
|
|
6
|
+
export async function invokeTaskFromEdge(input) {
|
|
7
|
+
try {
|
|
8
|
+
return await invokeTask(input.parsed, {
|
|
9
|
+
world: input.world,
|
|
10
|
+
context: input.context,
|
|
11
|
+
establish: input.establish,
|
|
12
|
+
readStdin: input.readStdin,
|
|
13
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (error instanceof TypeError)
|
|
18
|
+
throw new CliUsageError(error.message);
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
2
22
|
function value(command, name) {
|
|
3
23
|
const item = command.flags[name];
|
|
4
24
|
return typeof item === "string" ? item : undefined;
|
|
@@ -17,8 +37,8 @@ function priority(raw) {
|
|
|
17
37
|
function state(raw) { return raw; }
|
|
18
38
|
function ids(items) { return items; }
|
|
19
39
|
function limit(command) { const raw = value(command, "limit"); return raw === undefined ? undefined : Number(raw); }
|
|
20
|
-
async function invokeAdd(tasks, command, input) {
|
|
21
|
-
const selectedNamespace = namespace(value(command, "namespace"));
|
|
40
|
+
async function invokeAdd(tasks, command, input, current) {
|
|
41
|
+
const selectedNamespace = namespace(value(command, "namespace")) ?? current;
|
|
22
42
|
const actor = input.actor;
|
|
23
43
|
if (command.stdin === "document") {
|
|
24
44
|
return tasks.addDocument({
|
|
@@ -54,17 +74,96 @@ async function invokeUpdate(tasks, command, readStdin) {
|
|
|
54
74
|
...(addRelates === undefined ? {} : { addRelates }), ...(dropRelates === undefined ? {} : { dropRelates }),
|
|
55
75
|
});
|
|
56
76
|
}
|
|
57
|
-
async function
|
|
77
|
+
async function addMutationRequest(command, input, current) {
|
|
78
|
+
const selectedNamespace = namespace(value(command, "namespace")) ?? current;
|
|
79
|
+
if (command.stdin === "document")
|
|
80
|
+
return { action: "task.addDocument", input: {
|
|
81
|
+
markdown: await input.readStdin(),
|
|
82
|
+
namespace: selectedNamespace,
|
|
83
|
+
} };
|
|
84
|
+
const body = value(command, "body"), note = value(command, "note");
|
|
85
|
+
const initialState = state(value(command, "state")), selectedPriority = priority(value(command, "priority"));
|
|
86
|
+
const needs = ids(values(command, "needs")), parent = value(command, "parent");
|
|
87
|
+
const supersedes = ids(values(command, "supersedes")), relates = ids(values(command, "relates"));
|
|
88
|
+
return { action: "task.add", input: {
|
|
89
|
+
title: command.positionals[0], namespace: selectedNamespace,
|
|
90
|
+
...(body === undefined ? {} : { body }), ...(note === undefined ? {} : { note }),
|
|
91
|
+
...(initialState === undefined ? {} : { state: initialState }),
|
|
92
|
+
...(selectedPriority === undefined ? {} : { priority: selectedPriority }),
|
|
93
|
+
...(needs === undefined ? {} : { needs }), ...(parent === undefined ? {} : { parent: parent }),
|
|
94
|
+
...(supersedes === undefined ? {} : { supersedes }), ...(relates === undefined ? {} : { relates }),
|
|
95
|
+
} };
|
|
96
|
+
}
|
|
97
|
+
async function updateMutationRequest(command, input) {
|
|
98
|
+
const body = command.stdin === "body" ? await input.readStdin() : value(command, "body");
|
|
99
|
+
const appendBody = command.stdin === "append" ? await input.readStdin() : value(command, "append");
|
|
100
|
+
const note = command.stdin === "note" ? await input.readStdin() : value(command, "note");
|
|
101
|
+
const title = value(command, "title"), selectedPriority = priority(value(command, "priority"));
|
|
102
|
+
const addNeeds = ids(values(command, "needs")), dropNeeds = ids(values(command, "drop-needs"));
|
|
103
|
+
const parent = value(command, "parent"), addSupersedes = ids(values(command, "supersedes"));
|
|
104
|
+
const dropSupersedes = ids(values(command, "drop-supersedes")), addRelates = ids(values(command, "relates"));
|
|
105
|
+
const dropRelates = ids(values(command, "drop-relates"));
|
|
106
|
+
return { action: "task.update", id: command.positionals[0], input: {
|
|
107
|
+
...(title === undefined ? {} : { title }), ...(body === undefined ? {} : { body }),
|
|
108
|
+
...(appendBody === undefined ? {} : { appendBody }), ...(note === undefined ? {} : { note }),
|
|
109
|
+
...(selectedPriority === undefined ? {} : { priority: selectedPriority }),
|
|
110
|
+
...(addNeeds === undefined ? {} : { addNeeds }), ...(dropNeeds === undefined ? {} : { dropNeeds }),
|
|
111
|
+
...(command.flags["no-parent"] === true ? { parent: null }
|
|
112
|
+
: parent === undefined ? {} : { parent: parent }),
|
|
113
|
+
...(addSupersedes === undefined ? {} : { addSupersedes }),
|
|
114
|
+
...(dropSupersedes === undefined ? {} : { dropSupersedes }),
|
|
115
|
+
...(addRelates === undefined ? {} : { addRelates }), ...(dropRelates === undefined ? {} : { dropRelates }),
|
|
116
|
+
} };
|
|
117
|
+
}
|
|
118
|
+
function lifecycleMutationRequest(command) {
|
|
119
|
+
const id = command.positionals[0];
|
|
120
|
+
switch (command.action) {
|
|
121
|
+
case "start": return { action: "task.start", id };
|
|
122
|
+
case "stop": return { action: "task.stop", id };
|
|
123
|
+
case "resume": return { action: "task.resume", id };
|
|
124
|
+
case "hold": return { action: "task.hold", ids: command.positionals };
|
|
125
|
+
case "done": return { action: "task.done", ids: command.positionals, ...(value(command, "note") === undefined ? {} : { note: value(command, "note") }) };
|
|
126
|
+
case "drop": return { action: "task.drop", ids: command.positionals, ...(value(command, "note") === undefined ? {} : { note: value(command, "note") }) };
|
|
127
|
+
default: throw new Error(`task action cannot forward: ${command.action}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function mutationRequest(command, input, current) {
|
|
131
|
+
if (command.action === "add")
|
|
132
|
+
return await addMutationRequest(command, input, current);
|
|
133
|
+
if (command.action === "compose")
|
|
134
|
+
return { action: "task.compose", markdown: await input.readStdin(), namespace: current };
|
|
135
|
+
if (command.action === "update")
|
|
136
|
+
return await updateMutationRequest(command, input);
|
|
137
|
+
return lifecycleMutationRequest(command);
|
|
138
|
+
}
|
|
139
|
+
function validatedMutationRequest(request) {
|
|
140
|
+
switch (request.action) {
|
|
141
|
+
case "task.add":
|
|
142
|
+
case "task.addDocument": return decodeTaskMutationRequest(request.action, { input: request.input });
|
|
143
|
+
case "task.compose": return decodeTaskMutationRequest(request.action, { markdown: request.markdown, namespace: request.namespace });
|
|
144
|
+
case "task.update": return decodeTaskMutationRequest(request.action, { id: request.id, input: request.input });
|
|
145
|
+
case "task.start":
|
|
146
|
+
case "task.stop":
|
|
147
|
+
case "task.resume": return decodeTaskMutationRequest(request.action, { id: request.id });
|
|
148
|
+
case "task.hold": return decodeTaskMutationRequest(request.action, { ids: request.ids });
|
|
149
|
+
case "task.done":
|
|
150
|
+
case "task.drop": return decodeTaskMutationRequest(request.action, { ids: request.ids, ...(request.note === undefined ? {} : { note: request.note }) });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function readScope(command, current) {
|
|
154
|
+
return command.flags.world === true ? { scope: "world" } : { namespace: current ?? [] };
|
|
155
|
+
}
|
|
156
|
+
async function invokeRead(tasks, command, current) {
|
|
58
157
|
const id = command.positionals[0];
|
|
59
158
|
switch (command.action) {
|
|
60
159
|
case "show": {
|
|
61
160
|
const detail = await tasks.task({ id }).read();
|
|
62
161
|
return detail ?? { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
|
|
63
162
|
}
|
|
64
|
-
case "ls": return tasks.list({ selection: command.flags.all === true ? "all" : command.flags.closed === true ? "closed" : "active", ...(command
|
|
65
|
-
case "ready": return tasks.ready({ ...(command
|
|
66
|
-
case "blocked": return tasks.blocked({ ...(command
|
|
67
|
-
case "query": return tasks.query({ ...(command.where === undefined ? {} : { where: command.where }), ...(command
|
|
163
|
+
case "ls": return tasks.list({ selection: command.flags.all === true ? "all" : command.flags.closed === true ? "closed" : "active", ...readScope(command, current), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
|
|
164
|
+
case "ready": return tasks.ready({ ...readScope(command, current), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
|
|
165
|
+
case "blocked": return tasks.blocked({ ...readScope(command, current), ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
|
|
166
|
+
case "query": return tasks.query({ ...(command.where === undefined ? {} : { where: command.where }), ...readScope(command, current), ...(value(command, "sort") === undefined ? {} : { sort: value(command, "sort") }), ...(limit(command) === undefined ? {} : { limit: limit(command) }) });
|
|
68
167
|
case "tree": return tasks.task({ id }).tree();
|
|
69
168
|
case "doctor": return tasks.doctor();
|
|
70
169
|
default: throw new Error(`task action is not a read: ${command.action}`);
|
|
@@ -75,9 +174,9 @@ function isWorldObservation(command) {
|
|
|
75
174
|
|| command.action === "query" || command.action === "doctor";
|
|
76
175
|
}
|
|
77
176
|
function diagnostic(error) { return error instanceof Error ? error.message : String(error); }
|
|
78
|
-
async function observeWorldRead(tasks, command) {
|
|
177
|
+
async function observeWorldRead(tasks, command, current) {
|
|
79
178
|
try {
|
|
80
|
-
return { kind: "present", value: await invokeRead(tasks, command) };
|
|
179
|
+
return { kind: "present", value: await invokeRead(tasks, command, current) };
|
|
81
180
|
}
|
|
82
181
|
catch (error) {
|
|
83
182
|
return { kind: "failed", failure: { message: diagnostic(error) } };
|
|
@@ -97,21 +196,13 @@ function missingWorld(command) {
|
|
|
97
196
|
}
|
|
98
197
|
return missing(command.positionals[0]);
|
|
99
198
|
}
|
|
100
|
-
|
|
101
|
-
let world = input.world;
|
|
102
|
-
if (world === null && (command.action === "add" || command.action === "compose"
|
|
103
|
-
|| (command.action === "namespace" && command.positionals.length > 0))) {
|
|
104
|
-
world = await input.establish();
|
|
105
|
-
}
|
|
106
|
-
if (world === null)
|
|
107
|
-
return missingWorld(command);
|
|
108
|
-
const tasks = Tasks.of(world);
|
|
199
|
+
async function invokeLocalMutation(tasks, command, input, current) {
|
|
109
200
|
if (isWorldObservation(command))
|
|
110
|
-
return observeWorldRead(tasks, command);
|
|
201
|
+
return observeWorldRead(tasks, command, current);
|
|
111
202
|
if (command.action === "show" || command.action === "tree")
|
|
112
|
-
return invokeRead(tasks, command);
|
|
203
|
+
return invokeRead(tasks, command, current);
|
|
113
204
|
if (command.action === "add")
|
|
114
|
-
return await invokeAdd(tasks, command, input);
|
|
205
|
+
return await invokeAdd(tasks, command, input, current ?? []);
|
|
115
206
|
if (command.action === "update")
|
|
116
207
|
return await invokeUpdate(tasks, command, input.readStdin);
|
|
117
208
|
const id = command.positionals[0];
|
|
@@ -131,10 +222,39 @@ export async function invokeTask(command, input) {
|
|
|
131
222
|
case "namespace": {
|
|
132
223
|
const selected = namespace(command.positionals[0]);
|
|
133
224
|
if (selected !== undefined)
|
|
134
|
-
await
|
|
135
|
-
return
|
|
225
|
+
await writeTaskNamespaceContext(input.context.directory, selected);
|
|
226
|
+
return { kind: "accepted", value: selected ?? current ?? [] };
|
|
136
227
|
}
|
|
137
|
-
case "compose": return tasks.compose({ markdown: await input.readStdin(), ...(input.actor === undefined ? {} : { actor: input.actor }) });
|
|
228
|
+
case "compose": return tasks.compose({ markdown: await input.readStdin(), namespace: current ?? [], ...(input.actor === undefined ? {} : { actor: input.actor }) });
|
|
138
229
|
default: throw new Error(`task action has no invocation: ${command.action}`);
|
|
139
230
|
}
|
|
140
231
|
}
|
|
232
|
+
function establishesWorld(command) {
|
|
233
|
+
return command.action === "add" || command.action === "compose"
|
|
234
|
+
|| (command.action === "namespace" && command.positionals.length > 0);
|
|
235
|
+
}
|
|
236
|
+
function forwardsMutation(command) {
|
|
237
|
+
return command.action !== "show" && command.action !== "tree"
|
|
238
|
+
&& command.action !== "namespace" && !isWorldObservation(command);
|
|
239
|
+
}
|
|
240
|
+
export async function invokeTask(command, input) {
|
|
241
|
+
const world = input.world ?? (establishesWorld(command) ? await input.establish() : null);
|
|
242
|
+
if (world === null)
|
|
243
|
+
return missingWorld(command);
|
|
244
|
+
const tasks = Tasks.of(world);
|
|
245
|
+
const contextSensitive = command.action === "namespace" || command.action === "add" || command.action === "compose"
|
|
246
|
+
|| ((command.action === "ls" || command.action === "ready" || command.action === "blocked" || command.action === "query") && command.flags.world !== true);
|
|
247
|
+
let current;
|
|
248
|
+
if (contextSensitive) {
|
|
249
|
+
const resolved = await resolveTaskNamespaceContext(input.context);
|
|
250
|
+
if (typeof resolved === "object" && "kind" in resolved)
|
|
251
|
+
return { kind: "refused", refusal: resolved };
|
|
252
|
+
current = resolved;
|
|
253
|
+
}
|
|
254
|
+
const requests = injectedBodyRequests();
|
|
255
|
+
if (requests !== null && forwardsMutation(command)) {
|
|
256
|
+
const request = validatedMutationRequest(await mutationRequest(command, input, current ?? []));
|
|
257
|
+
return await requestBodyTask({ directory: requests, world, request });
|
|
258
|
+
}
|
|
259
|
+
return await invokeLocalMutation(tasks, command, input, current);
|
|
260
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type TaskQueryExpression } from "../../task/
|
|
2
|
-
export type { TaskQueryExpression } from "../../task/
|
|
1
|
+
import { type TaskQueryExpression } from "../../task/query.js";
|
|
2
|
+
export type { TaskQueryExpression } from "../../task/query.js";
|
|
3
3
|
export declare function parseTaskQueryExpression(source: string): TaskQueryExpression;
|
|
4
4
|
export declare function validateTaskLimit(source: string): void;
|
|
5
5
|
export declare function validateTaskParent(source: string): void;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { TASK_RELATION_PREDICATE_FIELDS, } from "../../task/
|
|
2
|
-
import { MAX_TASK_LIMIT, normalizeTaskQuery } from "../../task/query.js";
|
|
1
|
+
import { MAX_TASK_LIMIT, TASK_RELATION_PREDICATE_FIELDS, normalizeTaskQuery, } from "../../task/query.js";
|
|
3
2
|
function syntax(message, offset) { throw new Error(`${message} at column ${offset + 1}`); }
|
|
4
3
|
function scanString(source, offset) {
|
|
5
4
|
let index = offset + 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CliUsageError, isBlankInput, usageLine
|
|
1
|
+
import { CliUsageError, isBlankInput, usageLine } from "../usage.js";
|
|
2
2
|
import { parseTaskQueryExpression, validateTaskLimit, validateTaskParent, } from "./task-query.js";
|
|
3
3
|
const COMMON = { json: "boolean" };
|
|
4
4
|
const TASK_COMMAND_SPECS = {
|
|
@@ -9,18 +9,18 @@ const TASK_COMMAND_SPECS = {
|
|
|
9
9
|
[--note <text>] [--actor <actor>]
|
|
10
10
|
[--needs <TaskId>]... [--parent <TaskId>]
|
|
11
11
|
[--supersedes <TaskId>]... [--relates <TaskId>]...
|
|
12
|
-
[--body <text>]
|
|
13
|
-
task add [--namespace <ns>] [--actor <actor>]
|
|
12
|
+
[--body <text>]
|
|
13
|
+
task add [--namespace <ns>] [--actor <actor>] -`,
|
|
14
14
|
purpose: "Create one Task from flags or a canonical stdin document.",
|
|
15
15
|
},
|
|
16
|
-
show: { arity: [1, 1], flags: COMMON, usage: "task show <TaskId>
|
|
17
|
-
ls: { arity: [0, 0], flags: { ...COMMON, closed: "boolean", all: "boolean", world: "boolean", limit: "value" }, usage: "task ls [--closed | --all] [--world] [--limit <n>]
|
|
18
|
-
ready: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task ready [--world] [--parent <TaskId>] [--limit <n>]
|
|
19
|
-
blocked: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>]
|
|
16
|
+
show: { arity: [1, 1], flags: COMMON, usage: "task show <TaskId>", purpose: "Read one Task and its relationships." },
|
|
17
|
+
ls: { arity: [0, 0], flags: { ...COMMON, closed: "boolean", all: "boolean", world: "boolean", limit: "value" }, usage: "task ls [--closed | --all] [--world] [--limit <n>]", purpose: "List Tasks in the selected scope." },
|
|
18
|
+
ready: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task ready [--world] [--parent <TaskId>] [--limit <n>]", purpose: "List open Tasks whose every need is terminal." },
|
|
19
|
+
blocked: { arity: [0, 0], flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" }, usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>]", purpose: "List Tasks blocked by dependencies." },
|
|
20
20
|
query: { arity: [0, 0], flags: { ...COMMON, where: "value", world: "boolean", sort: "value", limit: "value" }, usage: `task query [--where <expression>] [--world]
|
|
21
|
-
[--sort priority|created|updated|id] [--limit <n>]
|
|
22
|
-
tree: { arity: [1, 1], flags: COMMON, usage: "task tree <TaskId>
|
|
23
|
-
doctor: { arity: [0, 0], flags: COMMON, usage: "task doctor
|
|
21
|
+
[--sort priority|created|updated|id] [--limit <n>]`, purpose: "Query Task facts with a typed boolean expression." },
|
|
22
|
+
tree: { arity: [1, 1], flags: COMMON, usage: "task tree <TaskId>", purpose: "Read one Task parent decomposition tree." },
|
|
23
|
+
doctor: { arity: [0, 0], flags: COMMON, usage: "task doctor", purpose: "Inspect Task authority without repairing it." },
|
|
24
24
|
update: {
|
|
25
25
|
arity: [1, 1], flags: { ...COMMON, title: "value", body: "value", append: "value", note: "value", priority: "value", needs: "repeat", "drop-needs": "repeat", parent: "value", "no-parent": "boolean", supersedes: "repeat", "drop-supersedes": "repeat", relates: "repeat", "drop-relates": "repeat" },
|
|
26
26
|
usage: `task update <TaskId> [--title <text>] [--body <text>|- | --append <text>|-]
|
|
@@ -28,17 +28,17 @@ task add [--namespace <ns>] [--actor <actor>] [--json] -`,
|
|
|
28
28
|
[--priority 0..3] [--needs <TaskId>]... [--drop-needs <TaskId>]...
|
|
29
29
|
[--parent <TaskId> | --no-parent]
|
|
30
30
|
[--supersedes <TaskId>]... [--drop-supersedes <TaskId>]...
|
|
31
|
-
[--relates <TaskId>]... [--drop-relates <TaskId>]
|
|
31
|
+
[--relates <TaskId>]... [--drop-relates <TaskId>]...`,
|
|
32
32
|
purpose: "Apply one or more patches to a Task.",
|
|
33
33
|
},
|
|
34
|
-
start: { arity: [1, 1], flags: COMMON, usage: "task start <TaskId>
|
|
35
|
-
stop: { arity: [1, 1], flags: COMMON, usage: "task stop <TaskId>
|
|
36
|
-
hold: { arity: [1, Number.POSITIVE_INFINITY], flags: COMMON, usage: "task hold <TaskId>...
|
|
37
|
-
resume: { arity: [1, 1], flags: COMMON, usage: "task resume <TaskId>
|
|
38
|
-
done: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task done <TaskId>... [--note <text>]
|
|
39
|
-
drop: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task drop <TaskId>... [--note <text>]
|
|
40
|
-
namespace: { arity: [0, 1], flags: COMMON, usage: "task namespace [<namespace>]
|
|
41
|
-
compose: { arity: [0, 0], stdin: "compose", flags: { ...COMMON, actor: "value" }, usage: "task compose [--actor <actor>]
|
|
34
|
+
start: { arity: [1, 1], flags: COMMON, usage: "task start <TaskId>", purpose: "Move one open Task into progress." },
|
|
35
|
+
stop: { arity: [1, 1], flags: COMMON, usage: "task stop <TaskId>", purpose: "Return one in-progress Task to open." },
|
|
36
|
+
hold: { arity: [1, Number.POSITIVE_INFINITY], flags: COMMON, usage: "task hold <TaskId>...", purpose: "Put one or more Tasks on hold." },
|
|
37
|
+
resume: { arity: [1, 1], flags: COMMON, usage: "task resume <TaskId>", purpose: "Return one held Task to open." },
|
|
38
|
+
done: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task done <TaskId>... [--note <text>]", purpose: "Mark one or more Tasks done." },
|
|
39
|
+
drop: { arity: [1, Number.POSITIVE_INFINITY], flags: { ...COMMON, note: "value" }, usage: "task drop <TaskId>... [--note <text>]", purpose: "Drop one or more Tasks." },
|
|
40
|
+
namespace: { arity: [0, 1], flags: COMMON, usage: "task namespace [<namespace>]", purpose: "Read or replace the current Task namespace." },
|
|
41
|
+
compose: { arity: [0, 0], stdin: "compose", flags: { ...COMMON, actor: "value" }, usage: "task compose [--actor <actor>] -", purpose: "Admit Task documents independently; partial admission has no cross-file atomicity or rollback." },
|
|
42
42
|
};
|
|
43
43
|
export function isTaskAction(value) {
|
|
44
44
|
return value !== undefined && Object.hasOwn(TASK_COMMAND_SPECS, value);
|
|
@@ -46,14 +46,14 @@ export function isTaskAction(value) {
|
|
|
46
46
|
export function renderTaskHelp(action) {
|
|
47
47
|
if (action !== undefined) {
|
|
48
48
|
const spec = TASK_COMMAND_SPECS[action];
|
|
49
|
-
return
|
|
49
|
+
return `${spec.purpose}\n\n${usageLine(spec.usage)}`;
|
|
50
50
|
}
|
|
51
|
-
return
|
|
51
|
+
return [
|
|
52
52
|
"usage: keiyaku task <command> ...",
|
|
53
53
|
"",
|
|
54
54
|
"commands:",
|
|
55
55
|
...Object.values(TASK_COMMAND_SPECS).flatMap((spec) => spec.usage.split("\n").map((line) => ` ${line}`).concat(` ${spec.purpose}`)),
|
|
56
|
-
].join("\n")
|
|
56
|
+
].join("\n");
|
|
57
57
|
}
|
|
58
58
|
export function renderTaskUsage(action) {
|
|
59
59
|
return usageLine(TASK_COMMAND_SPECS[action].usage);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Repo } from "../
|
|
1
|
+
import { Repo } from "../library/repo.js";
|
|
2
2
|
import { type WorldRoot } from "../world.js";
|
|
3
3
|
import { type ParsedCommand } from "./parse.js";
|
|
4
4
|
export type CliCoordinates = Readonly<{
|
|
@@ -7,13 +7,17 @@ export type CliCoordinates = Readonly<{
|
|
|
7
7
|
repo?: Repo;
|
|
8
8
|
world: WorldRoot | null;
|
|
9
9
|
candidateWorld: WorldRoot | null;
|
|
10
|
+
taskContext: Readonly<{
|
|
11
|
+
directory: string;
|
|
12
|
+
boundary: string;
|
|
13
|
+
}>;
|
|
10
14
|
establishWorld: () => Promise<WorldRoot>;
|
|
11
15
|
}>;
|
|
12
16
|
export type CliCoordinateInput = Readonly<{
|
|
13
17
|
processCwd?: string;
|
|
14
18
|
cwd?: string;
|
|
15
19
|
repo?: string;
|
|
20
|
+
gitPath?: string;
|
|
16
21
|
command: ParsedCommand;
|
|
17
22
|
}>;
|
|
18
|
-
export declare function assertExplicitRepoUse(command: ParsedCommand, repo: string | undefined): void;
|
|
19
23
|
export declare function resolveCliCoordinates(input: CliCoordinateInput): Promise<CliCoordinates>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { realpath } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { NoGitWorldError, Repo } from "../
|
|
3
|
+
import { NoGitWorldError, Repo } from "../library/repo.js";
|
|
4
4
|
import { World, WorldError } from "../world.js";
|
|
5
|
-
import { CliUsageError } from "./parse.js";
|
|
5
|
+
import { CliUsageError, commandRepoPolicy } from "./parse.js";
|
|
6
6
|
async function canonicalInvocationCwd(input) {
|
|
7
7
|
try {
|
|
8
8
|
return await realpath(input);
|
|
@@ -11,9 +11,12 @@ async function canonicalInvocationCwd(input) {
|
|
|
11
11
|
throw new CliUsageError(`invocation cwd is not an existing directory: ${input}`);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
async function discoverRepoAt(coordinate) {
|
|
14
|
+
async function discoverRepoAt(coordinate, gitPath) {
|
|
15
15
|
try {
|
|
16
|
-
return {
|
|
16
|
+
return {
|
|
17
|
+
kind: "present",
|
|
18
|
+
repo: await Repo.at({ path: coordinate, ...(gitPath === undefined ? {} : { gitPath }) }),
|
|
19
|
+
};
|
|
17
20
|
}
|
|
18
21
|
catch (error) {
|
|
19
22
|
if (error instanceof NoGitWorldError)
|
|
@@ -21,55 +24,6 @@ async function discoverRepoAt(coordinate) {
|
|
|
21
24
|
throw error;
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
function repoPolicy(command) {
|
|
25
|
-
switch (command.command) {
|
|
26
|
-
case "bind":
|
|
27
|
-
case "amend":
|
|
28
|
-
case "deliver":
|
|
29
|
-
case "review":
|
|
30
|
-
case "arc":
|
|
31
|
-
case "abandon":
|
|
32
|
-
case "audit":
|
|
33
|
-
case "reconcile":
|
|
34
|
-
case "show":
|
|
35
|
-
case "region":
|
|
36
|
-
return { use: "required", acceptsExplicit: true };
|
|
37
|
-
case "ls":
|
|
38
|
-
return { use: command.query.kind === "contracts" ? "required" : "none", acceptsExplicit: false };
|
|
39
|
-
case "status":
|
|
40
|
-
case "tell":
|
|
41
|
-
return { use: "optional", acceptsExplicit: false };
|
|
42
|
-
case "history":
|
|
43
|
-
return "contract" in command
|
|
44
|
-
? { use: "required", acceptsExplicit: true }
|
|
45
|
-
: { use: "optional", acceptsExplicit: false };
|
|
46
|
-
case "fork":
|
|
47
|
-
return { use: "optional", acceptsExplicit: true };
|
|
48
|
-
case "wait":
|
|
49
|
-
case "kill": {
|
|
50
|
-
const contractSelector = command.akuma.some((selector) => selector.startsWith("kei/"));
|
|
51
|
-
return { use: contractSelector ? "required" : "optional", acceptsExplicit: contractSelector };
|
|
52
|
-
}
|
|
53
|
-
case "call":
|
|
54
|
-
return {
|
|
55
|
-
use: command.contract === undefined ? "none" : "required",
|
|
56
|
-
acceptsExplicit: command.contract !== undefined,
|
|
57
|
-
};
|
|
58
|
-
case "settings":
|
|
59
|
-
case "task":
|
|
60
|
-
case "install":
|
|
61
|
-
return { use: "none", acceptsExplicit: false };
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function refuseUnusedRepo(command) {
|
|
65
|
-
if (command.command === "call")
|
|
66
|
-
throw new CliUsageError("--repo has no consumer without --contract");
|
|
67
|
-
throw new CliUsageError(`--repo has no consumer for ${command.command}`);
|
|
68
|
-
}
|
|
69
|
-
export function assertExplicitRepoUse(command, repo) {
|
|
70
|
-
if (repo !== undefined && !repoPolicy(command).acceptsExplicit)
|
|
71
|
-
refuseUnusedRepo(command);
|
|
72
|
-
}
|
|
73
27
|
function repoFor(use, discovery) {
|
|
74
28
|
if (use === "none")
|
|
75
29
|
return undefined;
|
|
@@ -106,19 +60,21 @@ async function resolveWorld(cwd, repo) {
|
|
|
106
60
|
export async function resolveCliCoordinates(input) {
|
|
107
61
|
const processCwd = resolve(input.processCwd ?? ".");
|
|
108
62
|
const cwd = await canonicalInvocationCwd(resolve(processCwd, input.cwd ?? "."));
|
|
109
|
-
const invocationRepo = await discoverRepoAt(cwd);
|
|
63
|
+
const invocationRepo = await discoverRepoAt(cwd, input.gitPath);
|
|
110
64
|
const selectedRepo = input.repo === undefined
|
|
111
65
|
? invocationRepo
|
|
112
|
-
: await discoverRepoAt(resolve(cwd, input.repo));
|
|
66
|
+
: await discoverRepoAt(resolve(cwd, input.repo), input.gitPath);
|
|
113
67
|
const worldRepo = invocationRepo.kind === "present" ? invocationRepo.repo : undefined;
|
|
114
|
-
const repo = repoFor(
|
|
68
|
+
const repo = repoFor(commandRepoPolicy(input.command).use, selectedRepo);
|
|
115
69
|
const world = await resolveWorld(cwd, worldRepo);
|
|
70
|
+
const boundary = worldRepo === undefined ? world.root ?? world.candidate ?? cwd : worldRepo.cwd;
|
|
116
71
|
return {
|
|
117
72
|
cwd,
|
|
118
73
|
cwdSource: input.cwd === undefined ? "process" : "input",
|
|
119
74
|
...(repo === undefined ? {} : { repo }),
|
|
120
75
|
world: world.root,
|
|
121
76
|
candidateWorld: world.candidate,
|
|
77
|
+
taskContext: { directory: cwd, boundary },
|
|
122
78
|
establishWorld: world.establish,
|
|
123
79
|
};
|
|
124
80
|
}
|