@astrosheep/keiyaku 0.1.14 → 0.1.16
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/common/constants.js +2 -0
- package/build/common/errors.js +12 -0
- package/build/config/term-presets.js +42 -39
- package/build/handlers/close.js +30 -33
- package/build/handlers/help.js +6 -1
- package/build/handlers/start.js +38 -24
- package/build/index.js +1 -3
- package/build/types/tooling.js +24 -17
- package/build/utils/git-ops.js +10 -0
- package/build/utils/keiyaku-document.js +542 -0
- package/build/utils/keiyaku-document.test.js +263 -0
- package/build/utils/text-utils.js +0 -81
- package/build/workflow/ask.js +8 -8
- package/build/workflow/contract.js +18 -2
- package/build/workflow/drive.js +6 -11
- package/build/workflow/present.js +12 -7
- package/build/workflow/prompts.js +12 -12
- package/build/workflow/response-builders.js +47 -112
- package/build/workflow/round-summary.js +2 -2
- package/build/workflow/start.js +496 -0
- package/package.json +3 -3
- package/build/workflow/summon.js +0 -188
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export const KEIYAKU_FILE = "KEIYAKU.md";
|
|
2
|
+
export const KEIYAKU_DRAFT_FILE = "KEIYAKU.draft.md";
|
|
3
|
+
export const KEIYAKU_DRAFT_NEW_FILE = "KEIYAKU.draft.new.md";
|
|
2
4
|
export const TRACE_FILE = "KEIYAKU_TRACE.md";
|
|
3
5
|
export const ROUND_SUBAGENTS = ["agent-a", "agent-b", "agent-c"];
|
package/build/common/errors.js
CHANGED
|
@@ -62,6 +62,14 @@ function hintForFlowCode(code, message) {
|
|
|
62
62
|
return "Title cannot be converted to a valid branch token for `keiyaku/<title>`.";
|
|
63
63
|
case "UNKNOWN_SUBAGENT":
|
|
64
64
|
return unknownSubagentHint();
|
|
65
|
+
case "FROM_FILE_NOT_FOUND":
|
|
66
|
+
return "The path in `from_file` does not exist. Use an existing file path (absolute or relative to `cwd`).";
|
|
67
|
+
case "INVALID_KEIYAKU_DRAFT":
|
|
68
|
+
return "Invalid draft/input. Provide `title`, `goal`, `context`, and non-empty `criteria` (or include them in `from_file` with proper section headers).";
|
|
69
|
+
case "KEIYAKU_FILE_EXISTS":
|
|
70
|
+
return `\`${preset.tools.start.name}\` requires a clean slate. Remove existing \`KEIYAKU.md\` before starting.`;
|
|
71
|
+
case "DRAFT_FILE_EXISTS":
|
|
72
|
+
return `Existing \`KEIYAKU.draft.md\` detected. Use it via \`from_file\` or delete it before starting.`;
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
const MESSAGE_HINT_PATTERNS = [
|
|
@@ -93,6 +101,10 @@ const MESSAGE_HINT_PATTERNS = [
|
|
|
93
101
|
{ code: "ROUND_SUBAGENT_FAILED", patterns: ["failed during subagent execution"] },
|
|
94
102
|
{ code: "INVALID_BRANCH_TITLE", patterns: ["cannot be converted to a valid branch name"] },
|
|
95
103
|
{ code: "UNKNOWN_SUBAGENT", patterns: ["Unknown subagent"] },
|
|
104
|
+
{ code: "FROM_FILE_NOT_FOUND", patterns: ["from_file path does not exist"] },
|
|
105
|
+
{ code: "INVALID_KEIYAKU_DRAFT", patterns: ["invalid keiyaku draft"] },
|
|
106
|
+
{ code: "KEIYAKU_FILE_EXISTS", patterns: ["pre-flight failed: KEIYAKU.md already exists"] },
|
|
107
|
+
{ code: "DRAFT_FILE_EXISTS", patterns: ["pre-flight failed: KEIYAKU.draft.md exists but from_file does not target it"] },
|
|
96
108
|
];
|
|
97
109
|
function inferFlowCodeFromMessage(message) {
|
|
98
110
|
for (const entry of MESSAGE_HINT_PATTERNS) {
|
|
@@ -7,13 +7,13 @@ export const DEFAULT_AVAILABLE_NAMES = [
|
|
|
7
7
|
export const DEFAULT_SUBAGENT_NAME = 'A-tier';
|
|
8
8
|
const DEFAULT_VERDICT_CONFIG = {
|
|
9
9
|
thresholds: {
|
|
10
|
-
precise:
|
|
11
|
-
minimal:
|
|
12
|
-
isolated:
|
|
13
|
-
idiomatic:
|
|
14
|
-
cohesive:
|
|
10
|
+
precise: 10,
|
|
11
|
+
minimal: 8,
|
|
12
|
+
isolated: 8,
|
|
13
|
+
idiomatic: 6,
|
|
14
|
+
cohesive: 8,
|
|
15
15
|
},
|
|
16
|
-
minTotalScore:
|
|
16
|
+
minTotalScore: 40,
|
|
17
17
|
};
|
|
18
18
|
export const DEFAULT_PRESET = {
|
|
19
19
|
id: 'default',
|
|
@@ -57,12 +57,13 @@ export const DEFAULT_PRESET = {
|
|
|
57
57
|
title: 'Sign Keiyaku',
|
|
58
58
|
description: 'Initialize a Keiyaku (Contract). Bind a Servant to a dedicated workspace (branch).\nYou are the Architect; they are the Instrument. Define the Goal and Scope clearly.\nThe contract isolates their existence until the objective is met.\nCall ONCE to seal the bond.\n\nFlow: ${start} → [${drive} x N] → ${close}',
|
|
59
59
|
args: {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
from_file: "Optional markdown draft path. Loads `# title` + required sections from file (relative to cwd unless absolute).",
|
|
61
|
+
title: 'Required unless provided via `from_file`. A concise codename for this hunt.',
|
|
62
|
+
goal: 'Required unless provided via `from_file`. The Kill Condition for this mission.',
|
|
63
|
+
directive: 'Optional First Step. Overrides `## Directive` from `from_file` when both are provided.',
|
|
64
|
+
context: 'Required unless provided via `from_file`. Mission intel: behavior gap, key files, logs, and critical background.',
|
|
65
|
+
constraints: 'Optional. Non-negotiable rules as a list of strings. If omitted, the draft value (if any) is used.',
|
|
66
|
+
criteria: 'Required unless provided via `from_file`. Verifiable checks proving completion.',
|
|
66
67
|
name: 'Optional ${identity} profile to execute this mission. Available: ${available_names}.',
|
|
67
68
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
68
69
|
},
|
|
@@ -103,11 +104,11 @@ export const DEFAULT_PRESET = {
|
|
|
103
104
|
petition: 'REQUIRED. CLAIM declares fulfillment; FORFEIT concedes failure.\nREQUIRES AN ACTIVE KEIYAKU (started via ${start}).\nIf any score wavers, do not claim—return to ${drive}.',
|
|
104
105
|
criteriaChecks: 'REQUIRED. For CLAIM: evidence that each criterion is met. For FORFEIT: honest account of what remains unfinished.',
|
|
105
106
|
constraintsChecks: 'REQUIRED. For CLAIM: evidence that each constraint stayed compliant. For FORFEIT: list known violations or unresolved risk.',
|
|
106
|
-
score_precise: 'REQUIRED (0-
|
|
107
|
-
score_minimal: 'REQUIRED (0-
|
|
108
|
-
score_isolated: 'REQUIRED (0-
|
|
109
|
-
score_idiomatic: 'REQUIRED (0-
|
|
110
|
-
score_cohesive: 'REQUIRED (0-
|
|
107
|
+
score_precise: 'REQUIRED (0-10). Architectural placement. 10 = exact layer, exact boundary, zero misplacement.',
|
|
108
|
+
score_minimal: 'REQUIRED (0-10). Economy of change. 10 = no avoidable lines, no speculative edits, no hidden bloat.',
|
|
109
|
+
score_isolated: 'REQUIRED (0-10). Surgical containment. 10 = zero unrelated files, zero opportunistic cleanup, zero collateral.',
|
|
110
|
+
score_idiomatic: 'REQUIRED (0-10). Native fluency. 10 = naming, structure, style indistinguishable from the codebase.',
|
|
111
|
+
score_cohesive: 'REQUIRED (0-10). Single responsibility. 10 = each unit does one thing, boundaries intact.',
|
|
111
112
|
oath: 'Required for CLAIM. Your binding word. The Contract holds you to it.\nVerbatim: ${oath_text}',
|
|
112
113
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
113
114
|
},
|
|
@@ -158,12 +159,13 @@ export const POCKET_PRESET = {
|
|
|
158
159
|
title: 'I Choose You!',
|
|
159
160
|
description: 'Initialize the Battle Phase. Send a Critter (Servant) into a dedicated Arena (branch).\nYou are the Trainer; they are the Fighter. Define the Victory Condition (Goal) clearly.\nThe battle continues in this Arena until the Badge is won.\nCall ONCE to start the encounter.\n\nFlow: ${start} → [${drive} x N] → ${close}',
|
|
160
161
|
args: {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
from_file: 'Optional battle plan markdown path with title + sections.',
|
|
163
|
+
title: 'Required unless provided via `from_file`. Battle card title for this encounter.',
|
|
164
|
+
goal: 'Required unless provided via `from_file`. Victory condition for this battle.',
|
|
165
|
+
directive: 'Optional Turn 1 strategy (overrides draft directive).',
|
|
166
|
+
context: 'Required unless provided via `from_file`. Battle background and repro clues.',
|
|
167
|
+
constraints: 'Optional battle rules as a list of strings. Uses draft constraints if omitted.',
|
|
168
|
+
criteria: 'Required unless provided via `from_file`. Concrete checks proving victory.',
|
|
167
169
|
name: 'Optional ${identity} to send into battle. Available: ${available_names}.',
|
|
168
170
|
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
169
171
|
},
|
|
@@ -198,11 +200,11 @@ export const POCKET_PRESET = {
|
|
|
198
200
|
petition: 'REQUIRED. CLAIM seeks Badge; FORFEIT forfeits the match.\nREQUIRES AN ACTIVE BATTLE (started via ${start}).\nIf stats are low, continue with ${drive}.',
|
|
199
201
|
criteriaChecks: 'REQUIRED. Badge-by-badge proof for CLAIM, or reason for Forfeit.',
|
|
200
202
|
constraintsChecks: 'REQUIRED. Rule-by-rule proof that constraints were respected, or known breaks when forfeiting.',
|
|
201
|
-
score_precise: 'REQUIRED score (0-
|
|
202
|
-
score_minimal: 'REQUIRED score (0-
|
|
203
|
-
score_isolated: 'REQUIRED score (0-
|
|
204
|
-
score_idiomatic: "REQUIRED score (0-
|
|
205
|
-
score_cohesive: 'REQUIRED score (0-
|
|
203
|
+
score_precise: 'REQUIRED score (0-10). 10 means a Critical Hit: exact layer, exact target, zero meaningful misplacement.',
|
|
204
|
+
score_minimal: 'REQUIRED score (0-10). 10 means Max Efficiency: no wasted PP, no extra motion.',
|
|
205
|
+
score_isolated: 'REQUIRED score (0-10). 10 means 1v1 Focus: zero side-quests, zero unrelated damage.',
|
|
206
|
+
score_idiomatic: "REQUIRED score (0-10). 10 means STAB (Same Type Attack Bonus): perfectly matches the codebase style.",
|
|
207
|
+
score_cohesive: 'REQUIRED score (0-10). 10 means Team Synergy: action serves one purpose with clean boundaries.',
|
|
206
208
|
oath: "Trainer's Honor Code. Required for CLAIM. Verbatim: ${oath_text}",
|
|
207
209
|
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
208
210
|
},
|
|
@@ -253,12 +255,13 @@ export const MISCHIEF_PRESET = {
|
|
|
253
255
|
title: 'Oi!',
|
|
254
256
|
description: "Initiate Grand Scheme. Summon a Minion to the Lair (branch).\nYou are the Mastermind; they are the Henchman. Define the Conquest (Goal) with dominance.\nThe minion is bound to this Lair until the plot is realized.\nCall ONCE to start the machine.\n\nFlow: ${start} → [${drive} x N] → ${close}",
|
|
255
257
|
args: {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
from_file: 'Optional scheme markdown path with title + sectioned objectives.',
|
|
259
|
+
title: 'Required unless provided via `from_file`. Operation codename.',
|
|
260
|
+
goal: 'Required unless provided via `from_file`. Conquest objective and end-state.',
|
|
261
|
+
directive: 'Optional first-order command (overrides draft directive).',
|
|
262
|
+
context: 'Required unless provided via `from_file`. Briefing dossier and technical clues.',
|
|
263
|
+
constraints: 'Optional decrees as a list of strings. Uses draft constraints when omitted.',
|
|
264
|
+
criteria: 'Required unless provided via `from_file`. Verifiable triumph conditions.',
|
|
262
265
|
name: 'Optional ${identity} to command this operation. Available: ${available_names}.',
|
|
263
266
|
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
264
267
|
},
|
|
@@ -293,11 +296,11 @@ export const MISCHIEF_PRESET = {
|
|
|
293
296
|
petition: 'REQUIRED. CLAIM demands rule; FORFEIT admits defeat.\nREQUIRES AN ACTIVE SCHEME (started via ${start}).\nIf the plan is weak, improve it with ${drive}.',
|
|
294
297
|
criteriaChecks: 'REQUIRED. Proof of conquest for CLAIM, or reason for self-destruct.',
|
|
295
298
|
constraintsChecks: 'REQUIRED. Constraint-by-constraint compliance proof for CLAIM, or confession of violations for FORFEIT.',
|
|
296
|
-
score_precise: 'REQUIRED (0-
|
|
297
|
-
score_minimal: 'REQUIRED (0-
|
|
298
|
-
score_isolated: 'REQUIRED (0-
|
|
299
|
-
score_idiomatic: 'REQUIRED (0-
|
|
300
|
-
score_cohesive: 'REQUIRED (0-
|
|
299
|
+
score_precise: 'REQUIRED (0-10). Architectural placement. 10 = exact layer, exact boundary, zero misplacement.',
|
|
300
|
+
score_minimal: 'REQUIRED (0-10). Economy of change. 10 = no avoidable lines, no speculative edits, no hidden bloat.',
|
|
301
|
+
score_isolated: 'REQUIRED (0-10). Surgical containment. 10 = zero unrelated files, zero opportunistic cleanup, zero collateral.',
|
|
302
|
+
score_idiomatic: 'REQUIRED (0-10). Native fluency. 10 = naming, structure, style indistinguishable from the codebase.',
|
|
303
|
+
score_cohesive: 'REQUIRED (0-10). Single responsibility. 10 = each unit does one thing, boundaries intact.',
|
|
301
304
|
oath: "Mastermind's Vow. Required for CLAIM. Verbatim: ${oath_text}",
|
|
302
305
|
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
303
306
|
},
|
package/build/handlers/close.js
CHANGED
|
@@ -2,48 +2,53 @@ import { appendDebugLog } from "../utils/debug-log.js";
|
|
|
2
2
|
import { presentWork } from "../workflow/present.js";
|
|
3
3
|
import { buildCloseDoneResponse, buildCloseDropResponse, } from "../workflow/response-builders.js";
|
|
4
4
|
import { resolveTermPreset } from "../config/term-presets.js";
|
|
5
|
+
import { closeToolSchema } from "../types/tooling.js";
|
|
5
6
|
import { handleToolError } from "./shared.js";
|
|
6
7
|
export function createCloseHandler() {
|
|
7
|
-
return async (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
return async (args, extra) => {
|
|
9
|
+
let petition = "UNKNOWN";
|
|
10
|
+
let workingDir = process.cwd();
|
|
11
|
+
let criteriaCheckParts = [];
|
|
12
|
+
let constraintsCheckParts = [];
|
|
13
|
+
let oath;
|
|
14
|
+
let scoreLine;
|
|
11
15
|
try {
|
|
16
|
+
const input = closeToolSchema.parse(args);
|
|
17
|
+
petition = input.petition;
|
|
18
|
+
workingDir = input.cwd || process.cwd();
|
|
19
|
+
if (input.petition === "CLAIM") {
|
|
20
|
+
criteriaCheckParts = input.criteriaChecks;
|
|
21
|
+
constraintsCheckParts = input.constraintsChecks;
|
|
22
|
+
oath = input.oath;
|
|
23
|
+
scoreLine = `Scores: precise=${input.score_precise} minimal=${input.score_minimal} isolated=${input.score_isolated} idiomatic=${input.score_idiomatic} cohesive=${input.score_cohesive}`;
|
|
24
|
+
}
|
|
12
25
|
appendDebugLog(`tool close start petition=${petition} cwd=${workingDir} criteriaChecks=${criteriaCheckParts.length} constraintsChecks=${constraintsCheckParts.length}`, {
|
|
13
26
|
cwd: workingDir,
|
|
14
27
|
section: "script",
|
|
15
28
|
});
|
|
16
29
|
const outcome = await presentWork({
|
|
30
|
+
...input,
|
|
17
31
|
cwd: workingDir,
|
|
18
|
-
petition,
|
|
19
|
-
criteriaChecks: criteriaCheckParts,
|
|
20
|
-
constraintsChecks: constraintsCheckParts,
|
|
21
|
-
score_precise,
|
|
22
|
-
score_minimal,
|
|
23
|
-
score_isolated,
|
|
24
|
-
score_idiomatic,
|
|
25
|
-
score_cohesive,
|
|
26
|
-
oath,
|
|
27
32
|
signal: extra.signal,
|
|
28
33
|
});
|
|
29
|
-
if (petition === "CLAIM") {
|
|
30
|
-
if (!("result" in outcome) || outcome.result !== "
|
|
34
|
+
if (input.petition === "CLAIM") {
|
|
35
|
+
if (!("result" in outcome) || outcome.result !== "merged") {
|
|
31
36
|
throw new Error("Unexpected CLAIM outcome shape");
|
|
32
37
|
}
|
|
33
38
|
const finalOutcome = outcome;
|
|
34
|
-
appendDebugLog(`tool close CLAIM success branch=${finalOutcome.
|
|
39
|
+
appendDebugLog(`tool close CLAIM success branch=${finalOutcome.currentBranch} base=${finalOutcome.baseBranch}`, {
|
|
35
40
|
cwd: workingDir,
|
|
36
41
|
section: "script",
|
|
37
42
|
});
|
|
38
43
|
return buildCloseDoneResponse(finalOutcome, {
|
|
39
44
|
criteriaChecks: criteriaCheckParts,
|
|
40
45
|
constraintsChecks: constraintsCheckParts,
|
|
41
|
-
score_precise,
|
|
42
|
-
score_minimal,
|
|
43
|
-
score_isolated,
|
|
44
|
-
score_idiomatic,
|
|
45
|
-
score_cohesive,
|
|
46
|
-
oath,
|
|
46
|
+
score_precise: input.score_precise,
|
|
47
|
+
score_minimal: input.score_minimal,
|
|
48
|
+
score_isolated: input.score_isolated,
|
|
49
|
+
score_idiomatic: input.score_idiomatic,
|
|
50
|
+
score_cohesive: input.score_cohesive,
|
|
51
|
+
oath: input.oath,
|
|
47
52
|
cwd: workingDir,
|
|
48
53
|
});
|
|
49
54
|
}
|
|
@@ -51,19 +56,11 @@ export function createCloseHandler() {
|
|
|
51
56
|
throw new Error("Unexpected FORFEIT outcome shape");
|
|
52
57
|
}
|
|
53
58
|
const finalOutcome = outcome;
|
|
54
|
-
appendDebugLog(`tool close FORFEIT success branch=${finalOutcome.
|
|
59
|
+
appendDebugLog(`tool close FORFEIT success branch=${finalOutcome.currentBranch} base=${finalOutcome.baseBranch}`, {
|
|
55
60
|
cwd: workingDir,
|
|
56
61
|
section: "script",
|
|
57
62
|
});
|
|
58
63
|
return buildCloseDropResponse(finalOutcome, {
|
|
59
|
-
criteriaChecks: criteriaCheckParts,
|
|
60
|
-
constraintsChecks: constraintsCheckParts,
|
|
61
|
-
score_precise,
|
|
62
|
-
score_minimal,
|
|
63
|
-
score_isolated,
|
|
64
|
-
score_idiomatic,
|
|
65
|
-
score_cohesive,
|
|
66
|
-
oath,
|
|
67
64
|
cwd: workingDir,
|
|
68
65
|
});
|
|
69
66
|
}
|
|
@@ -78,8 +75,8 @@ export function createCloseHandler() {
|
|
|
78
75
|
`Petition: ${petition}`,
|
|
79
76
|
`Criteria checks (${criteriaCheckParts.length}): ${criteriaCheckParts.join("; ")}`,
|
|
80
77
|
`Constraints checks (${constraintsCheckParts.length}): ${constraintsCheckParts.join("; ")}`,
|
|
81
|
-
|
|
82
|
-
...(oath ? [`Oath: ${oath}`] : []),
|
|
78
|
+
...(scoreLine ? [scoreLine] : []),
|
|
79
|
+
...(petition === "CLAIM" && oath ? [`Oath: ${oath}`] : []),
|
|
83
80
|
`Path: ${workingDir}`,
|
|
84
81
|
],
|
|
85
82
|
});
|
package/build/handlers/help.js
CHANGED
|
@@ -5,9 +5,14 @@ export function createHelpHandler(preset) {
|
|
|
5
5
|
"# Keiyaku System Help",
|
|
6
6
|
"",
|
|
7
7
|
"## Core Files (.keiyaku/)",
|
|
8
|
-
"These files define the 'Law' of the project.
|
|
8
|
+
"These files define the 'Law' and configuration of the project.",
|
|
9
9
|
"",
|
|
10
10
|
"- **base-constraints.md**: Mandatory architectural boundaries and coding standards.",
|
|
11
|
+
" - **Purpose**: Global constraints injected into every mission.",
|
|
12
|
+
" - **Logic**: The system prioritize extracting all list items (`-` or `*`) as individual constraints.",
|
|
13
|
+
" - **Formatting**: Use lists for constraints. You can use H3+ headers (`###`) for organization, but they are stripped if the section contains lists.",
|
|
14
|
+
" - **Strict Rule**: DO NOT use H1 (`#`) or H2 (`##`) within constraints or as content if they aren't meant to be item separators, as they will trigger validation errors.",
|
|
15
|
+
"- **settings.json**: Local configuration for the Keiyaku environment.",
|
|
11
16
|
"",
|
|
12
17
|
preset.usageGuide,
|
|
13
18
|
"",
|
package/build/handlers/start.js
CHANGED
|
@@ -1,35 +1,48 @@
|
|
|
1
1
|
import { appendDebugLog } from "../utils/debug-log.js";
|
|
2
|
-
import {
|
|
2
|
+
import { startKeiyaku } from "../workflow/start.js";
|
|
3
3
|
import { buildKeiyakuSuccessResponse, } from "../workflow/response-builders.js";
|
|
4
4
|
import { resolveTermPreset } from "../config/term-presets.js";
|
|
5
5
|
import { handleToolError } from "./shared.js";
|
|
6
|
+
function normalizeOptionalArg(value) {
|
|
7
|
+
if (value === undefined)
|
|
8
|
+
return undefined;
|
|
9
|
+
return value.trim().length > 0 ? value : undefined;
|
|
10
|
+
}
|
|
6
11
|
export function createStartHandler() {
|
|
7
|
-
return async ({ title, goal, directive, context, constraints, criteria, name, cwd }, extra) => {
|
|
12
|
+
return async ({ from_file, title, goal, directive, context, constraints, criteria, name, cwd }, extra) => {
|
|
8
13
|
const workingDir = cwd || process.cwd();
|
|
14
|
+
const normalizedFromFile = normalizeOptionalArg(from_file);
|
|
9
15
|
try {
|
|
10
16
|
appendDebugLog(`tool start cwd=${workingDir}`, { cwd: workingDir, section: "script" });
|
|
11
|
-
const result =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
const result = normalizedFromFile
|
|
18
|
+
? await startKeiyaku({
|
|
19
|
+
cwd: workingDir,
|
|
20
|
+
from_file: normalizedFromFile,
|
|
21
|
+
title: normalizeOptionalArg(title),
|
|
22
|
+
goal: normalizeOptionalArg(goal),
|
|
23
|
+
directive: normalizeOptionalArg(directive),
|
|
24
|
+
context: normalizeOptionalArg(context),
|
|
25
|
+
constraints,
|
|
26
|
+
criteria,
|
|
27
|
+
name,
|
|
28
|
+
signal: extra.signal,
|
|
29
|
+
})
|
|
30
|
+
: await startKeiyaku({
|
|
31
|
+
cwd: workingDir,
|
|
32
|
+
title: title ?? "",
|
|
33
|
+
goal: goal ?? "",
|
|
34
|
+
directive: normalizeOptionalArg(directive),
|
|
35
|
+
context: context ?? "",
|
|
36
|
+
constraints,
|
|
37
|
+
criteria: criteria ?? [],
|
|
38
|
+
name,
|
|
39
|
+
signal: extra.signal,
|
|
40
|
+
});
|
|
41
|
+
appendDebugLog(`tool start success branch=${result.currentBranch} base=${result.baseBranch} round=${result.round}`, {
|
|
23
42
|
cwd: workingDir,
|
|
24
43
|
section: "script",
|
|
25
44
|
});
|
|
26
45
|
return buildKeiyakuSuccessResponse(result, {
|
|
27
|
-
title,
|
|
28
|
-
goal,
|
|
29
|
-
directive,
|
|
30
|
-
context,
|
|
31
|
-
constraints,
|
|
32
|
-
criteria,
|
|
33
46
|
name,
|
|
34
47
|
cwd: workingDir,
|
|
35
48
|
});
|
|
@@ -42,12 +55,13 @@ export function createStartHandler() {
|
|
|
42
55
|
cwd: workingDir,
|
|
43
56
|
logLabel: "tool start",
|
|
44
57
|
inputEcho: [
|
|
45
|
-
`
|
|
46
|
-
`
|
|
58
|
+
...(normalizedFromFile ? [`From file: ${normalizedFromFile}`] : []),
|
|
59
|
+
...(title ? [`Title: ${title}`] : []),
|
|
60
|
+
...(goal ? [`Goal: ${goal}`] : []),
|
|
47
61
|
...(directive ? [`Directive: ${directive}`] : []),
|
|
48
|
-
`Criteria (${criteria.length}): ${criteria.join("; ")}
|
|
62
|
+
...(criteria ? [`Criteria (${criteria.length}): ${criteria.join("; ")}`] : []),
|
|
49
63
|
...(context ? [`Context: ${context}`] : []),
|
|
50
|
-
...(constraints ? [`Constraints: ${constraints}`] : []),
|
|
64
|
+
...(constraints ? [`Constraints (${constraints.length}): ${constraints.join("; ")}`] : []),
|
|
51
65
|
...(name ? [`${preset.identity}: ${name}`] : []),
|
|
52
66
|
`Path: ${workingDir}`,
|
|
53
67
|
],
|
package/build/index.js
CHANGED
|
@@ -41,9 +41,7 @@ function registerTools(server) {
|
|
|
41
41
|
const askPreset = renderedPreset.tools.ask;
|
|
42
42
|
const closePreset = renderedPreset.tools.close;
|
|
43
43
|
const helpPreset = renderedPreset.tools.help;
|
|
44
|
-
const dynamicCloseSchema =
|
|
45
|
-
...closePreset.args,
|
|
46
|
-
});
|
|
44
|
+
const dynamicCloseSchema = closeToolSchema;
|
|
47
45
|
const dynamicStartSchema = applyArgumentDescriptions(startToolSchema, {
|
|
48
46
|
...startPreset.args,
|
|
49
47
|
});
|
package/build/types/tooling.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const startToolSchema = z.object({
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
from_file: z.string().optional(),
|
|
4
|
+
title: z.string().optional(),
|
|
5
|
+
goal: z.string().optional(),
|
|
5
6
|
directive: z.string().optional(),
|
|
6
|
-
context: z.string(),
|
|
7
|
-
constraints: z.string(),
|
|
8
|
-
criteria: z.array(z.string().trim().min(1)).min(1),
|
|
7
|
+
context: z.string().optional(),
|
|
8
|
+
constraints: z.array(z.string().trim().min(1)).min(1).optional(),
|
|
9
|
+
criteria: z.array(z.string().trim().min(1)).min(1).optional(),
|
|
9
10
|
name: z.string().optional(),
|
|
10
11
|
cwd: z.string().optional(),
|
|
11
12
|
});
|
|
@@ -21,16 +22,22 @@ export const askToolSchema = z.object({
|
|
|
21
22
|
name: z.string().optional(),
|
|
22
23
|
cwd: z.string().optional(),
|
|
23
24
|
});
|
|
24
|
-
export const closeToolSchema = z.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
export const closeToolSchema = z.discriminatedUnion("petition", [
|
|
26
|
+
z.object({
|
|
27
|
+
petition: z.literal("CLAIM"),
|
|
28
|
+
criteriaChecks: z.array(z.string().trim().min(1)).min(1),
|
|
29
|
+
constraintsChecks: z.array(z.string().trim().min(1)).min(1),
|
|
30
|
+
score_precise: z.number().min(0).max(10),
|
|
31
|
+
score_minimal: z.number().min(0).max(10),
|
|
32
|
+
score_isolated: z.number().min(0).max(10),
|
|
33
|
+
score_idiomatic: z.number().min(0).max(10),
|
|
34
|
+
score_cohesive: z.number().min(0).max(10),
|
|
35
|
+
oath: z.string().optional(),
|
|
36
|
+
cwd: z.string().optional(),
|
|
37
|
+
}),
|
|
38
|
+
z.object({
|
|
39
|
+
petition: z.literal("FORFEIT"),
|
|
40
|
+
cwd: z.string().optional(),
|
|
41
|
+
}),
|
|
42
|
+
]);
|
|
36
43
|
export const helpToolSchema = z.object({});
|
package/build/utils/git-ops.js
CHANGED
|
@@ -265,6 +265,16 @@ export async function getKeiyakuBase(cwd, branchName) {
|
|
|
265
265
|
return null;
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
+
export async function getLatestCommitHash(cwd) {
|
|
269
|
+
const git = createGit(cwd);
|
|
270
|
+
try {
|
|
271
|
+
const hash = await git.revparse(["--short", "HEAD"]);
|
|
272
|
+
return hash.trim();
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
throw wrapGitError("rev-parse --short HEAD", err, cwd);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
268
278
|
export async function clearKeiyakuBase(cwd, branchName) {
|
|
269
279
|
const git = createGit(cwd);
|
|
270
280
|
try {
|