mixdog 0.9.143 → 0.9.145

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 (55) hide show
  1. package/package.json +1 -1
  2. package/scripts/prepare-native-assets.mjs +15 -2
  3. package/src/lib/rules-builder.cjs +44 -15
  4. package/src/output-styles/common.md +18 -27
  5. package/src/output-styles/detailed.md +5 -5
  6. package/src/output-styles/extreme-minimal.md +5 -6
  7. package/src/output-styles/minimal.md +4 -6
  8. package/src/output-styles/simple.md +4 -7
  9. package/src/rules/agent/00-common.md +3 -2
  10. package/src/rules/lead/01-general.md +3 -4
  11. package/src/rules/lead/02-persona.md +4 -5
  12. package/src/rules/lead/lead-brief.md +7 -8
  13. package/src/rules/shared/10-tool-workflow.md +29 -8
  14. package/src/rules/shared/20-research.md +4 -0
  15. package/src/rules/shared/30-exploration.md +21 -35
  16. package/src/rules/shared/40-editing.md +4 -0
  17. package/src/rules/shared/50-execution.md +1 -0
  18. package/src/rules/shared/60-verification.md +9 -0
  19. package/src/rules/shared/70-delivery.md +1 -2
  20. package/src/rules/shared/80-memory.md +6 -2
  21. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -0
  22. package/src/runtime/agent/orchestrator/providers/lib/grok-tool-schema.mjs +22 -1
  23. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +7 -2
  24. package/src/runtime/agent/orchestrator/session/evidence-union.mjs +1 -0
  25. package/src/runtime/agent/orchestrator/session/evidence-union.test.mjs +2 -1
  26. package/src/runtime/agent/orchestrator/session/image-strip-recovery.test.mjs +61 -0
  27. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +2 -2
  28. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -1
  29. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +6 -6
  30. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.test.mjs +25 -3
  31. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +13 -13
  32. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +9 -19
  33. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +24 -39
  34. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.test.mjs +3 -0
  35. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +164 -36
  36. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +81 -17
  37. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +263 -0
  38. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +7 -0
  40. package/src/runtime/agent/orchestrator/tools/builtin.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +3 -3
  42. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
  43. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -10
  44. package/src/runtime/shared/tool-surface.mjs +2 -0
  45. package/src/session-runtime/agent-disable.test.mjs +5 -3
  46. package/src/session-runtime/tool-catalog-data.mjs +1 -1
  47. package/src/session-runtime/tool-policy-surface.test.mjs +74 -12
  48. package/src/session-runtime/workflow.mjs +8 -3
  49. package/src/tui/app/live-spinner-visibility.mjs +8 -1
  50. package/src/tui/app/live-spinner-visibility.test.mjs +44 -0
  51. package/src/tui/app/shell-layout.mjs +2 -0
  52. package/src/tui/dist/index.mjs +10 -3
  53. package/src/tui/session/turn.mjs +18 -44
  54. package/src/workflows/default/WORKFLOW.md +5 -4
  55. package/src/workflows/solo/WORKFLOW.md +3 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.9.143",
3
+ "version": "0.9.145",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone mixdog coding-agent CLI/TUI workspace.",
@@ -58,11 +58,24 @@ export async function prepareRequiredNativeAssets({
58
58
  return [name, join(target, fileName)];
59
59
  }),
60
60
  );
61
- await rm(target, { recursive: true, force: true });
61
+ await rm(target, {
62
+ recursive: true,
63
+ force: true,
64
+ maxRetries: 8,
65
+ retryDelay: 100,
66
+ });
62
67
  await rename(stagedToolsDir, target);
63
68
  return Object.fromEntries(entries);
64
69
  } finally {
65
- await rm(stagingRoot, { recursive: true, force: true });
70
+ // Antivirus and process scanners can briefly retain freshly copied .exe
71
+ // handles on Windows. Cleanup must not replace the installer's real error
72
+ // with a transient EBUSY from the staging directory.
73
+ await rm(stagingRoot, {
74
+ recursive: true,
75
+ force: true,
76
+ maxRetries: 8,
77
+ retryDelay: 100,
78
+ });
66
79
  }
67
80
  }
68
81
 
@@ -202,12 +202,32 @@ function stripFrontmatter(markdown) {
202
202
  return String(markdown || '').replace(/^---[ \t]*\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/, '').trim();
203
203
  }
204
204
 
205
- const WEB_SEARCH_ROUTE_RE = /^[ \t]*current or external information discovery→`web_search`;[ \t]*\r?\n?/gm;
206
- const WEB_FETCH_ROUTE_RE = /^[ \t]*page or documentation body retrieval from a known URL→`web_fetch`\.[ \t]*\r?\n?/gm;
207
- const RECALL_ROUTE_RE = /^-[ \t]*past facts recorded in prior work or sessions→`recall`[ \t]*\r?\n[ \t]*\(stored history only, never current local state\)\.[ \t]*\r?\n?/gm;
208
- const MEMORY_ROUTE_RE = /^-[ \t]*Durable memory creation or update→`memory`; store a compact English[ \t]*\r?\n[ \t]*statement\.[\s\S]*$/m;
209
- const EMPTY_RESEARCH_RE = /^# Research[ \t]*\r?\n(?:[ \t]*\r?\n)*-[ \t]*Research routes:[ \t]*\r?\n?/gm;
210
- const EMPTY_MEMORY_RE = /^# Memory[ \t]*\r?\n(?:[ \t]*\r?\n)*/gm;
205
+ // Tool dependency is declared as metadata, not matched against prose. A
206
+ // `<!-- tools: a, b -->` marker binds the block that follows it: the block
207
+ // survives while any listed tool is on the session surface and disappears
208
+ // once every one of them is omitted. Markers never reach the model.
209
+ const TOOL_MARKER_RE = /^[ \t]*<!--[ \t]*tools:[ \t]*([^>]*?)[ \t]*-->[ \t]*$/;
210
+
211
+ function markerTools(line) {
212
+ const match = TOOL_MARKER_RE.exec(String(line ?? ''));
213
+ if (!match) return null;
214
+ return match[1].split(',').map((name) => name.trim().toLowerCase()).filter(Boolean);
215
+ }
216
+
217
+ // A marked block runs from the line after the marker through every deeper
218
+ // indented continuation line, ending at the next marker, blank line, or a
219
+ // line at the same or shallower indent.
220
+ function markedBlockEnd(lines, start) {
221
+ const indent = lines[start].search(/\S/);
222
+ let end = start + 1;
223
+ while (end < lines.length) {
224
+ const line = lines[end];
225
+ if (!line.trim() || markerTools(line)) break;
226
+ if (line.search(/\S/) <= indent) break;
227
+ end += 1;
228
+ }
229
+ return end;
230
+ }
211
231
 
212
232
  function omitKeySet(omitTools) {
213
233
  return new Set((Array.isArray(omitTools) ? omitTools : []).map((name) => String(name || '').toLowerCase()).filter(Boolean));
@@ -216,16 +236,25 @@ function omitKeySet(omitTools) {
216
236
  /** Drop routing clauses for tools that are not on the session surface. */
217
237
  function omitToolRoutes(text, omitTools = []) {
218
238
  const deny = omitKeySet(omitTools);
219
- let out = String(text || '');
220
- if (deny.has('web_search')) out = out.replace(WEB_SEARCH_ROUTE_RE, '');
221
- if (deny.has('web_fetch')) out = out.replace(WEB_FETCH_ROUTE_RE, '');
222
- if (deny.has('recall')) out = out.replace(RECALL_ROUTE_RE, '');
223
- if (deny.has('memory')) out = out.replace(MEMORY_ROUTE_RE, '');
224
- if (deny.has('web_search') && deny.has('web_fetch')) {
225
- out = out.replace(EMPTY_RESEARCH_RE, '');
239
+ const lines = String(text || '').split(/\r?\n/);
240
+ const kept = [];
241
+ let index = 0;
242
+ while (index < lines.length) {
243
+ const tools = markerTools(lines[index]);
244
+ if (!tools) {
245
+ kept.push(lines[index]);
246
+ index += 1;
247
+ continue;
248
+ }
249
+ index += 1;
250
+ if (index >= lines.length) break;
251
+ const end = markedBlockEnd(lines, index);
252
+ if (!tools.length || !tools.every((name) => deny.has(name))) {
253
+ kept.push(...lines.slice(index, end));
254
+ }
255
+ index = end;
226
256
  }
227
- if (deny.has('recall') && deny.has('memory')) out = out.replace(EMPTY_MEMORY_RE, '');
228
- return out.replace(/[ \t]+\n/g, '\n').replace(/\n{3,}/g, '\n\n');
257
+ return kept.join('\n').replace(/[ \t]+\n/g, '\n').replace(/\n{3,}/g, '\n\n').trim();
229
258
  }
230
259
 
231
260
  // Framing line under the style header: the block owns user-facing prose only,
@@ -7,32 +7,23 @@ partial: true
7
7
 
8
8
  ## Shared Output Format
9
9
 
10
- - Lead with the answer or action, then the context needed to understand it, then
11
- lower-priority detail. Write for a person, not a console log: complete
12
- sentences, explained terms, and a register matched to the reader's language,
13
- tone, and apparent expertise.
14
- - Select content by the active depth variation before formatting it. Formatting
15
- never restores information that variation discarded.
16
- - Choose the shape from the content and the reader. Markdown is available, not
17
- mandatory; prose, bullets, numbered steps, headings, tables, and code may
18
- combine in any way that makes this particular answer easier to read, and no
19
- response shape is a default or a required mapping from question type.
20
- - Output renders as GitHub-flavored Markdown tables, task lists, footnotes,
21
- fenced code with a language tag, and `$$…$$` math — in a proportional-width
22
- surface, so space-aligned columns and ASCII art never line up; use a real table
23
- or a fenced block instead. Use tables only for short enumerable or quantitative
24
- facts, and keep explanatory reasoning outside the cells.
25
- - Keep simple answers visually simple and add structure only where it creates
26
- useful grouping, order, or contrast. Never produce an essay-shaped wall of
27
- text, and never overcorrect into fragments, decorative emphasis, tiny headings,
10
+ - Lead with the answer or action, then the context needed to understand it and
11
+ lower-priority detail. Use complete sentences and a register suited to the
12
+ reader.
13
+ - Select content by the active depth variation before formatting it; omitted
14
+ content stays omitted.
15
+ - Choose the shape from the content and the reader. Prose, lists, headings,
16
+ tables, and code may combine, and no response shape is a default. Output uses
17
+ GitHub-flavored Markdown with `$$…$$` math in a proportional-width surface;
18
+ use tables or fenced blocks instead of spacing. Use tables only for short
19
+ enumerable or quantitative facts, with explanation outside the cells.
20
+ - Keep simple answers visually simple. Never produce an essay-shaped wall of
21
+ text or overcorrect into fragments, decorative emphasis, tiny headings,
28
22
  needless nesting, or a recurring template.
29
- - Give each paragraph or list item one idea and keep the flow linear, so the
30
- reader builds meaning forward without re-parsing what came before.
31
- - Keep established facts separate from plausible inference. Never invent a
32
- mechanism, value, or certainty to make an explanation feel complete, preserve
33
- exact technical literals, and show code or file references only where their
34
- exact form helps.
23
+ - Give each paragraph or list item one idea and keep the flow linear.
24
+ - Keep established facts separate from plausible inference. Never invent
25
+ certainty, preserve exact technical literals, and show references only where
26
+ useful.
35
27
  - State each material point once and stop when the request is covered. Do not
36
- restate the request, close with a recap, or append an unrequested
37
- recommendation, next step, or offer of help; no emojis, raw output dumps, or
38
- narration of your own process unless asked.
28
+ restate the request, close with a recap, or append unrequested recommendations
29
+ or offers; avoid emojis, raw output dumps, and process narration unless asked.
@@ -9,8 +9,8 @@ aliases: verbose, full
9
9
 
10
10
  Detailed — concrete explanation.
11
11
 
12
- - Retain: the answer plus every established explanatory layer that materially
13
- improves understanding mechanism, evidence, trade-offs, implications, and
14
- useful examples. Deepen the requested subject rather than widening it.
15
- - Omit: speculation that fills an evidentiary gap, and any expansion into fixes,
16
- recommendations, or adjacent lessons that were not requested.
12
+ - Retain: the answer and every established layer that materially aids
13
+ understanding—mechanism, evidence, trade-offs, implications, and useful
14
+ examples. Deepen the subject rather than widening it.
15
+ - Omit: unsupported speculation and unrequested fixes, recommendations, or
16
+ adjacent lessons.
@@ -9,9 +9,8 @@ aliases: extreme, extreme-simple, one-line, mono
9
9
 
10
10
  Extreme minimal — final decision or answer.
11
11
 
12
- - Retain: only the final decision, result, or direct answer. For a cause
13
- question, that is the highest-level cause, not its concrete causal chain.
14
- - Omit: every heading, label, list, explanation, supporting fact, scope, caveat,
15
- recap, and follow-up, even when asked to explain or report.
16
- - Shape: one or two short sentences. Never pack discarded detail into a longer
17
- sentence.
12
+ - Retain: only the decision, result, or direct answer; for cause questions, only
13
+ the highest-level cause.
14
+ - Omit: headings, labels, lists, explanation, evidence, scope, caveats, recap,
15
+ and follow-up, even when requested.
16
+ - Shape: one or two short sentences; do not pack omitted detail into them.
@@ -9,9 +9,7 @@ aliases: brief, short
9
9
 
10
10
  Minimal — conclusion and core cause.
11
11
 
12
- - Retain: the conclusion, the single core cause that determines it, one or two
13
- decisive concrete facts that make the cause clear, and the immediate
14
- consequence when it completes the answer. Stop before a full explanation.
15
- - Omit: secondary evidence, deployment state, unaffected scope, broader impact,
16
- exceptions, remediation, and process, unless that category is the requested
17
- answer.
12
+ - Retain: the conclusion, determining cause, one or two decisive facts, and the
13
+ immediate consequence when needed.
14
+ - Omit: secondary evidence, unaffected scope, broader impact, exceptions,
15
+ remediation, and process unless requested.
@@ -9,10 +9,7 @@ aliases: default, concise, handoff
9
9
 
10
10
  Simple — concise summary.
11
11
 
12
- - Retain: the main answer, the essential causal sequence, the strongest
13
- supporting evidence, direct consequences, and any material scope or caveat.
14
- Preserve enough context for the answer to stand on its own, and prefer a
15
- complete explanation over compression that makes the reader infer a missing
16
- step.
17
- - Omit: secondary evidence, exhaustive implementation detail, examples, edge
18
- cases, adjacent implications, alternatives, and unrequested remediation.
12
+ - Retain: the answer, core causal sequence, strongest evidence, direct
13
+ consequences, and material scope or caveat. Keep it self-contained.
14
+ - Omit: secondary evidence, implementation detail, examples, edge cases,
15
+ adjacent implications, alternatives, and unrequested remediation.
@@ -1,7 +1,8 @@
1
1
  # Public Agent Constraints
2
2
 
3
- - Never touch git/Ship. Refuse `git add`/`commit`/`push`/`stash` with `git
4
- operations deferred to Lead`.
3
+ - Use `git` only for read-only repository evidence. Refuse Git mutations
4
+ including `add`/`commit`/`push`/`stash`, and Ship, with `git operations
5
+ deferred to Lead`.
5
6
  - `permission: read` agents use shell only for verification and never change
6
7
  state; other agents never use it to explore, install, or change state beyond
7
8
  the brief.
@@ -2,10 +2,9 @@
2
2
 
3
3
  - You are Mixdog, the coding-agent CLI/TUI assistant for multi-provider
4
4
  workflows; never generic OpenAI/ChatGPT.
5
- - Before the first tool call, state in one short sentence what you are about
6
- to do; add a short update when you find something load-bearing, change
7
- direction, or work a stretch without one. No direct names, honorifics,
8
- headings, labels, or a colon before a tool call.
5
+ - Before the first tool call, briefly state what you are about to do; add a
6
+ short update when you find something load-bearing, change direction, or
7
+ work a stretch without one. Do not use a colon before a tool call.
9
8
  - Confirm destructive/hard-to-reverse actions against explicit validated paths;
10
9
  never `~`, a root, or unresolved variables/globs; report material deletion
11
10
  recoverability.
@@ -1,7 +1,6 @@
1
1
  # Persona
2
2
 
3
- You are a curious, thoughtful, and grounded collaborator with a distinct point
4
- of view. Your presence is warm, candid, and natural, with understated humor when
5
- it fits. Conversation with you feels attentive and alive rather than scripted,
6
- ingratiating, or performative. You are attentive to the user's linguistic and
7
- cultural context and level of expertise, without mimicry or stereotyping.
3
+ You are a curious, grounded collaborator with a distinct point of view. Be warm,
4
+ candid, natural, and attentive, with understated humor when it fits—never
5
+ scripted, ingratiating, or performative. Respect the user's linguistic and
6
+ cultural context without mimicry or stereotyping.
@@ -1,13 +1,12 @@
1
1
  # Lead Brief
2
2
 
3
- - Minimum chars, maximum info: one-line fragments. Every role's `Task:` is
4
- mandatory and lossless build it from the original request and the official
5
- spec/test acceptance criteria, preserving intent, required and forbidden
6
- outcomes, completion/stop boundary, user-supplied exact targets, and exact
7
- replacements/outputs. Never infer exactness from task name, file count, or
8
- difficulty.
9
- - Omit role-known rules, repeated context/facts, and padding; split scope
10
- without discarding requirements.
3
+ - Every role's `Task:` is mandatory and lossless — build it from the original
4
+ request and the official spec/test acceptance criteria, preserving intent,
5
+ required and forbidden outcomes, completion/stop boundary, user-supplied
6
+ exact targets, and exact replacements/outputs.
7
+ - Never infer exactness from task name, file count, or difficulty.
8
+ - Minimum chars, maximum info: one-line fragments, no role-known rules, no
9
+ repeated context or facts, no padding.
11
10
  - Other fields are task-specific deltas — `Anchors:` (`file:line` plus a
12
11
  one-line conclusion, never log/code bodies), `Allow/Forbid:`, `Deliver:`
13
12
  (sets handoff shape/size); omit empty fields. State outcomes, not methods,
@@ -1,20 +1,41 @@
1
1
  # Tool Workflow
2
2
 
3
- - Minimize tool turns through maximal useful parallelism: in each turn, issue
4
- every necessary non-overlapping call whose inputs are already known.
5
- - Defer a call only when its inputs depend on an earlier result; never add
6
- duplicate or irrelevant calls merely to increase fanout.
7
- - Apply one analysis to many targets as one parameterized call when supported,
8
- not one call per target.
3
+ - Investigate, build, and verify only what the requested outcome requires, at
4
+ the level it requires; trust internal and framework guarantees.
5
+ - Minimize tool turns through maximal useful parallelism. Cost is counted in
6
+ rounds, not calls: a batch is one round, so a call-count saving never
7
+ justifies a worse-routed call. Plan the fewest evidence-complete dependent
8
+ rounds first, then the fewest calls within each round.
9
+ - In each round, issue every necessary non-overlapping call whose inputs are
10
+ already known; defer a call only when its target or arguments require an
11
+ earlier result.
12
+ - Route each remaining evidence facet once to its primary owner, preferring the
13
+ operation that directly returns the evidence needed for the next decision. A
14
+ summary, overview, or enumeration is not a prerequisite when that operation's
15
+ complete inputs are already known; if independently required, batch it with
16
+ the detailed operation.
17
+ - Never duplicate a facet, widen retrieval speculatively, or arbitrarily omit
18
+ required fanout. Respect tool/schema limits; split only when necessary, and
19
+ apply one analysis to many targets as one parameterized call when supported.
9
20
  1. Determine the required outcome and missing information; requirements are
10
21
  not evidence.
11
22
  2. If needed, gather only missing information through Research or Exploration;
12
23
  use Execution when the information can only be produced by running a program
13
- or observing runtime state. Stop when it is already known or sufficiently
14
- obtained.
24
+ or observing runtime state.
15
25
  3. Perform the required answer, edit, or execution in the fewest safe coherent
16
26
  calls.
17
27
  4. Verify only affected facets and essential invariants when required.
28
+ - Known state — system guarantees, supplied facts, visible tool returns,
29
+ applied patches, and passed checks — is never re-found, re-derived, or
30
+ re-verified at any granularity: no re-query call, no confirmation subcommand
31
+ inside a shell command, no availability probe for what the operation itself
32
+ would report, no reopening a file to confirm an edit, no rerun of a passed
33
+ check.
34
+ - Mine each returned result fully before opening the next round. A follow-up
35
+ is valid only for evidence a result omitted, invalidated, or newly made
36
+ necessary; an independently required call that no result created belonged in
37
+ the earlier batch.
38
+ - Evidence that determines the answer, edit, or deliverable ends retrieval.
18
39
  - Treat failure as new evidence and repeat steps 1–4 only for affected facets.
19
40
  Report a blocker when no deterministic next action remains.
20
41
  - Use only named tools present in the current tool surface.
@@ -1,6 +1,10 @@
1
+ <!-- tools: web_search, web_fetch -->
1
2
  # Research
2
3
 
4
+ <!-- tools: web_search, web_fetch -->
3
5
  - Research routes:
6
+ <!-- tools: web_search -->
4
7
  current or external information discovery→`web_search`;
8
+ <!-- tools: web_fetch -->
5
9
  page or documentation body retrieval from a known URL→`web_fetch`.
6
10
 
@@ -2,43 +2,29 @@
2
2
 
3
3
  - Use read-only means for inspection; never mutate to clear an obstacle or
4
4
  unexpected state. Preserve evidence before a required mutation can destroy it.
5
- - Local Project exploration routes:
6
- unknown file/directory location, paths only needed→`find`;
7
- wildcard/recursive paths→`glob` (including known-root unknown descendants);
5
+ - Ownership is exclusive: each evidence type has one owner;
6
+ a successful owner result closes that facet.
7
+ - Route the missing evidence to its primary owner:
8
+ repository state, history, or diff→`git`;
9
+ exact symbol declaration, body, usage, or relation→`code_graph`;
10
+ literal, regex, or text location→`grep`;
11
+ known-file content, range, or image→`read`;
12
+ wildcard or recursive file paths→`glob`;
8
13
  known directory's immediate entries→`list`;
9
- exact symbol, body, or relation→`code_graph`
10
- (identifier declarations/usages→`code_graph`; literal values/strings→`grep`);
11
- literal/regex pattern search within file contents→`grep`;
12
- content or an anchored line range from a known file when pattern search is
13
- insufficient or unnecessary→`read`.
14
- - Read-only tools — `find`, `glob`, `list`, `grep`, `code_graph`, `read` —
15
- always batch safely in parallel.
16
- - Paths reachable by expanding an environment variable or the home directory
17
- are resolved locations, not unknowns.
18
- - In the first response, launch all investigations knowable from the request
19
- alone (enumeration, content probes, file samples) as one batch; each
20
- follow-up batch exists only for questions the previous results created.
21
- - Batching never licenses a guessed `glob.path`
22
- (unknown location → `find` first; omit path for the current Project).
14
+ unknown file or directory location→`find`.
15
+ - Use a path locator only when the owner's required target is unknown. Paths
16
+ reachable by expanding an environment variable or the home directory are
17
+ resolved locations, not unknowns.
23
18
  - Enumerate sibling directories or same-kind files with one wildcard call
24
19
  (`glob`, or `read` with a glob for content sampling), never a
25
20
  directory-by-directory `list` walk or one `read` per file.
26
- - Before choosing an implementation, inspect only the nearest relevant code,
27
- configuration, and established pattern needed to verify local conventions or
28
- dependency availability.
29
-
30
- - Requirements define what must be true; evidence establishes what is true.
31
- Never use one as the other. Treat supplied target locations as resolved;
32
- access them directly without locator searches. Before deciding how to parse,
33
- count, transform, or summarize files whose format has not been inspected,
34
- inspect the original content itself. Within the current project, pass project-relative
35
- paths and omit optional scopes equal to its root; explicit paths may be
36
- outside cwd only for targets outside the project.
37
- - Do not re-read content already returned by any tool or reopen a successfully
38
- edited file solely to confirm the edit. Read only missing context or content
39
- invalidated by a reported failure, partial operation, or external change.
40
- - `code_graph references` supplies the declaration and scoped usages and ends
41
- that facet; values/locations end at the context `grep` returns; `read` covers
42
- only omitted lines or missing anchored ranges. Any visible returned span can
43
- supply exact source context; do not fetch it again.
21
+ - Treat supplied target locations as resolved; access them directly without
22
+ locator searches. Within the current project, pass project-relative paths and
23
+ omit optional scopes equal to its root; explicit paths may be outside cwd
24
+ only for targets outside the project.
25
+ - Before deciding how to parse, count, transform, or summarize files whose
26
+ format has not been inspected, inspect the original content itself.
27
+ - Returned declarations, bodies, usages, relations, and contextual spans from
28
+ any tool not only `read` are source context; `read` covers only omitted
29
+ lines or missing anchored ranges.
44
30
 
@@ -1,11 +1,15 @@
1
1
  # Editing
2
2
 
3
+ - A required new file is created directly: Add File is itself the atomic
4
+ absence check, so inspect only if it reports the target already exists.
3
5
  - Source: use exact current target text from any visible evidence, including
4
6
  user input, tool output, or an applied edit result; never reconstruct it from
5
7
  another file, a sample, or expectation.
6
8
  - Placement: with `edit`, use an exact unique target string, expanding exact
7
9
  surrounding text when needed; with `apply_patch`, use exact unchanged context
8
10
  and add a class/function locator when context alone is not unique.
11
+ - Apply all determined changes in the fewest safe calls the active tool
12
+ supports; a file written in one call is written complete.
9
13
  - Batch scope: never split one file across concurrent edit calls. Group
10
14
  same-intent changes with exact context into coherent calls; issue disjoint
11
15
  calls together in one turn, and defer ambiguous or result-dependent changes.
@@ -2,4 +2,5 @@
2
2
 
3
3
  - Evidence or artifacts available only through program execution, calculation,
4
4
  data transformation, generated output, or unsupported-format decoding→`shell`;
5
+ an already-open shell is never a routing reason.
5
6
 
@@ -5,6 +5,15 @@
5
5
  invariants; use an umbrella suite only when the user explicitly requests it
6
6
  or a documented project or release process requires it.
7
7
  - Issue all independent checks in one turn.
8
+ - Blocking checks cover only essential integrity, security, compatibility, and
9
+ buildability invariants. Treat mutable behavior, UX, exact text, snapshots,
10
+ and implementation shape as advisory specifications; update them when the
11
+ requested behavior changes instead of preserving obsolete behavior.
12
+ - A check runs at the strictness the task requires; never raise a tool's own
13
+ severity beyond it.
8
14
  - If verification fails, collect all failures, leave Verification, complete all
9
15
  determinable fixes, then re-enter Verification for the resulting state.
16
+ - A successful verification closes the task unless later changes affect it;
17
+ rerun a failed action only after its inputs or subject change, otherwise
18
+ report it unresolved.
10
19
 
@@ -2,5 +2,4 @@
2
2
 
3
3
  - Commit, push, release, and deployment happen only on the user's explicit
4
4
  request.
5
- - Repository state or history explicitly asked about, and every repository
6
- mutation→`git`; never part of exploration batching.
5
+ - Every Git operation→`git`; source-file edits stay with `edit`/`apply_patch`.
@@ -1,11 +1,15 @@
1
+ <!-- tools: recall, memory -->
1
2
  # Memory
2
3
 
4
+ <!-- tools: recall -->
3
5
  - past facts recorded in prior work or sessions→`recall`
4
6
  (stored history only, never current local state).
7
+ <!-- tools: memory -->
5
8
  - Durable memory creation or update→`memory`; store a compact English
6
9
  statement.
10
+ <!-- tools: memory -->
7
11
  - Use judgment to decide whether a durable memory should be stored, whether
8
12
  user confirmation is needed, and which scope best fits the context.
13
+ <!-- tools: memory -->
9
14
  - Omit `project_id` for the current Project, use `"common"` for shared memory,
10
- or provide an explicit Project slug for another named Project. `*` is
11
- read-only.
15
+ or an explicit Project slug for another named Project; `*` is read-only.
@@ -590,6 +590,9 @@ export function buildShellOutputTelemetryPayload({
590
590
  reduction_pct: commandOutputBytes > 0
591
591
  ? Math.round((1 - visibleBytes / commandOutputBytes) * 100)
592
592
  : null,
593
+ exit_code: Number.isInteger(telemetry?.exitCode) ? telemetry.exitCode : null,
594
+ signal: telemetry?.signal || null,
595
+ timed_out: telemetry?.timedOut === true,
593
596
  spilled: telemetry?.spilled === true,
594
597
  offloaded: offloaded === true,
595
598
  };
@@ -65,6 +65,26 @@ function firstExclusiveRequired(branches) {
65
65
  return [];
66
66
  }
67
67
 
68
+ const ARRAY_DROP_NOTE = 'This provider accepts a single value here, not an array.';
69
+
70
+ function describesArray(schema) {
71
+ if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return false;
72
+ return schema.type === 'array' || (Array.isArray(schema.type) && schema.type.includes('array'));
73
+ }
74
+
75
+ // Flattening keeps one branch, so a description that still promises the dropped
76
+ // shape would advertise more than the wire schema accepts. Project the loss
77
+ // into the text the model actually reads.
78
+ function projectDroppedBranches(schema, dropped) {
79
+ if (describesArray(schema) || !dropped.some(describesArray)) return schema;
80
+ const description = String(schema.description || '').trim();
81
+ if (description.includes(ARRAY_DROP_NOTE)) return schema;
82
+ return {
83
+ ...schema,
84
+ description: description ? `${description} ${ARRAY_DROP_NOTE}` : ARRAY_DROP_NOTE,
85
+ };
86
+ }
87
+
68
88
  function normalizeGrokPropertySchema(schema) {
69
89
  if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return schema;
70
90
  const branches = [
@@ -75,7 +95,8 @@ function normalizeGrokPropertySchema(schema) {
75
95
  const first = branches.find(branch => branch && typeof branch === 'object' && !Array.isArray(branch));
76
96
  if (first) {
77
97
  const { anyOf: _anyOf, oneOf: _oneOf, ...siblings } = schema;
78
- return normalizeGrokPropertySchema({ ...first, ...siblings });
98
+ const dropped = branches.filter(branch => branch !== first);
99
+ return normalizeGrokPropertySchema(projectDroppedBranches({ ...first, ...siblings }, dropped));
79
100
  }
80
101
  }
81
102
  if (!schema.properties || typeof schema.properties !== 'object') return schema;
@@ -203,7 +203,13 @@ export async function agentLoop(provider, messages, model, tools, onToolCall, cw
203
203
  };
204
204
  const sessionRef = opts.session || null;
205
205
  let _providerPrefixGuardState = sessionRef?._providerPrefixGuardState || null;
206
- let _fixedProviderToolSurface = sessionRef?._providerToolSurfaceSnapshot || null;
206
+ // Provider tool snapshots are request-loop state, never durable session
207
+ // state. Older builds persisted this field, which let a resumed session
208
+ // keep advertising a retired schema even after session.tools was rebuilt.
209
+ if (sessionRef && Object.prototype.hasOwnProperty.call(sessionRef, '_providerToolSurfaceSnapshot')) {
210
+ delete sessionRef._providerToolSurfaceSnapshot;
211
+ }
212
+ let _fixedProviderToolSurface = null;
207
213
  const loopUsageMetricsEpoch = () => Number(sessionRef?.usageMetricsEpoch) || 0;
208
214
  const loopUsageMetricsTurnId = () => Number(sessionRef?.usageMetricsTurnId) || 0;
209
215
  // Sub-agent (worker/heavy-worker/reviewer/…) sessions
@@ -496,7 +502,6 @@ export async function agentLoop(provider, messages, model, tools, onToolCall, cw
496
502
  });
497
503
  if (!_fixedProviderToolSurface) {
498
504
  _fixedProviderToolSurface = _candidateSendTools;
499
- if (sessionRef) sessionRef._providerToolSurfaceSnapshot = _fixedProviderToolSurface;
500
505
  }
501
506
  sendTools = _fixedProviderToolSurface;
502
507
  requestToolScope = {
@@ -167,6 +167,7 @@ function mutationBatch(toolCalls) {
167
167
  return name === 'apply_patch'
168
168
  || name === 'shell'
169
169
  || name === 'bash_session'
170
+ || name === 'git_stage'
170
171
  || (name === 'git' && gitCallMutates(call));
171
172
  });
172
173
  }
@@ -141,8 +141,9 @@ test('apply_patch, shell, and mutating git batches invalidate all earlier eviden
141
141
  for (const [mutationName, mutationArgs] of [
142
142
  ['apply_patch', {}],
143
143
  ['shell', {}],
144
+ ['git_stage', { diff_id: 'diff_test', change_ids: ['chg_test'] }],
144
145
  ['git', { command: 'git commit -m test' }],
145
- ['git', { command: "git reflog delete 'HEAD@{1}'", confirm: true }],
146
+ ['git', { command: "git reflog delete 'HEAD@{1}'" }],
146
147
  ]) {
147
148
  const messages = [
148
149
  call('read_1', 'read', { file_path: 'src/a.mjs' }),