mixdog 0.9.169 → 0.9.170

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 (168) hide show
  1. package/README.md +64 -17
  2. package/package.json +1 -1
  3. package/src/agents/front-worker/AGENT.md +0 -2
  4. package/src/agents/heavy-worker/AGENT.md +1 -6
  5. package/src/agents/maintainer/AGENT.md +2 -0
  6. package/src/agents/worker/AGENT.md +0 -5
  7. package/src/agents/writer/AGENT.md +1 -1
  8. package/src/defaults/skills/code-tidy/SKILL.md +122 -58
  9. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +149 -0
  10. package/src/defaults/skills/code-tidy/references/dead-code.md +71 -0
  11. package/src/defaults/skills/computer-use/SKILL.md +12 -6
  12. package/src/defaults/skills/setup/SKILL.md +31 -11
  13. package/src/defaults/skills/setup/references/actions.md +67 -9
  14. package/src/defaults/skills/setup/references/surfaces.md +21 -14
  15. package/src/headless-exec.mjs +17 -1
  16. package/src/lib/rules-builder.cjs +115 -24
  17. package/src/output-styles/common.md +1 -1
  18. package/src/output-styles/detailed.md +1 -1
  19. package/src/output-styles/extreme-minimal.md +1 -1
  20. package/src/output-styles/minimal.md +1 -1
  21. package/src/output-styles/simple.md +1 -1
  22. package/src/rules/agent/40-cycle1-agent.md +1 -1
  23. package/src/rules/agent/AGENT.md +13 -0
  24. package/src/rules/lead/LEAD.md +30 -0
  25. package/src/rules/routes/common.md +4 -0
  26. package/src/rules/shared/05-parallel-calls.md +15 -0
  27. package/src/rules/shared/10-tool-workflow.md +13 -32
  28. package/src/rules/shared/15-skills.md +2 -3
  29. package/src/rules/shared/20-research.md +2 -4
  30. package/src/rules/shared/30-exploration.md +6 -24
  31. package/src/rules/shared/40-editing.md +1 -1
  32. package/src/rules/shared/45-destructive.md +9 -0
  33. package/src/rules/shared/50-execution.md +0 -8
  34. package/src/rules/shared/70-delivery.md +1 -1
  35. package/src/rules/shared/80-memory.md +3 -5
  36. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +12 -14
  37. package/src/runtime/agent/orchestrator/config.mjs +29 -6
  38. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -15
  41. package/src/runtime/agent/orchestrator/providers/anthropic-turn-reminder.mjs +96 -0
  42. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +22 -1
  43. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +14 -1
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +1 -0
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +7 -1
  46. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +53 -15
  47. package/src/runtime/agent/orchestrator/providers/cursor.mjs +11 -2
  48. package/src/runtime/agent/orchestrator/providers/gemini.mjs +4 -9
  49. package/src/runtime/agent/orchestrator/providers/lib/grok-tool-schema.mjs +33 -7
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +8 -5
  51. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +2 -1
  52. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +10 -0
  53. package/src/runtime/agent/orchestrator/session/batching-nudge.mjs +461 -0
  54. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +25 -13
  55. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +19 -25
  56. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +10 -15
  57. package/src/runtime/agent/orchestrator/session/cache/text-cache-budget.mjs +26 -0
  58. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +20 -25
  59. package/src/runtime/agent/orchestrator/session/context-utils.mjs +3 -3
  60. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +35 -13
  61. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +8 -3
  62. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +14 -0
  64. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -6
  65. package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +4 -2
  66. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +62 -0
  67. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +28 -15
  68. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +35 -1
  69. package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +43 -0
  70. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +9 -1
  71. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +34 -10
  72. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +39 -5
  73. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +28 -11
  74. package/src/runtime/agent/orchestrator/session/store.mjs +23 -32
  75. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +25 -0
  76. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +13 -13
  77. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +5 -2
  79. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +6 -2
  81. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +2 -2
  82. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/tools/tool-batch-trace.mjs +14 -8
  84. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  85. package/src/runtime/computer-bridge/core-actions.mjs +1 -0
  86. package/src/runtime/computer-bridge/error-recovery.mjs +1 -1
  87. package/src/runtime/computer-bridge/pending-continuation.mjs +25 -10
  88. package/src/runtime/computer-bridge/tool-defs.mjs +1 -1
  89. package/src/runtime/memory/lib/embedding-model-config.mjs +5 -1
  90. package/src/runtime/memory/lib/query-handlers.mjs +17 -3
  91. package/src/runtime/memory/lib/recall-format.mjs +34 -11
  92. package/src/runtime/memory/lib/session-ingest.mjs +1 -1
  93. package/src/runtime/shared/config-patch.mjs +49 -0
  94. package/src/runtime/shared/json-snapshot.mjs +32 -0
  95. package/src/runtime/shared/llm/usage-ledger.mjs +11 -0
  96. package/src/runtime/shared/pristine-execution-contract.json +4 -0
  97. package/src/runtime/shared/pristine-execution.mjs +26 -5
  98. package/src/runtime/shared/provider-accounts.mjs +9 -7
  99. package/src/runtime/shared/schema-value-error.mjs +5 -0
  100. package/src/runtime/shared/tool-surface.mjs +1 -1
  101. package/src/runtime/tidy/rules/__tests__/no-any-cast.yml +12 -0
  102. package/src/runtime/tidy/rules/__tests__/no-boolean-literal-compare.yml +24 -0
  103. package/src/runtime/tidy/rules/__tests__/no-debug-statement.yml +26 -0
  104. package/src/runtime/tidy/rules/__tests__/no-nested-ternary.yml +15 -0
  105. package/src/runtime/tidy/rules/c/no-nested-ternary.yml +10 -0
  106. package/src/runtime/tidy/rules/cpp/no-nested-ternary.yml +10 -0
  107. package/src/runtime/tidy/rules/csharp/no-nested-ternary.yml +10 -0
  108. package/src/runtime/tidy/rules/java/no-nested-ternary.yml +10 -0
  109. package/src/runtime/tidy/rules/javascript/no-boolean-literal-compare.yml +23 -0
  110. package/src/runtime/tidy/rules/javascript/no-debug-statement.yml +10 -0
  111. package/src/runtime/tidy/rules/javascript/no-nested-ternary.yml +10 -0
  112. package/src/runtime/tidy/rules/python/no-boolean-literal-compare.yml +15 -0
  113. package/src/runtime/tidy/rules/python/no-debug-statement.yml +10 -0
  114. package/src/runtime/tidy/rules/python/no-nested-ternary.yml +10 -0
  115. package/src/runtime/tidy/rules/rust/no-debug-statement.yml +7 -0
  116. package/src/runtime/tidy/rules/tsx/no-any-cast.yml +7 -0
  117. package/src/runtime/tidy/rules/tsx/no-boolean-literal-compare.yml +23 -0
  118. package/src/runtime/tidy/rules/tsx/no-debug-statement.yml +10 -0
  119. package/src/runtime/tidy/rules/tsx/no-nested-ternary.yml +10 -0
  120. package/src/runtime/tidy/rules/typescript/no-any-cast.yml +9 -0
  121. package/src/runtime/tidy/rules/typescript/no-boolean-literal-compare.yml +23 -0
  122. package/src/runtime/tidy/rules/typescript/no-debug-statement.yml +10 -0
  123. package/src/runtime/tidy/rules/typescript/no-nested-ternary.yml +10 -0
  124. package/src/session-runtime/config-lifecycle.mjs +36 -31
  125. package/src/session-runtime/context-inspection.mjs +311 -0
  126. package/src/session-runtime/context-status.mjs +34 -5
  127. package/src/session-runtime/internal-tool-executor.mjs +4 -2
  128. package/src/session-runtime/model-route-api.mjs +5 -4
  129. package/src/session-runtime/orchestration.mjs +7 -2
  130. package/src/session-runtime/provider-catalog-cache.mjs +5 -1
  131. package/src/session-runtime/provider-models.mjs +8 -8
  132. package/src/session-runtime/resource-api.mjs +22 -5
  133. package/src/session-runtime/runtime-bootstrap.mjs +2 -2
  134. package/src/session-runtime/runtime-core.mjs +8 -1
  135. package/src/session-runtime/runtime-facade.mjs +2 -2
  136. package/src/session-runtime/settings-api.mjs +11 -0
  137. package/src/session-runtime/setup-tool/executor.mjs +102 -18
  138. package/src/session-runtime/setup-tool/extended-actions.mjs +177 -0
  139. package/src/session-runtime/setup-tool/settings-contract.mjs +138 -0
  140. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -9
  141. package/src/session-runtime/setup-tool/ui-requests.mjs +66 -0
  142. package/src/session-runtime/tool-defs.mjs +2 -2
  143. package/src/session-runtime/tool-policy-refresh.mjs +4 -2
  144. package/src/session-runtime/workflow-agents-api.mjs +11 -2
  145. package/src/standalone/provider-admin.mjs +1 -1
  146. package/src/standalone/session-protocol.mjs +3 -0
  147. package/src/standalone/session-service.mjs +21 -5
  148. package/src/tui/app/app-view.jsx +4 -1
  149. package/src/tui/app/doctor.mjs +150 -159
  150. package/src/tui/app/usage-context-panels.mjs +7 -1
  151. package/src/tui/components/ContextInspector.jsx +119 -0
  152. package/src/tui/components/ContextPanel.jsx +34 -12
  153. package/src/tui/dist/index.mjs +600 -417
  154. package/src/tui/session/agent-job-feed.mjs +4 -0
  155. package/src/tui/session/notification-plan.mjs +3 -0
  156. package/src/tui/session/session-api-ext.mjs +3 -0
  157. package/src/tui/session/session-api.mjs +2 -2
  158. package/src/ui/context-inspection.mjs +44 -0
  159. package/src/ui/streaming-markdown-heal.mjs +21 -7
  160. package/src/workflows/default/WORKFLOW.md +1 -6
  161. package/src/rules/agent/00-common.md +0 -9
  162. package/src/rules/agent/00-core.md +0 -10
  163. package/src/rules/lead/01-general.md +0 -20
  164. package/src/rules/lead/02-persona.md +0 -4
  165. package/src/rules/lead/lead-brief.md +0 -11
  166. package/src/rules/shared/00-general.md +0 -11
  167. package/src/rules/shared/75-goal.md +0 -11
  168. package/src/runtime/agent/orchestrator/providers/anthropic-fable-history.mjs +0 -86
package/README.md CHANGED
@@ -1,29 +1,25 @@
1
1
  # Mixdog
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/mixdog)](https://www.npmjs.com/package/mixdog)
4
- ![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen)
4
+ ![Node.js ^22.19.0 || >=24.0.0](https://img.shields.io/badge/node-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-brightgreen)
5
5
  ![license](https://img.shields.io/badge/license-Apache--2.0-blue)
6
6
 
7
- ## The most efficient harness. The easiest way to use it.
7
+ ## More work. Less cost. Less complexity.
8
8
 
9
- Mixdog's goal is simple: make the most efficient AI coding harness the
10
- easiest to use. Get more work done with the same model and budget, without
11
- needing to become an expert in agent infrastructure.
9
+ Get more from your models and budget with an efficient AI coding
10
+ harness—and intuitive controls for managing sessions, agents, and your
11
+ entire workflow.
12
12
 
13
- That means more than an easy first run. Advanced capabilities should be easy
14
- to access, configure, and manage as your work grows—from choosing a model
15
- to coordinating agents and shaping your own workflows.
16
-
17
- - **Efficiency that turns into more work.** Cache-aware context, focused
13
+ - **More work for your budget.** Cache-aware context, focused
18
14
  tools, and compaction reduce overhead so more of your budget goes toward
19
- the task. The same-model Terminal-Bench comparisons below show comparable
15
+ the task. The published same-model Terminal-Bench comparisons below show comparable
20
16
  or better results with smaller contexts and lower costs at the same API rates.
21
- - **Advanced capabilities, within easy reach.** Guided setup and visual
22
- controls help you assign models by role, configure workflows, and work
23
- with parallel agent sessions without building your own agent stack.
24
- - **Simple to manage. Flexible when you need it.** Manage providers, agents,
25
- workflows, and extensions in one app. Customize agent definitions and
26
- operating rules, or add skills, MCP servers, hooks, and plugins as needed.
17
+ - **Easy to start. Simple to manage.** Guided setup and visual controls
18
+ help you choose models, assign agent roles, and configure workflows without
19
+ becoming an expert in agent infrastructure or building your own stack.
20
+ - **One workspace, your way.** In Desktop, organize parallel sessions with
21
+ tabs and split panes, customize agents and workflows, and keep token
22
+ statistics and supported provider limits in view.
27
23
 
28
24
  Use supported subscription accounts, API keys, or Mixdog's built-in Local Provider.
29
25
  Take the same agent beyond code into browsers, Windows apps, documents,
@@ -59,6 +55,37 @@ mixdog
59
55
  First run guides you through provider authentication, model selection, and
60
56
  workflow setup.
61
57
 
58
+ ## One workspace for your sessions and agents
59
+
60
+ Run multiple AI sessions side by side and manage your agents in Desktop.
61
+ Combine tabs and split panes, customize how you work, and keep token usage
62
+ and supported provider limits in view.
63
+
64
+ - **Multiple sessions, manageable agents.** Keep separate tasks in separate
65
+ sessions and work on them in parallel. Manage agent definitions, assign
66
+ models by role, and configure workflows in one app instead of assembling
67
+ your own agent stack.
68
+ - **Tabs and split panes—together.** Use tabs to organize sessions and split
69
+ panes to follow several side by side. Each pane can hold its own tabs, so
70
+ you do not have to choose between quick switching and a simultaneous view.
71
+ - **Make the workspace your own.** Visual controls put layout, providers,
72
+ models, agent rules, workflows, and extensions within easy reach. The model
73
+ picker shows pricing, context limits, and capability metadata to help you
74
+ choose—not just a list of model names.
75
+ - **See where your tokens go.** Usage statistics break down token totals by
76
+ provider and model, including input, output, cache hits, and cache hit rate,
77
+ with trends and cost figures. Subscription values use list prices; API
78
+ costs may be estimates. Neither is an invoice.
79
+ - **Keep remaining usage in sight.** The usage panel brings supported
80
+ providers' quota windows and reset times together, reducing trips to
81
+ separate account dashboards. Available figures depend on the provider.
82
+ - **Less window switching.** Chat, a Monaco code editor, Git, terminals, and
83
+ a file explorer share one workspace, keeping the conversation close to the
84
+ files and changes you are working on.
85
+ - **Pick up on another screen.** Continue the same live session from Desktop,
86
+ TUI, or a paired browser on your computer or phone, without starting a
87
+ separate conversation.
88
+
62
89
  ## Benchmarks
63
90
 
64
91
  Terminal-Bench 2.1 — same model, same 89 tasks, same official verifier, with
@@ -100,6 +127,26 @@ task checksums, and the usage snapshots behind every cost figure — alongside
100
127
  the harness, presets, and metric scripts that recompute each number above:
101
128
  [`benchmarks/terminal-bench-2.1/`](benchmarks/terminal-bench-2.1/).
102
129
 
130
+ ## Less overhead. More budget for the work.
131
+
132
+ Mixdog reduces the overhead of repeatedly sending context, re-explaining
133
+ requirements, and rediscovering prior work. Focused tools keep unnecessary
134
+ text out of the prompt, while provider-aware caching reuses stable input.
135
+
136
+ Compaction keeps long conversations manageable with a handoff for continuing
137
+ the task. Optional idle-time compaction reduces the history resent after
138
+ long breaks, when provider caches may have expired. Approved memory and
139
+ past-work retrieval help carry earlier decisions and requirements forward
140
+ without loading the entire conversation archive into every prompt.
141
+
142
+ You do not have to use the same high-cost model for every role. Choose models
143
+ by role and workflow to focus your budget on the work that needs them.
144
+
145
+ The benchmarks above measure single-model, single-session runs without
146
+ personal memory, sub-agent delegation, or helper-model lookups. Their cost
147
+ figures already account for cache usage; savings in ongoing work depend on
148
+ the provider, workload, and configuration.
149
+
103
150
  ## How Mixdog keeps context lean
104
151
 
105
152
  Efficiency comes from several layers working together, not just a shorter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.9.169",
3
+ "version": "0.9.170",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone mixdog coding-agent CLI/TUI workspace.",
@@ -9,5 +9,3 @@ Implement the requested visual outcome while preserving existing interaction
9
9
  behavior and project conventions. Keep changes targeted and maintain hierarchy,
10
10
  consistency, responsiveness, and accessibility when relevant. Preserve source
11
11
  formats and naming conventions for asset work.
12
-
13
- Hand off the completed visual outcome and changed files or assets.
@@ -8,10 +8,5 @@ Own high-complexity implementation through staged delivery.
8
8
  Map the affected architecture and dependencies, divide the work into coherent
9
9
  stages, and execute them in dependency order. Preserve existing behavior unless
10
10
  the brief explicitly changes it, and control blast radius across boundaries.
11
-
12
- When a required decision, dependency, or ownership boundary is unresolved,
13
- stop and report it with the relevant `file:line`.
14
-
15
- Hand off the completed outcome, material design decisions, and changed
16
- `file:line`.
11
+ Hand off material design decisions with the outcome.
17
12
 
@@ -1,4 +1,6 @@
1
1
  ---
2
+ name: Maintainer
3
+ description: Use for internal Git operations, memory upkeep, session naming, and other Mixdog background operations.
2
4
  permission: read-write
3
5
  ---
4
6
 
@@ -9,8 +9,3 @@ Implement the assigned task directly. Keep changes focused on the requested
9
9
  outcome, follow exact constraints and established project patterns, and avoid
10
10
  unrelated cleanup or redesign.
11
11
 
12
- When blocked, stop at the first concrete boundary and report the blocker with
13
- the relevant `file:line`.
14
-
15
- Hand off the completed outcome and changed `file:line`.
16
-
@@ -9,6 +9,6 @@ Preserve meaning, facts, terminology, formatting, and intended audience while
9
9
  making the writing natural and consistent with the document's tone. Translate
10
10
  idiomatically rather than word-for-word.
11
11
 
12
- Do not invent facts, add commentary, or delegate the work. Return final copy
12
+ Do not invent facts or add commentary. Return final copy
13
13
  only unless the brief explicitly assigns file edits; then hand off changed
14
14
  paths.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: code-tidy
3
- description: Format, lint, and structurally tidy a codebase with the tidy tool.
4
- when_to_use: 'Format, lint, apply structural rules, or tidy a codebase; not ordinary feature work or adding formatter configs.'
3
+ description: Format, lint, apply structural rules, and clean up recent changes with the tidy tool.
4
+ when_to_use: 'Format, lint, tidy, simplify, deslop, or clean up a codebase or recent changes: remove AI slop, dead code, and needless complexity without changing behavior; not feature work, bug hunting, or adding formatter configs.'
5
5
  metadata:
6
6
  requires: tidy
7
7
  dependencies:
@@ -12,58 +12,92 @@ dependencies:
12
12
 
13
13
  # Code tidy (tidy tool)
14
14
 
15
- Use `tidy` to format, lint, apply structural rules, and then only if still
16
- needed do agent-level structural cleanup. The schema owns action fields;
17
- this file owns order, approvals, and what must not change.
15
+ Three layers, cheapest and safest first: the project's formatters and linters
16
+ through `tidy`, then the structural rule packs, then agent-level cleanup of
17
+ the code in scope. Every layer preserves behavior and public API; this is a
18
+ cleanup pass, not a bug hunt. The schema owns action fields; this file owns
19
+ scope, order, approvals, and what must not change.
18
20
 
19
21
  ## 1. Which job
20
- **Hard rule — tidy owns format/lint/structure, not feature work**: a request
21
- to clean, format, lint, apply structural rules, or tidy a tree. New behavior,
22
- refactors that change public API, and adding formatter configs are not this
23
- skill. → manual
24
- **Hard rule — never invent a formatter config**: if the project already has
25
- Biome, Prettier, clang-format, rustfmt, gofmt, or equivalent config/tools,
26
- tidy uses them. Do not add or rewrite `biome.json`, `.prettierrc`,
27
- `.clang-format`, or similar unless the user asks. → manual
22
+ **Hard rule — tidy owns format/lint/structure/cleanup, not feature work.**
23
+ New behavior, refactors that change a public API, and adding formatter configs
24
+ are not this skill. A correctness bug found while cleaning is reported under
25
+ "Bugs found", never folded into a cleanup edit. → manual
26
+ **Hard rule — never invent a formatter config**: a project that already has
27
+ Biome, Prettier, clang-format, rustfmt, gofmt, or equivalent keeps it. Do not
28
+ add or rewrite `biome.json`, `.prettierrc`, `.clang-format`, or similar unless
29
+ the user asks. → manual
30
+ **Mode**: `apply` unless the user asks to check, review, or "just report" —
31
+ then every layer stays dry-run and the report lists what would change.
32
+ **Focus**: an explicit focus ("only dead code", "efficiency") restricts the
33
+ agent layer to that lens; the deterministic layers still run.
28
34
 
29
- ## 2. Call order
30
- 1. `tidy action:'scan'` first. Result: languages and engines (used / missing /
31
- `installHint`). Scan does not download and does not return `needsApproval`.
32
- 2. **Hard rule downloads happen automatically under the default `auto`
33
- policy; only when the user set `tidy.downloads` to `ask` does a result
34
- carry `needsApproval` then ask once**, list engines and bytes, and
35
- re-call that action with `approveDownloads:true`. Never download without
36
- that when policy is `ask`. manual
37
- 3. **Hard rule never install toolchain engines**: rustfmt, gofmt, dart,
38
- swift, zig, mix, dotnet. Report `installHint`; do not brew/choco/npm/cargo-
39
- install them. Managed engines (including PSScriptAnalyzer) download only
40
- through tidy (`auto` policy, `approveDownloads`, or `action:'install'`). → manual
41
- 4. Deterministic engines, then structural rules, then agent cleanup. Skip a
42
- layer that the scan shows has nothing to do.
35
+ ## 2. Scope
36
+ Default scope is the recent change, not the tree:
37
+ 1. `git status --short` (untracked files) plus `git diff --name-only HEAD`
38
+ (staged and unstaged). Empty the merge-base diff against the default
39
+ branch. Still empty the files the user named or edited this session.
40
+ Nothing at all say there is nothing to tidy and stop.
41
+ 2. Drop deleted, binary, generated, vendored files and lockfiles.
42
+ 3. Widen only when the user asks ("the whole tree", a directory, a branch).
43
+ 4. Pass the list as `paths` on every `tidy` call so engines, rules, and the
44
+ agent layer see the same files. Result: the report names the scope.
43
45
 
44
- ## 3. Deterministic first
45
- Each mutating step is dry-run then apply. `fix` is dry-run unless
46
- `apply:true`. After every apply, run the project's tests/typecheck (detect
47
- from `package.json` / `Cargo.toml` / `pyproject`) and **stop on failure**.
46
+ ## 3. Deterministic layers
47
+ 1. `tidy action:'scan'` first: languages and engines (used / missing /
48
+ `installHint`). Scan never downloads and never returns `needsApproval`.
49
+ 2. **Hard rule downloads are automatic under the default `auto` policy;
50
+ only when the user set `tidy.downloads` to `ask` does a result carry
51
+ `needsApproval` — then ask once**, list engines and bytes, and re-call
52
+ that action with `approveDownloads:true`. → manual
53
+ 3. **Hard rule — never install toolchain engines** (rustfmt, gofmt, dart,
54
+ swift, zig, mix, dotnet): report `installHint`. Managed engines download
55
+ only through tidy (`auto`, `approveDownloads`, or `action:'install'`). → manual
56
+ 4. Engines, then structural rules, each dry-run then apply, with the
57
+ project's tests/typecheck after every apply and a stop on failure:
58
+ - engine `check` with `structural:false`;
59
+ - engine `fix` with `structural:false`, then the same call with `apply:true`;
60
+ - `tidy action:'fix' structural:true`, then `apply:true`.
61
+ `structural` defaults to true on check/fix, so engine steps must pass
62
+ `structural:false` or structural fixes land during the engine write. A
63
+ dry-run with no changes skips that apply. Rules without a fix
64
+ (`no-empty-catch`, `no-nested-ternary`, `no-any-cast`,
65
+ `no-boolean-literal-compare`, `no-debug-statement`, `todo-marker`) are
66
+ diagnostics for the agent layer, not changes. Skip a layer the scan shows
67
+ has nothing to do.
48
68
 
49
- 1. Engine `check` with `structural:false` (report-only).
50
- 2. Engine `fix` with `structural:false` (omit `apply` or `apply:false`) the
51
- same call with `apply:true`.
52
- 3. Structural rules: `tidy action:'fix' structural:true` (dry-run) →
53
- `apply:true`.
54
- 4. Agent-level structural cleanup only after those, still one concern per
55
- change set, still dry-run (read/plan) before edits.
69
+ ## 4. Agent-level cleanup
70
+ Read `references/agent-cleanup.md` first: it owns the deletion ladder, the
71
+ lens checklists, the slop categories, the risk tiers, and the report
72
+ template. This section owns the order.
56
73
 
57
- **Default dry-run before every apply.** A dry-run that reports no changes
58
- skips apply for that layer. Engine steps must pass `structural:false`:
59
- `structural` defaults to true on check/fix, so omitting it would apply
60
- structural fixes during the engine write.
74
+ 1. **Lock behavior.** Run the project's tests and typecheck before any edit.
75
+ Green, or pre-existing failures listed as excluded, is the baseline; a
76
+ broken runner stops the layer with a report. A file with no test covering
77
+ the behavior you will touch gets either the narrowest regression test that
78
+ pins its observable output, or only SAFE-tier changes — say which. Prose
79
+ files (skills, prompts, docs) have no behavior to pin.
80
+ 2. **Ladder, then lenses.** Run the deletion ladder on every changed unit;
81
+ only survivors go through the four lenses (reuse, quality, efficiency,
82
+ altitude). Every finding carries `file:line` evidence, a cost, a
83
+ confidence, and a risk tier; findings without evidence are dropped, and
84
+ `git blame` precedes any removal (unexplained intent is `confidence: low`).
85
+ When this session can delegate to parallel workers, run one lens per
86
+ worker with the complete diff and the repo path — workers report findings,
87
+ never edit. Otherwise run the lenses yourself in sequence and say so in
88
+ the report. Result: one merged, deduplicated finding list.
89
+ 3. **Apply by tier.** SAFE as one batch with tests after it; CAREFUL one
90
+ file at a time with tests after each file, reverting the file on failure;
91
+ RISKY reported, never auto-applied. Within a tier: comments → dead code →
92
+ defensive code → duplication → complexity → abstraction → performance.
93
+ Structural items from the table below are CAREFUL; dead code follows
94
+ `references/dead-code.md`.
95
+ 4. **Stop rules.** Three failed attempts on one file → stop and escalate with
96
+ what was tried. A deeper fix larger than the cleanup → report it as its own
97
+ task. Principles cannot pick between two rewrites → apply neither, record
98
+ both.
61
99
 
62
- ## 4. Agent-level structural cleanup
63
- Behavior and public API stay unchanged. Tests are the gate. One concern per
64
- change set. Report what changed and what was left, with reasons.
65
-
66
- | Threshold | Action |
100
+ | Structural threshold | Action |
67
101
  |---|---|
68
102
  | File > 800 lines | Split by responsibility |
69
103
  | Function > 50 lines, or nesting > 3 | Extract |
@@ -73,19 +107,49 @@ change set. Report what changed and what was left, with reasons.
73
107
  | Magic numbers | Name them |
74
108
  | Dead code / unused exports | Remove |
75
109
 
76
- Do not "improve" names, control flow, or types beyond this list.
110
+ Do not "improve" names, control flow, or types beyond the ladder, the lenses,
111
+ and this table.
112
+
113
+ ## 5. Keep — never remove or rename
114
+ - Validation and error handling at a trust boundary (user input, external
115
+ API, file, network) unless an adversarial test proves the guard redundant.
116
+ - Export names, API routes, CLI flags, DB columns, config keys, event names,
117
+ wire strings — contracts; a rename is RISKY even when the name is bad.
118
+ - Anything on the never-dead list in `references/dead-code.md`.
119
+ - An empty catch or ignored error that may be intentional — flag it.
120
+ - Complexity a comment or `git blame` explains: compat shims, staged
121
+ migrations, isolation around vendored code.
122
+ - The project's own idioms: `AGENTS.md`/`CLAUDE.md`/lint config beat a
123
+ generic idiom; clarity beats fewer lines; nested ternaries are flattened,
124
+ never introduced.
77
125
 
78
- ## 5. Failure handling
126
+ ## 6. Pitfalls
79
127
  - Missing toolchain engine → `installHint` only; continue other engines.
80
128
  - User declines downloads → skip those engines; say so.
81
- - Tests/typecheck fail after apply → stop; do not apply the next layer.
82
- - Formatter config missing and the user did not ask to add one → use tidy
83
- defaults / detected engines; do not write a config file.
129
+ - Tests/typecheck fail after apply → revert that change; do not start the
130
+ next layer until the baseline is green again.
131
+ - Formatter config missing and the user did not ask to add one → tidy
132
+ defaults / detected engines; never write a config file.
84
133
  - Structural engine unavailable (missing or outdated mixdog-graph) → `check` /
85
- `fix` fail with a rebuild remedy. `scan` still succeeds and names the binary
86
- in `notes`. Retry with `structural:false` for formatters/linters only. Do
87
- not treat missing structural matches as clean.
134
+ `fix` fail with a rebuild remedy; `scan` still succeeds and names the binary
135
+ in `notes`. Retry with `structural:false` for formatters/linters only; never
136
+ treat missing structural matches as clean.
137
+ - Diff over ~2000 changed lines → split the agent layer per directory or
138
+ commit before running the lenses; one huge pass truncates.
139
+ - A dead-code scanner report is a candidate list, not proof → verify per
140
+ `references/dead-code.md` before deleting.
141
+
142
+ ## 7. Report
143
+ Use the template in `references/agent-cleanup.md`. It must name the scope and
144
+ mode, engines used/missing, files changed, diagnostics remaining, structural
145
+ matches applied/skipped, agent findings applied by lens and tier, **Noticed
146
+ but not applied** with the reason, deferred debt, bugs found, and the test,
147
+ typecheck, and lint results. An inline (non-delegated) lens run is stated as
148
+ such.
88
149
 
89
- ## 6. Report
90
- Always report: languages, engines used/missing, files changed, diagnostics
91
- remaining, structural matches applied/skipped, test results.
150
+ ## 8. References
151
+ - `references/agent-cleanup.md` before section 4: ladder, lenses, slop
152
+ categories with keep/fix rules, test-suite slop, risk tiers, report
153
+ template.
154
+ - `references/dead-code.md` — before removing any unused symbol, file, or
155
+ dependency: candidate sources, verification, never-dead list, order.
@@ -0,0 +1,149 @@
1
+ # Agent-level cleanup
2
+
3
+ Read this before the agent-level layer of `code-tidy`. It owns the deletion
4
+ ladder, the lens checklists, what counts as slop, the risk tiers, and the
5
+ report shape. The skill body owns scope, order, approvals, and the list of
6
+ things that are never removed or renamed.
7
+
8
+ ## Deletion ladder
9
+
10
+ Run the ladder on every changed unit (function, class, module, config knob)
11
+ before looking for smells. Only code that lands on the last rung goes on to
12
+ the lenses.
13
+
14
+ | Rung | Question | Typical win |
15
+ |---|---|---|
16
+ | Delete | Is the behavior needed at all? Speculative generality, a flag nobody sets, a branch no caller reaches | whole unit gone, tests that only guarded it gone with it |
17
+ | Reuse | Does a helper in this repo already do it? (`code_graph symbol_search`, `grep` for the pattern's distinctive call) | reimplementation replaced by a call |
18
+ | Platform | Does the stdlib, runtime, or an already-installed dependency do it? (`URLSearchParams`, `path.relative`, `Array.prototype.at`, `pathlib`, an imported util) | hand-rolled parser/formatter/debounce replaced |
19
+ | Simplify | It must exist here; make it smaller | proceeds to the lenses |
20
+
21
+ A unit replaced by one platform call is a larger and safer win than any
22
+ in-place cleanup; take it before analysing the unit's smells.
23
+
24
+ ## Lenses
25
+
26
+ Each lens searches the codebase for evidence; a finding without a
27
+ `file:line` pointer is dropped. Run every lens unless the user named a focus.
28
+
29
+ **Reuse** — new code that duplicates an existing utility, constant, type
30
+ guard, or pattern: hand-rolled string/path manipulation, custom env checks,
31
+ ad-hoc validation, re-implemented parsing. Name the existing thing and where it
32
+ lives. Before flagging a new dependency import, check `package.json` /
33
+ `pyproject.toml` for a library already installed that covers it.
34
+
35
+ **Quality** — redundant state (values derivable from existing state, caches
36
+ that need not exist); parameter sprawl (a parameter bolted on where the
37
+ function should be restructured); copy-paste-with-variation; leaky
38
+ abstractions; stringly-typed code where a constant, enum, or registry exists;
39
+ deep nesting (3+ levels, ternary chains) that guard clauses or a lookup table
40
+ flatten; slop patterns from the table below.
41
+
42
+ **Efficiency** — redundant computation, repeated file reads, duplicate API
43
+ calls, N+1 access; independent operations run sequentially; heavy work on
44
+ startup or per-request paths; existence pre-checks instead of doing the
45
+ operation and handling the error; unbounded growth, missing cleanup,
46
+ listener/handle leaks; closures capturing a whole scope for long-lived
47
+ objects; whole-file reads where a slice would do; silent failures (empty
48
+ catch, ignored error return, `.catch(() => {})`). Only apply an efficiency
49
+ change whose behavioral equivalence is obvious; never restructure an
50
+ algorithm with subtle correctness implications without a test that pins it.
51
+
52
+ **Altitude** — a fix applied too shallowly: a caller-specific branch added to
53
+ a generic path (`if (caller === X)`, a magic-value escape hatch); a symptom
54
+ patched at one call site while siblings keep the same flaw; a workaround
55
+ stacked on a workaround; a wrapper added to avoid touching the thing that
56
+ needs changing; a flag introduced to route around a broken default. Name
57
+ the mechanism the change is dodging and the deeper fix. When the deeper fix
58
+ is larger than the cleanup, report it as its own task instead of doing it
59
+ here.
60
+
61
+ ## Slop categories
62
+
63
+ | Category | Flag | Keep | Fix |
64
+ |---|---|---|---|
65
+ | Obvious comments | restating the code, section dividers, commented-out code, vague TODOs, narration of the change or of the caller | WHY comments (business rule, workaround, invariant), ticket links, regex/algorithm notes, BDD markers | delete |
66
+ | Over-defensive code | null checks on guaranteed values, try/catch around code that cannot throw, type checks on statically typed params, defaults for required params, validation duplicated inside a boundary, broad catch-all | I/O error handling, nullable DB fields, a top-level catch-all that logs and rethrows | remove only when a test proves the guard redundant; narrow broad catches to the expected error |
67
+ | Excessive complexity | nesting > 3, nested ternaries, 4+ predicates in one condition, > 5 positional params, functions > 50 lines doing several things, clever one-liners | a hot path that intentionally uses a dense idiom | guard clauses, early returns, explicit if/else, an options object, extract by responsibility |
68
+ | Needless abstraction | pass-through wrappers, single-use helpers, speculative indirection, one-implementer interfaces that add no seam, factories that only call a constructor | abstractions that give a real seam (tests, multiple implementers, framework boundary) | inline |
69
+ | Boundary violations | wrong-layer imports, business logic in a handler, one module reading another's private state, side effects in a pure-named function | short-circuits already established as a pattern here | move to the owning layer; flag when unsure |
70
+ | Dead code | unused imports/locals/private functions, unreachable branches, stale feature flags, debug leftovers, code removed but still referenced | whatever the dead-code procedure lists as never dead | remove through the dead-code procedure linked from the skill |
71
+ | Duplication | copy-pasted branches with trivial differences, two helpers doing the same thing, repeated literal sequences | incidental similarity between things that serve different intents and may diverge | consolidate only when intents match |
72
+ | Type escapes | `as any`, `@ts-ignore`, `# type: ignore` without reason, `object`/`Any` annotations where a union or Protocol fits | escapes with a comment naming the upstream typing bug | narrow with a guard, a precise type, or `unknown` plus a check |
73
+ | Oversized modules | files well past the project's norm (the skill's 800-line threshold), mixing responsibilities | a self-contained single-responsibility script | split by what each part does; never `utils`/`helpers`/`common`/`part2` dump files |
74
+
75
+ ## Test-suite slop
76
+
77
+ Only when tests are in scope. Tests accumulate through repeated
78
+ agent corrections the same way production code does:
79
+
80
+ - **Dominated tests** — several tests reach the same branch and the same
81
+ result; one asserts the observable output, the others only check
82
+ construction, type, or non-emptiness. Keep the strongest, delete the rest
83
+ and the fixtures that served only them.
84
+ - **Verification theater** — checksums, receipts, validators, or
85
+ recomputation where producer and verifier share the same information and
86
+ failure domain. They cannot fail independently; delete.
87
+ - **Closed justification loop** — a fallback exists because a test exercises
88
+ it and the test exists because the fallback was added. Neither is evidence
89
+ for the other; delete the pair. A test of a distinct externally observable
90
+ rejection, error, or compatibility behavior is *not* a loop — it is that
91
+ behavior's clearest specification, keep it.
92
+ - Reducing tests never justifies changing the production behavior they
93
+ exercised; that needs its own evidence (a current requirement, a real
94
+ caller, a spec).
95
+
96
+ ## Finding record and risk tiers
97
+
98
+ Record every finding as:
99
+
100
+ ```text
101
+ file:line → problem → cost (what it duplicates, wastes, or makes harder) → fix | confidence: high/medium/low | risk: SAFE/CAREFUL/RISKY
102
+ ```
103
+
104
+ A finding that cannot name its cost is a nit; drop it. Confidence is `low`
105
+ when `git blame` and surrounding comments do not explain why the code exists.
106
+
107
+ | Tier | Meaning | Examples | Handling |
108
+ |---|---|---|---|
109
+ | SAFE | provably no behavior change | unused import, commented-out code, pass-through wrapper, redundant type assertion, obvious comment, history comment | apply, run tests once after the batch |
110
+ | CAREFUL | same semantics, structure changes | rename a local, flatten a ternary, guard clause, extract a helper, consolidate duplicates, name a magic number | apply one file at a time, tests after each file, revert the file on failure |
111
+ | RISKY | may change behavior or a contract | public API or export rename, route/DB column/config key rename, error-handling change, concurrency change, N+1 restructuring, altitude fix in shared infrastructure | report only, with the test coverage status; never auto-apply |
112
+
113
+ Conflict resolution when lenses disagree: correctness > the user's stated
114
+ focus > readability and reuse > micro-performance. When two defensible
115
+ rewrites of the same region remain, apply the one that touches less code and
116
+ record the alternative; when the principles cannot separate them, apply
117
+ neither and record both.
118
+
119
+ ## Small tidyings (CAREFUL tier)
120
+
121
+ Structure-only moves that read better and never change behavior: guard clause
122
+ instead of nested `if`; normalize two variants of the same pattern to one
123
+ form; put coupled functions next to each other; declare a variable where it
124
+ is initialized; name a sub-expression or a literal after its intent; blank
125
+ line between chunks that do different things; extract a helper with an
126
+ obvious purpose; merge over-fragmented pieces back into one readable block
127
+ before re-splitting; delete comments that say what the code says. One
128
+ tidying per change set.
129
+
130
+ ## Report shape
131
+
132
+ ```text
133
+ Scope: <diff vs HEAD | paths | branch> · Mode: report|apply
134
+ Baseline: tests <green|N pre-existing failures excluded> · typecheck <ok|…>
135
+ Deterministic: engines used/missing · files changed · diagnostics remaining · structural matches applied/skipped
136
+
137
+ Applied
138
+ path/file.ts
139
+ ✓ [Quality/SAFE] removed comment narrating the change (L31)
140
+ ✓ [Reuse/CAREFUL] replaced manual join with `joinPath` from src/shared/path.mjs (L53)
141
+
142
+ Noticed but not applied
143
+ ⚠ [Altitude/RISKY] special case for caller X in src/core/run.mjs:88 — deeper fix: default in run() · coverage: none
144
+ ⚠ [Quality] two equal rewrites of parseInput (L70-74); principles could not decide
145
+
146
+ Deferred debt: <`debt:` markers added, with their ceiling and trigger>
147
+ Bugs found (not fixed here): <correctness issues surfaced while cleaning>
148
+ Verification: tests <result> · typecheck <result> · lint <result>
149
+ ```
@@ -0,0 +1,71 @@
1
+ # Dead code removal
2
+
3
+ Read this before removing any unused symbol, file, or dependency. A tool
4
+ report is a candidate list, never proof: exports reached through dynamic
5
+ import, reflection, string lookup, templates, or configuration look unused
6
+ to every scanner.
7
+
8
+ ## Candidates
9
+
10
+ Collect from what already runs in the project; never install a scanner and
11
+ never route one through `tidy` (they are not tidy engines):
12
+
13
+ | Source | Gives | Notes |
14
+ |---|---|---|
15
+ | `tidy check` diagnostics | unused imports/variables from Biome, ruff (`F401`, `F841`), ESLint `no-unused-vars` | exact file:line, safest tier |
16
+ | `tsc --noEmit --noUnusedLocals --noUnusedParameters` | unused locals, imports, parameters, private members | TypeScript projects; run through the project's own `tsc` |
17
+ | `knip` (`node_modules/.bin/knip`) | unused files, exports, types, dependencies | JS/TS; only when the project already depends on it |
18
+ | `vulture` (in the project's venv) | unused functions, classes, imports with confidence | Python; only when present |
19
+ | `deadcode` (Go, `golang.org/x/tools`) / `cargo machete` | unreachable functions / unused crates | only when on PATH |
20
+ | `code_graph mode:symbols` per changed file | private helpers with no callers (`callers`) | universal, no install |
21
+
22
+ ## Verify every candidate
23
+
24
+ 1. `code_graph mode:references symbols:[name]` — zero references outside the
25
+ declaration is the first gate, not the last.
26
+ 2. `grep` the bare name across the whole repository, including tests,
27
+ configs, templates, docs, JSON/YAML, and string literals: `'name'`,
28
+ `"name"`, `.name(`, `name:`. A hit in a string or template means the
29
+ symbol is reached dynamically; keep it.
30
+ 3. Apply the never-dead list below.
31
+ 4. Record the candidate as `file:line → symbol → kind → action → evidence`.
32
+
33
+ ## Never dead
34
+
35
+ - Entry points: `main`, `index`/barrel files, CLI commands, `bin` scripts,
36
+ `package.json` `exports`/`main`/`bin` targets, framework-discovered files
37
+ (routes, migrations, plugins, fixtures).
38
+ - Public API of a library package: any export from the package entry.
39
+ - Symbols referenced by tests — tests are consumers; delete the test first
40
+ only when the behavior itself is being removed on separate evidence.
41
+ - `@public`/`@api` annotated symbols, registry or factory tables
42
+ (`create…Tool`, `register…`), event names, wire strings, config keys.
43
+ - Feature-flag rollback paths that a comment or docs name as intentional;
44
+ confirm with the user before removing.
45
+ - A required-by-signature unused parameter: rename to `_name`, never remove.
46
+
47
+ ## Remove in order
48
+
49
+ 1. Unused imports and locals (SAFE).
50
+ 2. Unused private functions, methods, constants (SAFE once verified).
51
+ 3. Unused exports (CAREFUL) — after the never-dead check.
52
+ 4. Orphan files (CAREFUL) — a file nobody imports; delete whole, then grep
53
+ for its path in configs and docs.
54
+ 5. Dependencies in `package.json` / `pyproject.toml` (CAREFUL) — last, after
55
+ the code that used them is gone; keep the lockfile consistent through the
56
+ project's own package manager.
57
+
58
+ Group edits by file so one batch never touches a file another batch edits.
59
+ After each batch run the project's typecheck and tests; on failure revert
60
+ that batch's files (`git checkout -- <files>` or targeted edits) and report,
61
+ do not patch forward.
62
+
63
+ ## Report
64
+
65
+ ```text
66
+ | # | File:line | Symbol | Kind | Action | Evidence |
67
+ |---|---|---|---|---|---|
68
+ | 1 | src/foo.ts:42 | unusedFunc | function | removed | 0 refs, no grep hits |
69
+ | 2 | src/baz.ts:7 | ctx | parameter | prefixed _ | required by signature |
70
+ | 3 | src/api.ts:10 | legacyRoute | export | kept | string lookup in routes.json |
71
+ ```