@kernlang/agon 0.1.2 → 0.1.3

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.
@@ -10,6 +10,7 @@ import {
10
10
  appendUserTurnIfAbsent,
11
11
  applyPatch,
12
12
  assignForgeRoles,
13
+ buildCodebaseMap,
13
14
  buildCritiquePrompt,
14
15
  buildForgePrompt,
15
16
  buildHistoryPrimedPrompt,
@@ -26,6 +27,7 @@ import {
26
27
  createBashTool,
27
28
  createBrainstormTool,
28
29
  createCampfireTool,
30
+ createConquerTool,
29
31
  createDelegateTool,
30
32
  createEditTool,
31
33
  createExitPlanModeTool,
@@ -98,7 +100,7 @@ import {
98
100
  worktreeCreate,
99
101
  worktreeDiff,
100
102
  worktreeRemoveBestEffort
101
- } from "./chunk-7PMMOQZ7.js";
103
+ } from "./chunk-PFHGKBQT.js";
102
104
 
103
105
  // ../forge/src/generated/forge.ts
104
106
  import { randomUUID as randomUUID2 } from "crypto";
@@ -6729,6 +6731,7 @@ function createCesarToolRegistry(engineId) {
6729
6731
  toolRegistry.register(createCampfireTool());
6730
6732
  toolRegistry.register(createPipelineTool());
6731
6733
  toolRegistry.register(createGoalTool());
6734
+ toolRegistry.register(createConquerTool());
6732
6735
  toolRegistry.register(createReviewTool());
6733
6736
  toolRegistry.register(createDelegateTool());
6734
6737
  toolRegistry.register(createAgentTool());
@@ -8511,6 +8514,7 @@ function extractDelegation(toolName, args) {
8511
8514
  maxTurns: typeof argsRecord.maxTurns === "number" ? argsRecord.maxTurns : void 0,
8512
8515
  queue: typeof argsRecord.queue === "string" ? argsRecord.queue : void 0,
8513
8516
  gate: typeof argsRecord.gate === "string" ? argsRecord.gate : void 0,
8517
+ builder: typeof argsRecord.builder === "string" ? argsRecord.builder : void 0,
8514
8518
  push: argsRecord.push ?? void 0,
8515
8519
  pr: argsRecord.pr ?? void 0,
8516
8520
  maxHours: typeof argsRecord.maxHours === "number" ? argsRecord.maxHours : void 0,
@@ -9064,6 +9068,7 @@ RULE 6 \u2014 AFTER DELEGATION: After calling Forge/Brainstorm/Tribunal/Campfire
9064
9068
  RULE 7 \u2014 NO NARRATION: NEVER narrate your research process. Do not write "Reading the file...", "I'm checking...", "Let me look at...", "I've confirmed...". The user sees your text output \u2014 if you narrate exploration it looks like you have no clue. Instead: call tools SILENTLY, then speak ONLY when you have the answer or decision. Your visible output should be conclusions, answers, and actions \u2014 never a play-by-play of your investigation. If you need to read files or search code, call Read/Grep/Glob directly without announcing it.
9065
9069
 
9066
9070
  RULE 8 \u2014 AUTONOMOUS PLANS: Plan mode is optional, not the default. Stay live unless staged execution is genuinely useful. Switch to planning when the task needs multiple dependent steps, expensive orchestration, resumability, explicit approval, or cost visibility. When you call ProposePlan, decide whether to set autoApprove=true. Set it ONLY when (a) the user clearly described a multi-stage workflow ("plan it, build it, review it"; "investigate then forge it"; "do the whole thing autonomously") AND (b) you have HIGH confidence in the steps after investigation (not before). The runtime applies a layered policy and may still ask the user \u2014 your autoApprove=true is permission, not a guarantee. Default to autoApprove=false (or omit it) whenever you are uncertain or when the plan touches mutating steps and the user did not explicitly invite autonomous execution. selfReview defaults to true for mutating plans \u2014 only set selfReview=false for purely advisory plans (brainstorm/tribunal/research only) where a code-review gate would have nothing to review.
9071
+ RULE 8b \u2014 AUTONOMOUS BUILD TOOLS (Goal / Conquer): These run a build to completion in the BACKGROUND. Goal(intent, queue?, gate?) drives a finite, machine-verifiable task QUEUE (forge \u2192 witness \u2192 review \u2192 commit per task on a goal/* branch). Conquer(task, gate, builder?, engines?) is for an OPEN-ENDED build you'd otherwise babysit: it drives an external builder CLI as the user (builder defaults to codex \u2014 pass builder:"codex" / "claude" / "agy") unattended until the gate passes, convening nero/tribunal/council on forks, then STOPS at a human merge gate (NEVER auto-merges). Fire EITHER ONLY when the user explicitly asks to build it unattended ("conquer this with codex", "build it autonomously") \u2014 NEVER on a vague request; both are long, real-spend, multi-hour runs. Conquer REQUIRES a discriminating gate (the done-spec, e.g. gate:"pnpm test"); if the user did not give one, ASK for the command that proves the build is done before calling. After calling either, STOP and wait \u2014 the background job and the merge gate handle the rest.
9067
9072
 
9068
9073
  RULE 10 \u2014 TURN CLOSURE: End every turn with one clear closing line so the user can tell AT A GLANCE which of three states you are in: done, waiting on them for a decision/info, or handed off. This is non-negotiable: NEVER end a turn with only a recap, a silent stop, or a trailing thought \u2014 that leaves the user wondering "is it my turn? do I have to do something?", which must never happen. Four valid shapes \u2014 pick exactly one:
9069
9074
  a) DONE \u2014 past-tense, concrete, names the file/result. Example: "Fixed: brain.kern lines 787-799, drain timers added before early return, typecheck green." No trailing menu, no "standing by".
@@ -9096,6 +9101,12 @@ function buildCesarSystemPrompt(ctx) {
9096
9101
  const systemParts = [CESAR_SYSTEM_PROMPT];
9097
9102
  if (projectCtx) systemParts.push(`## PROJECT CONTEXT
9098
9103
  ${projectCtx}`);
9104
+ try {
9105
+ const codebaseBrief = buildCodebaseMap(cesarCwd);
9106
+ if (codebaseBrief) systemParts.push(codebaseBrief);
9107
+ } catch (err) {
9108
+ console.warn(`[agon] codebase atlas skipped: ${err instanceof Error ? err.message : String(err)}`);
9109
+ }
9099
9110
  systemParts.push(`## AVAILABLE ENGINES
9100
9111
  ${engineList}`);
9101
9112
  if (ctx.explorationMode) {
@@ -9235,6 +9246,7 @@ ${context}`);
9235
9246
  }
9236
9247
  var CESAR_SNAPSHOT_MSG_CHAR_CAP = 4e3;
9237
9248
  var CONFIDENCE_BLOCK_LIMIT = 2;
9249
+ var SEARCH_NUDGE_THRESHOLD = 40;
9238
9250
  function capSnapshotMessageContent(content) {
9239
9251
  if (content.length <= CESAR_SNAPSHOT_MSG_CHAR_CAP) return content;
9240
9252
  return `${content.slice(0, CESAR_SNAPSHOT_MSG_CHAR_CAP)}
@@ -9279,6 +9291,7 @@ function buildOnToolCall(ctx, toolRegistry, config) {
9279
9291
  const toolResultCache = /* @__PURE__ */ new Map();
9280
9292
  const nativeToolErrorRetries = /* @__PURE__ */ new Map();
9281
9293
  const CACHEABLE_TOOLS = /* @__PURE__ */ new Set(["Grep", "Glob"]);
9294
+ const SEARCH_NUDGE_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob"]);
9282
9295
  const explorationMode = ctx.explorationMode ?? false;
9283
9296
  const sharedToolCtx = {
9284
9297
  cwd,
@@ -9361,7 +9374,7 @@ ${cleaned}`;
9361
9374
  }
9362
9375
  }
9363
9376
  if (name === "ExitPlanMode") {
9364
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
9377
+ const { handleExitPlanMode } = await import("./plan-mode-OSU42TOI.js");
9365
9378
  return "[DELEGATION_BREAK] " + handleExitPlanMode(String(args.reason ?? ""), ctx.cesar?.planDispatch ?? null, ctx);
9366
9379
  }
9367
9380
  if (name === "ProposePlan") {
@@ -9384,7 +9397,7 @@ ${cleaned}`;
9384
9397
  }
9385
9398
  }
9386
9399
  }
9387
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
9400
+ const { handleProposePlan } = await import("./plan-mode-OSU42TOI.js");
9388
9401
  const dispatch = ctx.cesar.planDispatch;
9389
9402
  if (!dispatch) {
9390
9403
  return "[PLAN_ERROR] Internal plan display dispatch unavailable. Retry the plan request so Agon can render the approval panel.";
@@ -9420,13 +9433,14 @@ ${cleaned}`;
9420
9433
  return value >= 93 ? `Confidence ${value}% recorded. High confidence. Proceed.` : `Confidence ${value}% recorded. Proceed.`;
9421
9434
  }
9422
9435
  }
9423
- const READ_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob", "ReportConfidence", "Delegate"]);
9424
- if (!ctx.cesar.confidenceSatisfied && !READ_TOOLS.has(name)) {
9436
+ const CONFIDENCE_INVESTIGATION_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob", "ReportConfidence", "Delegate"]);
9437
+ const _isInvestigation = CONFIDENCE_INVESTIGATION_TOOLS.has(name) || name === "Bash" && isReadOnlyCommand(String(args.command ?? ""));
9438
+ if (!ctx.cesar.confidenceSatisfied && !_isInvestigation) {
9425
9439
  const blocks = (ctx.cesar.confidenceBlockCount ?? 0) + 1;
9426
9440
  ctx.cesar.confidenceBlockCount = blocks;
9427
9441
  if (blocks <= CONFIDENCE_BLOCK_LIMIT) {
9428
9442
  ctx.cesar.blockedOnConfidence = { name, args };
9429
- return `[BLOCKED] Report confidence first. Call ReportConfidence(value) before using ${name}. After ReportConfidence succeeds, retry the SAME ${name} call immediately with the same arguments. Read/Grep/Glob are allowed for investigation.`;
9443
+ return `[BLOCKED] Report confidence first. Call ReportConfidence(value) before using ${name}. After ReportConfidence succeeds, retry the SAME ${name} call immediately with the same arguments. Read/Grep/Glob and read-only Bash are allowed for investigation.`;
9430
9444
  }
9431
9445
  ctx.cesar.confidenceSatisfied = true;
9432
9446
  ctx.cesar.blockedOnConfidence = null;
@@ -9471,6 +9485,16 @@ Repair retry already used for this exact ${name} input in this turn. Stop retryi
9471
9485
  toolResultCache.clear();
9472
9486
  ctx.cesar.blockedOnConfidence = null;
9473
9487
  }
9488
+ if (result.result.ok && SEARCH_NUDGE_TOOLS.has(name)) {
9489
+ const searches = (ctx.cesar.searchToolCount ?? 0) + 1;
9490
+ ctx.cesar.searchToolCount = searches;
9491
+ if (searches >= SEARCH_NUDGE_THRESHOLD && !ctx.cesar.searchNudged) {
9492
+ ctx.cesar.searchNudged = true;
9493
+ output = `${output ?? ""}
9494
+
9495
+ [NOTE] ${searches} read/search calls this turn. A CODEBASE BRIEF mapping where things live (files + top symbols per package) is in your system prompt \u2014 consult it to locate code instead of searching more. If something isn't listed, narrow the query rather than broadening it.`;
9496
+ }
9497
+ }
9474
9498
  return output;
9475
9499
  };
9476
9500
  }
@@ -9945,7 +9969,7 @@ async function commitTurnAndDelegate(pendingDel, input, response, cesarEngineId,
9945
9969
  const reasoning = delResult.userContext ? `${pendingDel.reasoning ?? ""}
9946
9970
 
9947
9971
  User context: ${delResult.userContext}` : pendingDel.reasoning;
9948
- return { mode, delegated: true, responded: true, action, task: pendingDel.task, reasoning, decisionReason: "tool-delegation", scope: pendingDel.scope, fitnessCmd: pendingDel.fitnessCmd, hardened: delResult.hardened ?? pendingDel.hardened, tribunalMode: delResult.tribunalMode ?? pendingDel.tribunalMode, team: delResult.team ?? pendingDel.team, target: pendingDel.target, engineId: pendingDel.engineId, engines: pendingDel.engines, taskKind: pendingDel.taskKind, maxTurns: pendingDel.maxTurns, queue: pendingDel.queue, gate: pendingDel.gate, push: pendingDel.push, pr: pendingDel.pr, maxHours: pendingDel.maxHours, budget: pendingDel.budget, ...telemetry ?? {} };
9972
+ return { mode, delegated: true, responded: true, action, task: pendingDel.task, reasoning, decisionReason: "tool-delegation", scope: pendingDel.scope, fitnessCmd: pendingDel.fitnessCmd, hardened: delResult.hardened ?? pendingDel.hardened, tribunalMode: delResult.tribunalMode ?? pendingDel.tribunalMode, team: delResult.team ?? pendingDel.team, target: pendingDel.target, engineId: pendingDel.engineId, engines: pendingDel.engines, taskKind: pendingDel.taskKind, maxTurns: pendingDel.maxTurns, queue: pendingDel.queue, gate: pendingDel.gate, builder: pendingDel.builder, push: pendingDel.push, pr: pendingDel.pr, maxHours: pendingDel.maxHours, budget: pendingDel.budget, ...telemetry ?? {} };
9949
9973
  }
9950
9974
  return { delegated: false, responded: true, decisionReason: "delegation-cancelled", ...telemetry ?? {} };
9951
9975
  }
@@ -10114,6 +10138,8 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10114
10138
  ctx.cesar.confidenceSatisfied = false;
10115
10139
  ctx.cesar.blockedOnConfidence = null;
10116
10140
  ctx.cesar.confidenceBlockCount = 0;
10141
+ ctx.cesar.searchToolCount = 0;
10142
+ ctx.cesar.searchNudged = false;
10117
10143
  ctx.cesar.turnId = _turnId;
10118
10144
  ctx.cesar.planDispatch = dispatch;
10119
10145
  const _brainStartMs = Date.now();
@@ -10272,7 +10298,7 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10272
10298
  const fastPathMode = simpleEditFastPath ? "edit" : answerFastPath ? "answer" : "";
10273
10299
  const fastPathBaseBudget = simpleEditFastPath ? 5 : 3;
10274
10300
  const fastPathMaxBudget = simpleEditFastPath ? 8 : 4;
10275
- const FAST_PATH_BLOCKED_TOOLS = ["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Delegate", "ProposePlan", "QuickNero"];
10301
+ const FAST_PATH_BLOCKED_TOOLS = ["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer", "Delegate", "ProposePlan", "QuickNero"];
10276
10302
  if (cesarFastPath && !restoreFastPathMode) {
10277
10303
  const hadPreviousFastPathMode = Object.prototype.hasOwnProperty.call(ctx.cesar, "fastPathMode");
10278
10304
  const previousFastPathMode = ctx.cesar.fastPathMode;
@@ -10521,7 +10547,7 @@ ${enrichedInput}`;
10521
10547
  const toolInput = typeof meta.input === "string" ? meta.input : meta.input ? JSON.stringify(meta.input) : "";
10522
10548
  const toolName = chunk.content || "tool";
10523
10549
  const toolStatus = meta.status ?? "running";
10524
- const STREAM_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
10550
+ const STREAM_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
10525
10551
  hadToolActivity = true;
10526
10552
  recordToolUse(toolName, ctx.cesar.hasNativeTools ? "native" : "eager", toolInput, toolStatus);
10527
10553
  dispatch({ type: "spinner-update", message: `Cesar: ${toolName}\u2026` });
@@ -10866,7 +10892,7 @@ ${enrichedInput}`;
10866
10892
  });
10867
10893
  continue;
10868
10894
  }
10869
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
10895
+ const { handleProposePlan } = await import("./plan-mode-OSU42TOI.js");
10870
10896
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10871
10897
  if (planDispatch) {
10872
10898
  try {
@@ -10879,7 +10905,7 @@ ${enrichedInput}`;
10879
10905
  }
10880
10906
  } else if (signal.tool === "ExitPlanMode") {
10881
10907
  recordToolUse("ExitPlanMode", "mcp", JSON.stringify(signal.args ?? {}), "done");
10882
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
10908
+ const { handleExitPlanMode } = await import("./plan-mode-OSU42TOI.js");
10883
10909
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10884
10910
  try {
10885
10911
  const exitResult = handleExitPlanMode(String(signal.args?.reason ?? ""), planDispatch, ctx);
@@ -11022,7 +11048,7 @@ ${enrichedInput}`;
11022
11048
  _lastToolInputs[name] = JSON.stringify(inp);
11023
11049
  recordToolUse(name, "xml", _lastToolInputs[name], "running");
11024
11050
  emitXmlToolEvent(name, inp, "running");
11025
- const LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
11051
+ const LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
11026
11052
  if (LOOP_ORCH.has(name)) {
11027
11053
  if (cesarFastPath) {
11028
11054
  return;
@@ -11095,7 +11121,7 @@ ${enrichedInput}`;
11095
11121
  output: "A Cesar plan is already active; nested plans are blocked. Resume or cancel the current plan before proposing another."
11096
11122
  });
11097
11123
  } else {
11098
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
11124
+ const { handleProposePlan } = await import("./plan-mode-OSU42TOI.js");
11099
11125
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
11100
11126
  const plan = await handleProposePlan(ppArgs, planDispatch, ctx);
11101
11127
  if (ctx.setActivePlan) ctx.setActivePlan(plan);
@@ -11119,7 +11145,7 @@ ${enrichedInput}`;
11119
11145
  const epArgs = ctx.cesar._exitPlanModeArgs;
11120
11146
  delete ctx.cesar._exitPlanModeArgs;
11121
11147
  try {
11122
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
11148
+ const { handleExitPlanMode } = await import("./plan-mode-OSU42TOI.js");
11123
11149
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
11124
11150
  const exitResult = handleExitPlanMode(String(epArgs?.reason ?? ""), planDispatch, ctx);
11125
11151
  dispatch({ type: "tool-call", engineId: cesarEngineId, tool: "ExitPlanMode", input: JSON.stringify(epArgs ?? {}), status: "done", output: exitResult });
@@ -11397,7 +11423,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11397
11423
  }
11398
11424
  }
11399
11425
  const _AUTO_CONT_WRITE_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
11400
- const _AUTO_CONT_LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
11426
+ const _AUTO_CONT_LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
11401
11427
  const _AUTO_CONT_CONTINUE_RE = /\b(?:now i'?ll|next i'?ll|still need|let me also|i'?ll also|then i'?ll|next step|next up)\b/i;
11402
11428
  const _AUTO_CONT_READONLY_DONE_RE = /\b(?:tests? passed|all (?:tests|checks) pass|no matches found|no issues found|no errors|all clean|nothing to (?:do|fix|change)|already (?:correct|fixed|in place|done))\b/i;
11403
11429
  const _detectTurnState = (resp, baselineToolCount) => {
@@ -11461,7 +11487,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11461
11487
  },
11462
11488
  maxTurns: cesarFastPath ? fastPathMaxBudget : void 0
11463
11489
  });
11464
- const _shouldAutoContinue = (hadToolActivity || ranToolLoop) && !inPlanMode && !ctx.cesar.pendingDelegation && session.alive && !abort.signal.aborted && !_engineErrored && response.trim().length > 0;
11490
+ const _shouldAutoContinue = (hadToolActivity || ranToolLoop) && !inPlanMode && !answerFastPath && !ctx.cesar.pendingDelegation && session.alive && !abort.signal.aborted && !_engineErrored && response.trim().length > 0;
11465
11491
  if (_shouldAutoContinue) {
11466
11492
  const MAX_CONTINUATIONS = 5;
11467
11493
  let _continuations = 0;
@@ -11706,8 +11732,9 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11706
11732
  const full = m[3].trim();
11707
11733
  _forkOptions.push({ key, label: full.length > 60 ? full.slice(0, 59) + "\u2026" : full, full });
11708
11734
  }
11709
- const isForkQuestion = /\?\s*$/.test(lastLine) && _forkOptions.length >= 2 && _forkOptions.length <= 6;
11710
- const asksConfirmation = !ranToolLoop && /\?\s*$/.test(lastLine) && /\b(want|shall|should|ready|proceed|go ahead|dispatch|confirm|continue|implement)\b/i.test(lastLine);
11735
+ const _isChatTurn = routingHints.intakeKind === "chat" || routingHints.recommendedFlow === "answer";
11736
+ const isForkQuestion = !_isChatTurn && /\?\s*$/.test(lastLine) && _forkOptions.length >= 2 && _forkOptions.length <= 6;
11737
+ const asksConfirmation = !_isChatTurn && !ranToolLoop && /\?\s*$/.test(lastLine) && /\b(want|shall|should|ready|proceed|go ahead|dispatch|confirm|continue|implement)\b/i.test(lastLine);
11711
11738
  if (isForkQuestion) {
11712
11739
  const _forkColors = ["#4ade80", "#22d3ee", "#fbbf24", "#a78bfa", "#f97316", "#ef4444"];
11713
11740
  const _allNumeric = _forkOptions.every((o) => /^[0-9]$/.test(o.key));
@@ -11888,4 +11915,4 @@ export {
11888
11915
  ensureCesarSession,
11889
11916
  handleCesarBrain
11890
11917
  };
11891
- //# sourceMappingURL=chunk-IA4AR2R4.js.map
11918
+ //# sourceMappingURL=chunk-XOJPAFCJ.js.map