mixdog 0.9.109 → 0.9.111

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 (96) hide show
  1. package/package.json +1 -2
  2. package/scripts/routing-corpus.mjs +5 -6
  3. package/scripts/run-suite.mjs +2 -1
  4. package/src/app.mjs +0 -1
  5. package/src/defaults/agents.json +0 -12
  6. package/src/defaults/skills/setup/SKILL.md +1 -1
  7. package/src/headless-command.mjs +1 -3
  8. package/src/headless-role.mjs +2 -4
  9. package/src/help.mjs +1 -1
  10. package/src/rules/shared/01-tool.md +33 -37
  11. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +6 -6
  12. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +2 -25
  13. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +3 -3
  14. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -1
  15. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +1 -1
  16. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +7 -1
  17. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +0 -1
  18. package/src/runtime/agent/orchestrator/config.mjs +6 -6
  19. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -2
  20. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +1 -1
  21. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -3
  22. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -20
  23. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +7 -1
  24. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +31 -18
  25. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -3
  26. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +98 -12
  27. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +64 -0
  28. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -9
  29. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +18 -1
  30. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +25 -16
  31. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +7 -25
  32. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +0 -12
  33. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +1 -1
  34. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +1 -1
  35. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +24 -0
  36. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +5 -5
  37. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -29
  38. package/src/runtime/agent/orchestrator/stall-policy.mjs +2 -3
  39. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +13 -6
  40. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +4 -6
  41. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +11 -2
  42. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +2 -2
  43. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +2 -15
  44. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -1
  45. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +22 -35
  46. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +37 -14
  47. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +33 -61
  48. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +65 -4
  49. package/src/runtime/agent/orchestrator/tools/patch-manifest.json +11 -11
  50. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +6 -37
  51. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -5
  52. package/src/runtime/channels/lib/output-forwarder.mjs +0 -13
  53. package/src/runtime/channels/lib/tool-format.mjs +1 -2
  54. package/src/runtime/search/index.mjs +12 -6
  55. package/src/runtime/search/tool-defs.mjs +2 -2
  56. package/src/runtime/shared/agent-route-config.mjs +2 -3
  57. package/src/runtime/shared/child-spawn-gate.mjs +1 -1
  58. package/src/runtime/shared/pristine-execution-contract.json +4 -1
  59. package/src/runtime/shared/resource-admission.mjs +1 -1
  60. package/src/runtime/shared/tool-card-model.mjs +3 -5
  61. package/src/runtime/shared/tool-primitives.mjs +0 -1
  62. package/src/runtime/shared/tool-result-summary.mjs +0 -7
  63. package/src/runtime/shared/tool-surface.mjs +1 -14
  64. package/src/session-runtime/runtime-core.mjs +1 -24
  65. package/src/session-runtime/session-title.mjs +14 -1
  66. package/src/session-runtime/settings-api.mjs +0 -8
  67. package/src/session-runtime/tool-catalog-data.mjs +4 -7
  68. package/src/session-runtime/tool-catalog-schema.mjs +1 -1
  69. package/src/session-runtime/workflow-agents-api.mjs +0 -3
  70. package/src/session-runtime/workflow.mjs +3 -7
  71. package/src/standalone/agent-tool/helpers.mjs +0 -1
  72. package/src/standalone/agent-tool/render.mjs +1 -1
  73. package/src/standalone/agent-tool/shard-spread.mjs +2 -2
  74. package/src/standalone/agent-tool/spawn-flow.mjs +18 -0
  75. package/src/standalone/session-client.mjs +79 -20
  76. package/src/standalone/session-protocol.mjs +0 -1
  77. package/src/standalone/session-transport.mjs +19 -3
  78. package/src/tui/app/model-options.mjs +2 -3
  79. package/src/tui/app/onboarding-steps.mjs +1 -1
  80. package/src/tui/app/settings-picker.mjs +0 -12
  81. package/src/tui/app/transcript-row-estimate.mjs +1 -1
  82. package/src/tui/app/use-transcript-activity.mjs +7 -17
  83. package/src/tui/dist/index.mjs +9 -51
  84. package/src/tui/session/agent-envelope.mjs +1 -1
  85. package/src/tui/session/live-share.mjs +1 -1
  86. package/src/tui/session/session-api.mjs +0 -10
  87. package/src/tui/session/turn.mjs +2 -2
  88. package/src/tui/session-local.mjs +8 -11
  89. package/src/ui/statusline-agents.mjs +1 -2
  90. package/src/ui/statusline-format.mjs +1 -1
  91. package/src/ui/statusline.mjs +1 -6
  92. package/src/workflows/default/WORKFLOW.md +2 -1
  93. package/src/agents/explore/AGENT.md +0 -8
  94. package/src/agents/explore/agent.json +0 -6
  95. package/src/rules/agent/30-explorer.md +0 -55
  96. package/src/standalone/explore-tool.mjs +0 -770
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.9.109",
3
+ "version": "0.9.111",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone mixdog coding-agent CLI/TUI workspace.",
@@ -125,7 +125,6 @@
125
125
  "bench:run": "node scripts/bench-run.mjs",
126
126
  "bench:recall": "node scripts/recall-bench.mjs",
127
127
  "bench:tui-load": "node scripts/tui-runtime-load-bench.mjs",
128
- "bench:explore": "node scripts/explore-bench.mjs",
129
128
  "bench:output-style": "node scripts/output-style-bench.mjs",
130
129
  "bench:session-context": "node scripts/session-context-bench.mjs",
131
130
  "bench:session-transport": "node scripts/session-transport-bench.mjs",
@@ -68,7 +68,6 @@ function argsSummary(tool, args) {
68
68
  const values = args.symbols || args.files || args.symbol || args.file || '';
69
69
  return clip(`${args.mode || '?'}:${Array.isArray(values) ? `[${values.length}]${values[0] || ''}` : values}`);
70
70
  }
71
- case 'explore': return arr(args.query);
72
71
  case 'find': return clip(args.query);
73
72
  case 'glob': return clip(Array.isArray(args.pattern) ? args.pattern[0] : args.pattern);
74
73
  case 'list': return clip(basename(String(args.path || '')));
@@ -95,7 +94,7 @@ function targetValues(tool, args) {
95
94
  ? (args.files != null ? 'files' : 'file')
96
95
  : symbolMode || args.mode === 'symbols' ? (args.symbols != null ? 'symbols' : 'symbol') : 'file';
97
96
  } else if (tool === 'grep' || tool === 'glob') key = 'pattern';
98
- else if (tool === 'find' || tool === 'explore') key = 'query';
97
+ else if (tool === 'find') key = 'query';
99
98
  const value = args[key];
100
99
  return Array.isArray(value) ? value : value == null ? [] : [value];
101
100
  }
@@ -110,7 +109,7 @@ function batchFields(tool, args) {
110
109
  ? (args?.files != null ? 'files' : args?.file != null ? 'file' : args?.symbols != null ? 'symbols' : 'symbol')
111
110
  : null].filter(Boolean);
112
111
  }
113
- return [tool === 'read' || tool === 'list' ? 'path' : tool === 'find' || tool === 'explore' ? 'query' : null].filter(Boolean);
112
+ return [tool === 'read' || tool === 'list' ? 'path' : tool === 'find' ? 'query' : null].filter(Boolean);
114
113
  }
115
114
  function compatibleBatchCalls(tool, left, right) {
116
115
  if (tool === 'read') {
@@ -149,7 +148,7 @@ function batchSpec(tool, args, forcedField = null) {
149
148
  : (args.symbols != null ? 'symbols' : 'symbol');
150
149
  return { field, values: targetValues(tool, args) };
151
150
  }
152
- const fieldName = forcedField || (tool === 'read' || tool === 'list' ? 'path' : tool === 'grep' || tool === 'glob' ? 'pattern' : tool === 'find' || tool === 'explore' ? 'query' : null);
151
+ const fieldName = forcedField || (tool === 'read' || tool === 'list' ? 'path' : tool === 'grep' || tool === 'glob' ? 'pattern' : tool === 'find' ? 'query' : null);
153
152
  if (!fieldName) return null;
154
153
  const value = args[fieldName];
155
154
  return { field: fieldName, values: Array.isArray(value) ? value : value == null ? [] : [value] };
@@ -166,7 +165,7 @@ function sameIterationBatchObservations(sequence) {
166
165
  if (isMutation(next.tool)) break;
167
166
  group.push(next);
168
167
  }
169
- for (const candidate of ['read', 'grep', 'find', 'glob', 'list', 'explore', 'code_graph']) {
168
+ for (const candidate of ['read', 'grep', 'find', 'glob', 'list', 'code_graph']) {
170
169
  if (candidate === 'read') {
171
170
  const calls = group.filter((entry) => entry.tool === 'read' && !entry.failed).map((entry) => ({ entry, targets: readTargets(entry.rawArgs) })).filter(({ targets }) => targets?.length);
172
171
  if (calls.some(({ entry, targets }, index) => calls.some(({ entry: other, targets: otherTargets }, otherIndex) => (
@@ -238,7 +237,7 @@ function buildCase(sid, toolRows) {
238
237
  const observations = [];
239
238
  if (sequence.some((s) => s.tool === 'code_graph' && s.rawArgs?.mode === 'find_symbol' && !s.rawArgs?.file && !s.rawArgs?.files)) flags.push('find_symbol_noscope');
240
239
  // Exact duplicate requests are the only relookup signal available in tool
241
- // traces. Do not infer waste from counts, roles, turns, or explore→inspection:
240
+ // traces. Do not infer waste from counts, roles, turns, or locator→inspection:
242
241
  // exploration followed by inspection can be the intended route.
243
242
  const seenRequests = new Set();
244
243
  const readWindows = [];
@@ -25,7 +25,6 @@ export const SUITES = {
25
25
  'dead-owner-attach-test.mjs',
26
26
  'debounced-skills-async-save-test.mjs',
27
27
  'dispatch-persist-recovery-test.mjs',
28
- 'explore-prompt-policy-test.mjs',
29
28
  'find-fuzzy-hidden-test.mjs',
30
29
  'ingest-pure-conversation-smoke.mjs',
31
30
  'internal-tools-normalization-test.mjs',
@@ -51,6 +50,7 @@ export const SUITES = {
51
50
  'pretool-ask-runtime-test.mjs',
52
51
  'prompt-input-parity-test.mjs',
53
52
  'reactive-compact-persist-smoke.mjs',
53
+ 'reasoning-replay-policy-test.mjs',
54
54
  'repl-stream-finalize-test.mjs',
55
55
  'result-classification-test.mjs',
56
56
  'rg-runner-test.mjs',
@@ -60,6 +60,7 @@ export const SUITES = {
60
60
  'session-title-controller-test.mjs',
61
61
  'set-effort-config-test.mjs',
62
62
  'shell-jobs-windows-hide-test.mjs',
63
+ 'spawn-ws-prewarm-test.mjs',
63
64
  'spinner-meta-test.mjs',
64
65
  'statusline-agents-test.mjs',
65
66
  'statusline-quota-hysteresis-test.mjs',
package/src/app.mjs CHANGED
@@ -87,7 +87,6 @@ export async function run(argv = [], classifiedInvocation = null) {
87
87
  model: opts.model,
88
88
  effort: opts.effort,
89
89
  fast: opts.fast,
90
- explore: opts.explore,
91
90
  webSearch: opts.webSearch,
92
91
  memory: opts.memory,
93
92
  cwd: process.cwd(),
@@ -1,17 +1,5 @@
1
1
  {
2
2
  "agents": [
3
- {
4
- "agent": "explorer",
5
- "slot": "explore",
6
- "systemFile": "rules/agent/30-explorer.md",
7
- "description": "Filesystem navigation agent invoked by the `explore` MCP tool",
8
- "invokedBy": "explore",
9
- "toolSchemaProfile": "read",
10
- "schemaAllowedTools": ["grep", "find", "glob", "code_graph"],
11
- "kind": "retrieval",
12
- "permission": "read",
13
- "stallCap": { "idleSeconds": 240, "toolRunningSeconds": 180 }
14
- },
15
3
  {
16
4
  "agent": "cycle1-agent",
17
5
  "slot": "cycle1",
@@ -73,7 +73,7 @@ apply it, and verify the result.
73
73
  ### Workflow / agent definitions
74
74
 
75
75
  1. Workflows and agents are Markdown packs. Built-in services are Web Search,
76
- Explore, and Maintainer. Mixdog ships editable starter agents `worker`,
76
+ and Maintainer. Mixdog ships editable starter agents `worker`,
77
77
  `heavy-worker`, and `reviewer`; custom packs live at
78
78
  `<mixdogData>/workflows/<id>/WORKFLOW.md` and
79
79
  `<mixdogData>/agents/<id>/AGENT.md`.
@@ -1,10 +1,9 @@
1
1
  const VALUE_OPTIONS = new Set(['--provider', '--model', '--effort', '--workflow']);
2
2
  const FLAG_OPTIONS = new Set([
3
3
  '--readonly', '--help', '-h', '--plain', '--react', '--remote', '--onboarding', '--fast',
4
- '--explore', '--web-search', '--memory',
4
+ '--web-search', '--memory',
5
5
  ]);
6
6
  const HEADLESS_ROLE_ALIASES = new Map([
7
- ['explorer', 'explore'], ['explore', 'explore'],
8
7
  ['maint', 'maintainer'], ['maintenance', 'maintainer'], ['maintainer', 'maintainer'],
9
8
  ['worker', 'worker'],
10
9
  ['heavy', 'heavy-worker'], ['heavyworker', 'heavy-worker'], ['heavy-worker', 'heavy-worker'],
@@ -108,7 +107,6 @@ export function classifyCliInvocation(argv = []) {
108
107
  model: parsed.values['--model'],
109
108
  effort: parsed.values['--effort'],
110
109
  fast: argv.includes('--fast'),
111
- explore: argv.includes('--explore'),
112
110
  webSearch: argv.includes('--web-search'),
113
111
  memory: argv.includes('--memory'),
114
112
  toolMode: argv.includes('--readonly') ? 'readonly' : 'full',
@@ -83,7 +83,6 @@ export async function runHeadlessRole({
83
83
  model,
84
84
  effort,
85
85
  fast,
86
- explore = false,
87
86
  webSearch = false,
88
87
  memory = false,
89
88
  cwd = process.cwd(),
@@ -93,11 +92,10 @@ export async function runHeadlessRole({
93
92
  } = {}) {
94
93
  const cleanAgent = clean(agent);
95
94
  const cleanMessage = clean(message);
96
- // Classic headless surface: explorer, web search, and memory tools start OFF
97
- // and opt back in per run (--explore / --web-search / --memory). An explicit
95
+ // Classic headless surface: web search and memory tools start OFF
96
+ // and opt back in per run (--web-search / --memory). An explicit
98
97
  // MIXDOG_FEATURE_* value from the caller environment always wins.
99
98
  for (const [key, enabled] of [
100
- ['MIXDOG_FEATURE_EXPLORE', explore],
101
99
  ['MIXDOG_FEATURE_WEB_SEARCH', webSearch],
102
100
  ['MIXDOG_FEATURE_MEMORY', memory],
103
101
  ]) {
package/src/help.mjs CHANGED
@@ -21,7 +21,7 @@ export const HELP_LINES = [
21
21
  '',
22
22
  'Headless role commands require an explicit provider/model pair and run with',
23
23
  'ephemeral config/data; host behavioral config and personal state are not loaded.',
24
- 'Roles: explore, worker, heavy-worker, reviewer, maintainer, web-researcher.',
24
+ 'Roles: worker, heavy-worker, reviewer, maintainer, web-researcher.',
25
25
  '',
26
26
  'Slash commands (inside mixdog):',
27
27
  ' /clear start a fresh chat (alias: /new)',
@@ -2,51 +2,47 @@
2
2
 
3
3
  - Baseline routing assigns each facet directly by the evidence needed to
4
4
  determine the complete edit:
5
- path/name only→`find`; wildcard/recursive paths→`glob`; exact directory
6
- entries→`list`;
5
+ path/name only→`find`; wildcard/recursive paths→`glob` (including known-root
6
+ unknown descendants); exact directory entries→`list`;
7
7
  source content/value/`path:line`→`grep`; exact symbol/relation→`code_graph`;
8
8
  known file/range→`read`;
9
- web/current→`search`; returned URL body→`web_fetch`; prior work→`recall`;
9
+ web/current→`search`; returned URL body→`web_fetch`; prior work→`recall`
10
+ (history only, never current local state);
10
11
  durable compact English memory→`memory`; explicit project change→`cwd`;
11
12
  explicit user-requested conversation reset→`session_manage`.
12
13
  Use only named tools present in the current tool surface.
13
- `explore`, when exposed, is a fast path only for facets whose repository
14
- coordinates remain unknown: call it first once for all such independent
15
- facets in one query array. It returns the minimal complete direct
16
- `path:line` anchors, not analysis or solutions; resume baseline routing
17
- from those anchors.
18
14
  - Act only on verified identities (cwd/project/user/tool-returned) — paths,
19
15
  module specifiers, symbols, data/record shapes alike; a guessed identity is
20
- itself a facet, verified by the cheapest batched probe (one lookup or sample
21
- record) before anything depends on it. Within the current project, pass
16
+ verified by one lookup or sample only when the next call or edit references
17
+ it. Within the current project, pass
22
18
  project-relative paths and omit optional scopes equal to its root; explicit
23
19
  paths may be outside cwd only for targets outside the project.
24
- - A conclusive result ends its facet, and known state task/brief-supplied
25
- facts, returned content, and the effects of your own successful calls — is
26
- never re-acquired: never broaden, repeat, or reconfirm. Follow up only when
27
- prior output is needed to form the next call; on failure rerun only the
28
- failed check.
29
- Batch calls iff no call needs another's output (as input or to decide its
30
- need/scope) or can change another's inputs/state; otherwise serialize, and
31
- drop a call whose deciding evidence already suffices. Before each retrieval
32
- batch, deduplicate every facet the task still requires, route each once to
33
- the cheapest sufficient tool with all required variants/scopes, and launch
34
- every independent call together. Never
35
- split one decision across overlapping facets, duplicate/broaden a facet
36
- through another tool, add `shell`/`apply_patch` mutation merely to widen
37
- retrieval, reserve known work, or cap fanout.
38
- Take the cheapest sufficient evidence per facet:
39
- symbol relations end at `code_graph`, values/locations end at the context
40
- grep returns; `read` covers only what returned spans cannot, as an anchored
41
- offset/limit window never a full-file read when a window suffices;
42
- adjacent context around an edit point counts as needed evidence. The moment
43
- evidence determines the edit, stop retrieving and patch.
44
- - Once the edit is determined, finish in one assistant turn: one
45
- `apply_patch` per file or cohesive unit, all patches first, then one batched
46
- verification `shell` for required postconditions only; runtime waits
47
- for every patch and skips the shell if any fails. Retry only failed envelopes.
48
- Create or edit text only with `apply_patch`, never `shell`. Earlier `shell`
49
- is only for executable/runtime/state evidence unavailable to file tools—an
50
- independent facet, batched with the rest.
20
+ - Plan the fewest dependent rounds, then the fewest calls. A conclusive
21
+ result ends its facet, and known state task/brief-supplied facts,
22
+ returned content, your own successful calls' effects is never
23
+ re-acquired, broadened, or reconfirmed. Batch calls iff none needs
24
+ another's output or can change another's inputs/state; otherwise
25
+ serialize. Before each batch, deduplicate the facets still required by the request,
26
+ route each once to the cheapest sufficient tool with all required
27
+ variants/scopes, and launch every independent call together never
28
+ split or duplicate a facet across tools, mutate merely to widen
29
+ retrieval, reserve known work, or cap fanout. Symbol relations end at
30
+ `code_graph`; values/locations end at the context grep returns; `read`
31
+ covers only what returned spans cannot, as an anchored offset/limit
32
+ window. The moment evidence determines the answer, edit, or deliverable,
33
+ stop retrieving; patch if needed.
34
+ - Once the edit or deliverable is determined, finish in one assistant turn:
35
+ issue `apply_patch` calls serially, never in parallel; use one cohesive call
36
+ with one file section per target, all patches first, then one
37
+ batched verification `shell` that runs the real required postconditions
38
+ on every changed file and produced artifact, never echoes a claim;
39
+ runtime waits for every patch and skips the shell
40
+ if any fails. Retry only failed envelopes; rerun a failed check only
41
+ after a fix that can change its result, else report it unresolved.
42
+ Hand-authored text is edited only with `apply_patch`; computed artifacts
43
+ (data/reports/derived values) come from `shell` computation, never
44
+ hand-transcribed numbers. Earlier `shell` is only for runtime/state
45
+ evidence unavailable to file tools—an independent facet, batched with
46
+ the rest.
51
47
  - A background `task_id` ends the turn; completion resumes work. Never poll;
52
48
  use task control only for recovery or a required blocking result.
@@ -47,7 +47,7 @@ import { resourceAdmission } from '../../../shared/resource-admission.mjs';
47
47
  export { resolveMaintenanceRoute } from './maintenance-route.mjs';
48
48
 
49
49
  // Cap agent role synthesis to ~3000 tokens (~12 KB at the 4 B/tok
50
- // working average). Pool B explore/recall/search answers occasionally land
50
+ // working average). Pool B recall/search answers occasionally land
51
51
  // 8-10k-token walls that then ride in the Lead context for the rest of the
52
52
  // turn; the cap keeps those outliers bounded without touching the 95%+ of
53
53
  // answers already under the threshold.
@@ -68,7 +68,7 @@ function formatCompactElapsedSeconds(ms) {
68
68
 
69
69
  // True when an abort explicitly opted into partial salvage — the error object
70
70
  // or the abort reason carries `salvagePartial: true`. A DEADLINE-driven caller
71
- // (explore hard timeout) sets it so the anchors the sub-agent already produced
71
+ // A hard timeout sets it so partial output the sub-agent already produced
72
72
  // are returned instead of discarded; user cancellation (ESC) never sets it and
73
73
  // keeps the throw-everything behaviour.
74
74
  function salvagePartialRequested(error, signal) {
@@ -151,7 +151,7 @@ export function resolveHiddenRoleSchemaAllowedTools(hidden) {
151
151
  * against config.presets.
152
152
  * - null — unresolved.
153
153
  *
154
- * Explore and memory hidden roles mirror public spawning precedence:
154
+ * Hidden maintenance roles mirror public spawning precedence:
155
155
  * `agents.<role>` (including the `agents.maintenance` alias) → workflow route →
156
156
  * maintenance route → Main. The cycle1/2/3 agents share the memory knob via
157
157
  * their `maintKey: 'memory'` override. Scheduler and webhook are unchanged.
@@ -293,7 +293,7 @@ export function makeAgentDispatch(opts = {}) {
293
293
  agentId: agent,
294
294
  });
295
295
 
296
- // Callers (e.g. aiWrapped explore dispatch) may pass an explicit
296
+ // Callers may pass an explicit
297
297
  // `cwd` to scope the agent's filesystem view. Absolute path expected
298
298
  // (aiWrapped already expands `~` and resolves relatives). When unset
299
299
  // we pass `null` through instead of falling back to `process.cwd()`
@@ -418,7 +418,7 @@ export function makeAgentDispatch(opts = {}) {
418
418
  const _idleController = (agentWatchdogPolicyActive(_watchdogPolicy) && _linkSignal)
419
419
  ? new AbortController()
420
420
  : null;
421
- // Do not link factory parent, per-call explore cancellation, and the
421
+ // Do not link factory parent, per-call cancellation, and the
422
422
  // watchdog one at a time: each link replaces the previous listener in
423
423
  // runtime-liveness. One composite survives askSession's controller
424
424
  // swap and makes every source reach the provider call.
@@ -497,7 +497,7 @@ export function makeAgentDispatch(opts = {}) {
497
497
  });
498
498
  process.stderr.write(`[agent-dispatch] agent=${agent} session=${session.id} elapsed=${Date.now() - _agentDispatchT0}ms\n`);
499
499
  const raw = result?.content || '';
500
- // Brief cap. Agent role answers (explore/recall/search)
500
+ // Brief cap. Agent role answers (recall/search)
501
501
  // occasionally balloon to 8-10k token walls that then ride in the
502
502
  // parent Lead's context for the rest of the turn. A 3000-token
503
503
  // (~12 KB) ceiling trims the long tail while leaving the vast
@@ -1,7 +1,5 @@
1
1
  /**
2
- * Agent loop ceilings. Lead and general delegated agents share one high
3
- * runaway guard. Explorer is the sole bounded exception: locator work gets at
4
- * at most five tool-capable turns, followed by the loop's tool-less report turn.
2
+ * Agent loop ceilings. Lead and delegated agents share one high runaway guard.
5
3
  */
6
4
 
7
5
  function envPositiveInt(name, fallback) {
@@ -15,29 +13,8 @@ function envPositiveInt(name, fallback) {
15
13
  // to raise/lower the safety ceiling, never used as a general task-length budget.
16
14
  export const LEAD_MAX_LOOP_ITERATIONS = envPositiveInt('MIXDOG_AGENT_MAX_LOOP', 200);
17
15
 
18
- // Explorer's first turn is the whole maximum-fanout search; turns 2-5 are
19
- // bounded miss recovery. The override may shorten this but never add a sixth.
20
- export const EXPLORE_MAX_LOOP_ITERATIONS = Math.min(
21
- 5,
22
- envPositiveInt('MIXDOG_EXPLORE_MAX_LOOP', 5),
23
- );
24
-
25
- /**
26
- * Resolve the hard cap used by agentLoop for this session.
27
- *
28
- * Explorer: the lowest positive explicit/session value, clamped to its
29
- * dedicated five-turn ceiling. Others: explicit → session-pinned → shared guard.
30
- */
16
+ /** Resolve the hard cap used by agentLoop for this session. */
31
17
  export function resolveSessionMaxLoopIterations(sessionRef, explicit) {
32
- const sessionAgent = String(sessionRef?.agent || '').trim().toLowerCase();
33
- if (sessionAgent === 'explorer' || sessionAgent === 'explore') {
34
- const requested = Number.isFinite(explicit) && explicit > 0
35
- ? Math.floor(explicit)
36
- : Number.isFinite(sessionRef?.maxLoopIterations) && sessionRef.maxLoopIterations > 0
37
- ? Math.floor(sessionRef.maxLoopIterations)
38
- : EXPLORE_MAX_LOOP_ITERATIONS;
39
- return Math.min(EXPLORE_MAX_LOOP_ITERATIONS, requested);
40
- }
41
18
  if (Number.isFinite(explicit) && explicit > 0) return Math.floor(explicit);
42
19
  if (Number.isFinite(sessionRef?.maxLoopIterations) && sessionRef.maxLoopIterations > 0) {
43
20
  return Math.floor(sessionRef.maxLoopIterations);
@@ -17,7 +17,7 @@ import {
17
17
  // Ordering guarantee, stated in stall-policy.mjs: the provider layer — which
18
18
  // can retry in place or fall back to non-streaming — must fire STRICTLY before
19
19
  // the agent watchdog's terminal abort. Role abort budgets (worker/reviewer
20
- // 300s, explore 240s) sat at or BELOW the provider semantic-idle window
20
+ // 300s) sat at or BELOW the provider semantic-idle window
21
21
  // (300s), inverting that order: the watchdog aborted the shared signal first,
22
22
  // so the provider's recovery never ran and the `agent_stall` failure — which
23
23
  // the classifier calls retryable — died on throwIfAborted instead. Hold the
@@ -140,7 +140,7 @@ export function watchdogPartialHandoffFromError(error, session, messageStartInde
140
140
  }
141
141
 
142
142
  // Salvage path for NON-watchdog aborts that explicitly opt in (the abort error
143
- // / abort reason carries `salvagePartial: true` — e.g. the explore wall-clock
143
+ // / abort reason carries `salvagePartial: true` — e.g. a bounded wall-clock
144
144
  // hard timeout). Same collection rule as the watchdog handoff: only assistant
145
145
  // text appended during this run. Plain user cancellation never opts in, so ESC
146
146
  // still discards the run.
@@ -266,7 +266,7 @@ export function resolveAgentWatchdogPolicy(agent, overrides = {}) {
266
266
  ? Math.min(DEFAULT_STALE_TIMEOUT_MS, backstopMs)
267
267
  : DEFAULT_STALE_TIMEOUT_MS;
268
268
  // Same floor for the public backstop: a workflow role (worker 300s,
269
- // explore 240s) must not undercut the provider window either.
269
+ // role-specific caps must not undercut the provider window either.
270
270
  idleStaleMs = Math.max(idleStaleMs, PROVIDER_RECOVERY_FLOOR_MS);
271
271
  }
272
272
 
@@ -29,7 +29,7 @@ export function resolveMaintenanceRoute({ preset, optsPreset, agent, config: cfg
29
29
  try {
30
30
  const config = cfgIn || loadConfig({ secrets: false });
31
31
  const key = hidden.maintKey || hidden.slot;
32
- const role = key === 'explore' ? 'explore' : (key === 'memory' ? 'maintainer' : '');
32
+ const role = key === 'memory' ? 'maintainer' : '';
33
33
  if (!role) return config?.maintenance?.[key] ?? null;
34
34
  const candidates = [
35
35
  ...configuredAgentRouteCandidates(config, role),
@@ -49,7 +49,7 @@ function normalizeAgentCompactionConfig(value = {}, { memoryEnabled = true } = {
49
49
 
50
50
  /**
51
51
  * @param {object} opts
52
- * @param {string} opts.agent — canonical agent name ('worker', 'explorer', ...)
52
+ * @param {string} opts.agent — canonical agent name ('worker', 'reviewer', ...)
53
53
  * @param {string} opts.presetName — resolved preset identifier
54
54
  * @param {object} opts.preset — resolved preset object from agent-config
55
55
  * @param {object} opts.runtimeSpec — resolveRuntimeSpec output; must carry .scopeKey / .lane
@@ -39,7 +39,13 @@ export function createTitleCompletion(deps = {}) {
39
39
  config,
40
40
  });
41
41
  if (!route || typeof route !== 'object') {
42
- throw new Error('Session title maintenance route is unresolved.');
42
+ const error = new Error('Session title maintenance route is unresolved.');
43
+ // Machine-readable marker: callers (session-title controller)
44
+ // downgrade this to a one-shot "titling disabled" skip instead of
45
+ // logging a stack per session (e.g. bench profiles without a
46
+ // maintainer/default route).
47
+ error.code = 'MAINTENANCE_ROUTE_UNRESOLVED';
48
+ throw error;
43
49
  }
44
50
  const providerName = String(route.provider || '').trim();
45
51
  const model = String(route.model || '').trim();
@@ -137,7 +137,6 @@ const TOOL_ARG_KEYS = {
137
137
  list: ['path', 'head_limit', 'offset'],
138
138
  recall: ['query', 'limit', 'session_id', 'cwd'],
139
139
  search: ['query', 'limit', 'cwd'],
140
- explore: ['query', 'queries', 'limit', 'cwd'],
141
140
  code_graph: ['mode', 'file', 'files', 'symbol', 'symbols', 'body', 'language', 'limit', 'depth', 'page', 'cwd'],
142
141
  shell: ['command', 'cwd', 'timeout', 'mode', 'run_in_background', 'persistent', 'session_id'],
143
142
  task: ['task_id', 'action', 'timeout_ms', 'poll_ms'],
@@ -22,13 +22,12 @@ export function getPluginData() {
22
22
  // Canonical maintenance defaults. Single source of truth — imported by
23
23
  // llm/index.mjs and setup-server.mjs so UI/runtime cannot drift from config.
24
24
  //
25
- // Explore and Maintainer start without a route so they dynamically inherit the
26
- // Main route. Their explicit routes live canonically in `agents.explore` and
27
- // `agents.maintainer`; load-time migration still accepts the older workflow /
28
- // maintenance aliases.
25
+ // Maintainer starts without a route so it dynamically inherits the Main route.
26
+ // Its explicit route lives canonically in `agents.maintainer`; load-time
27
+ // migration still accepts the older workflow / maintenance aliases.
29
28
  // Webhook endpoints may omit a model and use the fallback route below.
30
29
  // Legacy route slots accepted only at config ingress for migration.
31
- const MAINTENANCE_SLOTS = Object.freeze(['explore', 'memory']);
30
+ const MAINTENANCE_SLOTS = Object.freeze(['memory']);
32
31
 
33
32
  // --- User profile (statusline /profile) -------------------------------------
34
33
  // Supported response languages for the /profile picker. `system` is the default
@@ -340,7 +339,8 @@ function canonicalizeShellStorage(value) {
340
339
  function canonicalizeModulesStorage(value) {
341
340
  const modules = configObject(value);
342
341
  delete modules.memory;
343
- for (const name of ['search', 'explore']) {
342
+ delete modules.explore;
343
+ for (const name of ['search']) {
344
344
  if (!Object.prototype.hasOwnProperty.call(modules, name)) continue;
345
345
  const raw = modules[name];
346
346
  modules[name] = {
@@ -711,8 +711,7 @@ export function loadScopedRoleInstructions(agent, provider = null) {
711
711
  agentRuleSectionsToEmit = hiddenPairs.map(p => `## ${p.name}\n\n${p.body}`);
712
712
  agentSectionsToEmit = agentSections;
713
713
  } else if (agent && classification.retrieval.has(agent)) {
714
- // Retrieval agents (explorer) get their own contract section
715
- // (rules/agent/30-explorer.md) in BP2.
714
+ // Retrieval agents get their own contract section in BP2.
716
715
  const self = hiddenPairs.find(p => p.name === agent);
717
716
  agentRuleSectionsToEmit = self ? [`## ${self.name}\n\n${self.body}`] : [];
718
717
  agentSectionsToEmit = agentSections.filter(s =>
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * This module persists the minimum needed to recover:
10
10
  * - handle (`dispatch_<tool>_...`)
11
- * - tool (`recall` / `search` / `explore`)
11
+ * - tool (`recall` / `search`)
12
12
  * - queries (for the abort message)
13
13
  * - createdAt
14
14
  *
@@ -2,7 +2,7 @@
2
2
  * Internal hidden agents — Mixdog-managed, user-untouchable.
3
3
  *
4
4
  * Unlike public workflow agents, these hidden agents are NEVER exposed to callers of the `agent` tool. They are
5
- * invoked only by internal handlers (explore / recall / search) and carry
5
+ * invoked only by internal handlers (recall / search) and carry
6
6
  * their own system prompt + tool-set policy.
7
7
  *
8
8
  * Lookup order (agent-dispatch.resolveMaintenanceRoute):
@@ -20,7 +20,7 @@
20
20
  * found" error rather than silently mis-dispatching.
21
21
  *
22
22
  * Kind classification:
23
- * - 'retrieval' : short-lived hidden retrieval agents (explore).
23
+ * - 'retrieval' : short-lived hidden retrieval agents.
24
24
  * - 'maintenance' : background-trigger hidden agents (memory cycle and
25
25
  * title generation). Receive only their own self section.
26
26
  *
@@ -184,7 +184,7 @@ export function listHiddenAgentsByKind(kind) {
184
184
 
185
185
  /**
186
186
  * Return the agents/<name>.md sections a hidden agent shares in its BP2 catalog
187
- * (in addition to its own self section). Drives the explorer→worker cache
187
+ * (in addition to its own self section). Drives hidden-role cache
188
188
  * alignment declaratively instead of a hard-coded agent-name branch in
189
189
  * collect.mjs. Returns [] when the agent declares none.
190
190
  */