@astrosheep/keiyaku 0.1.7 → 0.1.9

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.
@@ -33,7 +33,7 @@ function hintForFlowCode(code, message) {
33
33
  case "NOT_GIT_REPO":
34
34
  return "The provided `cwd` is not a git repository.";
35
35
  case "ACTIVE_KEIYAKU_EXISTS":
36
- return "An active keiyaku branch already exists in this repository. Continue with `drive`, or use `close` + `ABANDON` to drop it.";
36
+ return "An active keiyaku branch already exists in this repository. Continue with `drive`, or use `close` + `FORFEIT` to drop it.";
37
37
  case "EXISTING_KEIYAKU_BRANCH_FOUND":
38
38
  return "At least one local `keiyaku/*` branch already exists in this repository.";
39
39
  case "EMPTY_PARAM":
@@ -49,7 +49,7 @@ function hintForFlowCode(code, message) {
49
49
  case "DONE_MERGE_CONFLICT":
50
50
  return "DONE encountered a git merge conflict.";
51
51
  case "CLOSE_QUALITY_GATE_FAILED":
52
- return "INVOKE was denied because one or more verification thresholds were not met (check .keiyaku/settings.json).";
52
+ return "CLAIM was denied because one or more verification thresholds were not met (check .keiyaku/settings.json).";
53
53
  case "OATH_MISMATCH":
54
54
  return message;
55
55
  case "SUBAGENT_DID_NOT_ADVANCE_ROUND":
@@ -72,7 +72,7 @@ const MESSAGE_HINT_PATTERNS = [
72
72
  { code: "MISSING_KEIYAKU_BASE", patterns: ["is missing base metadata"] },
73
73
  { code: "MISSING_PROTOCOL_FILES", patterns: ["missing protocol files"] },
74
74
  { code: "DONE_MERGE_CONFLICT", patterns: ["DONE merge conflict"] },
75
- { code: "CLOSE_QUALITY_GATE_FAILED", patterns: ["God's Wrath: INVOKE denied"] },
75
+ { code: "CLOSE_QUALITY_GATE_FAILED", patterns: ["God's Wrath: CLAIM denied"] },
76
76
  {
77
77
  code: "OATH_MISMATCH",
78
78
  patterns: [
@@ -39,7 +39,7 @@ export const DEFAULT_PRESET = {
39
39
  'Intel acquired. This was stateless—no contract, no branch.',
40
40
  'To act on this knowledge: ${start} a Keiyaku, or ${drive} an existing one.',
41
41
  ],
42
- closeInvoke: [
42
+ closeClaim: [
43
43
  'Contract fulfilled. Branch merged.',
44
44
  'You are back on base.',
45
45
  'Next assignment: ${start} when ready.',
@@ -147,7 +147,7 @@ export const POCKET_PRESET = {
147
147
  "Data Recorded: Use '${start}' to begin the encounter, or '${drive}' to use this intel.",
148
148
  "Still Searching? Keep using '${ask}' to fill the Dex.",
149
149
  ],
150
- closeInvoke: [
150
+ closeClaim: [
151
151
  'Critter Captured! The entry is logged in the PC (base branch).',
152
152
  "Heal up. Use '${start}' to challenge the next opponent.",
153
153
  ],
@@ -198,16 +198,16 @@ export const POCKET_PRESET = {
198
198
  close: {
199
199
  name: 'capture',
200
200
  title: 'End Battle',
201
- description: 'Attempt Capture. Present the weakened target for League Inspection.\nWARNING: The League (System) checks every Badge. If you attempt to `INVOKE` with fainted code, Disqualification (ABANDON) is immediate.\nOnly throw the Ball when the target is 100% ready.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
201
+ description: 'Attempt Capture. Present the weakened target for League Inspection.\nWARNING: The League (System) checks every Badge. If you attempt to `CLAIM` with fainted code, Disqualification (FORFEIT) is immediate.\nOnly throw the Ball when the target is 100% ready.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
202
202
  args: {
203
- petition: 'REQUIRED. INVOKE seeks Badge; ABANDON forfeits the match.\nREQUIRES AN ACTIVE BATTLE (started via ${START_TOOL_NAME}).\nIf stats are low, continue with ${DRIVE_TOOL_NAME}.',
204
- criteriaChecks: 'REQUIRED. Badge-by-badge proof for INVOKE, or reason for Forfeit.',
203
+ petition: 'REQUIRED. CLAIM seeks Badge; FORFEIT forfeits the match.\nREQUIRES AN ACTIVE BATTLE (started via ${START_TOOL_NAME}).\nIf stats are low, continue with ${DRIVE_TOOL_NAME}.',
204
+ criteriaChecks: 'REQUIRED. Badge-by-badge proof for CLAIM, or reason for Forfeit.',
205
205
  score_precise: 'REQUIRED score (0-5). 5 means a Critical Hit: exact layer, exact target, zero meaningful misplacement.',
206
206
  score_minimal: 'REQUIRED score (0-5). 5 means Max Efficiency: no wasted PP, no extra motion.',
207
207
  score_isolated: 'REQUIRED score (0-5). 5 means 1v1 Focus: zero side-quests, zero unrelated damage.',
208
208
  score_idiomatic: "REQUIRED score (0-5). 5 means STAB (Same Type Attack Bonus): perfectly matches the codebase style.",
209
209
  score_cohesive: 'REQUIRED score (0-5). 5 means Team Synergy: action serves one purpose with clean boundaries.',
210
- oath: "Trainer's Honor Code. Required for INVOKE. Verbatim: ${OATH_TEXT}",
210
+ oath: "Trainer's Honor Code. Required for CLAIM. Verbatim: ${OATH_TEXT}",
211
211
  cwd: 'Optional battlefield path (repository root). Defaults to current arena.',
212
212
  },
213
213
  },
@@ -243,7 +243,7 @@ export const MISCHIEF_PRESET = {
243
243
  "Intel Stolen: Use '${start}' to launch the scheme, or '${drive}' to exploit this weakness.",
244
244
  "Still Puzzled? Send the spy ('${ask}') out again.",
245
245
  ],
246
- closeInvoke: [
246
+ closeClaim: [
247
247
  'Scheme Successful. The Lair is merged. The Minion is fed.',
248
248
  "Plotting something new? Use '${start}' for the next conquest.",
249
249
  ],
@@ -294,16 +294,16 @@ export const MISCHIEF_PRESET = {
294
294
  close: {
295
295
  name: 'yoshi',
296
296
  title: 'Yoshi!',
297
- description: 'The Final Reveal. Present your Masterpiece to the Dark Council (System).\nWARNING: The Council destroys failure. If you `INVOKE` with weak plans, the Self-Destruct (ABANDON) will trigger.\nOnly reveal the Doomsday Device when it is fully operational.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
297
+ description: 'The Final Reveal. Present your Masterpiece to the Dark Council (System).\nWARNING: The Council destroys failure. If you `CLAIM` with weak plans, the Self-Destruct (FORFEIT) will trigger.\nOnly reveal the Doomsday Device when it is fully operational.\n\nFlow: ${START_TOOL_NAME} → [${DRIVE_TOOL_NAME} x N] → ${CLOSE_TOOL_NAME}',
298
298
  args: {
299
- petition: 'REQUIRED. INVOKE demands rule; ABANDON admits defeat.\nREQUIRES AN ACTIVE SCHEME (started via ${START_TOOL_NAME}).\nIf the plan is weak, improve it with ${DRIVE_TOOL_NAME}.',
300
- criteriaChecks: 'REQUIRED. Proof of conquest for INVOKE, or reason for self-destruct.',
299
+ petition: 'REQUIRED. CLAIM demands rule; FORFEIT admits defeat.\nREQUIRES AN ACTIVE SCHEME (started via ${START_TOOL_NAME}).\nIf the plan is weak, improve it with ${DRIVE_TOOL_NAME}.',
300
+ criteriaChecks: 'REQUIRED. Proof of conquest for CLAIM, or reason for self-destruct.',
301
301
  score_precise: 'REQUIRED score (0-5). 5 means Laser Focus: exact cut, zero meaningful drift.',
302
302
  score_minimal: 'REQUIRED score (0-5). 5 means Ruthless Efficiency: no wasted movement, no excess.',
303
303
  score_isolated: 'REQUIRED score (0-5). 5 means Perfect Containment: no collateral damage.',
304
304
  score_idiomatic: 'REQUIRED score (0-5). 5 means Native Tongue: matches the lair\'s dialect perfectly.',
305
305
  score_cohesive: 'REQUIRED score (0-5). 5 means Absolute Loyalty: each unit serves the master plan.',
306
- oath: "Mastermind's Vow. Required for INVOKE. Verbatim: ${OATH_TEXT}",
306
+ oath: "Mastermind's Vow. Required for CLAIM. Verbatim: ${OATH_TEXT}",
307
307
  cwd: 'Optional lair path (repository root). Defaults to current command chamber.',
308
308
  },
309
309
  },
@@ -24,12 +24,12 @@ export function createCloseHandler() {
24
24
  oath,
25
25
  signal: extra.signal,
26
26
  });
27
- if (petition === "INVOKE") {
27
+ if (petition === "CLAIM") {
28
28
  if (!("result" in outcome) || outcome.result !== "done") {
29
- throw new Error("Unexpected INVOKE outcome shape");
29
+ throw new Error("Unexpected CLAIM outcome shape");
30
30
  }
31
31
  const finalOutcome = outcome;
32
- appendDebugLog(`tool close INVOKE success branch=${finalOutcome.branch} base=${finalOutcome.baseBranch}`, {
32
+ appendDebugLog(`tool close CLAIM success branch=${finalOutcome.branch} base=${finalOutcome.baseBranch}`, {
33
33
  cwd: workingDir,
34
34
  section: "script",
35
35
  });
@@ -45,10 +45,10 @@ export function createCloseHandler() {
45
45
  });
46
46
  }
47
47
  if (!("result" in outcome) || outcome.result !== "dropped") {
48
- throw new Error("Unexpected ABANDON outcome shape");
48
+ throw new Error("Unexpected FORFEIT outcome shape");
49
49
  }
50
50
  const finalOutcome = outcome;
51
- appendDebugLog(`tool close ABANDON success branch=${finalOutcome.branch} base=${finalOutcome.baseBranch}`, {
51
+ appendDebugLog(`tool close FORFEIT success branch=${finalOutcome.branch} base=${finalOutcome.baseBranch}`, {
52
52
  cwd: workingDir,
53
53
  section: "script",
54
54
  });
@@ -22,7 +22,7 @@ export const askToolSchema = z.object({
22
22
  cwd: z.string().optional(),
23
23
  });
24
24
  export const closeToolSchema = z.object({
25
- petition: z.enum(["INVOKE", "ABANDON"]),
25
+ petition: z.enum(["CLAIM", "FORFEIT"]),
26
26
  criteriaChecks: z.array(z.string().trim().min(1)).min(1),
27
27
  score_precise: z.number().min(0).max(5),
28
28
  score_minimal: z.number().min(0).max(5),
@@ -61,9 +61,9 @@ function truncateForMessage(text, maxChars) {
61
61
  async function buildActiveKeiyakuStartMessage(cwd, branch) {
62
62
  const lines = [
63
63
  `active keiyaku already exists (${branch})`,
64
- "This task is still active. Decide whether to continue or abandon it.",
64
+ "This task is still active. Decide whether to continue or forfeit it.",
65
65
  "Continue: run drive on the current keiyaku branch.",
66
- "Abandon: run close with petition=ABANDON to drop the branch.",
66
+ "Forfeit: run close with petition=FORFEIT to drop the branch.",
67
67
  ];
68
68
  try {
69
69
  const keiyakuPath = path.join(cwd, KEIYAKU_FILE);
@@ -417,7 +417,7 @@ export async function handleClose(input) {
417
417
  }
418
418
  const title = keiyakuBranch.slice("keiyaku/".length);
419
419
  const petition = input.petition;
420
- if (petition === "ABANDON") {
420
+ if (petition === "FORFEIT") {
421
421
  let round = 0;
422
422
  try {
423
423
  const trace = await fs.readFile(path.join(cwd, TRACE_FILE), "utf-8");
@@ -433,7 +433,7 @@ export async function handleClose(input) {
433
433
  await git.clearKeiyakuBase(cwd, keiyakuBranch);
434
434
  }
435
435
  catch (err) {
436
- throw wrapFlowError(`execute ABANDON (${keiyakuBranch} -> ${baseBranch})`, err);
436
+ throw wrapFlowError(`execute FORFEIT (${keiyakuBranch} -> ${baseBranch})`, err);
437
437
  }
438
438
  return {
439
439
  status: "success",
@@ -441,12 +441,12 @@ export async function handleClose(input) {
441
441
  round,
442
442
  branch: keiyakuBranch,
443
443
  baseBranch,
444
- diff: "Abandoned without merge.",
444
+ diff: "Forfeited without merge.",
445
445
  };
446
446
  }
447
447
  await ensureKeiyakuFiles(cwd);
448
448
  const traceContent = await readTraceContent(cwd);
449
- if (petition === "INVOKE") {
449
+ if (petition === "CLAIM") {
450
450
  const verdict = await resolveVerdictConfig(cwd);
451
451
  const failedCommandments = CLOSE_SCORE_FIELDS.flatMap((field) => {
452
452
  const score = input[field];
@@ -476,15 +476,15 @@ export async function handleClose(input) {
476
476
  }
477
477
  await assertCleanWorkingTree(cwd);
478
478
  try {
479
- const invokeDiffLog = `[INVOKE] Collecting diff preview against base '${baseBranch}'`;
479
+ const invokeDiffLog = `[CLAIM] Collecting diff preview against base '${baseBranch}'`;
480
480
  console.error(invokeDiffLog);
481
481
  appendDebugLog(invokeDiffLog, { cwd, section: "script" });
482
- const invokeReadLog = "[INVOKE] Reading keiyaku protocol files";
482
+ const invokeReadLog = "[CLAIM] Reading keiyaku protocol files";
483
483
  console.error(invokeReadLog);
484
484
  appendDebugLog(invokeReadLog, { cwd, section: "script" });
485
485
  const keiyakuContent = await fs.readFile(path.join(cwd, KEIYAKU_FILE), "utf-8");
486
486
  const message = buildMergeMessage(title, keiyakuContent, traceContent);
487
- const invokeCleanupLog = "[INVOKE] Removing protocol files and creating cleanup commit";
487
+ const invokeCleanupLog = "[CLAIM] Removing protocol files and creating cleanup commit";
488
488
  console.error(invokeCleanupLog);
489
489
  appendDebugLog(invokeCleanupLog, { cwd, section: "script" });
490
490
  await fs.unlink(path.join(cwd, KEIYAKU_FILE));
@@ -492,15 +492,15 @@ export async function handleClose(input) {
492
492
  await git.addFiles(cwd, "-A");
493
493
  await git.commit(cwd, `keiyaku(${title}): cleanup`);
494
494
  const diff = await git.getDiffPreviewText(cwd, baseBranch);
495
- const invokeCheckoutLog = `[INVOKE] Checking out base branch '${baseBranch}'`;
495
+ const invokeCheckoutLog = `[CLAIM] Checking out base branch '${baseBranch}'`;
496
496
  console.error(invokeCheckoutLog);
497
497
  appendDebugLog(invokeCheckoutLog, { cwd, section: "script" });
498
498
  await git.checkoutBranch(cwd, baseBranch);
499
- const invokeMergeLog = `[INVOKE] Merging '${keiyakuBranch}' into '${baseBranch}'`;
499
+ const invokeMergeLog = `[CLAIM] Merging '${keiyakuBranch}' into '${baseBranch}'`;
500
500
  console.error(invokeMergeLog);
501
501
  appendDebugLog(invokeMergeLog, { cwd, section: "script" });
502
502
  await git.merge(cwd, keiyakuBranch, message);
503
- const invokeFinalizeLog = `[INVOKE] Deleting merged branch '${keiyakuBranch}' and clearing metadata`;
503
+ const invokeFinalizeLog = `[CLAIM] Deleting merged branch '${keiyakuBranch}' and clearing metadata`;
504
504
  console.error(invokeFinalizeLog);
505
505
  appendDebugLog(invokeFinalizeLog, { cwd, section: "script" });
506
506
  await git.deleteBranch(cwd, keiyakuBranch);
@@ -518,9 +518,9 @@ export async function handleClose(input) {
518
518
  catch (err) {
519
519
  const conflictFiles = await git.getUnmergedFiles(cwd);
520
520
  if (conflictFiles.length > 0) {
521
- throw new FlowError("DONE_MERGE_CONFLICT", `INVOKE merge conflict between ${keiyakuBranch} and ${baseBranch} (CONFLICTS: ${conflictFiles.join(", ")})`, err);
521
+ throw new FlowError("DONE_MERGE_CONFLICT", `CLAIM merge conflict between ${keiyakuBranch} and ${baseBranch} (CONFLICTS: ${conflictFiles.join(", ")})`, err);
522
522
  }
523
- throw wrapFlowError(`execute INVOKE (merge ${keiyakuBranch} into ${baseBranch})`, err);
523
+ throw wrapFlowError(`execute CLAIM (merge ${keiyakuBranch} into ${baseBranch})`, err);
524
524
  }
525
525
  }
526
526
  throw new Error(`unsupported close petition: ${petition}`);
@@ -189,13 +189,13 @@ export function buildCloseDoneResponse(result, input) {
189
189
  const { status: _status, ...resultData } = result;
190
190
  const closeToolName = getCloseToolName();
191
191
  const inputEcho = [
192
- `Petition: INVOKE`,
192
+ `Petition: CLAIM`,
193
193
  ...formatList("Criteria Checks", input.criteriaChecks, { maxItems: 10, maxItemChars: 220 }),
194
194
  `Scores: precise=${input.score_precise}/5 minimal=${input.score_minimal}/5 isolated=${input.score_isolated}/5 idiomatic=${input.score_idiomatic}/5 cohesive=${input.score_cohesive}/5`,
195
195
  ...formatMaybe("Oath", input.oath, 220),
196
196
  ...formatMaybe("CWD", input.cwd, 300),
197
197
  ];
198
- const nextHints = renderHints(resolveTermPreset().nextHints.closeInvoke);
198
+ const nextHints = renderHints(resolveTermPreset().nextHints.closeClaim);
199
199
  const inputSection = buildSection("Input", inputEcho);
200
200
  const diffSection = result.diff ? buildSection("Diff", result.diff) : "";
201
201
  const infoLines = [
@@ -203,7 +203,7 @@ export function buildCloseDoneResponse(result, input) {
203
203
  ...formatMaybe("Current Branch", result.branch, 200),
204
204
  ...formatMaybe("Base Branch", result.baseBranch, 200),
205
205
  ];
206
- const text = assembleResponse("Keiyaku Fulfilled (INVOKE)", `Merged '${result.branch}' into '${result.baseBranch}'. Deleted feature branch.`, [inputSection, diffSection], nextHints, infoLines);
206
+ const text = assembleResponse("Keiyaku Fulfilled (CLAIM)", `Merged '${result.branch}' into '${result.baseBranch}'. Deleted feature branch.`, [inputSection, diffSection], nextHints, infoLines);
207
207
  return {
208
208
  content: [{ type: "text", text }],
209
209
  structuredContent: buildSuccessStructuredContent(closeToolName, {
@@ -218,7 +218,7 @@ export function buildCloseDropResponse(result, input) {
218
218
  const { status: _status, ...resultData } = result;
219
219
  const closeToolName = getCloseToolName();
220
220
  const inputEcho = [
221
- `Petition: ABANDON`,
221
+ `Petition: FORFEIT`,
222
222
  ...formatList("Reasons/Checks", input.criteriaChecks, { maxItems: 10, maxItemChars: 220 }),
223
223
  `Scores: precise=${input.score_precise}/5 minimal=${input.score_minimal}/5 isolated=${input.score_isolated}/5 idiomatic=${input.score_idiomatic}/5 cohesive=${input.score_cohesive}/5`,
224
224
  ...formatMaybe("CWD", input.cwd, 300),
@@ -230,7 +230,7 @@ export function buildCloseDropResponse(result, input) {
230
230
  ...formatMaybe("Current Branch", result.branch, 200),
231
231
  ...formatMaybe("Base Branch", result.baseBranch, 200),
232
232
  ];
233
- const text = assembleResponse("Keiyaku Abandoned (ABANDON)", `Deleted '${result.branch}'. Switched back to '${result.baseBranch}'.`, [inputSection], nextHints, infoLines);
233
+ const text = assembleResponse("Keiyaku Forfeited (FORFEIT)", `Deleted '${result.branch}'. Switched back to '${result.baseBranch}'.`, [inputSection], nextHints, infoLines);
234
234
  return {
235
235
  content: [{ type: "text", text }],
236
236
  structuredContent: buildSuccessStructuredContent(closeToolName, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrosheep/keiyaku",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "MCP server for running iterative keiyaku workflows with Codex subagents.",
5
5
  "license": "MIT",
6
6
  "type": "module",