mixdog 0.9.110 → 0.9.112

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 (95) hide show
  1. package/package.json +10 -59
  2. package/scripts/routing-corpus.mjs +5 -6
  3. package/src/app.mjs +0 -1
  4. package/src/defaults/agents.json +0 -12
  5. package/src/defaults/skills/setup/SKILL.md +1 -1
  6. package/src/headless-command.mjs +1 -3
  7. package/src/headless-role.mjs +2 -4
  8. package/src/help.mjs +1 -1
  9. package/src/rules/shared/01-tool.md +11 -9
  10. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +6 -6
  11. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +2 -25
  12. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +3 -3
  13. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -1
  14. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +1 -1
  15. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +0 -1
  16. package/src/runtime/agent/orchestrator/config.mjs +5 -6
  17. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -2
  18. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +1 -1
  19. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -3
  20. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  21. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +3 -1
  22. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +11 -1
  23. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +17 -12
  24. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +9 -1
  25. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +32 -11
  26. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +74 -3
  27. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +33 -32
  28. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +1 -1
  29. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +0 -12
  30. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +1 -1
  31. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +1 -1
  32. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +5 -5
  33. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -29
  34. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -0
  35. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +1 -5
  36. package/src/runtime/agent/orchestrator/stall-policy.mjs +0 -1
  37. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +7 -7
  38. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +14 -30
  39. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -7
  40. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +1 -1
  41. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +4 -4
  42. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +2 -2
  43. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +4 -17
  44. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +40 -0
  45. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +0 -1
  46. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -1
  47. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +22 -35
  48. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
  49. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -5
  50. package/src/runtime/channels/lib/output-forwarder.mjs +0 -13
  51. package/src/runtime/channels/lib/tool-format.mjs +1 -2
  52. package/src/runtime/search/index.mjs +12 -6
  53. package/src/runtime/search/tool-defs.mjs +2 -2
  54. package/src/runtime/shared/agent-route-config.mjs +0 -6
  55. package/src/runtime/shared/child-spawn-gate.mjs +1 -1
  56. package/src/runtime/shared/resource-admission.mjs +1 -1
  57. package/src/runtime/shared/tool-card-model.mjs +3 -5
  58. package/src/runtime/shared/tool-primitives.mjs +0 -1
  59. package/src/runtime/shared/tool-result-summary.mjs +0 -7
  60. package/src/runtime/shared/tool-surface.mjs +1 -14
  61. package/src/session-runtime/runtime-core.mjs +1 -24
  62. package/src/session-runtime/settings-api.mjs +9 -9
  63. package/src/session-runtime/tool-catalog-data.mjs +4 -7
  64. package/src/session-runtime/tool-catalog-schema.mjs +1 -1
  65. package/src/session-runtime/workflow-agents-api.mjs +0 -3
  66. package/src/session-runtime/workflow.mjs +3 -7
  67. package/src/standalone/agent-tool/helpers.mjs +0 -1
  68. package/src/standalone/agent-tool/render.mjs +1 -1
  69. package/src/standalone/agent-tool/shard-spread.mjs +2 -2
  70. package/src/standalone/daemon.mjs +1 -0
  71. package/src/standalone/session-client.mjs +79 -20
  72. package/src/standalone/session-protocol.mjs +1 -1
  73. package/src/standalone/session-transport.mjs +19 -3
  74. package/src/tui/app/model-options.mjs +2 -3
  75. package/src/tui/app/onboarding-steps.mjs +1 -1
  76. package/src/tui/app/settings-picker.mjs +0 -12
  77. package/src/tui/app/transcript-row-estimate.mjs +1 -1
  78. package/src/tui/app/use-transcript-activity.mjs +7 -17
  79. package/src/tui/dist/index.mjs +9 -51
  80. package/src/tui/session/agent-envelope.mjs +1 -1
  81. package/src/tui/session/live-share.mjs +1 -1
  82. package/src/tui/session/session-api.mjs +2 -11
  83. package/src/tui/session/session-flow.mjs +25 -1
  84. package/src/tui/session/turn.mjs +2 -2
  85. package/src/tui/session-local.mjs +8 -11
  86. package/src/ui/statusline-agents.mjs +1 -2
  87. package/src/ui/statusline-format.mjs +1 -1
  88. package/src/ui/statusline-segments.mjs +20 -5
  89. package/src/ui/statusline.mjs +1 -6
  90. package/scripts/run-suite.mjs +0 -102
  91. package/src/agents/explore/AGENT.md +0 -8
  92. package/src/agents/explore/agent.json +0 -6
  93. package/src/rules/agent/30-explorer.md +0 -55
  94. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +0 -188
  95. 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.110",
3
+ "version": "0.9.112",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone mixdog coding-agent CLI/TUI workspace.",
@@ -48,72 +48,24 @@
48
48
  "prepublishOnly": "node -e \"if(!process.env.CI){console.error('local npm publish is disabled — run npm run release:patch');process.exit(1)}\"",
49
49
  "start": "node src/cli.mjs",
50
50
  "smoke": "node scripts/smoke.mjs",
51
- "test:contract": "node scripts/run-suite.mjs contract",
52
- "smoke:all": "npm run smoke && npm run smoke:boot && npm run smoke:patch && npm run smoke:output && npm run smoke:tui && npm run smoke:live-worker",
51
+ "smoke:all": "npm run smoke && npm run smoke:boot && npm run smoke:patch && npm run smoke:compact",
53
52
  "smoke:boot": "node scripts/boot-smoke.mjs",
54
53
  "smoke:compact": "node scripts/compact-smoke.mjs",
55
- "test:compact": "node --test scripts/compact-active-turn-test.mjs scripts/compact-file-reattach-test.mjs scripts/compact-prior-context-flatten-test.mjs scripts/compact-recall-digest-test.mjs scripts/compact-pressure-test.mjs",
56
- "test:context": "node --test scripts/context-mcp-metering-test.mjs scripts/v4a-context-miss-excerpt-test.mjs",
54
+ "test:compact": "node --test scripts/suite-compact-test.mjs",
57
55
  "smoke:loop": "node scripts/smoke-loop.mjs",
58
56
  "smoke:loop:final": "node scripts/smoke-loop-report.mjs --require-complete --min-elapsed 5h --min-iterations 400 --max-gap 60s --max-smoke-ms 10000 --max-avg-smoke-ms 8500 --max-step-ms smoke.mjs=4000 --max-step-ms boot-smoke.mjs=8000 --max-rss-mb 140 --max-rss-growth-mb 50",
59
57
  "smoke:loop:report": "node scripts/smoke-loop-report.mjs",
60
58
  "test:tool-contracts": "node scripts/tool-smoke.mjs",
61
59
  "smoke:patch": "node scripts/apply-patch-edit-smoke.mjs",
62
- "smoke:patch-replay": "node scripts/apply-patch-replay-smoke.mjs",
63
- "smoke:tool-rescue": "node scripts/tool-rescue-smoke.mjs",
64
- "smoke:output": "node scripts/output-style-smoke.mjs",
65
- "smoke:tui": "node scripts/build-tui.mjs && node scripts/tui-render-smoke.mjs && npm run test:tui-input-render && npm run test:tui-streaming-window && npm run test:tui-queue",
66
- "smoke:freevars": "node scripts/freevar-smoke.mjs",
67
- "smoke:logguard": "node scripts/log-writer-guard-smoke.mjs",
68
- "smoke:live-worker": "node scripts/live-worker-smoke.mjs",
69
- "smoke:agent-tag-reuse": "node scripts/agent-tag-reuse-smoke.mjs",
70
- "test:agent-terminal-reap": "node scripts/agent-terminal-reap-test.mjs",
71
- "test:agent-job-views": "node --test scripts/agent-job-terminal-view-test.mjs",
72
- "test:agent-fanout": "node scripts/agent-parallel-smoke.mjs && node --test scripts/agent-route-batch-test.mjs scripts/execution-completion-dedup-test.mjs",
73
- "test:toolcall": "node --test scripts/toolcall-args-test.mjs",
74
- "test:tool-batching": "node --test scripts/eager-patch-shell-order-test.mjs scripts/session-bench-batching-test.mjs scripts/tool-cwd-rebind-test.mjs",
75
- "test:shipmode": "node --test scripts/ship-mode-test.mjs",
76
- "test:shellhardening": "node --test scripts/shell-hardening-test.mjs scripts/shell-failure-diagnostics-test.mjs scripts/windows-hide-spawn-options-test.mjs scripts/shell-job-session-scope-test.mjs",
77
- "test:placeholder": "node --test scripts/compacted-placeholder-scrub-test.mjs",
78
- "test:providers": "node --test scripts/provider-toolcall-test.mjs scripts/provider-contract-test.mjs scripts/provider-stream-stall-test.mjs scripts/provider-stream-outcome-test.mjs scripts/stream-frame-fault-matrix-test.mjs scripts/gemini-provider-test.mjs scripts/anthropic-transport-policy-test.mjs scripts/anthropic-native-block-replay-test.mjs scripts/openai-oauth-ws-1006-retry-test.mjs scripts/stream-close-retry-test.mjs scripts/openai-end-turn-signal-test.mjs",
79
- "test:provider-admission": "node --test scripts/provider-admission-scheduler-test.mjs scripts/provider-stream-json-test.mjs",
80
- "test:resource-admission": "node --test scripts/resource-admission-test.mjs scripts/child-spawn-isolation-test.mjs scripts/owner-fair-gate-test.mjs",
81
- "test:deferred-tools": "node --test scripts/deferred-tool-loading-test.mjs",
82
- "test:anthropic-oauth-race": "node --test scripts/anthropic-oauth-refresh-race-test.mjs",
83
- "test:grok-oauth-race": "node --test scripts/grok-oauth-refresh-race-test.mjs",
84
- "test:atomiclock": "node --test scripts/atomic-lock-tryonce-test.mjs",
85
- "test:keychain": "node --test scripts/keychain-prewarm-test.mjs",
86
- "test:memory-leaks": "node --expose-gc --test scripts/memory-retention-test.mjs scripts/memory-worker-stability-test.mjs scripts/session-transport-test.mjs apps/desktop/src/renderer/memory-retention.test.mjs",
87
- "test:memory-routing": "node --test scripts/memory-cycle-routing-test.mjs scripts/maintenance-default-routes-test.mjs scripts/embedding-worker-exit-test.mjs scripts/embedding-runtime-prune-test.mjs",
88
- "test:embedding-runtime": "node --test scripts/embedding-runtime-prune-test.mjs scripts/memory-pg-recovery-test.mjs && node scripts/verify-embedding-runtime.mjs",
89
- "test:embedding-runtime:core": "node --test scripts/embedding-runtime-prune-test.mjs scripts/memory-pg-recovery-test.mjs && node scripts/verify-embedding-runtime.mjs --core",
60
+ "test:shellhardening": "node --test scripts/suite-shellhardening-test.mjs",
61
+ "test:providers": "node --test scripts/provider-toolcall-test.mjs scripts/provider-contract-test.mjs scripts/provider-stream-outcome-test.mjs",
90
62
  "test:embedding-runtime:warmup": "node scripts/verify-embedding-runtime.mjs --warmup",
91
- "prepare:code-graph-test": "node scripts/prepare-code-graph-test.mjs",
92
- "test:code-graph-dispatch": "node --test scripts/code-graph-dispatch-test.mjs",
93
- "test:tui-queue": "node --test scripts/submit-commandbusy-race-test.mjs scripts/steering-drain-buckets-test.mjs scripts/abort-recovery-test.mjs scripts/message-rewind-test.mjs scripts/execution-pending-resume-kick-test.mjs scripts/execution-resume-esc-integration-test.mjs scripts/pending-stale-injection-test.mjs",
94
- "test:tui-input-render": "node --test scripts/prompt-immediate-render-test.mjs scripts/prompt-key-parity-test.mjs",
95
- "test:tui-streaming-window": "node --test scripts/streaming-tail-window-test.mjs scripts/tui-store-frame-batch-test.mjs && node scripts/tui-transcript-jitter-harness.mjs",
96
- "test:tui-ambiguous-width": "node --test scripts/tui-ambiguous-width-test.mjs",
97
- "test:release-assets": "node --check scripts/verify-release-assets.mjs && node --check scripts/verify-release-assets-test.mjs && node --check scripts/deploy-workflow-test.mjs && node --check scripts/release-version-discipline-test.mjs && node --test scripts/verify-release-assets-test.mjs scripts/deploy-workflow-test.mjs scripts/release-version-discipline-test.mjs",
98
- "test:release-focused": "npm run test:release-focused:contracts && npm run test:release-focused:providers && npm run test:release-focused:compact && npm run test:release-focused:session",
99
- "test:release-focused:contracts": "npm run test:release-assets && npm run test:tool-contracts && npm run test:tool-batching && npm run test:placeholder && npm run smoke:patch && npm run test:patch-binary-cache",
100
- "test:release-focused:providers": "npm run test:providers && npm run test:deferred-tools && npm run test:compact && npm run test:context && npm run prepare:code-graph-test && node --test scripts/code-graph-root-federation-test.mjs scripts/code-graph-aggregate-cwd-test.mjs && npm run test:code-graph-dispatch && node --test scripts/code-graph-disk-hit-test.mjs",
101
- "test:release-focused:compact": "npm run smoke:compact && npm run test:shellhardening",
102
- "test:release-focused:session": "npm run test:project-registry && npm run test:session && npm run test:workflow-editor && npm run test:embedding-runtime && node --test scripts/tui-transcript-perf-test.mjs",
103
- "test:native-edit-wire": "node --test scripts/native-edit-wire-test.mjs",
104
- "test:patch-binary-cache": "node --test scripts/patch-binary-cache-test.mjs",
105
- "test:patch-parity": "node --test scripts/v4a-parity-test.mjs",
106
- "test:project-registry": "node --test scripts/project-registry-isolation-test.mjs",
107
- "test:session-transport": "node --test scripts/fair-call-scheduler-test.mjs scripts/session-transport-test.mjs scripts/session-tui-parity-test.mjs scripts/session-recovery-test.mjs scripts/session-submit-delivery-test.mjs scripts/daemon-process-lifetime-test.mjs scripts/session-multipane-stress-test.mjs && node --test scripts/runtime-isolation-stress-test.mjs",
108
- "smoke:session": "node scripts/session-smoke.mjs",
109
- "test:session": "node --test scripts/runtime-turn-contract-test.mjs scripts/session-orphan-sweep-test.mjs scripts/interrupted-turn-history-test.mjs scripts/turn-checkpoint-crash-test.mjs scripts/turn-outcome-fault-matrix-test.mjs scripts/session-save-fault-store-test.mjs scripts/session-disk-authority-test.mjs scripts/session-load-cache-race-test.mjs scripts/agent-loop-complete-turn-test.mjs scripts/session-heartbeat-lifecycle-test.mjs scripts/remote-transition-order-test.mjs scripts/session-new-reset-test.mjs scripts/turn-ttft-critical-path-test.mjs",
110
- "test:live-canary": "node --test scripts/live-canary-test.mjs",
111
- "test:rebindtail": "node --test scripts/forwarder-rebind-tail-test.mjs scripts/channel-remote-format-test.mjs",
112
- "test:workflow-editor": "node --test scripts/workflow-id-test.mjs scripts/workflow-pack-editor-test.mjs",
113
- "test:route-scope": "node --test scripts/route-scope-isolation-test.mjs",
114
- "test:schedule-reload": "node --test scripts/schedule-reload-arm-test.mjs",
63
+ "test:release-assets": "node --check scripts/verify-release-assets.mjs && node --check scripts/release-gate-test.mjs && node --test scripts/release-gate-test.mjs",
64
+ "test:release-focused": "npm run test:release-critical && npm run test:compact && npm run test:shellhardening && npm run test:tool-contracts && npm run test:session && npm run test:session-transport",
65
+ "test:release-critical": "npm run test:release-assets && npm run smoke:patch && npm run test:providers",
66
+ "test:session-transport": "node --test scripts/session-transport-test.mjs",
67
+ "test:session": "node --test scripts/runtime-turn-contract-test.mjs scripts/session-save-fault-store-test.mjs",
115
68
  "test:media": "node --test src/runtime/media/store.test.mjs src/runtime/media/renditions.test.mjs src/runtime/media/adapters/codex-image.test.mjs",
116
- "test:shell-harness": "node --test scripts/shell-harness-regression-test.mjs",
117
69
  "failures": "node scripts/tool-failures.mjs",
118
70
  "trace:llm": "node scripts/llm-trace-summary.mjs",
119
71
  "diag:sessions": "node scripts/session-diag.mjs",
@@ -125,7 +77,6 @@
125
77
  "bench:run": "node scripts/bench-run.mjs",
126
78
  "bench:recall": "node scripts/recall-bench.mjs",
127
79
  "bench:tui-load": "node scripts/tui-runtime-load-bench.mjs",
128
- "bench:explore": "node scripts/explore-bench.mjs",
129
80
  "bench:output-style": "node scripts/output-style-bench.mjs",
130
81
  "bench:session-context": "node scripts/session-context-bench.mjs",
131
82
  "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 = [];
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)',
@@ -8,15 +8,10 @@
8
8
  known file/range→`read`;
9
9
  web/current→`search`; returned URL body→`web_fetch`; prior work→`recall`
10
10
  (history only, never current local state);
11
- durable compact English memory→`memory`; explicit project change→`cwd`;
11
+ durable compact English memory→`memory`; explicit Project change→`cwd`
12
+ (`shell.cwd` is call-local and never changes the Project);
12
13
  explicit user-requested conversation reset→`session_manage`.
13
14
  Use only named tools present in the current tool surface.
14
- `explore`, when exposed, is a fast path only for facets whose repository
15
- coordinates remain unknown: call it first once for all such independent
16
- facets in one query array. It returns direct `path:line` anchors, not
17
- analysis or solutions; anchors are tool-verified coordinates that END
18
- their location facets — never re-locate or second-guess them; resume
19
- baseline routing from them.
20
15
  - Act only on verified identities (cwd/project/user/tool-returned) — paths,
21
16
  module specifiers, symbols, data/record shapes alike; a guessed identity is
22
17
  verified by one lookup or sample only when the next call or edit references
@@ -32,13 +27,20 @@
32
27
  route each once to the cheapest sufficient tool with all required
33
28
  variants/scopes, and launch every independent call together — never
34
29
  split or duplicate a facet across tools, mutate merely to widen
35
- retrieval, reserve known work, or cap fanout. Symbol relations end at
30
+ retrieval, reserve known work, or cap fanout. Guessed terms go wide
31
+ with batched fan-out; narrow a scope only on verified cues — returned
32
+ siblings/conventions or known literals. Mine each returned output for
33
+ every remaining facet before the next round. Symbol relations end at
36
34
  `code_graph`; values/locations end at the context grep returns; `read`
37
35
  covers only what returned spans cannot, as an anchored offset/limit
38
36
  window. The moment evidence determines the answer, edit, or deliverable,
39
37
  stop retrieving; patch if needed.
40
38
  - Once the edit or deliverable is determined, finish in one assistant turn:
41
- one `apply_patch` per file or cohesive unit, all patches first, then one
39
+ before `apply_patch`, obtain every target hunk's exact current content and
40
+ anchor from `grep`, `code_graph`, or `read`; never infer patch context from
41
+ another file, a sample, or expected text. Then issue `apply_patch` calls
42
+ serially, never in parallel; use one cohesive call with one file section per
43
+ target, all patches first, then one
42
44
  batched verification `shell` that runs the real required postconditions
43
45
  on every changed file and produced artifact, never echoes a claim;
44
46
  runtime waits for every patch and skips the shell
@@ -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
@@ -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,7 @@ 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
+ for (const name of ['search']) {
344
343
  if (!Object.prototype.hasOwnProperty.call(modules, name)) continue;
345
344
  const raw = modules[name];
346
345
  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
  */
@@ -107,6 +107,12 @@ function _anthropicSseError(event) {
107
107
  err.httpStatus = status;
108
108
  err.status = status;
109
109
  }
110
+ // Wire-error marker: an error type OUTSIDE the documented enumeration
111
+ // (no status resolved above) default-retries under the shared wire-error
112
+ // contract instead of failing the turn as 'unknown'. Typed statuses and
113
+ // the fatal-code deny-list still take precedence in classifyError().
114
+ err.providerWireError = true;
115
+ if (typeof type === 'string' && type && type !== 'error') err.providerErrorCode = type;
110
116
  return err;
111
117
  }
112
118
 
@@ -841,7 +841,8 @@ function handleCompatResponsesStreamEvent(event, state, { label, parseResponsesT
841
841
  // Copy the TYPED failure evidence a Responses `response.failed` / `error`
842
842
  // event carries (numeric HTTP status, provider error code/type) onto the
843
843
  // thrown error. Message text is never parsed, and nothing is synthesized when
844
- // the event declares no typed status.
844
+ // the event declares no typed status. The wire-event marker routes the error
845
+ // through the fatal-code deny-list / default-retry classification.
845
846
  function _applyTypedResponsesFailure(err, event) {
846
847
  const detail = event?.response?.error || event?.error || null;
847
848
  const typed = typedStatusFrom(detail, event);
@@ -849,6 +850,7 @@ function _applyTypedResponsesFailure(err, event) {
849
850
  const code = detail?.code ?? detail?.type ?? event?.code ?? null;
850
851
  if (code != null && code !== '') err.providerErrorCode = String(code);
851
852
  if (detail) err.providerError = detail;
853
+ err.providerWireError = true;
852
854
  return err;
853
855
  }
854
856
 
@@ -959,9 +959,15 @@ export async function sendViaHttpSse({
959
959
  case 'response.failed': {
960
960
  const msg = event.response?.error?.message || event.error?.message || event.message || 'response.failed';
961
961
  const err = new Error(`OpenAI OAuth HTTP fallback response.failed: ${msg}`);
962
- // Typed status only — a text-only failure stays unclassified.
962
+ // Typed status only — nothing is synthesized from text. The
963
+ // frame itself is preserved so the wire-error default-retry
964
+ // classification applies (fatal codes stay terminal).
965
+ err.responseFailed = event;
963
966
  const typed = typedStatusFrom(event.response?.error, event.error, event);
964
967
  if (typed) err.httpStatus = typed;
968
+ const detail = event.response?.error || event.error || null;
969
+ const code = detail?.code ?? detail?.type ?? null;
970
+ if (typeof code === 'string' && code) err.providerErrorCode = code;
965
971
  throw err;
966
972
  }
967
973
  case 'response.incomplete': {
@@ -987,8 +993,12 @@ export async function sendViaHttpSse({
987
993
  case 'error': {
988
994
  const msg = event.message || event.error?.message || 'unknown';
989
995
  const err = new Error(`OpenAI OAuth HTTP fallback error: ${msg}`);
996
+ // Same wire-error contract as response.failed.
997
+ err.responseFailed = event;
990
998
  const typed = typedStatusFrom(event.error, event);
991
999
  if (typed) err.httpStatus = typed;
1000
+ const code = event.error?.code ?? event.error?.type ?? event.code ?? null;
1001
+ if (typeof code === 'string' && code) err.providerErrorCode = code;
992
1002
  throw err;
993
1003
  }
994
1004
  default: