@astrosheep/keiyaku 2.9.4 → 2.9.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/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +1 -0
- package/build/agents/harness/execution-handle.js +1 -0
- package/build/agents/harness/outcome.js +31 -5
- package/build/agents/harness/projection.js +151 -78
- package/build/agents/harness/router.js +2 -1
- package/build/agents/providers/claude-agent-sdk/adapter.js +13 -1
- package/build/agents/providers/claude-agent-sdk/registration.js +2 -1
- package/build/agents/providers/codex-app-server/adapter.js +43 -10
- package/build/agents/providers/codex-app-server/events.js +23 -0
- package/build/agents/providers/codex-app-server/registration.js +2 -1
- package/build/agents/providers/opencode-sdk/adapter.js +7 -0
- package/build/agents/providers/opencode-sdk/registration.js +2 -1
- package/build/agents/providers/pi/adapter.js +10 -0
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +3 -1
- package/build/agents/types.js +2 -0
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +1 -1
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/meta.js +20 -11
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +1 -2
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +2 -2
- package/build/cli/commands/contract/renew/meta.js +4 -4
- package/build/cli/commands/metadata.js +3 -2
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +1 -1
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/meta.js +1 -1
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +2 -2
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +10 -4
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/show/meta.js +1 -1
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +2 -3
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +9 -2
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +3 -3
- package/build/cli/index.js +59 -75
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +19 -2
- package/build/cli/parse-metadata.js +1 -7
- package/build/cli/parse-selectors.js +1 -0
- package/build/cli/parse.js +16 -7
- package/build/cli/projection-address.js +6 -1
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/errors.js +18 -1
- package/build/cli/render/format.js +5 -2
- package/build/cli/render/misc.js +3 -1
- package/build/cli/render/projection-activity.js +12 -6
- package/build/cli/render/status.js +28 -18
- package/build/cli/render/success-response.js +6 -5
- package/build/cli/render/task.js +12 -43
- package/build/cli/render/terminal-failure.js +7 -2
- package/build/cli/render/wait.js +36 -8
- package/build/config/env-keys.js +2 -0
- package/build/config/env.js +3 -0
- package/build/core/amend.js +20 -94
- package/build/core/arc.js +14 -6
- package/build/core/audit/candidate.js +48 -0
- package/build/core/audit/coordinates.js +180 -0
- package/build/core/audit/evidence.js +158 -0
- package/build/core/audit/facade.js +42 -0
- package/build/core/audit/readiness.js +4 -0
- package/build/core/audit/report.js +38 -0
- package/build/core/audit.js +1 -0
- package/build/core/bind.js +1 -1
- package/build/core/call/execution.js +1 -0
- package/build/core/contract-view.js +2 -3
- package/build/core/draft.js +33 -20
- package/build/core/entry.js +3 -4
- package/build/core/markdown/lex.js +2 -1
- package/build/core/projection/generation/database.js +41 -16
- package/build/core/projection/generation/model.js +22 -2
- package/build/core/projection/generation/projection-generation-execution.js +20 -7
- package/build/core/projection/generation/projection-generation-launcher.js +4 -4
- package/build/core/projection/generation/projection-generation-runner.js +1 -0
- package/build/core/projection/generation/store.js +1 -1
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +2 -2
- package/build/core/projection/projection-execution-observer.js +35 -21
- package/build/core/projection/projection-life-observer.js +16 -2
- package/build/core/projection/projection-status.js +67 -22
- package/build/core/projection/projection-terminal-failure.js +2 -0
- package/build/core/projection/projection-wait.js +6 -9
- package/build/core/projection/projection-wake.js +30 -6
- package/build/core/renew.js +41 -22
- package/build/core/scope.js +129 -2
- package/build/core/seal.js +36 -15
- package/build/core/settlement/petition-claim-gates.js +4 -33
- package/build/core/settlement/petition-preview.js +1 -1
- package/build/core/settlement/petition.js +10 -3
- package/build/core/settlement/settlement.js +3 -10
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +48 -28
- package/build/core/stored-agent-event.js +3 -2
- package/build/core/task/board.js +1 -0
- package/build/core/task/commands.js +20 -12
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +1 -1
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +214 -0
- package/build/core/task/settlement-git.js +115 -16
- package/build/core/task/settlement-policy.js +17 -9
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +125 -51
- package/build/core/task/task-store-repository.js +1 -0
- package/build/core/task/task.js +2 -0
- package/build/flow-error.js +2 -4
- package/build/generated/version.js +2 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/index.js +7 -7
- package/build/telemetry/logger.js +4 -2
- package/package.json +1 -1
- package/skills/keiyaku/SKILL.md +2 -2
- package/skills/keiyaku-akuma/SKILL.md +17 -6
- package/skills/keiyaku-task/SKILL.md +16 -7
- package/skills/keiyaku-workflow/SKILL.md +48 -13
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createGit, wrapGitError } from "../core.js";
|
|
2
|
+
import { diffPathspecArgs } from "./pathspec.js";
|
|
3
|
+
import { parseHunkRange, parseUnifiedHunks, splitDiffByFile } from "./parsers.js";
|
|
4
|
+
function parseRawDiff(output) {
|
|
5
|
+
const fields = output.split("\0");
|
|
6
|
+
const files = [];
|
|
7
|
+
let index = 0;
|
|
8
|
+
while (index < fields.length) {
|
|
9
|
+
const header = fields[index++];
|
|
10
|
+
if (!header)
|
|
11
|
+
continue;
|
|
12
|
+
const statusToken = header.trim().split(/\s+/).at(-1) ?? "";
|
|
13
|
+
const status = statusToken[0];
|
|
14
|
+
if (status !== "A" && status !== "M" && status !== "D" && status !== "R" && status !== "C" && status !== "T" && status !== "U")
|
|
15
|
+
continue;
|
|
16
|
+
const firstPath = fields[index++] ?? "";
|
|
17
|
+
if (status === "R" || status === "C") {
|
|
18
|
+
const path = fields[index++] ?? "";
|
|
19
|
+
files.push({
|
|
20
|
+
oldPath: firstPath,
|
|
21
|
+
path,
|
|
22
|
+
status,
|
|
23
|
+
similarity: Number.parseInt(statusToken.slice(1), 10) || 0,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
files.push({ path: firstPath, status });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
function withoutTerminalPatchDelimiter(patch) {
|
|
33
|
+
return patch.endsWith("\n") ? patch.slice(0, -1) : patch;
|
|
34
|
+
}
|
|
35
|
+
function parseNumstat(output) {
|
|
36
|
+
const fields = output.split("\0");
|
|
37
|
+
const stats = [];
|
|
38
|
+
let index = 0;
|
|
39
|
+
while (index < fields.length) {
|
|
40
|
+
const record = fields[index++];
|
|
41
|
+
if (!record)
|
|
42
|
+
continue;
|
|
43
|
+
const [added = "0", removed = "0", path = ""] = record.split("\t");
|
|
44
|
+
const binary = added === "-" || removed === "-";
|
|
45
|
+
if (path) {
|
|
46
|
+
stats.push({ path, insertions: binary ? 0 : Number.parseInt(added, 10) || 0, deletions: binary ? 0 : Number.parseInt(removed, 10) || 0, binary });
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const oldPath = fields[index++] ?? "";
|
|
50
|
+
const newPath = fields[index++] ?? "";
|
|
51
|
+
stats.push({ path: newPath, oldPath, insertions: binary ? 0 : Number.parseInt(added, 10) || 0, deletions: binary ? 0 : Number.parseInt(removed, 10) || 0, binary });
|
|
52
|
+
}
|
|
53
|
+
return stats;
|
|
54
|
+
}
|
|
55
|
+
function structuredLines(raw, oldStart, newStart) {
|
|
56
|
+
let oldLine = oldStart;
|
|
57
|
+
let newLine = newStart;
|
|
58
|
+
const lines = [];
|
|
59
|
+
for (const line of raw) {
|
|
60
|
+
if (line.startsWith("\"))
|
|
61
|
+
continue;
|
|
62
|
+
if (line.startsWith("+")) {
|
|
63
|
+
lines.push({ kind: "addition", content: line.slice(1), oldLine: null, newLine: newLine++ });
|
|
64
|
+
}
|
|
65
|
+
else if (line.startsWith("-")) {
|
|
66
|
+
lines.push({ kind: "deletion", content: line.slice(1), oldLine: oldLine++, newLine: null });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
lines.push({ kind: "context", content: line.startsWith(" ") ? line.slice(1) : line, oldLine: oldLine++, newLine: newLine++ });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return lines;
|
|
73
|
+
}
|
|
74
|
+
function parsePatchHunks(section) {
|
|
75
|
+
return parseUnifiedHunks([...section]).hunks.flatMap((hunk, index) => {
|
|
76
|
+
const range = parseHunkRange(hunk.header);
|
|
77
|
+
if (!range)
|
|
78
|
+
return [];
|
|
79
|
+
return [{
|
|
80
|
+
index,
|
|
81
|
+
header: hunk.header,
|
|
82
|
+
oldStart: range.oldStart,
|
|
83
|
+
oldLines: range.oldLines,
|
|
84
|
+
newStart: range.newStart,
|
|
85
|
+
newLines: range.newLines,
|
|
86
|
+
lines: structuredLines(hunk.lines, range.oldStart, range.newStart),
|
|
87
|
+
}];
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export async function readStructuredDiff(cwd, from, to, options = {}) {
|
|
91
|
+
const git = createGit(cwd);
|
|
92
|
+
const range = `${from}..${to}`;
|
|
93
|
+
const pathspec = diffPathspecArgs({ excludePaths: options.excludePaths });
|
|
94
|
+
try {
|
|
95
|
+
const [raw, numstat, patch] = await Promise.all([
|
|
96
|
+
git.raw(["diff", "--raw", "-z", "--find-renames", range, ...pathspec]),
|
|
97
|
+
git.raw(["diff", "--numstat", "-z", "--find-renames", range, ...pathspec]),
|
|
98
|
+
git.raw(["diff", "--no-color", "--no-ext-diff", "--unified=3", "--find-renames", range, ...pathspec]),
|
|
99
|
+
]);
|
|
100
|
+
const rawFiles = parseRawDiff(raw);
|
|
101
|
+
const stats = parseNumstat(numstat);
|
|
102
|
+
const sections = splitDiffByFile(withoutTerminalPatchDelimiter(patch));
|
|
103
|
+
const files = rawFiles.map((file, index) => {
|
|
104
|
+
const stat = stats[index];
|
|
105
|
+
return {
|
|
106
|
+
...file,
|
|
107
|
+
insertions: stat?.insertions ?? 0,
|
|
108
|
+
deletions: stat?.deletions ?? 0,
|
|
109
|
+
binary: stat?.binary ?? false,
|
|
110
|
+
hunks: parsePatchHunks(sections[index] ?? []),
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
from,
|
|
115
|
+
to,
|
|
116
|
+
files,
|
|
117
|
+
stat: {
|
|
118
|
+
filesChanged: files.length,
|
|
119
|
+
insertions: files.reduce((sum, file) => sum + file.insertions, 0),
|
|
120
|
+
deletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
throw wrapGitError(`diff --find-renames ${range}`, error, cwd);
|
|
126
|
+
}
|
|
127
|
+
}
|
package/build/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import { VERSION, GIT_HASH } from "./generated/version.js";
|
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import { getConfig, initializeConfig } from "./config/env.js";
|
|
5
5
|
import { ENV_KEYS } from "./config/env-keys.js";
|
|
6
|
-
import {
|
|
6
|
+
import { formatErrorWithCause } from "./telemetry/logger.js";
|
|
7
7
|
import { runProjectionGenerationRuntime } from "./core/projection/index.js";
|
|
8
8
|
import { renderCliHelp, runCliCommand } from "./cli/index.js";
|
|
9
|
-
import { installCliOutputStreamErrorPolicy } from "./cli/output-stream-error-policy.js";
|
|
9
|
+
import { installCliOutputStreamErrorPolicy, writeCliOutput } from "./cli/output-stream-error-policy.js";
|
|
10
10
|
import { assertSubagentCliCommandAllowed } from "./cli/subagent-guard.js";
|
|
11
11
|
installCliOutputStreamErrorPolicy(process.stdout, process.stderr);
|
|
12
12
|
const packageVersion = VERSION;
|
|
@@ -45,16 +45,16 @@ async function main() {
|
|
|
45
45
|
args: cliArgs,
|
|
46
46
|
});
|
|
47
47
|
if (cliArgs.length === 1 && cliArgs[0] === "--version") {
|
|
48
|
-
|
|
48
|
+
await writeCliOutput(process.stdout, `${GIT_HASH ? `${packageVersion} (${GIT_HASH})` : packageVersion}\n`);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
if (cliArgs.length === 0 || (cliArgs.length === 1 && (cliArgs[0] === "--help" || cliArgs[0] === "-h"))) {
|
|
52
|
-
|
|
52
|
+
await writeCliOutput(process.stdout, `${renderCliHelp(packageVersion)}\n`);
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
process.exitCode = await runCliCommand(cliArgs);
|
|
56
56
|
}
|
|
57
|
-
main().catch((err) => {
|
|
58
|
-
|
|
59
|
-
process.
|
|
57
|
+
await main().catch(async (err) => {
|
|
58
|
+
await writeCliOutput(process.stderr, `${formatErrorWithCause("Fatal error:", err)}\n`);
|
|
59
|
+
process.exitCode = 1;
|
|
60
60
|
});
|
|
@@ -31,6 +31,9 @@ function stringifyUnknown(error) {
|
|
|
31
31
|
return String(error);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
export function formatErrorWithCause(message, error) {
|
|
35
|
+
return `${message} ${stringifyUnknown(error)}`;
|
|
36
|
+
}
|
|
34
37
|
export function logInfo(message, options = {}) {
|
|
35
38
|
log("info", message, options);
|
|
36
39
|
}
|
|
@@ -41,6 +44,5 @@ export function logError(message, options = {}) {
|
|
|
41
44
|
log("error", message, options);
|
|
42
45
|
}
|
|
43
46
|
export function logErrorWithCause(message, error, options = {}) {
|
|
44
|
-
|
|
45
|
-
logError(`${message} ${details}`, options);
|
|
47
|
+
logError(formatErrorWithCause(message, error), options);
|
|
46
48
|
}
|
package/package.json
CHANGED
package/skills/keiyaku/SKILL.md
CHANGED
|
@@ -25,7 +25,7 @@ cd .keiyaku/wt/<place> # work here yourself, or call an Ak
|
|
|
25
25
|
keiyaku call <akuma> "fix it" # worker leaves reviewed source as a dirty tree
|
|
26
26
|
# host coordinator reviews, then git -C <worktree> add/commit accepted paths
|
|
27
27
|
keiyaku status # is anything stuck? what's next?
|
|
28
|
-
keiyaku petition <<'EOF'
|
|
28
|
+
keiyaku petition - <<'EOF' # done: seal + settle; the oath is required
|
|
29
29
|
## Oath
|
|
30
30
|
I fixed the flaky test; suite is green.
|
|
31
31
|
EOF
|
|
@@ -33,7 +33,7 @@ EOF
|
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
That's the whole loop. Skip the task when the work needs no planning:
|
|
36
|
-
`keiyaku bind --place NAME --objective TEXT --scope GLOB --checks CHECK` (or the same as Markdown
|
|
36
|
+
`keiyaku bind --place NAME --objective TEXT --scope GLOB --checks CHECK` (or the same as Markdown through `keiyaku bind -` — `bind --help` shows the shape).
|
|
37
37
|
|
|
38
38
|
## Getting oriented
|
|
39
39
|
|
|
@@ -8,9 +8,10 @@ allowed-tools: Bash(keiyaku *)
|
|
|
8
8
|
|
|
9
9
|
Running devils. Contract lifecycle = `keiyaku-workflow` skill.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Core ideas
|
|
12
12
|
|
|
13
|
-
- **profile** —
|
|
13
|
+
- **profile** — callable configuration: frontmatter selects provider/model;
|
|
14
|
+
Markdown body gives instructions. Project overrides user, which overrides builtin.
|
|
14
15
|
- **projection** (`name/8hex`) — one live run of a devil. This is the id for `wait` / `tell` / `kill`.
|
|
15
16
|
- **artifact** (`rsp_…`) — what a finished run left behind. This is the id for `revive`.
|
|
16
17
|
|
|
@@ -22,6 +23,7 @@ failed/dead state alone is not a reason to revive.
|
|
|
22
23
|
|
|
23
24
|
```bash
|
|
24
25
|
keiyaku akuma ls # who's callable
|
|
26
|
+
keiyaku akuma view NAME # resolved profile + live projections
|
|
25
27
|
keiyaku call NAME "do the thing" # run in foreground until it finishes
|
|
26
28
|
keiyaku call NAME --wait 10m "do the thing" # bounded: after 10m you get a snapshot, it keeps running
|
|
27
29
|
keiyaku call NAME --detach "do the thing" # fire and forget; note the projection id
|
|
@@ -34,19 +36,28 @@ keiyaku kill <proj-id> # stop it; record survives, revive
|
|
|
34
36
|
keiyaku status # forgot an id? it's on the board
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
<repo>/.keiyaku/akuma/<name>.md project profile
|
|
43
|
+
<KEIYAKU_HOME>/akuma/<name>.md user profile (normally ~/.keiyaku)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use `keiyaku akuma view NAME` to inspect the resolved source and configuration.
|
|
47
|
+
|
|
37
48
|
## Expectations
|
|
38
49
|
|
|
39
50
|
- Omit tell's bracketed `--wait DURATION` option for silent success: exit 0,
|
|
40
51
|
zero output. Supply it to perform the ordinary bounded join after acceptance.
|
|
41
52
|
Silence **is** the receipt — do not re-send. Effects show up in `wait`/`status`.
|
|
42
|
-
- Body is required for `call`/`tell`.
|
|
53
|
+
- Body is required for `call`/`tell`. Literal `-` selects stdin; unselected
|
|
54
|
+
piped bytes are ignored and cannot change an argv body.
|
|
43
55
|
- A `--wait`/`--timeout` expiry prints a live snapshot and exits 0 — the run continues; rejoin with `wait` anytime.
|
|
44
56
|
- `wait` is repeatable: on a finished run it shows the final transcript again.
|
|
45
|
-
- Only `--contract ADDR` attaches a new call to a contract (by place, slug, or full id). Without it, call is standalone; `--bare` remains an explicit synonym. `call` only — `revive` takes neither and follows artifact provenance.
|
|
46
57
|
|
|
47
58
|
## Occasional flags
|
|
48
59
|
|
|
49
60
|
- `--incognito` — no artifact written, no revive possible (call)
|
|
50
61
|
- `--effort LEVEL` — provider effort override; needs a model set (call, revive, tell)
|
|
51
|
-
-
|
|
52
|
-
|
|
62
|
+
- `--repo DIR` — override repository inference only when the contract ledger
|
|
63
|
+
lives in a different repository.
|
|
@@ -8,22 +8,26 @@ allowed-tools: Bash(keiyaku *)
|
|
|
8
8
|
|
|
9
9
|
Planning notes that live in the repo. Executing them is `keiyaku-workflow` (`bind --task`).
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Core ideas
|
|
12
12
|
|
|
13
|
-
A task is a
|
|
13
|
+
A task is a tracked planning fact, not a worker or execution. Its immutable ID
|
|
14
|
+
is a normalized title slug with a numeric collision suffix when needed. It has
|
|
15
|
+
priority 0–3 (0 highest), optional body, and no branch of its own.
|
|
14
16
|
|
|
15
17
|
```
|
|
16
18
|
open ⇄ in_progress → done | drop
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
**Ready** = open + every `needs` dependency
|
|
21
|
+
**Ready** = open + every `needs` dependency satisfied. `needs` only orders
|
|
22
|
+
tasks; binding is what turns ready planning facts into one executable contract.
|
|
20
23
|
|
|
21
24
|
## Common usage
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
keiyaku task add
|
|
27
|
+
keiyaku task add - < task.md # literal - reads the task body from stdin
|
|
25
28
|
keiyaku task add "title" --pri 1 --needs k-aaa # priority + dependency at birth
|
|
26
|
-
keiyaku task ls # all
|
|
29
|
+
keiyaku task ls # all nonterminal tasks
|
|
30
|
+
keiyaku task ls --filter state=ready --sort priority,modified
|
|
27
31
|
keiyaku task show k-xxxx # full detail and parent-children tree
|
|
28
32
|
keiyaku task start k-xxxx # mark in_progress (start ≠ execute)
|
|
29
33
|
keiyaku task stop k-xxxx # back to open
|
|
@@ -41,10 +45,15 @@ keiyaku task doctor # check board integrity
|
|
|
41
45
|
## Promoting to a contract
|
|
42
46
|
|
|
43
47
|
```bash
|
|
44
|
-
keiyaku bind --task
|
|
48
|
+
keiyaku bind --task fix-parser
|
|
49
|
+
keiyaku bind --task fix-parser --task fix-parser-help - < contract.md
|
|
45
50
|
```
|
|
46
51
|
|
|
47
|
-
Only
|
|
52
|
+
Only ready tasks bind. Multi-bind only when the tasks describe one delivery
|
|
53
|
+
intent, share a coherent write surface, and should settle together; otherwise
|
|
54
|
+
keep separate contracts and express order with task `needs` or contract
|
|
55
|
+
`--after`. The first task supplies name/objective defaults; provide a partial
|
|
56
|
+
bind document for any missing `Scope` or `Checks`.
|
|
48
57
|
|
|
49
58
|
## Gotcha
|
|
50
59
|
|
|
@@ -8,9 +8,15 @@ allowed-tools: Bash(keiyaku *)
|
|
|
8
8
|
|
|
9
9
|
How a contract lives. Running akuma is the `keiyaku-akuma` skill; task planning is `keiyaku-task`.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Core ideas
|
|
12
12
|
|
|
13
|
-
A contract
|
|
13
|
+
- A contract is one delivery intent with one ledger, branch, and linked worktree.
|
|
14
|
+
- Workers edit and test; the host reviews their dirty tree and commits accepted bytes.
|
|
15
|
+
- `audit` reads one pinned candidate. `petition` is the settlement action.
|
|
16
|
+
- Scope is an audit boundary, not a write lock. Amend changed intent before delivery.
|
|
17
|
+
- An arc is a named story chapter for one coherent stretch inside the contract.
|
|
18
|
+
|
|
19
|
+
Lifecycle:
|
|
14
20
|
|
|
15
21
|
```
|
|
16
22
|
bound → active → petitioned → claimed | forfeited
|
|
@@ -21,9 +27,10 @@ bound → active → petitioned → claimed | forfeited
|
|
|
21
27
|
```bash
|
|
22
28
|
keiyaku bind --place fix-pump --objective "make the pump test pass" \
|
|
23
29
|
--scope "src/pump/**" --checks "pump tests green"
|
|
24
|
-
# or the same four fields as Markdown: keiyaku bind < contract.md
|
|
30
|
+
# or the same four fields as Markdown: keiyaku bind - < contract.md
|
|
25
31
|
# (# <name> / ## Objective / ## Scope / ## Checks)
|
|
26
|
-
# or promote
|
|
32
|
+
# or promote one or more ready tasks:
|
|
33
|
+
keiyaku bind --task fix-parser --task fix-parser-help - < contract.md
|
|
27
34
|
|
|
28
35
|
cd .keiyaku/wt/fix-pump # worker edits/tests here and leaves a dirty tree
|
|
29
36
|
|
|
@@ -31,7 +38,10 @@ cd .keiyaku/wt/fix-pump # worker edits/tests here and leaves a dirty tr
|
|
|
31
38
|
git -C .keiyaku/wt/fix-pump add -- <accepted-paths>
|
|
32
39
|
git -C .keiyaku/wt/fix-pump commit -m "fix pump"
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
# Rehearse the exact pinned delivery before settlement:
|
|
42
|
+
keiyaku @fix-pump audit
|
|
43
|
+
|
|
44
|
+
keiyaku petition - <<'EOF'
|
|
35
45
|
## Oath
|
|
36
46
|
I made the pump test pass; ran the suite, all green.
|
|
37
47
|
EOF
|
|
@@ -41,37 +51,62 @@ EOF
|
|
|
41
51
|
# The oath is required (OATH_MISSING otherwise) and checked for presence, not content.
|
|
42
52
|
```
|
|
43
53
|
|
|
54
|
+
A task is optional planning, not a prerequisite. Bind directly for new work;
|
|
55
|
+
use `--task` only when promoting existing tracked planning into this contract.
|
|
56
|
+
|
|
44
57
|
That's the whole small case: bind → worker dirty-tree handoff → host review/commit → petition.
|
|
45
58
|
|
|
46
|
-
|
|
59
|
+
Multi-bind tasks only when they are evidence for the same delivery intent, share
|
|
60
|
+
one coherent write surface, and should settle together. This reduces competing
|
|
61
|
+
contracts/worktrees; it does not replace `needs` or contract `--after` ordering.
|
|
62
|
+
|
|
63
|
+
`audit` is read-only and never invokes an Akuma or settles the contract. Exit 0
|
|
64
|
+
means it constructed the report, not that the candidate is acceptable. Use
|
|
65
|
+
`--diff-budget BYTES` for bounded output and `--json` for complete typed facts.
|
|
66
|
+
|
|
67
|
+
Commissioned workers never write Git metadata. The host alone reviews and
|
|
68
|
+
commits accepted bytes before `arc`, `renew`, or `petition`.
|
|
69
|
+
|
|
70
|
+
Dispatch rule: every time a dispatcher sends a worker, whether through
|
|
71
|
+
`keiyaku call` or any other agent tool, the prompt must explicitly tell that
|
|
72
|
+
worker to read the worktree-root `.keiyaku/KEIYAKU.md` first and follow its
|
|
73
|
+
objective, scope, and checks. The file is the contract-body carrier; do not
|
|
74
|
+
copy its rendered body into a dispatch prompt.
|
|
47
75
|
|
|
48
76
|
## Mid-flight commands (use when needed, skip otherwise)
|
|
49
77
|
|
|
50
78
|
```bash
|
|
51
|
-
keiyaku arc < arc.md
|
|
79
|
+
keiyaku arc - < arc.md # optional iteration boundary: seals the current intent, opens
|
|
52
80
|
# the next. Markdown: # <title> / ## Objective / ## Brief.
|
|
53
81
|
# Only needed when one contract has multiple distinct pushes.
|
|
54
82
|
keiyaku renew # main moved under you → rebase onto it. Refuses on conflict
|
|
55
83
|
# instead of guessing; resolve, then renew again.
|
|
56
|
-
keiyaku amend < amendment.md # scope/checks changed → update the paper before the code
|
|
84
|
+
keiyaku amend - < amendment.md # scope/checks changed → update the paper before the code
|
|
85
|
+
# Scope terms can be appended durably during a lifecycle operation:
|
|
86
|
+
keiyaku @fix-pump arc --append-scope "docs/generated/**" - < arc.md
|
|
87
|
+
keiyaku @fix-pump renew --append-scope "docs/generated/**"
|
|
57
88
|
keiyaku log # this contract's history
|
|
58
89
|
```
|
|
59
90
|
|
|
60
91
|
`amend` accepts prose plus an optional ordered scope-pattern delta:
|
|
61
92
|
|
|
62
|
-
|
|
93
|
+
````markdown
|
|
63
94
|
Clarify the owned documentation surface.
|
|
64
95
|
|
|
65
|
-
## Scope
|
|
96
|
+
## Scope Append
|
|
97
|
+
```
|
|
66
98
|
docs/**
|
|
67
99
|
!docs/generated/**
|
|
68
100
|
```
|
|
101
|
+
````
|
|
69
102
|
|
|
70
|
-
`Scope
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
`Scope Append` appends ordered raw gitignore-subset lines in one column-zero
|
|
104
|
+
backtick fence; `Scope Add` and Markdown bullets are rejected. A later
|
|
105
|
+
`!pattern` can narrow earlier scope. Use `--append-scope PATTERN` when a
|
|
106
|
+
lifecycle operation discovers one durable term.
|
|
73
107
|
|
|
74
108
|
Gotchas:
|
|
109
|
+
- `-C DIR` selects the effective working directory; repository discovery starts there.
|
|
75
110
|
- Base drift blocks petition — if main moved, `renew` first; petition tells you.
|
|
76
111
|
- After an explicit `arc` seals, new loose commits need another `arc` before `renew`/`petition` accept them.
|
|
77
112
|
- Not in the worktree? Address a contract with `--contract ADDR` (place, slug, or full id) or the `keiyaku @addr <verb>` prefix.
|