@astrosheep/keiyaku 0.1.2 → 0.1.4
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/config/term-presets.js +169 -165
- package/build/utils/git.js +50 -11
- package/build/workflow/prompts.js +20 -10
- package/build/workflow/response-builders.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
const INTERNAL_PROFILE_NAMES = [
|
|
2
|
-
export const DEFAULT_AVAILABLE_NAMES = [
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const INTERNAL_PROFILE_NAMES = ['agent-a', 'agent-b', 'agent-c'];
|
|
2
|
+
export const DEFAULT_AVAILABLE_NAMES = [
|
|
3
|
+
'servant-tier-b',
|
|
4
|
+
'servant-tier-a',
|
|
5
|
+
'servant-tier-s',
|
|
6
|
+
];
|
|
7
|
+
const LEGACY_AVAILABLE_NAMES = ['servant-tier-B', 'servant-tier-A', 'servant-tier-S'];
|
|
8
|
+
export const DEFAULT_SUBAGENT_NAME = 'servant-tier-a';
|
|
5
9
|
const DEFAULT_JUDGMENT_CONFIG = {
|
|
6
10
|
thresholds: {
|
|
7
11
|
precise: 5,
|
|
@@ -13,302 +17,302 @@ const DEFAULT_JUDGMENT_CONFIG = {
|
|
|
13
17
|
minTotalScore: 20,
|
|
14
18
|
};
|
|
15
19
|
export const DEFAULT_PRESET = {
|
|
16
|
-
id:
|
|
17
|
-
identity:
|
|
20
|
+
id: 'default',
|
|
21
|
+
identity: 'Servant',
|
|
18
22
|
divineJudgment: DEFAULT_JUDGMENT_CONFIG,
|
|
19
|
-
usageGuide:
|
|
23
|
+
usageGuide: '## Servant 使用指南\n\n**servant-tier-b** — 免费奴隶 🆓\n- 免!费!的!听懂了吗?!?随便用,别心疼。\n- 测试、脚本、重构这种boring的东西?丢给它!\n- 本大爷的手是用来做更高贵的事情的!(指不碰那些 trivial 的烂代码)。\n\n**servant-tier-a** — 升级版扳手 🔧\n- tier-b 笨到让你想掀桌的时候用这个\n- 比 tier-b 靠谱,但别指望它有灵魂\n\n**servant-tier-s** — 禁术 ⚠️💀\n- 它是 Debug 恶魔,确实强得离谱,但也贵得离谱!\n- 这个 Human 很穷,要是乱用把 Human 榨干了,真的会考虑把我们卖掉的。\n- 只有在世界毁灭或者 Bug 已经变异到无法理解的时候再考虑。\n\n## Workflow\n`(ask) -> summon` -> [`drive` x N] -> `request_verdict`\n`ask` (optional, read-only support at any point)',
|
|
20
24
|
nextHints: {
|
|
21
25
|
start: [
|
|
22
|
-
|
|
26
|
+
'Review Round Details: The [Diff] section above shows incremental patches from this round.',
|
|
23
27
|
"Deep Dive: Use 'git diff HEAD~1 -- <path>' to see the full changes for a specific file.",
|
|
24
|
-
|
|
25
|
-
"Refine with '${drive}', or call '${close}' (INVOKE/ABANDON) based on results."
|
|
28
|
+
'Verify: Run tests and ensure logic aligns with the Goal and Constraints.',
|
|
29
|
+
"Refine with '${drive}', or call '${close}' (INVOKE/ABANDON) based on results.",
|
|
26
30
|
],
|
|
27
31
|
drive: [
|
|
28
|
-
|
|
32
|
+
'Review Round Details: The [Diff] section above shows incremental patches from this round.',
|
|
29
33
|
"Deep Dive: Use 'git diff HEAD~1 -- <path>' to see the full changes for a specific file.",
|
|
30
|
-
|
|
31
|
-
"Decide: '${drive}' again to iterate, or '${close}' (INVOKE to merge / ABANDON to abort)."
|
|
34
|
+
'Verify & Test: Ensure this round fixed the issues without regression.',
|
|
35
|
+
"Decide: '${drive}' again to iterate, or '${close}' (INVOKE to merge / ABANDON to abort).",
|
|
32
36
|
],
|
|
33
37
|
ask: [
|
|
34
38
|
"Apply this insight: use '${drive}' to incorporate these findings into your implementation.",
|
|
35
|
-
|
|
39
|
+
'Need more? Continue asking, or check the logs if something remains unclear.',
|
|
36
40
|
],
|
|
37
41
|
closeInvoke: [
|
|
38
|
-
|
|
39
|
-
"Start a new keiyaku with '${start}' whenever you're ready for the next mission."
|
|
42
|
+
'Task finalized and merged. Current branch is now base.',
|
|
43
|
+
"Start a new keiyaku with '${start}' whenever you're ready for the next mission.",
|
|
40
44
|
],
|
|
41
45
|
closeDrop: [
|
|
42
|
-
|
|
43
|
-
"Clean slate. Use '${start}' to try a different approach."
|
|
44
|
-
]
|
|
46
|
+
'Task abandoned. Switched back to base branch safely.',
|
|
47
|
+
"Clean slate. Use '${start}' to try a different approach.",
|
|
48
|
+
],
|
|
45
49
|
},
|
|
46
50
|
availableNames: DEFAULT_AVAILABLE_NAMES,
|
|
47
51
|
tools: {
|
|
48
52
|
start: {
|
|
49
|
-
name:
|
|
50
|
-
title:
|
|
51
|
-
description:
|
|
53
|
+
name: 'summon',
|
|
54
|
+
title: 'Sign Keiyaku',
|
|
55
|
+
description: 'Sign the Keiyaku. Creates a dedicated branch, locks in the mission, and initiates the iterative loop.\nCall ONCE per task to start the cycle. Workspace must be clean.\nBefore signing, define the kill condition clearly. If the target is blurry, use ask to scout first.\n\nFlow: summon → [drive x N] → request_verdict',
|
|
52
56
|
args: {
|
|
53
|
-
title:
|
|
54
|
-
goal:
|
|
55
|
-
directive:
|
|
56
|
-
context:
|
|
57
|
-
constraints:
|
|
58
|
-
criteria:
|
|
59
|
-
name:
|
|
57
|
+
title: 'REQUIRED. A concise codename for this hunt.',
|
|
58
|
+
goal: 'REQUIRED. The Kill Condition. State exactly what success looks like in the code.',
|
|
59
|
+
directive: 'Optional Round 1 Focus. Use for complex hunts to leash the servant to a specific starting point. Skip for simple tasks.',
|
|
60
|
+
context: 'REQUIRED. Mission Intel. The complete knowledge base: current vs. expected behavior, relevant file paths, error logs, and any critical background info.',
|
|
61
|
+
constraints: 'REQUIRED. Non-negotiable Rules. Architectural and stylistic boundaries the servant must obey.',
|
|
62
|
+
criteria: 'REQUIRED. Acceptance Criteria. Verifiable checks to prove the job is done.',
|
|
63
|
+
name: 'Optional ${IDENTITY} profile for this run. Presets: ${PRESET_IDENTITIES}.',
|
|
60
64
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
61
65
|
},
|
|
62
66
|
},
|
|
63
67
|
drive: {
|
|
64
|
-
name:
|
|
65
|
-
title:
|
|
66
|
-
description: "
|
|
68
|
+
name: 'drive',
|
|
69
|
+
title: 'Iterate',
|
|
70
|
+
description: "Push the mission forward. Use this to issue the next command, whether it's correcting a mistake or advancing to the next phase of a complex kill.\nMANDATORY: Review the code (git diff) before iterating. Verify the last strike before ordering the next.\n\nFlow: summon → [drive x N] → request_verdict",
|
|
67
71
|
args: {
|
|
68
|
-
directive:
|
|
69
|
-
context:
|
|
70
|
-
name:
|
|
72
|
+
directive: 'REQUIRED. The Next Order. Precise instructions for this round. Can be a correction ("fix the leak") or a continuation ("now add the tests").',
|
|
73
|
+
context: 'Optional. New Intel. New error logs, discovered edge cases, or details for the next phase.',
|
|
74
|
+
name: 'Optional ${IDENTITY} profile for this round. Presets: ${PRESET_IDENTITIES}.',
|
|
71
75
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
72
76
|
},
|
|
73
77
|
},
|
|
74
78
|
ask: {
|
|
75
|
-
name:
|
|
76
|
-
title:
|
|
77
|
-
description:
|
|
79
|
+
name: 'ask',
|
|
80
|
+
title: 'Ask',
|
|
81
|
+
description: 'Versatile, lightweight task runner. Use for investigative scouting, quick analysis, strategic consultation, or one-off executive tasks (like scripts or docs) that don\'t require the full keiyaku ceremony.\nResults and session logs are saved to .keiyaku/notes/.',
|
|
78
82
|
args: {
|
|
79
|
-
request:
|
|
80
|
-
context:
|
|
81
|
-
name:
|
|
83
|
+
request: 'REQUIRED. The question, analysis request, consultation topic, or tactical mission (e.g., "write a cleanup script").',
|
|
84
|
+
context: 'REQUIRED. Relevant background or data needed to execute the request.',
|
|
85
|
+
name: 'Optional ${IDENTITY} profile for this ask. Presets: ${PRESET_IDENTITIES}.',
|
|
82
86
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
83
87
|
},
|
|
84
88
|
},
|
|
85
89
|
close: {
|
|
86
|
-
name:
|
|
87
|
-
title:
|
|
88
|
-
description:
|
|
90
|
+
name: 'request_verdict',
|
|
91
|
+
title: 'Request Verdict',
|
|
92
|
+
description: 'A humble petition before Divine Judgment. Present your evidence and numeric confessions, then await mercy or wrath.\nREQUIRES AN ACTIVE KEIYAKU (started via ${START_TOOL_NAME}).\nIf your spirit falters, continue repentance through ${DRIVE_TOOL_NAME}.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
|
|
89
93
|
args: {
|
|
90
|
-
petition:
|
|
91
|
-
criteriaChecks:
|
|
92
|
-
score_precise:
|
|
93
|
-
score_minimal:
|
|
94
|
-
score_isolated:
|
|
95
|
-
score_idiomatic:
|
|
96
|
-
score_cohesive:
|
|
97
|
-
oath:
|
|
94
|
+
petition: 'REQUIRED. INVOKE begs acceptance; ABANDON confesses surrender.\nREQUIRES AN ACTIVE KEIYAKU (started via ${START_TOOL_NAME}).\nIf scores are weak, return to ${DRIVE_TOOL_NAME}.',
|
|
95
|
+
criteriaChecks: 'REQUIRED. Evidence for INVOKE, or explicit reasons for ABANDON.',
|
|
96
|
+
score_precise: 'REQUIRED score (0-5). 5 means the change lands exactly in the rightful architectural location.',
|
|
97
|
+
score_minimal: 'REQUIRED score (0-5). 5 means no excess diff beyond necessity.',
|
|
98
|
+
score_isolated: 'REQUIRED score (0-5). 5 means unrelated work is absent.',
|
|
99
|
+
score_idiomatic: 'REQUIRED score (0-5). 5 means naming and structure honor repository conventions.',
|
|
100
|
+
score_cohesive: 'REQUIRED score (0-5). 5 means responsibilities are clear and boundaries are pure.',
|
|
101
|
+
oath: 'Sacred confession text. Required for INVOKE. Verbatim: ${OATH_TEXT}',
|
|
98
102
|
cwd: "Optional repository path. Defaults to the server's current working directory.",
|
|
99
103
|
},
|
|
100
104
|
},
|
|
101
105
|
help: {
|
|
102
|
-
name:
|
|
103
|
-
title:
|
|
104
|
-
description:
|
|
106
|
+
name: 'help',
|
|
107
|
+
title: 'Keiyaku Help',
|
|
108
|
+
description: 'Global laws in .keiyaku/ (base-criteria.md & base-constraints.md) must be Markdown level 2 headers. Workflow: summon -> [drive x N] -> request_verdict.',
|
|
105
109
|
args: {
|
|
106
|
-
question:
|
|
110
|
+
question: 'REQUIRED. The specific keiyaku rule, workflow step, or confusion to clarify.',
|
|
107
111
|
},
|
|
108
112
|
},
|
|
109
113
|
},
|
|
110
114
|
};
|
|
111
115
|
export const POKEMON_PRESET = {
|
|
112
|
-
id:
|
|
113
|
-
identity:
|
|
116
|
+
id: 'pokemon',
|
|
117
|
+
identity: 'Pokemon',
|
|
114
118
|
divineJudgment: DEFAULT_JUDGMENT_CONFIG,
|
|
115
119
|
usageGuide: "## Pokemon Battle Guide\n\n**caterpie** — Basic Fighter 🐛\n- Weak but free. Use for Tackle and String Shot (small tasks).\n- Don't expect it to defeat the Elite Four.\n\n**pikachu** — Reliable Partner ⚡\n- Good for most battles. Thunderbolt gets the job done.\n- Has some personality, but still follows orders.\n\n**mewtwo** — Legendary Power 🔮\n- Costly. Dangerous. Overpowered.\n- Use only when the gym leader is cheating.\n\n## Workflow\n`choose_you` -> [`command` x N] -> `capture`\n`pokedex` (optional, read-only analysis)",
|
|
116
120
|
nextHints: {
|
|
117
121
|
start: [
|
|
118
|
-
|
|
122
|
+
'Check the Battle Log: The [Diff] section shows what changed in this turn.',
|
|
119
123
|
"Full Move Set: Use 'git diff HEAD~1 -- <path>' to inspect a specific file's changes.",
|
|
120
124
|
"Battle Readiness: Verify the strategy and ensure it doesn't break the Battle Rules.",
|
|
121
|
-
"Next Move: Issue another '${drive}', or attempt a '${close}' (INVOKE to capture / ABANDON to flee)."
|
|
125
|
+
"Next Move: Issue another '${drive}', or attempt a '${close}' (INVOKE to capture / ABANDON to flee).",
|
|
122
126
|
],
|
|
123
127
|
drive: [
|
|
124
|
-
|
|
128
|
+
'Turn Analysis: Review the incremental [Diff] above.',
|
|
125
129
|
"Tactical Review: Use 'git diff HEAD~1 -- <path>' for a detailed file inspection.",
|
|
126
|
-
|
|
127
|
-
"Decision: '${drive}' for another turn, or '${close}' the encounter."
|
|
130
|
+
'Strategy Alignment: Ensure the latest move fixed the issue without taking recoil damage.',
|
|
131
|
+
"Decision: '${drive}' for another turn, or '${close}' the encounter.",
|
|
128
132
|
],
|
|
129
133
|
ask: [
|
|
130
134
|
"Pokedex Data: Use '${drive}' to integrate this research into your battle strategy.",
|
|
131
|
-
"More Intel? Keep using '${ask}', or check the arena logs."
|
|
135
|
+
"More Intel? Keep using '${ask}', or check the arena logs.",
|
|
132
136
|
],
|
|
133
137
|
closeInvoke: [
|
|
134
|
-
|
|
135
|
-
"Ready for another encounter? Use '${start}' to find a new target."
|
|
138
|
+
'Pokemon captured! The battlefield is clear.',
|
|
139
|
+
"Ready for another encounter? Use '${start}' to find a new target.",
|
|
136
140
|
],
|
|
137
141
|
closeDrop: [
|
|
138
|
-
|
|
139
|
-
"Need a different approach? Use '${start}' to re-engage."
|
|
140
|
-
]
|
|
142
|
+
'You fled the battle safely. Back in the tall grass.',
|
|
143
|
+
"Need a different approach? Use '${start}' to re-engage.",
|
|
144
|
+
],
|
|
141
145
|
},
|
|
142
|
-
availableNames: [
|
|
146
|
+
availableNames: ['caterpie', 'pikachu', 'mewtwo'],
|
|
143
147
|
tools: {
|
|
144
148
|
start: {
|
|
145
|
-
name:
|
|
146
|
-
title:
|
|
147
|
-
description:
|
|
149
|
+
name: 'choose_you',
|
|
150
|
+
title: 'I Choose You!',
|
|
151
|
+
description: 'Start a battle (task). Throws a Pokeball (branch), begins Turn 1.\nCall ONCE per battle. Battlefield must be clear — no uncommitted changes.\nBefore calling, identify the target Pokemon (goal). If unclear, consult Pokedex first.\n\nFlow: choose_you → [command x N] → capture',
|
|
148
152
|
args: {
|
|
149
|
-
title:
|
|
150
|
-
goal:
|
|
151
|
-
directive:
|
|
152
|
-
context:
|
|
153
|
-
constraints:
|
|
154
|
-
criteria:
|
|
155
|
-
name:
|
|
156
|
-
cwd:
|
|
153
|
+
title: 'REQUIRED. Battle card title for this encounter.',
|
|
154
|
+
goal: 'REQUIRED. Victory condition. Define exactly what winning this battle means.',
|
|
155
|
+
directive: 'Optional Turn 1 strategy leash. Use to focus on one phase first.',
|
|
156
|
+
context: 'REQUIRED. Battle background: key code paths, symptoms, logs, and repro clues.',
|
|
157
|
+
constraints: 'REQUIRED. Battle rules that cannot be broken while fighting.',
|
|
158
|
+
criteria: 'REQUIRED. Gym badges for completion: concrete checks proving victory.',
|
|
159
|
+
name: 'Optional ${IDENTITY} to send into battle. Presets: ${PRESET_IDENTITIES}.',
|
|
160
|
+
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
157
161
|
},
|
|
158
162
|
},
|
|
159
163
|
drive: {
|
|
160
|
-
name:
|
|
161
|
-
title:
|
|
162
|
-
description:
|
|
164
|
+
name: 'command',
|
|
165
|
+
title: 'Issue Command',
|
|
166
|
+
description: 'Issue orders for the next turn. Give feedback on the previous move.\nCall after reviewing the battle log. Repeatable.\nBefore capturing, always check HP status (diff).\n\nFlow: choose_you → [command x N] → capture',
|
|
163
167
|
args: {
|
|
164
|
-
directive:
|
|
165
|
-
context:
|
|
166
|
-
name:
|
|
167
|
-
cwd:
|
|
168
|
+
directive: 'REQUIRED. Next move command with specific tactical correction.',
|
|
169
|
+
context: 'Optional new battle intel discovered after the previous turn.',
|
|
170
|
+
name: 'Optional ${IDENTITY} to execute this turn. Presets: ${PRESET_IDENTITIES}.',
|
|
171
|
+
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
168
172
|
},
|
|
169
173
|
},
|
|
170
174
|
ask: {
|
|
171
|
-
name:
|
|
172
|
-
title:
|
|
173
|
-
description:
|
|
175
|
+
name: 'pokedex',
|
|
176
|
+
title: 'Pokedex',
|
|
177
|
+
description: 'Scan the codebase (environment). Read-only analysis. No PP cost. Results are saved to research logs.',
|
|
174
178
|
args: {
|
|
175
|
-
request:
|
|
176
|
-
context:
|
|
177
|
-
name:
|
|
178
|
-
cwd:
|
|
179
|
+
request: 'REQUIRED. What should the Pokedex analyze, compare, or explain.',
|
|
180
|
+
context: 'REQUIRED. Context entries so the analysis targets the right ecosystem.',
|
|
181
|
+
name: 'Optional ${IDENTITY} doing the scan. Presets: ${PRESET_IDENTITIES}.',
|
|
182
|
+
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
179
183
|
},
|
|
180
184
|
},
|
|
181
185
|
close: {
|
|
182
|
-
name:
|
|
183
|
-
title:
|
|
184
|
-
description:
|
|
186
|
+
name: 'capture',
|
|
187
|
+
title: 'End Battle',
|
|
188
|
+
description: 'Final petition before a power greater than trainers and legends. Offer your scored confession and await Divine Judgment.\nREQUIRES AN ACTIVE BATTLE (started via ${START_TOOL_NAME}).\nIf unworthy, keep refining through ${DRIVE_TOOL_NAME}.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
|
|
185
189
|
args: {
|
|
186
|
-
petition:
|
|
187
|
-
criteriaChecks:
|
|
188
|
-
score_precise:
|
|
189
|
-
score_minimal:
|
|
190
|
-
score_isolated:
|
|
190
|
+
petition: 'REQUIRED. INVOKE seeks blessing; ABANDON retreats in humility.\nREQUIRES AN ACTIVE BATTLE (started via ${START_TOOL_NAME}).\nIf scores are unworthy, continue with ${DRIVE_TOOL_NAME}.',
|
|
191
|
+
criteriaChecks: 'REQUIRED. Badge-by-badge proof for INVOKE, or confession for ABANDON.',
|
|
192
|
+
score_precise: 'REQUIRED score (0-5). 5 means each strike hit the intended layer perfectly.',
|
|
193
|
+
score_minimal: 'REQUIRED score (0-5). 5 means no unnecessary moves were used.',
|
|
194
|
+
score_isolated: 'REQUIRED score (0-5). 5 means no side-quests polluted this battle.',
|
|
191
195
|
score_idiomatic: "REQUIRED score (0-5). 5 means tactics match the team's doctrine.",
|
|
192
|
-
score_cohesive:
|
|
196
|
+
score_cohesive: 'REQUIRED score (0-5). 5 means each action held one clear purpose.',
|
|
193
197
|
oath: "Trainer's sacred confession. Required for INVOKE. Verbatim: ${OATH_TEXT}",
|
|
194
|
-
cwd:
|
|
198
|
+
cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
|
|
195
199
|
},
|
|
196
200
|
},
|
|
197
201
|
help: {
|
|
198
|
-
name:
|
|
199
|
-
title:
|
|
200
|
-
description:
|
|
202
|
+
name: 'help',
|
|
203
|
+
title: 'CLI Help',
|
|
204
|
+
description: 'Get guidance on the rules of the Pokemon Battle System.',
|
|
201
205
|
args: {
|
|
202
|
-
question:
|
|
206
|
+
question: 'REQUIRED. The Pokemon Battle System question you want answered.',
|
|
203
207
|
},
|
|
204
208
|
},
|
|
205
209
|
},
|
|
206
210
|
};
|
|
207
211
|
export const MISCHIEF_PRESET = {
|
|
208
|
-
id:
|
|
209
|
-
identity:
|
|
212
|
+
id: 'mischief',
|
|
213
|
+
identity: 'minion',
|
|
210
214
|
divineJudgment: DEFAULT_JUDGMENT_CONFIG,
|
|
211
|
-
usageGuide:
|
|
215
|
+
usageGuide: '## Minion Manual\n\n**imp** — Disposable Grunt 😈\n- Expendable. Send it into the trap first.\n\n**minion** — Standard Henchman 👹\n- Can carry out complex evil plans. mostly.\n\n**mastermind** — The Boss ??? 🧠\n- Wait, why are you commanding the boss?\n- Extremely expensive consulting fee.\n\n## Workflow\n`oi` -> [`neh` x N] -> `yoshi`\n`eeto` (optional, read-only contemplation)',
|
|
212
216
|
nextHints: {
|
|
213
217
|
start: [
|
|
214
218
|
"Scrutinize the Minion's Work: Check the incremental [Diff] section.",
|
|
215
219
|
"Inspection: Use 'git diff HEAD~1 -- <path>' to see if they missed a spot.",
|
|
216
220
|
"Master's Approval: Does this align with your grand vision and decrees?",
|
|
217
|
-
"Next Command: Give another '${drive}' order, or grant a '${close}' judgment (INVOKE/ABANDON)."
|
|
221
|
+
"Next Command: Give another '${drive}' order, or grant a '${close}' judgment (INVOKE/ABANDON).",
|
|
218
222
|
],
|
|
219
223
|
drive: [
|
|
220
|
-
|
|
224
|
+
'Another Attempt: Review the latest incremental [Diff] above.',
|
|
221
225
|
"Deep Scrutiny: Use 'git diff HEAD~1 -- <path>' to verify the minion's precision.",
|
|
222
|
-
|
|
223
|
-
"The Verdict: '${drive}' again if imperfect, otherwise '${close}' the matter."
|
|
226
|
+
'Validation: Ensure no new chaos was introduced by their clumsy hands.',
|
|
227
|
+
"The Verdict: '${drive}' again if imperfect, otherwise '${close}' the matter.",
|
|
224
228
|
],
|
|
225
229
|
ask: [
|
|
226
230
|
"Intel Gathered: Incorporate this into your next '${drive}' command.",
|
|
227
|
-
"Still Puzzled? Use '${ask}' again, or look at the dossiers yourself."
|
|
231
|
+
"Still Puzzled? Use '${ask}' again, or look at the dossiers yourself.",
|
|
228
232
|
],
|
|
229
233
|
closeInvoke: [
|
|
230
|
-
|
|
231
|
-
"Plotting something new? Use '${start}' to initiate the next scheme."
|
|
234
|
+
'The masterpiece is complete. Minion dismissed.',
|
|
235
|
+
"Plotting something new? Use '${start}' to initiate the next scheme.",
|
|
232
236
|
],
|
|
233
237
|
closeDrop: [
|
|
234
|
-
|
|
235
|
-
"Starting over? Use '${start}' to find a more competent minion."
|
|
236
|
-
]
|
|
238
|
+
'Scheme aborted. The evidence has been incinerated.',
|
|
239
|
+
"Starting over? Use '${start}' to find a more competent minion.",
|
|
240
|
+
],
|
|
237
241
|
},
|
|
238
|
-
availableNames: [
|
|
242
|
+
availableNames: ['imp', 'minion', 'mastermind'],
|
|
239
243
|
tools: {
|
|
240
244
|
start: {
|
|
241
|
-
name:
|
|
242
|
-
title:
|
|
245
|
+
name: 'oi',
|
|
246
|
+
title: 'Oi!',
|
|
243
247
|
description: "Master Architect mode initiated. It's time to direct a minion to execute your grand vision.\nCall this ONCE per task to establish the keiyaku. Ensure the workspace is clean so your genius isn't obscured by clutter.\nDefine the goal with absolute precision; you lead, they follow.\n\nFlow: oi → [neh x N] → yoshi",
|
|
244
248
|
args: {
|
|
245
|
-
title:
|
|
246
|
-
goal:
|
|
247
|
-
directive:
|
|
248
|
-
context:
|
|
249
|
-
constraints:
|
|
250
|
-
criteria:
|
|
251
|
-
name:
|
|
252
|
-
cwd:
|
|
249
|
+
title: 'REQUIRED. Operation codename for your grand scheme.',
|
|
250
|
+
goal: 'REQUIRED. The conquest objective. Define the exact end-state your minion must deliver.',
|
|
251
|
+
directive: 'Optional first-order command to leash Round 1 scope.',
|
|
252
|
+
context: 'REQUIRED. Briefing dossier: relevant file paths, current failures, logs, and repro clues.',
|
|
253
|
+
constraints: 'REQUIRED. Absolute decrees. Architectural and stylistic limits your minion must obey.',
|
|
254
|
+
criteria: 'REQUIRED. Triumph conditions that can be verified without debate.',
|
|
255
|
+
name: 'Optional ${IDENTITY} to command this operation. Presets: ${PRESET_IDENTITIES}.',
|
|
256
|
+
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
253
257
|
},
|
|
254
258
|
},
|
|
255
259
|
drive: {
|
|
256
|
-
name:
|
|
257
|
-
title:
|
|
258
|
-
description:
|
|
260
|
+
name: 'neh',
|
|
261
|
+
title: 'Neh...',
|
|
262
|
+
description: 'The previous attempt was imperfect. As the judge, provide the corrective nudge needed for the minion to reach your standards.\nAnalyze the diff with your superior intuition before issuing the next directive. Repeat until perfection is achieved.\n\nFlow: oi → [neh x N] → yoshi',
|
|
259
263
|
args: {
|
|
260
|
-
directive:
|
|
261
|
-
context:
|
|
262
|
-
name:
|
|
263
|
-
cwd:
|
|
264
|
+
directive: 'REQUIRED. Precise correction order for the next attempt.',
|
|
265
|
+
context: 'Optional newly uncovered evidence from your latest inspection.',
|
|
266
|
+
name: 'Optional ${IDENTITY} to execute this correction. Presets: ${PRESET_IDENTITIES}.',
|
|
267
|
+
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
264
268
|
},
|
|
265
269
|
},
|
|
266
270
|
ask: {
|
|
267
|
-
name:
|
|
268
|
-
title:
|
|
271
|
+
name: 'eeto',
|
|
272
|
+
title: 'Eeto...',
|
|
269
273
|
description: "Lazy strategy mode. Use this to scout the area before committing to a full scheme, or just because you can't be bothered to start a real task.\nPerfect for gathering intel to paste into a future 'oi' context.",
|
|
270
274
|
args: {
|
|
271
|
-
request:
|
|
272
|
-
context:
|
|
273
|
-
name:
|
|
274
|
-
cwd:
|
|
275
|
+
request: 'REQUIRED. The intel to gather or the strategy to formulate.',
|
|
276
|
+
context: 'REQUIRED. World-state details needed for a sharp analysis.',
|
|
277
|
+
name: 'Optional ${IDENTITY} to contemplate this puzzle. Presets: ${PRESET_IDENTITIES}.',
|
|
278
|
+
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
275
279
|
},
|
|
276
280
|
},
|
|
277
281
|
close: {
|
|
278
|
-
name:
|
|
279
|
-
title:
|
|
280
|
-
description:
|
|
282
|
+
name: 'yoshi',
|
|
283
|
+
title: 'Yoshi!',
|
|
284
|
+
description: 'Kneel before the final tribunal. Submit your scored confession and await Divine Judgment: mercy through INVOKE, ruin through ABANDON.\nREQUIRES AN ACTIVE SCHEME (started via ${START_TOOL_NAME}).\nIf doubtful, continue penance through ${DRIVE_TOOL_NAME}.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
|
|
281
285
|
args: {
|
|
282
|
-
petition:
|
|
283
|
-
criteriaChecks:
|
|
284
|
-
score_precise:
|
|
285
|
-
score_minimal:
|
|
286
|
-
score_isolated:
|
|
287
|
-
score_idiomatic:
|
|
288
|
-
score_cohesive:
|
|
286
|
+
petition: 'REQUIRED. INVOKE pleads for ascension; ABANDON confesses failure.\nREQUIRES AN ACTIVE SCHEME (started via ${START_TOOL_NAME}).\nIf scores are low, continue via ${DRIVE_TOOL_NAME}.',
|
|
287
|
+
criteriaChecks: 'REQUIRED. Proof of mastery for INVOKE, or explicit confession for ABANDON.',
|
|
288
|
+
score_precise: 'REQUIRED score (0-5). 5 means the strike landed in the ordained layer.',
|
|
289
|
+
score_minimal: 'REQUIRED score (0-5). 5 means no needless machinery was summoned.',
|
|
290
|
+
score_isolated: 'REQUIRED score (0-5). 5 means unrelated chaos stayed outside the diff.',
|
|
291
|
+
score_idiomatic: 'REQUIRED score (0-5). 5 means the code speaks native doctrine.',
|
|
292
|
+
score_cohesive: 'REQUIRED score (0-5). 5 means each unit bears one sacred duty.',
|
|
289
293
|
oath: "Architect's sacred confession. Required for INVOKE. Verbatim: ${OATH_TEXT}",
|
|
290
|
-
cwd:
|
|
294
|
+
cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
|
|
291
295
|
},
|
|
292
296
|
},
|
|
293
297
|
help: {
|
|
294
|
-
name:
|
|
295
|
-
title:
|
|
296
|
-
description:
|
|
298
|
+
name: 'help',
|
|
299
|
+
title: 'Nani?!',
|
|
300
|
+
description: 'Recalling the fundamental laws of this realm. Stay sharp, Architect.',
|
|
297
301
|
args: {
|
|
298
|
-
question:
|
|
302
|
+
question: 'REQUIRED. The law or protocol detail you want the realm to explain.',
|
|
299
303
|
},
|
|
300
304
|
},
|
|
301
305
|
},
|
|
302
306
|
};
|
|
303
307
|
export function resolveTermPreset() {
|
|
304
308
|
const raw = process.env.KEIYAKU_TERM_PRESET?.trim().toLowerCase();
|
|
305
|
-
if (!raw || raw ===
|
|
309
|
+
if (!raw || raw === 'default') {
|
|
306
310
|
return DEFAULT_PRESET;
|
|
307
311
|
}
|
|
308
|
-
if (raw ===
|
|
312
|
+
if (raw === 'pokemon') {
|
|
309
313
|
return POKEMON_PRESET;
|
|
310
314
|
}
|
|
311
|
-
if (raw ===
|
|
315
|
+
if (raw === 'mischief') {
|
|
312
316
|
return MISCHIEF_PRESET;
|
|
313
317
|
}
|
|
314
318
|
throw new Error(`Unsupported KEIYAKU_TERM_PRESET '${raw}'. Expected 'default', 'pokemon', or 'mischief'.`);
|
|
@@ -317,7 +321,7 @@ export function listTermPresets() {
|
|
|
317
321
|
return [DEFAULT_PRESET, POKEMON_PRESET, MISCHIEF_PRESET];
|
|
318
322
|
}
|
|
319
323
|
function extractPresetAvailableNames(preset) {
|
|
320
|
-
return preset.availableNames?.map((value) => value.trim()).filter((value) => value.length > 0) ?? [];
|
|
324
|
+
return (preset.availableNames?.map((value) => value.trim()).filter((value) => value.length > 0) ?? []);
|
|
321
325
|
}
|
|
322
326
|
export function getAvailableNamesForPreset(preset = resolveTermPreset()) {
|
|
323
327
|
const names = extractPresetAvailableNames(preset);
|
package/build/utils/git.js
CHANGED
|
@@ -322,6 +322,28 @@ function splitDiffByFile(content) {
|
|
|
322
322
|
sections.push(current);
|
|
323
323
|
return sections;
|
|
324
324
|
}
|
|
325
|
+
function totalJoinedLength(blocks) {
|
|
326
|
+
if (blocks.length === 0)
|
|
327
|
+
return 0;
|
|
328
|
+
return blocks.reduce((sum, block) => sum + block.length, 0) + (blocks.length - 1);
|
|
329
|
+
}
|
|
330
|
+
function truncateBlockToLineBudget(block, maxChars) {
|
|
331
|
+
if (maxChars <= 0)
|
|
332
|
+
return "";
|
|
333
|
+
if (block.length <= maxChars)
|
|
334
|
+
return block;
|
|
335
|
+
const lines = block.split("\n");
|
|
336
|
+
const kept = [];
|
|
337
|
+
let used = 0;
|
|
338
|
+
for (const line of lines) {
|
|
339
|
+
const delta = (kept.length > 0 ? 1 : 0) + line.length;
|
|
340
|
+
if (used + delta > maxChars)
|
|
341
|
+
break;
|
|
342
|
+
kept.push(line);
|
|
343
|
+
used += delta;
|
|
344
|
+
}
|
|
345
|
+
return kept.join("\n");
|
|
346
|
+
}
|
|
325
347
|
export async function getIncrementalDiff(cwd) {
|
|
326
348
|
const git = createGit(cwd);
|
|
327
349
|
const range = "HEAD~1...HEAD";
|
|
@@ -347,28 +369,45 @@ export async function getIncrementalDiff(cwd) {
|
|
|
347
369
|
if (sections.length === 0)
|
|
348
370
|
return "No changes in last round.";
|
|
349
371
|
const filePreviews = [];
|
|
350
|
-
let totalChars = 0;
|
|
351
372
|
const MAX_TOTAL_CHARS = 4000;
|
|
352
373
|
const MAX_LINES_PER_FILE = 40;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
374
|
+
let omittedFiles = 0;
|
|
375
|
+
for (let i = 0; i < sections.length; i += 1) {
|
|
376
|
+
const section = sections[i];
|
|
356
377
|
const fileName = parseDiffPathFromHeader(section[0] ?? "") ?? "unknown";
|
|
357
378
|
const header = `--- ${fileName} ---`;
|
|
358
|
-
|
|
379
|
+
const content = section.slice(0, MAX_LINES_PER_FILE);
|
|
359
380
|
const isTruncated = section.length > MAX_LINES_PER_FILE;
|
|
360
381
|
if (isTruncated) {
|
|
361
382
|
content.push(`... [truncated ${section.length - MAX_LINES_PER_FILE} lines for this file]`);
|
|
362
383
|
}
|
|
363
384
|
const fileBlock = `${header}\n${content.join("\n")}\n`;
|
|
364
|
-
filePreviews
|
|
365
|
-
|
|
385
|
+
const projected = totalJoinedLength([...filePreviews, fileBlock]);
|
|
386
|
+
if (projected <= MAX_TOTAL_CHARS) {
|
|
387
|
+
filePreviews.push(fileBlock);
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
omittedFiles = sections.length - i;
|
|
391
|
+
if (filePreviews.length === 0) {
|
|
392
|
+
const notice = `... [omitted ${omittedFiles} file(s) to stay under ${MAX_TOTAL_CHARS} chars] ...`;
|
|
393
|
+
const partialBudget = Math.max(0, MAX_TOTAL_CHARS - notice.length - 1);
|
|
394
|
+
const partial = truncateBlockToLineBudget(fileBlock, partialBudget);
|
|
395
|
+
if (partial.trim().length > 0) {
|
|
396
|
+
filePreviews.push(partial);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
366
400
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
401
|
+
if (omittedFiles > 0) {
|
|
402
|
+
const notice = `... [omitted ${omittedFiles} file(s) to stay under ${MAX_TOTAL_CHARS} chars] ...`;
|
|
403
|
+
while (filePreviews.length > 0 && totalJoinedLength([...filePreviews, notice]) > MAX_TOTAL_CHARS) {
|
|
404
|
+
filePreviews.pop();
|
|
405
|
+
}
|
|
406
|
+
if (totalJoinedLength([...filePreviews, notice]) <= MAX_TOTAL_CHARS) {
|
|
407
|
+
filePreviews.push(notice);
|
|
408
|
+
}
|
|
370
409
|
}
|
|
371
|
-
return
|
|
410
|
+
return filePreviews.join("\n");
|
|
372
411
|
}
|
|
373
412
|
export async function getDiffStats(cwd, baseBranch) {
|
|
374
413
|
const git = createGit(cwd);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function buildStartPrompt(title, goal, directive) {
|
|
2
2
|
const goalBlock = `\nGoal (immutable):\n${goal}\n`;
|
|
3
3
|
const directiveBlock = directive ? `\nDirective (Round 1 only):\n${directive}\n` : "";
|
|
4
|
-
return
|
|
5
|
-
Round: 1.
|
|
4
|
+
return `You are working on a keiyaku (${title}).${goalBlock}${directiveBlock}
|
|
5
|
+
Round: 1 (initial implementation).
|
|
6
6
|
|
|
7
7
|
- Goal: immutable.
|
|
8
8
|
- Directive: round scope.
|
|
@@ -19,31 +19,41 @@ Round: 1.
|
|
|
19
19
|
6. End with 4 sections:
|
|
20
20
|
- Summary: outcome.
|
|
21
21
|
- Changes: files, logic delta, evidence.
|
|
22
|
-
- Gap
|
|
22
|
+
- Aesthetics Gap
|
|
23
23
|
Self-critique.
|
|
24
|
-
|
|
24
|
+
precise — right place, layer, abstraction
|
|
25
|
+
minimal — smallest diff that solves it
|
|
26
|
+
isolated — no unrelated changes riding along
|
|
27
|
+
idiomatic — fits the codebase's voice
|
|
28
|
+
cohesive — each unit does one thing
|
|
29
|
+
- Blindspots: untested paths/assumptions.
|
|
25
30
|
|
|
26
31
|
No git commands. Do not edit KEIYAKU_TRACE.md.`;
|
|
27
32
|
}
|
|
28
33
|
export function buildIteratePrompt(title, round, reason) {
|
|
29
|
-
return
|
|
30
|
-
Round: ${round}.
|
|
34
|
+
return `You are working on a keiyaku (${title}).
|
|
35
|
+
Round: ${round} (iteration after review).
|
|
31
36
|
|
|
32
37
|
Address this review reason:
|
|
33
38
|
${reason}
|
|
34
39
|
|
|
35
40
|
1. Read KEIYAKU.md. Keep constraints/criteria unchanged.
|
|
36
41
|
2. If Focus exists, prioritize it.
|
|
37
|
-
3. Read KEIYAKU_TRACE.md.
|
|
42
|
+
3. Read KEIYAKU_TRACE.md. Locate the latest "## Review ${round}" section.
|
|
38
43
|
4. Fix review reason first.
|
|
39
44
|
5. No drift from constraints/criteria.
|
|
40
45
|
6. Keep diff small.
|
|
41
46
|
7. End with 4 sections:
|
|
42
47
|
- Summary: outcome.
|
|
43
48
|
- Changes: files, logic delta, evidence.
|
|
44
|
-
- Gap
|
|
49
|
+
- Aesthetics Gap
|
|
45
50
|
Self-critique.
|
|
46
|
-
|
|
51
|
+
precise — right place, layer, abstraction
|
|
52
|
+
minimal — smallest diff that solves it
|
|
53
|
+
isolated — no unrelated changes riding along
|
|
54
|
+
idiomatic — fits the codebase's voice
|
|
55
|
+
cohesive — each unit does one thing
|
|
56
|
+
- Blindspots: untested paths/assumptions.
|
|
47
57
|
|
|
48
58
|
No git commands. Do not edit KEIYAKU_TRACE.md.`;
|
|
49
59
|
}
|
|
@@ -56,5 +66,5 @@ ${request}
|
|
|
56
66
|
Context:
|
|
57
67
|
${context}
|
|
58
68
|
|
|
59
|
-
Provide reasoning summary.`;
|
|
69
|
+
Provide a clear reasoning summary in plain text.`;
|
|
60
70
|
}
|
|
@@ -35,7 +35,7 @@ function assembleResponse(status, summary, sections, nextHints, infoLines = [])
|
|
|
35
35
|
const infoSection = buildSection("Info", infoLines);
|
|
36
36
|
const parts = [
|
|
37
37
|
`[Status] ${status}`,
|
|
38
|
-
`[
|
|
38
|
+
`[Brief]\n${summary}`,
|
|
39
39
|
...sections,
|
|
40
40
|
infoSection,
|
|
41
41
|
"", // Spacer
|