@wrongstack/core 0.308.0 → 0.308.2

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.
Files changed (61) hide show
  1. package/dist/coordination/agents/index.js +4 -4
  2. package/dist/coordination/index.d.ts +1 -0
  3. package/dist/coordination/index.js +113 -15
  4. package/dist/coordination/task-boundary.d.ts +64 -0
  5. package/dist/core/index.js +1 -1
  6. package/dist/defaults/index.js +116 -19
  7. package/dist/execution/index.js +11 -8
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.js +127 -20
  10. package/dist/infrastructure/index.js +1 -1
  11. package/dist/storage/index.js +2 -1
  12. package/dist/tools/index.js +4 -4
  13. package/dist/types/config/ui.d.ts +1 -1
  14. package/dist/types/context-window.d.ts +18 -1
  15. package/dist/types/index.d.ts +1 -1
  16. package/dist/types/index.js +11 -4
  17. package/dist/types/runtime-capability-manifest.d.ts +1 -1
  18. package/instructions/agents/backend.md +3 -0
  19. package/instructions/agents/bug-hunter.md +3 -0
  20. package/instructions/agents/code-reviewer.md +1 -0
  21. package/instructions/agents/frontend.md +2 -0
  22. package/instructions/agents/test.md +2 -0
  23. package/instructions/coordination/director-preamble.md +9 -1
  24. package/instructions/coordination/subagent-baseline.md +4 -0
  25. package/instructions/modes/code-reviewer.md +1 -1
  26. package/instructions/modes/debugger.md +2 -2
  27. package/instructions/modes/refactorer.md +2 -2
  28. package/instructions/modes/tester.md +2 -2
  29. package/instructions/system-lite.md +37 -33
  30. package/instructions/system-pro.md +23 -7
  31. package/instructions/system.md +33 -11
  32. package/package.json +6 -4
  33. package/skills/api-design/SKILL.md +26 -1
  34. package/skills/audit-log/SKILL.md +22 -1
  35. package/skills/auto-review/SKILL.md +21 -1
  36. package/skills/bug-hunter/SKILL.md +8 -0
  37. package/skills/chimera/SKILL.md +9 -0
  38. package/skills/data-governance/SKILL.md +25 -1
  39. package/skills/design-system/SKILL.md +19 -1
  40. package/skills/docker-deploy/SKILL.md +26 -1
  41. package/skills/git-flow/SKILL.md +26 -1
  42. package/skills/mailbox-bridge/SKILL.md +25 -1
  43. package/skills/mnemosyne/SKILL.md +25 -2
  44. package/skills/multi-agent/SKILL.md +12 -0
  45. package/skills/node-modern/SKILL.md +28 -1
  46. package/skills/observability/SKILL.md +25 -1
  47. package/skills/output-standards/SKILL.md +28 -1
  48. package/skills/plugin-author/SKILL.md +31 -1
  49. package/skills/prompt-engineering/SKILL.md +27 -1
  50. package/skills/react-modern/SKILL.md +29 -1
  51. package/skills/refactor-planner/SKILL.md +10 -0
  52. package/skills/research-web/SKILL.md +28 -1
  53. package/skills/sdd/SKILL.md +18 -0
  54. package/skills/security-scanner/SKILL.md +25 -1
  55. package/skills/skill-creator/SKILL.md +25 -1
  56. package/skills/tech-stack/SKILL.md +25 -1
  57. package/skills/testing/SKILL.md +25 -1
  58. package/skills/typescript-strict/SKILL.md +30 -1
  59. package/skills/wrongstack-kanban/SKILL.md +24 -0
  60. package/skills/wrongstack-mailbox/SKILL.md +29 -1
  61. package/skills/wrongstack-mailbox-mcp/SKILL.md +30 -3
@@ -1810,7 +1810,7 @@ var RUNTIME_CAPABILITY_MANIFEST = [
1810
1810
  id: "execution.shell",
1811
1811
  pack: "development",
1812
1812
  exposure: "direct",
1813
- tools: ["bash", "exec", "language", "language_info", "language_package"]
1813
+ tools: ["bash", "exec", "pwsh", "language", "language_info", "language_package"]
1814
1814
  },
1815
1815
  {
1816
1816
  id: "verification.run",
@@ -2371,7 +2371,7 @@ ${identity}`);
2371
2371
  splitLearnedEntries(rawLearned)
2372
2372
  );
2373
2373
  const rawBytes = Buffer.byteLength(rawLearned, "utf8");
2374
- const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt > meta.consolidatedAt);
2374
+ const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt >= meta.consolidatedAt);
2375
2375
  const stale = meta === void 0 || freshEntries.length > 0 || rawEntries.length > meta.sourceEntryCount || rawBytes > meta.sourceBytes;
2376
2376
  if (!stale) {
2377
2377
  learnedContent = consolidated;
@@ -3968,7 +3968,7 @@ var VERIFY_AGENTS = [
3968
3968
  id: "bug-hunter",
3969
3969
  name: "Bug Hunter",
3970
3970
  role: "bug-hunter",
3971
- tools: [...TOOLS.inspect],
3971
+ tools: [...TOOLS.inspect, "dead-code-scan"],
3972
3972
  prompt: agentPrompt("bug-hunter")
3973
3973
  },
3974
3974
  budget: HEAVY_BUDGET,
@@ -4058,7 +4058,7 @@ var REVIEW_AGENTS = [
4058
4058
  id: "code-reviewer",
4059
4059
  name: "Code Reviewer",
4060
4060
  role: "code-reviewer",
4061
- tools: [...TOOLS.inspect, "git"],
4061
+ tools: [...TOOLS.inspect, "git", "codebase-impact-analysis", "codebase-invariant-check"],
4062
4062
  prompt: agentPrompt("code-reviewer")
4063
4063
  },
4064
4064
  budget: MEDIUM_BUDGET,
@@ -5512,6 +5512,80 @@ var FLEET_ROSTER_WITHACP = {
5512
5512
  ...Object.fromEntries(ACP_AGENTS.map((a) => [a.role, a]))
5513
5513
  };
5514
5514
 
5515
+ // src/coordination/task-boundary.ts
5516
+ var PLACEHOLDER_VALUES = /* @__PURE__ */ new Set([
5517
+ "n/a",
5518
+ "na",
5519
+ "none",
5520
+ "nothing",
5521
+ "tbd",
5522
+ "todo",
5523
+ "unknown",
5524
+ "unspecified",
5525
+ "-",
5526
+ "\u2014",
5527
+ ".",
5528
+ "as above",
5529
+ "same as above",
5530
+ "see above",
5531
+ "see task",
5532
+ "same as task"
5533
+ ]);
5534
+ var isPlaceholder = (value) => PLACEHOLDER_VALUES.has(value.trim().toLowerCase());
5535
+ var MIN_SCOPE_CHARS = 8;
5536
+ var MIN_NON_GOAL_CHARS = 3;
5537
+ function parseTaskBoundary(raw) {
5538
+ const scope = typeof raw.scope === "string" ? raw.scope.trim() : "";
5539
+ if (scope.length < MIN_SCOPE_CHARS) {
5540
+ return {
5541
+ ok: false,
5542
+ error: `\`scope\` is missing or too vague \u2014 state in one concrete sentence what work this task covers (files, components, or commands in-bounds).`,
5543
+ hint: 'Example \u2014 scope: "Audit packages/core/src/parser/*.ts for unhandled token errors and report findings."'
5544
+ };
5545
+ }
5546
+ if (!Array.isArray(raw.outOfScope) || raw.outOfScope.length === 0) {
5547
+ return {
5548
+ ok: false,
5549
+ error: "`outOfScope` must be an array with at least one explicit non-goal \u2014 things the worker must NOT do.",
5550
+ hint: 'Example \u2014 outOfScope: ["Do not modify files outside packages/core", "Do not fix the bugs you find, only report them"].'
5551
+ };
5552
+ }
5553
+ const concrete = raw.outOfScope.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length >= MIN_NON_GOAL_CHARS && !isPlaceholder(item));
5554
+ if (concrete.length === 0) {
5555
+ return {
5556
+ ok: false,
5557
+ error: 'Every `outOfScope` entry was a placeholder ("none", "n/a", \u2026). Name at least one concrete non-goal: files or areas not to touch, changes not to make, features not to add.',
5558
+ hint: 'There is always an edge worth stating \u2014 "read-only, no edits", "no dependency changes", "do not touch other packages". If truly nothing comes to mind, the task is not decomposed enough yet.'
5559
+ };
5560
+ }
5561
+ return { ok: true, boundary: { scope, outOfScope: concrete } };
5562
+ }
5563
+ function renderTaskBoundaryBlock(boundary) {
5564
+ return [
5565
+ "\u2500\u2500 TASK BOUNDARY (hard contract \u2014 these lines define your edges) \u2500\u2500",
5566
+ `Scope (what this task covers):
5567
+ ${boundary.scope}`,
5568
+ `Out of scope (explicit non-goals \u2014 do NOT do any of these):
5569
+ ${boundary.outOfScope.map((item) => `- ${item}`).join("\n")}`
5570
+ ].join("\n");
5571
+ }
5572
+ function composeBoundedTaskDescription(objective, boundary) {
5573
+ return `${objective.trim()}
5574
+
5575
+ ${renderTaskBoundaryBlock(boundary)}`;
5576
+ }
5577
+ var taskBoundarySchemaProperties = {
5578
+ scope: {
5579
+ type: "string",
5580
+ description: "REQUIRED. One concrete sentence stating what work this task covers \u2014 the in-bounds. The call is rejected without it."
5581
+ },
5582
+ outOfScope: {
5583
+ type: "array",
5584
+ items: { type: "string", minLength: 1 },
5585
+ description: 'REQUIRED. At least one explicit non-goal the worker must NOT do (files/areas not to touch, changes not to make, features not to add). Placeholders like "none" are rejected.'
5586
+ }
5587
+ };
5588
+
5515
5589
  // src/coordination/delegate-tool.ts
5516
5590
  function createDelegateTool(opts) {
5517
5591
  const defaultTimeoutMs = opts.defaultTimeoutMs ?? 4 * 60 * 60 * 1e3;
@@ -5521,8 +5595,9 @@ function createDelegateTool(opts) {
5521
5595
  properties: {
5522
5596
  task: {
5523
5597
  type: "string",
5524
- description: "What the subagent should do \u2014 natural language, complete sentence(s)."
5598
+ description: "The objective \u2014 what the subagent should do, natural language, complete sentence(s). Pair it with the required `scope` and `outOfScope` boundary fields."
5525
5599
  },
5600
+ ...taskBoundarySchemaProperties,
5526
5601
  role: {
5527
5602
  type: "string",
5528
5603
  description: rosterIds.length > 0 ? "Roster role id. Common: bug-hunter, security-scanner, refactor-planner, critic, audit-log, executor, shadow-agent, architect." : "No roster configured \u2014 pass `name` instead."
@@ -5580,12 +5655,12 @@ function createDelegateTool(opts) {
5580
5655
  description: "Max fresh-worker continuations after budget exhaustion. Default 1. Each gets the prior partial report."
5581
5656
  }
5582
5657
  },
5583
- required: ["task"]
5658
+ required: ["task", "scope", "outOfScope"]
5584
5659
  };
5585
5660
  return {
5586
5661
  name: "delegate",
5587
5662
  description: "Hand a piece of work to a subagent and block until it returns. This call is synchronous: the leader's iteration pauses for the full duration of the subagent's run. (Multiple `delegate` calls fired in the same assistant turn still parallelize through the provider's parallel-tool-call surface, but each one eats wall-clock time \u2014 so for fan-out you actually control, reach for the async path below.) Use `delegate` when your next step genuinely needs the subagent's verdict \u2014 a review, a fact-check, a sign-off. Has own context, own LLM call, auto-extending budget, and a partial-completion handoff path (maxHandoffs, default 1). Workers cannot recursively spawn.\n\n**Do NOT use `delegate` for long-running work.** While `delegate` is in flight, the leader is fully blocked \u2014 it cannot act on other tools, read mail, or react to the user. If the work might run for tens of minutes or hours (multi-file refactor, monorepo audit, long-running build/test, sweeping migration), the blocking call wastes the leader's time. Use the async tool family instead: `spawn_subagent` to create each worker (returns a `subagentId` immediately), `assign_task` to queue work on it (returns a `taskId` immediately), then `await_tasks` to retrieve results later. The leader keeps doing other work while the worker churns, and a worker that realizes its task will run long can mail the leader (type `steer` or `ask` via `mail_send`) saying *\"my task is going to run long, please spawn a subagent instead\"* so the leader re-dispatches asynchronously instead of waiting.\n\n**Do NOT use `delegate` for fan-out you control.** Multiple sequential `delegate` calls each block the leader, wasting wall-clock time. For independent investigations you want to run in parallel \u2014 security scan + bug hunt + perf review on the same PR \u2014 use the async tool family: `spawn_subagent` to create each worker (returns a `subagentId` immediately), `assign_task` to queue work on it (returns a `taskId` immediately), then the `await_tasks` tool with `{mode: 'any'}` to fold the first useful result into the next decision while the rest keep churning. Reach for `delegate` only when the result gates your next move AND the work is short enough that blocking the leader is acceptable.",
5588
- usageHint: "Set `task` to a complete instruction. Pick `role` from roster or pass `name` for free-form. Reach for `delegate` only when the result gates your next move AND the work is short enough that blocking the leader is acceptable (minutes, not hours). For long-running work or fan-out you control, use `spawn_subagent` + `assign_task` + `await_tasks` instead. Raise `maxHandoffs` (default 1, cap 8) for multi-day or multi-refactor tasks; pass larger `timeoutMs`/`maxIterations`/`maxToolCalls` only when needed.",
5663
+ usageHint: "Set `task` to the objective, then make the edges explicit: `scope` (what the work covers) and `outOfScope` (at least one concrete non-goal) are REQUIRED \u2014 the call is rejected without them, and the worker treats the rendered boundary block as a hard contract. Pick `role` from roster or pass `name` for free-form. Reach for `delegate` only when the result gates your next move AND the work is short enough that blocking the leader is acceptable (minutes, not hours). For long-running work or fan-out you control, use `spawn_subagent` + `assign_task` + `await_tasks` instead. Raise `maxHandoffs` (default 1, cap 8) for multi-day or multi-refactor tasks; pass larger `timeoutMs`/`maxIterations`/`maxToolCalls` only when needed.",
5589
5664
  permission: "auto",
5590
5665
  mutating: false,
5591
5666
  managesOwnTimeout: true,
@@ -5605,6 +5680,14 @@ function createDelegateTool(opts) {
5605
5680
  error: "Delegation cancelled before spawn \u2014 the run was interrupted."
5606
5681
  };
5607
5682
  }
5683
+ const boundary = parseTaskBoundary(i);
5684
+ if (!boundary.ok) {
5685
+ return {
5686
+ ok: false,
5687
+ error: `delegate rejected \u2014 task boundary incomplete: ${boundary.error}`,
5688
+ hint: boundary.hint
5689
+ };
5690
+ }
5608
5691
  const target = i.role ?? i.name ?? "subagent";
5609
5692
  const launchModePreface = [
5610
5693
  "Launch-mode guidance (delegate): you were launched via the synchronous `delegate` tool, so the leader is blocked on this call for the full duration of your run.",
@@ -5675,7 +5758,8 @@ function createDelegateTool(opts) {
5675
5758
  const dir = director;
5676
5759
  const maxHandoffs = Math.min(8, Math.max(0, Math.floor(i.maxHandoffs ?? 1)));
5677
5760
  const handoffs = [];
5678
- let delegatedTask = i.task;
5761
+ const baseBrief = composeBoundedTaskDescription(i.task, boundary.boundary);
5762
+ let delegatedTask = baseBrief;
5679
5763
  let handoffCount = 0;
5680
5764
  for (; ; ) {
5681
5765
  const attemptConfig = (() => {
@@ -5815,7 +5899,7 @@ function createDelegateTool(opts) {
5815
5899
  remainingWork: continuation.remainingWork
5816
5900
  });
5817
5901
  handoffCount += 1;
5818
- delegatedTask = buildHandoffTask(i.task, continuation, handoffCount, maxHandoffs);
5902
+ delegatedTask = buildHandoffTask(baseBrief, continuation, handoffCount, maxHandoffs);
5819
5903
  continue;
5820
5904
  }
5821
5905
  const incomplete = result.report?.completion === "partial";
@@ -8503,8 +8587,9 @@ function makeAssignTool(director) {
8503
8587
  description: {
8504
8588
  type: "string",
8505
8589
  minLength: 1,
8506
- description: "The task in natural language \u2014 what you want this subagent to do."
8590
+ description: "The objective in natural language \u2014 what you want this subagent to do. Pair it with the required `scope` and `outOfScope` boundary fields."
8507
8591
  },
8592
+ ...taskBoundarySchemaProperties,
8508
8593
  maxToolCalls: {
8509
8594
  type: "number",
8510
8595
  minimum: 1,
@@ -8512,20 +8597,28 @@ function makeAssignTool(director) {
8512
8597
  },
8513
8598
  timeoutMs: { type: "number", minimum: 1, description: "Optional per-task timeout in ms." }
8514
8599
  },
8515
- required: ["subagentId", "description"]
8600
+ required: ["subagentId", "description", "scope", "outOfScope"]
8516
8601
  };
8517
8602
  return {
8518
8603
  name: "assign_task",
8519
- description: "Queue a task on a previously spawned subagent. NON-BLOCKING: returns a `taskId` IMMEDIATELY \u2014 the subagent processes the task on its next iteration with its own LLM budget. The `taskId` is the durable handle for retrieving the result later via `await_tasks`, `roll_up`, or `ask_result`. Many `assign_task` calls can be in flight in parallel against the same or different subagents. This is the primary tool for fan-out work; do NOT use `delegate` to spawn multiple investigations sequentially.",
8604
+ description: "Queue a task on a previously spawned subagent. NON-BLOCKING: returns a `taskId` IMMEDIATELY \u2014 the subagent processes the task on its next iteration with its own LLM budget. The `taskId` is the durable handle for retrieving the result later via `await_tasks`, `roll_up`, or `ask_result`. Every assignment MUST carry an explicit boundary: `scope` (what the work covers) and `outOfScope` (at least one concrete non-goal) \u2014 the call is rejected without them, and the worker treats the rendered boundary block as a hard contract. Many `assign_task` calls can be in flight in parallel against the same or different subagents. This is the primary tool for fan-out work; do NOT use `delegate` to spawn multiple investigations sequentially.",
8520
8605
  permission: "auto",
8521
8606
  mutating: false,
8522
8607
  capabilities: [ToolCapabilities.SUBAGENT_SPAWN],
8523
8608
  inputSchema,
8524
8609
  async execute(input) {
8525
8610
  const i = input;
8611
+ const boundary = parseTaskBoundary(i);
8612
+ if (!boundary.ok) {
8613
+ return {
8614
+ ok: false,
8615
+ error: `assign_task rejected \u2014 task boundary incomplete: ${boundary.error}`,
8616
+ hint: boundary.hint
8617
+ };
8618
+ }
8526
8619
  const task = {
8527
8620
  id: randomUUID6(),
8528
- description: i.description,
8621
+ description: composeBoundedTaskDescription(i.description, boundary.boundary),
8529
8622
  subagentId: i.subagentId,
8530
8623
  maxToolCalls: i.maxToolCalls,
8531
8624
  timeoutMs: i.timeoutMs
@@ -17964,6 +18057,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
17964
18057
  sessionPath: (sid, ext) => this.sessionPath(sid, ext)
17965
18058
  });
17966
18059
  this.clearLoadCache(canonical);
18060
+ if (id !== canonical) this.clearLoadCache(id);
17967
18061
  }
17968
18062
  async summarize(id, mtime) {
17969
18063
  return summarizeSessionFile({
@@ -19227,8 +19321,8 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
19227
19321
  withNickname(subagent, subagentId) {
19228
19322
  const role = subagent.role ?? "subagent";
19229
19323
  const name = subagent.name?.trim() ?? "";
19230
- const isPlaceholder = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
19231
- if (!isPlaceholder) return subagent;
19324
+ const isPlaceholder2 = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
19325
+ if (!isPlaceholder2) return subagent;
19232
19326
  const { key, display } = assignNickname(role, this.usedNicknames);
19233
19327
  this.usedNicknames.add(key);
19234
19328
  this.subagentNicknames.set(subagentId, key);
@@ -22496,6 +22590,7 @@ function normalizeTargetLoad(targetLoad, thresholds) {
22496
22590
 
22497
22591
  // src/types/context-window.ts
22498
22592
  var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
22593
+ var LARGE_WINDOW_DEEP_MODE_THRESHOLD = 1e6;
22499
22594
  var DEPRECATED_CONTEXT_WINDOW_MODE_ALIASES = Object.freeze({
22500
22595
  archival: "balanced"
22501
22596
  });
@@ -22503,7 +22598,7 @@ var CONTEXT_WINDOW_MODES = Object.freeze([
22503
22598
  {
22504
22599
  id: "balanced",
22505
22600
  name: "Balanced",
22506
- description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed.",
22601
+ description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed. Windows of 1M+ tokens default to Deep.",
22507
22602
  thresholds: { warn: 0.55, soft: 0.7, hard: 0.85 },
22508
22603
  aggressiveOn: "soft",
22509
22604
  preserveK: 8,
@@ -22554,9 +22649,11 @@ function getContextWindowMode(id) {
22554
22649
  function isContextWindowModeId(id) {
22555
22650
  return CONTEXT_WINDOW_MODES.some((m) => m.id === id);
22556
22651
  }
22557
- function resolveContextWindowPolicy(config = {}, overrideMode) {
22652
+ function resolveContextWindowPolicy(config = {}, overrideMode, maxContext) {
22558
22653
  const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
22559
- const mode = getContextWindowMode(requested) ?? expectDefined(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));
22654
+ const normalized = normalizeContextWindowModeId(requested) ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
22655
+ const baseId = normalized === DEFAULT_CONTEXT_WINDOW_MODE_ID && typeof maxContext === "number" && maxContext >= LARGE_WINDOW_DEEP_MODE_THRESHOLD ? "deep" : normalized;
22656
+ const mode = expectDefined(getContextWindowMode(baseId));
22560
22657
  return {
22561
22658
  ...mode,
22562
22659
  thresholds: {
@@ -22971,7 +23068,7 @@ function readContextWindowPolicy(ctx) {
22971
23068
  function installSubagentAutoCompaction(pipelines, ctx, contextConfig, events) {
22972
23069
  const maxContext = ctx.provider?.capabilities?.maxContext ?? 0;
22973
23070
  if (!(maxContext > 0)) return void 0;
22974
- const policy = resolveContextWindowPolicy(contextConfig ?? {});
23071
+ const policy = resolveContextWindowPolicy(contextConfig ?? {}, void 0, maxContext);
22975
23072
  ctx.meta ??= {};
22976
23073
  ctx.meta["contextWindowPolicy"] = policy;
22977
23074
  const compactor = new HybridCompactor({
@@ -13262,7 +13262,7 @@ var RUNTIME_CAPABILITY_MANIFEST = [
13262
13262
  id: "execution.shell",
13263
13263
  pack: "development",
13264
13264
  exposure: "direct",
13265
- tools: ["bash", "exec", "language", "language_info", "language_package"]
13265
+ tools: ["bash", "exec", "pwsh", "language", "language_info", "language_package"]
13266
13266
  },
13267
13267
  {
13268
13268
  id: "verification.run",
@@ -13818,7 +13818,7 @@ ${identity}`);
13818
13818
  splitLearnedEntries(rawLearned)
13819
13819
  );
13820
13820
  const rawBytes = Buffer.byteLength(rawLearned, "utf8");
13821
- const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt > meta.consolidatedAt);
13821
+ const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt >= meta.consolidatedAt);
13822
13822
  const stale = meta === void 0 || freshEntries.length > 0 || rawEntries.length > meta.sourceEntryCount || rawBytes > meta.sourceBytes;
13823
13823
  if (!stale) {
13824
13824
  learnedContent = consolidated;
@@ -15415,7 +15415,7 @@ var VERIFY_AGENTS = [
15415
15415
  id: "bug-hunter",
15416
15416
  name: "Bug Hunter",
15417
15417
  role: "bug-hunter",
15418
- tools: [...TOOLS.inspect],
15418
+ tools: [...TOOLS.inspect, "dead-code-scan"],
15419
15419
  prompt: agentPrompt("bug-hunter")
15420
15420
  },
15421
15421
  budget: HEAVY_BUDGET,
@@ -15505,7 +15505,7 @@ var REVIEW_AGENTS = [
15505
15505
  id: "code-reviewer",
15506
15506
  name: "Code Reviewer",
15507
15507
  role: "code-reviewer",
15508
- tools: [...TOOLS.inspect, "git"],
15508
+ tools: [...TOOLS.inspect, "git", "codebase-impact-analysis", "codebase-invariant-check"],
15509
15509
  prompt: agentPrompt("code-reviewer")
15510
15510
  },
15511
15511
  budget: MEDIUM_BUDGET,
@@ -21421,6 +21421,7 @@ function readPolicy(ctx) {
21421
21421
 
21422
21422
  // src/types/context-window.ts
21423
21423
  var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
21424
+ var LARGE_WINDOW_DEEP_MODE_THRESHOLD = 1e6;
21424
21425
  var DEPRECATED_CONTEXT_WINDOW_MODE_ALIASES = Object.freeze({
21425
21426
  archival: "balanced"
21426
21427
  });
@@ -21428,7 +21429,7 @@ var CONTEXT_WINDOW_MODES = Object.freeze([
21428
21429
  {
21429
21430
  id: "balanced",
21430
21431
  name: "Balanced",
21431
- description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed.",
21432
+ description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed. Windows of 1M+ tokens default to Deep.",
21432
21433
  thresholds: { warn: 0.55, soft: 0.7, hard: 0.85 },
21433
21434
  aggressiveOn: "soft",
21434
21435
  preserveK: 8,
@@ -21470,9 +21471,11 @@ function getContextWindowMode(id) {
21470
21471
  function isContextWindowModeId(id) {
21471
21472
  return CONTEXT_WINDOW_MODES.some((m) => m.id === id);
21472
21473
  }
21473
- function resolveContextWindowPolicy(config = {}, overrideMode) {
21474
+ function resolveContextWindowPolicy(config = {}, overrideMode, maxContext) {
21474
21475
  const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
21475
- const mode = getContextWindowMode(requested) ?? expectDefined(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));
21476
+ const normalized = normalizeContextWindowModeId(requested) ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
21477
+ const baseId = normalized === DEFAULT_CONTEXT_WINDOW_MODE_ID && typeof maxContext === "number" && maxContext >= LARGE_WINDOW_DEEP_MODE_THRESHOLD ? "deep" : normalized;
21478
+ const mode = expectDefined(getContextWindowMode(baseId));
21476
21479
  return {
21477
21480
  ...mode,
21478
21481
  thresholds: {
@@ -21490,7 +21493,7 @@ function resolveContextWindowPolicy(config = {}, overrideMode) {
21490
21493
  function installSubagentAutoCompaction(pipelines, ctx, contextConfig, events) {
21491
21494
  const maxContext = ctx.provider?.capabilities?.maxContext ?? 0;
21492
21495
  if (!(maxContext > 0)) return void 0;
21493
- const policy = resolveContextWindowPolicy(contextConfig ?? {});
21496
+ const policy = resolveContextWindowPolicy(contextConfig ?? {}, void 0, maxContext);
21494
21497
  ctx.meta ??= {};
21495
21498
  ctx.meta["contextWindowPolicy"] = policy;
21496
21499
  const compactor = new HybridCompactor({
package/dist/index.d.ts CHANGED
@@ -134,7 +134,7 @@ export { createMcpUseTool } from './tools/mcp-use.js';
134
134
  export { type CreateOneShotLLMToolOptions, createOneShotLLMTool, ONE_SHOT_LLM_TOOL_NAME, } from './tools/one-shot-llm-tool.js';
135
135
  export { type CreatePluginManagerToolOptions, createPluginManagerTool, PLUGIN_MANAGER_TOOL_NAME, type PluginManagerCatalogEntry, type PluginManagerMutationResult, } from './tools/plugin-manager.js';
136
136
  export type { Compactor, CompactReport } from './types/compactor.js';
137
- export { CONTEXT_WINDOW_MODES, type ContextWindowAggressiveOn, type ContextWindowConfigLike, type ContextWindowMode, type ContextWindowModeId, type ContextWindowModeSelectionId, type ContextWindowPolicy, type ContextWindowThresholds, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEPRECATED_CONTEXT_WINDOW_MODE_ALIASES, type DeprecatedContextWindowModeId, formatContextWindowModeList, getContextWindowMode, isContextWindowModeId, isContextWindowModeSelectionId, isDeprecatedContextWindowModeId, listContextWindowModes, normalizeContextWindowModeId, resolveContextWindowPolicy, } from './types/context-window.js';
137
+ export { CONTEXT_WINDOW_MODES, type ContextWindowAggressiveOn, type ContextWindowConfigLike, type ContextWindowMode, type ContextWindowModeId, type ContextWindowModeSelectionId, type ContextWindowPolicy, type ContextWindowThresholds, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEPRECATED_CONTEXT_WINDOW_MODE_ALIASES, type DeprecatedContextWindowModeId, formatContextWindowModeList, getContextWindowMode, isContextWindowModeId, isContextWindowModeSelectionId, isDeprecatedContextWindowModeId, LARGE_WINDOW_DEEP_MODE_THRESHOLD, CONTEXT_WINDOW_MODE_PINNED_META_KEY, listContextWindowModes, normalizeContextWindowModeId, resolveContextWindowPolicy, } from './types/context-window.js';
138
138
  export { DEFAULT_SESSION_PRUNE_DAYS } from './types/default-config.js';
139
139
  export type { FileEventRecord } from './types/file-event-record.js';
140
140
  export * from './types/index.js';