@uniqbit/mate-core 0.18.5 → 1.0.0-canary.0

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 (209) hide show
  1. package/claude-plugin/hooks/companion-instructions.mjs +9 -0
  2. package/claude-plugin/hooks/hooks.json +12 -2
  3. package/package.json +10 -2
  4. package/src/brand/art.generated.ts +69 -0
  5. package/src/brand/index.ts +12 -0
  6. package/src/brand/palette.ts +19 -0
  7. package/src/brand/svg.generated.ts +8 -0
  8. package/src/brand/terminal.ts +83 -0
  9. package/src/brand/types.ts +33 -0
  10. package/src/cli/commands/artifact/artifact.ts +8 -0
  11. package/src/cli/commands/artifact/delivery/archive.ts +117 -0
  12. package/src/cli/commands/artifact/delivery/branch-flags.ts +55 -0
  13. package/src/cli/commands/artifact/delivery/environment.ts +104 -0
  14. package/src/cli/commands/artifact/delivery/link.ts +154 -0
  15. package/src/cli/commands/artifact/delivery/output.ts +58 -0
  16. package/src/cli/commands/artifact/finish/command.ts +33 -3
  17. package/src/cli/commands/artifact/finish/engine.ts +47 -3
  18. package/src/cli/commands/artifact/finish/finisher.ts +10 -0
  19. package/src/cli/commands/artifact/finish/openspec.ts +177 -138
  20. package/src/cli/commands/artifact/finish/secret-scan.ts +43 -0
  21. package/src/cli/commands/artifact/pending/command.ts +31 -3
  22. package/src/cli/commands/artifact/pending/discovery.ts +21 -57
  23. package/src/cli/commands/cap/graphify.ts +52 -3
  24. package/src/cli/commands/cap/index-cmd.ts +8 -1
  25. package/src/cli/commands/cap/openspec.ts +13 -25
  26. package/src/cli/commands/companion/open.ts +56 -39
  27. package/src/cli/commands/companion/update.ts +75 -42
  28. package/src/cli/commands/doctor.ts +176 -3
  29. package/src/cli/commands/plugin/install.ts +9 -4
  30. package/src/cli/commands/plugin/plugin.ts +3 -2
  31. package/src/cli/commands/report/adapter.ts +11 -2
  32. package/src/cli/commands/report/contract.ts +21 -0
  33. package/src/cli/commands/report/highlight.ts +34 -4
  34. package/src/cli/commands/report/markdown.ts +110 -0
  35. package/src/cli/commands/report/palette.ts +118 -0
  36. package/src/cli/commands/report/renderer.ts +456 -153
  37. package/src/cli/commands/report/types.ts +16 -0
  38. package/src/cli/commands/setup.ts +7 -15
  39. package/src/cli/commands/studio/client-asset.ts +16 -0
  40. package/src/cli/commands/studio/openspec-cli.ts +10 -58
  41. package/src/cli/commands/studio/routes.ts +2 -0
  42. package/src/cli/commands/studio/selection.ts +19 -1
  43. package/src/cli/commands/studio/server.ts +42 -1
  44. package/src/cli/commands/studio/views/client.ts +6 -616
  45. package/src/cli/commands/studio/views/dashboard/changes.tsx +5 -10
  46. package/src/cli/commands/studio/views/document.tsx +137 -69
  47. package/src/cli/commands/studio/views/markdown.tsx +250 -0
  48. package/src/cli/commands/studio/views/palette.ts +134 -0
  49. package/src/cli/commands/studio/views/reports/index.tsx +2 -7
  50. package/src/cli/commands/studio/views/skills/index.tsx +43 -62
  51. package/src/cli/commands/studio/views/specs/index.tsx +7 -15
  52. package/src/cli/commands/studio/views/studio-client/actions.ts +51 -0
  53. package/src/cli/commands/studio/views/studio-client/companion.ts +13 -0
  54. package/src/cli/commands/studio/views/studio-client/index.ts +32 -0
  55. package/src/cli/commands/studio/views/studio-client/keys.ts +3 -0
  56. package/src/cli/commands/studio/views/studio-client/main.ts +3 -0
  57. package/src/cli/commands/studio/views/studio-client/page.ts +146 -0
  58. package/src/cli/commands/studio/views/studio-client/panels.ts +57 -0
  59. package/src/cli/commands/studio/views/studio-client/reports.ts +122 -0
  60. package/src/cli/commands/studio/views/studio-client/theme.ts +63 -0
  61. package/src/cli/commands/studio/views/studio-client/vault-editor.ts +166 -0
  62. package/src/cli/commands/studio/views/studio-client/vault-pane.ts +202 -0
  63. package/src/cli/commands/studio/views/studio-client/vault-tree.ts +258 -0
  64. package/src/cli/commands/studio/views/studio-client.generated.ts +2 -0
  65. package/src/cli/commands/studio/views/styles.ts +217 -206
  66. package/src/cli/commands/studio/views/vault/state.ts +3 -5
  67. package/src/cli/commands/studio/views/workflow/delivery-path.tsx +370 -0
  68. package/src/cli/commands/studio/views/workflow/graph.ts +220 -0
  69. package/src/cli/commands/studio/views/workflow/index.tsx +2 -3
  70. package/src/cli/commands/studio/views/workflow/steps.ts +228 -287
  71. package/src/cli/commands/wrap.ts +5 -13
  72. package/src/cli/main.ts +4 -1
  73. package/src/cli/parse-flags.ts +25 -7
  74. package/src/cli/setup-selector.tsx +38 -162
  75. package/src/cli/usage.ts +4 -0
  76. package/src/hooks/companion-instructions.ts +190 -0
  77. package/src/hooks/hook-io.ts +63 -0
  78. package/src/hooks/session-banner.ts +21 -29
  79. package/src/hooks/session-guidance.ts +9 -17
  80. package/src/hooks/session-prepare.ts +115 -28
  81. package/src/hooks/validate-artifact-path.ts +82 -24
  82. package/src/index.ts +4 -0
  83. package/src/lib/change-layout.ts +154 -0
  84. package/src/lib/components/wizard-header.tsx +3 -1
  85. package/src/lib/context-mode-package.ts +24 -11
  86. package/src/lib/delivery/archive-change.ts +154 -0
  87. package/src/lib/delivery/branches.ts +108 -0
  88. package/src/lib/delivery/environment.ts +29 -0
  89. package/src/lib/delivery/forge.ts +279 -0
  90. package/src/lib/delivery/overlap.ts +202 -0
  91. package/src/lib/delivery/record-delivery.ts +196 -0
  92. package/src/lib/delivery/record.ts +343 -0
  93. package/src/lib/delivery/refresh.ts +174 -0
  94. package/src/lib/delivery/repository-access.ts +97 -0
  95. package/src/lib/delivery/stages.ts +111 -0
  96. package/src/lib/delivery/token.ts +58 -0
  97. package/src/lib/frontmatter.ts +18 -0
  98. package/src/lib/opencode-plugin-package.ts +5 -5
  99. package/src/lib/openspec-cli.ts +116 -0
  100. package/src/lib/openspec-scopes.ts +86 -0
  101. package/src/lib/orchestrator/adapters/claude-args.ts +50 -0
  102. package/src/lib/orchestrator/adapters/claude.ts +48 -40
  103. package/src/lib/orchestrator/adapters/opencode.ts +2 -0
  104. package/src/lib/orchestrator/editor.ts +9 -9
  105. package/src/lib/orchestrator/openspec-store.ts +14 -54
  106. package/src/lib/orchestrator/projection-claude-commands.ts +36 -0
  107. package/src/lib/orchestrator/projection-claude-links.ts +159 -0
  108. package/src/lib/orchestrator/projection-claude-skills.ts +19 -137
  109. package/src/lib/orchestrator/projection-entries.ts +45 -14
  110. package/src/lib/orchestrator/projection-runtime-documents.ts +15 -6
  111. package/src/lib/orchestrator/projection-types.ts +3 -0
  112. package/src/lib/orchestrator/refresh-working-claude-links.ts +87 -0
  113. package/src/lib/orchestrator/session-prepare.ts +45 -5
  114. package/src/lib/orchestrator/setup-compatibilities.ts +18 -75
  115. package/src/lib/orchestrator/types.ts +2 -2
  116. package/src/lib/orchestrator/wrap-pass.ts +22 -1
  117. package/src/lib/package-paths.ts +8 -0
  118. package/src/opencode/companion-hooks.ts +64 -5
  119. package/src/opencode/companion-policy.ts +37 -18
  120. package/src/opencode/projected-guidance.ts +4 -1
  121. package/src/opencode/session-prepare.ts +2 -1
  122. package/src/opencode/tui.tsx +4 -2
  123. package/src/runtime/artifact-refusal.ts +63 -0
  124. package/src/runtime/claude-delivery-plan.ts +89 -7
  125. package/src/runtime/commit-attribution-guard.ts +181 -0
  126. package/src/runtime/companion-guidance.ts +15 -3
  127. package/src/runtime/companion-instructions.ts +340 -0
  128. package/src/runtime/error-message.ts +4 -0
  129. package/src/runtime/index.ts +5 -0
  130. package/src/runtime/managed-block.ts +117 -0
  131. package/src/runtime/markdown-scan.ts +266 -0
  132. package/src/runtime/policy.ts +15 -1
  133. package/src/runtime/projected-flag.ts +7 -0
  134. package/src/runtime/projected-guidance.ts +1 -0
  135. package/src/runtime/runtime-document-manifest.ts +62 -11
  136. package/src/runtime/secret-guard.ts +148 -0
  137. package/src/runtime/secret-patterns.ts +164 -0
  138. package/src/runtime/secret-scan.ts +90 -0
  139. package/src/runtime/session-kind.ts +13 -0
  140. package/src/runtime/shell-heredoc.ts +81 -0
  141. package/src/runtime/wrap-state.ts +36 -2
  142. package/src/runtime/write-atomic.ts +64 -0
  143. package/src/templates/capabilities/openspec-cap/mate-minimal/schema.yaml +8 -6
  144. package/src/templates/capabilities/openspec-cap/mate-minimal/templates/spec.md +3 -5
  145. package/src/templates/capabilities/openspec-cap/mate-v1/schema.yaml +7 -9
  146. package/src/templates/capabilities/openspec-cap/mate-v1/templates/spec.md +3 -5
  147. package/src/templates/capabilities/openspec-cap/openspec-conventions.yaml +10 -12
  148. package/src/templates/mate-skills/THIRD-PARTY-NOTICES.md +40 -0
  149. package/src/templates/mate-skills/agents/mate-apply-change/SKILL.md +76 -0
  150. package/src/templates/mate-skills/agents/mate-apply-change/references/openspec-apply-change.md +198 -0
  151. package/src/templates/mate-skills/agents/mate-archive-change/SKILL.md +59 -0
  152. package/src/templates/mate-skills/{claude/mate-openspec-backfill → agents/mate-backfill-spec}/SKILL.md +4 -4
  153. package/src/templates/mate-skills/agents/mate-clarify-intent/SKILL.md +95 -0
  154. package/src/templates/mate-skills/agents/mate-explore-change/SKILL.md +50 -0
  155. package/src/templates/mate-skills/agents/mate-explore-change/references/openspec-explore.md +348 -0
  156. package/src/templates/mate-skills/agents/mate-grill-me/SKILL.md +3 -3
  157. package/src/templates/mate-skills/agents/mate-interview-me/SKILL.md +5 -5
  158. package/src/templates/mate-skills/agents/mate-propose-change/SKILL.md +103 -0
  159. package/src/templates/mate-skills/agents/mate-propose-change/references/openspec-propose.md +167 -0
  160. package/src/templates/mate-skills/agents/mate-propose-change/references/openspec-update-change.md +101 -0
  161. package/src/templates/mate-skills/{claude/mate-artifact-publish → agents/mate-publish-artifact}/SKILL.md +91 -23
  162. package/src/templates/mate-skills/agents/{mate-artifact-publish → mate-publish-artifact}/references/openspec.md +4 -3
  163. package/src/templates/mate-skills/agents/mate-show-me/SKILL.md +74 -16
  164. package/src/templates/mate-skills/agents/mate-simplify-code/SKILL.md +74 -68
  165. package/src/templates/mate-skills/claude/mate-apply-change/SKILL.md +76 -0
  166. package/src/templates/mate-skills/claude/mate-apply-change/references/openspec-apply-change.md +198 -0
  167. package/src/templates/mate-skills/claude/mate-archive-change/SKILL.md +59 -0
  168. package/src/templates/mate-skills/{agents/mate-openspec-backfill → claude/mate-backfill-spec}/SKILL.md +4 -4
  169. package/src/templates/mate-skills/claude/mate-clarify-intent/SKILL.md +95 -0
  170. package/src/templates/mate-skills/claude/mate-explore-change/SKILL.md +50 -0
  171. package/src/templates/mate-skills/claude/mate-explore-change/references/openspec-explore.md +348 -0
  172. package/src/templates/mate-skills/claude/mate-grill-me/SKILL.md +3 -3
  173. package/src/templates/mate-skills/claude/mate-interview-me/SKILL.md +5 -5
  174. package/src/templates/mate-skills/claude/mate-propose-change/SKILL.md +103 -0
  175. package/src/templates/mate-skills/claude/mate-propose-change/references/openspec-propose.md +167 -0
  176. package/src/templates/mate-skills/claude/mate-propose-change/references/openspec-update-change.md +101 -0
  177. package/src/templates/mate-skills/{agents/mate-artifact-publish → claude/mate-publish-artifact}/SKILL.md +91 -23
  178. package/src/templates/mate-skills/claude/{mate-artifact-publish → mate-publish-artifact}/references/openspec.md +4 -3
  179. package/src/templates/mate-skills/claude/mate-show-me/SKILL.md +74 -16
  180. package/src/templates/mate-skills/claude/mate-simplify-code/SKILL.md +74 -68
  181. package/src/templates/mate-skills/openspec-references.ts +140 -0
  182. package/src/templates/root/TEMPLATE_AGENTS.md +2 -2
  183. package/src/tools/setup/__snapshots__/runtime-surface-golden.test.ts.snap +3727 -320
  184. package/src/tools/setup/capabilities/context-mode.ts +25 -5
  185. package/src/tools/setup/capabilities/graphify-gate.ts +31 -0
  186. package/src/tools/setup/capabilities/graphify-secrets.ts +255 -0
  187. package/src/tools/setup/capabilities/graphify.ts +12 -0
  188. package/src/tools/setup/capabilities/openspec.ts +151 -270
  189. package/src/tools/setup/capabilities/tokensave.ts +36 -3
  190. package/src/tools/setup/context-services.ts +9 -17
  191. package/src/tools/setup/dynamic-plugins/install.ts +24 -28
  192. package/src/tools/setup/engine.ts +97 -21
  193. package/src/tools/setup/managed-output.ts +51 -0
  194. package/src/tools/setup/mate.ts +86 -11
  195. package/src/tools/setup/plugin.ts +35 -0
  196. package/src/tools/setup/plugins/guidance.ts +7 -4
  197. package/src/tools/setup/providers/agent-file-sections.ts +4 -2
  198. package/src/tools/setup/providers/claude-attribution.ts +65 -0
  199. package/src/tools/setup/providers/claude-plugin-folders.ts +625 -0
  200. package/src/tools/setup/providers/claude-plugin-hooks.ts +39 -19
  201. package/src/tools/setup/providers/claude.ts +284 -8
  202. package/src/tools/setup/providers/opencode.ts +180 -1
  203. package/src/tools/setup/utils.ts +14 -4
  204. package/src/tools/setup.ts +126 -10
  205. package/wrappers/bin/graphify +52 -4
  206. package/wrappers/bin/openspec +33 -9
  207. package/wrappers/lib/graphify-gate.mjs +8 -0
  208. package/src/cli/commands/studio/views/workflow/transcript.tsx +0 -190
  209. package/src/tools/setup/runtime-documents.ts +0 -291
@@ -21,7 +21,7 @@ Explain the current topic visually in a browser-rendered Mate report. Skip the p
21
21
 
22
22
  ## Subject
23
23
 
24
- - With no argument, explain the current topic or the applied change, as described below.
24
+ - With no argument, review the applied change when the user asks what a change did, or when the conversation is about work in the Working Repository and `git diff` there is not empty; otherwise explain the current topic. When both readings fit, review the change.
25
25
  - With an argument naming a spec capability (`$ARGUMENTS`, for example `acme-capability`), explain that capability instead: read its canonical spec under `openspec/specs/` in the Companion Repository and report its purpose, its requirements, and the flow or structure they establish. Name the capability in the report `metadata`, include a `diagram` section, and omit the `diff` section.
26
26
  - When the named capability has no canonical spec, say so, suggest close capability names from `openspec/specs/`, and write nothing: no report, no file.
27
27
 
@@ -89,6 +89,18 @@ src/
89
89
 
90
90
  - Show a whole block in the report when most of it is new, when omitted context would hide ownership or order, or when the user needs a copyable target shape.
91
91
 
92
+ ## Reviewing An Applied Change
93
+
94
+ - Read the change scope before drawing it, and draw the state after the change, not the one it replaced.
95
+ - Decide the diagram by what the change did. When it alters control flow or behaviour - new or changed branches, calls, ordering, return paths, or error handling - the first diagram is a `flowchart TD` of the resulting flow, limited to the part the change touches. A rename, a move, or an extraction that keeps behaviour identical gets one structure diagram and no flowchart.
96
+ - Mark new steps `added` and modified steps `changed`. Removed steps normally do not appear, since the diff shows what was there before; when removing a step is the point of the change, keep it as a `removed` node.
97
+ - When most of the drawn flow is new, marking every step carries no signal: mark at most the entry step `added`, and say in the caption that the flow is new.
98
+ - Keep a flowchart to about twelve nodes. Collapse a run of steps the change did not touch into one node instead of splitting the flow across several diagrams.
99
+ - When the change also alters structure - types, modules, or ownership - follow the flowchart with a structure diagram such as a `classDiagram`. A report carries at most two `diagram` sections, flowchart first, each with its own `caption`.
100
+ - Take the diff from `git diff` in the Working Repository. Keep only repository-relative paths in the patch, default to the working tree, and ask the user when their intent is a committed range instead.
101
+ - Run `git diff --numstat` over the same scope before choosing between the full diff and a curated report. Every excerpt is whole hunks copied unchanged from that diff.
102
+ - When the inspected scope has no changes, say so and omit the `diff` section. Never invent a patch.
103
+
92
104
  ## Browser Delivery
93
105
 
94
106
  The report is mandatory. Prefer `mate report --input <temporary-json-file>` without `--json` so the CLI reads the complete document reliably and renders self-contained HTML. The CLI chooses the surface: inside a Studio terminal it hosts the report in Studio, elsewhere it opens it in the default browser. The CLI also supports `mate report --input -` when JSON is piped to stdin; if stdin delivery reports empty or truncated JSON, switch to a temporary JSON file rather than retrying the same transport. If validation fails, fix the report document and retry; do not fall back to an inline explanation or JSON-only delivery.
@@ -105,19 +117,33 @@ Build a JSON document that conforms to the `mate-create-report` contract, then h
105
117
  A report assembled by this skill carries:
106
118
 
107
119
  - `metadata` naming the subject and a neutral repository label, never a local path
108
- - one `diagram` section for the structure or flow at issue, even when the visual is small
120
+ - `diagram` sections, even when the visual is small: one for a topic or capability report, one or two for a change review as Reviewing An Applied Change describes
109
121
  - use a `mermaid` payload for runtime control flow, call trees, data flow, or component relationships; use `text` only when a sketch or pseudocode is clearer
110
- - one `diff` section carrying the unified diff, when there is something to diff
111
- - a short `text` section next to each visual, saying what the reader should notice
122
+ - what changed, when there is something to diff: the complete unified diff in one `diff` section for a small change or when the user asks for it, otherwise a curated overview and excerpts as described in Curating A Large Diff
123
+ - a short Markdown `caption` on each `diagram` and `diff` section, saying what the reader should notice; do not repeat it in a separate `text` section
124
+ - a `text` section only for explanation that belongs to no single visual, with `"format": "markdown"` when it uses Markdown
125
+
126
+ A `diagram` section carries exactly one payload: `mermaid` for diagram source the report draws as a picture, or `text` for a monospace ASCII sketch or pseudocode block. A `diff` section carries a unified `patch` string. Both take an optional `caption`, rendered beneath the visual with the Markdown subset described in `mate-create-report`.
127
+
128
+ ```json
129
+ {
130
+ "id": "flow",
131
+ "title": "Saving a document",
132
+ "type": "diagram",
133
+ "mermaid": "flowchart TD\n save[save] --> check{unchanged?}\n check -->|yes| cached[return cached]\n check -->|no| write[write content]\n class check,cached added\n class write changed",
134
+ "caption": "Unchanged content now **returns early** instead of being rewritten."
135
+ }
136
+ ```
112
137
 
113
- A `diagram` section carries exactly one payload: `mermaid` for diagram source the report draws as a picture, or `text` for a monospace ASCII sketch or pseudocode block. A `diff` section carries a unified `patch` string.
138
+ When a change also alters structure, the second `diagram` section is a structure diagram:
114
139
 
115
140
  ```json
116
141
  {
117
142
  "id": "structure",
118
143
  "title": "Report rendering",
119
144
  "type": "diagram",
120
- "mermaid": "classDiagram\n Renderer --> Highlight : uses"
145
+ "mermaid": "classDiagram\n Renderer --> Highlight : uses",
146
+ "caption": "`Renderer` is the only caller of `Highlight`."
121
147
  }
122
148
  ```
123
149
 
@@ -126,23 +152,55 @@ A `diagram` section carries exactly one payload: `mermaid` for diagram source th
126
152
  "id": "changes",
127
153
  "title": "What changed",
128
154
  "type": "diff",
129
- "patch": "diff --git a/src/acme.ts b/src/acme.ts\n..."
155
+ "patch": "diff --git a/src/acme.ts b/src/acme.ts\n...",
156
+ "caption": "Validation moves **before** rendering."
130
157
  }
131
158
  ```
132
159
 
133
160
  If the document fails contract validation, report the diagnostic and correct the document. Do not fall back to hand-written HTML.
134
161
 
162
+ ## Curating A Large Diff
163
+
164
+ The reader already has the full diff in git; the report earns its place by choosing what is worth looking at.
165
+
166
+ - Measure first. Run `git diff --numstat` over the inspected scope and add the added and removed lines of every file; binary files count as zero.
167
+ - At or under 150 changed lines, or whenever the user asks for the full diff, include the complete unified diff in one `diff` section, whatever its size.
168
+ - Above 150 changed lines, curate:
169
+ - one `table` section with id `changed-files` and the columns File | Added | Removed | Role, listing every changed file in the scope, including tests, snapshots, and generated files. Added and Removed are numbers; Role is a short phrase such as "contract: optional fields" or "snapshot hashes".
170
+ - one to four focused `diff` sections with ids such as `diff-<topic>`, each making one point and carrying a `caption` that says why its hunks matter. Keep each section under about 60 lines.
171
+ - a `summary` metric labelled "Changed lines shown" with the value `<shown> of <total>`, where shown counts the `+` and `-` lines in the excerpts and total is the `--numstat` sum.
172
+ - Excerpts stay verbatim. A focused patch is the file's `diff --git`, `---`, and `+++` header followed by one or more whole hunks copied unchanged from `git diff`. Never alter, merge, or invent hunk lines, and never elide lines with `...`. Two hunks of the same file may share a section when they make the same point.
173
+ - Leave supporting files out of the excerpts: tests (`*.test.*`, `*.spec.*`, `__tests__/`), snapshots (`__snapshots__/`, `*.snap`), lockfiles (`bun.lock`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`), generated files (`*.generated.*`), and formatting-only hunks. They still appear in the `changed-files` table. Excerpt them when the change is about them or the user asks for them.
174
+
175
+ ```json
176
+ {
177
+ "id": "changed-files",
178
+ "title": "Changed files",
179
+ "type": "table",
180
+ "columns": ["File", "Added", "Removed", "Role"],
181
+ "rows": [
182
+ ["src/report/contract.ts", 48, 6, "contract: optional fields"],
183
+ ["src/report/renderer.test.ts", 210, 95, "tests"]
184
+ ]
185
+ }
186
+ ```
187
+
188
+ ```json
189
+ {
190
+ "id": "diff-contract",
191
+ "title": "Contract gains optional fields",
192
+ "type": "diff",
193
+ "patch": "diff --git a/src/report/contract.ts b/src/report/contract.ts\n--- a/src/report/contract.ts\n+++ b/src/report/contract.ts\n@@ -40,6 +40,8 @@\n...",
194
+ "caption": "New fields are **optional**, so existing documents still validate."
195
+ }
196
+ ```
197
+
135
198
  ## Mermaid Authoring Rules
136
199
 
137
200
  - Use Mermaid whenever the user asks for a diagram or the subject has meaningful control flow, sequencing, lifecycle, or relationships. A `text` payload is a deliberate fallback, not the default for runtime flows.
138
- - Pick the diagram type that matches the question: `classDiagram` for structure, `sequenceDiagram` for interaction between components, `stateDiagram-v2` for lifecycles, `flowchart TD` for control flow and call trees.
139
- - Keep labels short enough to read at report width. A label that needs a sentence belongs in the neighbouring `text` section.
201
+ - Pick the diagram type that matches the question: `classDiagram` for structure, `sequenceDiagram` for interaction between components, `stateDiagram-v2` for lifecycles, `flowchart TD` for control flow and call trees. For a change review, Reviewing An Applied Change decides the diagram instead.
202
+ - Keep labels short enough to read at report width. A label that needs a sentence belongs in the section's `caption`.
140
203
  - Do not use ELK-only layouts or math labels. The report loads the single-file mermaid build from a CDN, which does not carry those chunks.
141
- - Pair each Mermaid visual with a short neighbouring `text` section that calls out the ownership boundary or invariant the reader should notice.
204
+ - To mark nodes, apply the report's theme classes `added`, `changed`, or `removed` with `class a,b added` or `a:::added`. They follow the reader's colour scheme. Never fix a colour with `classDef`, `style`, or `linkStyle`: a fill picked for a white page hides the labels in dark mode, so the dark copy drops those lines.
205
+ - Give each Mermaid visual a short `caption` that calls out the ownership boundary or invariant the reader should notice.
142
206
  - Prefer the `text` payload for pseudocode, shallow file trees, or cases where a picture would genuinely obscure the point.
143
-
144
- ## Reviewing An Applied Change
145
-
146
- - Read the change scope before drawing it, then diagram the structure or flow the change establishes - not the structure it replaced.
147
- - Take the diff from `git diff` in the Working Repository. Keep only repository-relative paths in the patch, default to the working tree, and ask the user when their intent is a committed range instead.
148
- - When the inspected scope has no changes, say so and omit the `diff` section. Never invent a patch.
@@ -19,21 +19,12 @@ Simplify code by reducing complexity while preserving exact behavior. The goal i
19
19
 
20
20
  - Inspect the requested scope and its callers, callees, and tests before editing. Use the available code-graph tools before broad source scans.
21
21
  - Keep the refactor limited to the requested scope; do not make unrelated cleanup changes.
22
- - Run the relevant tests after each simplification. Do not modify tests merely to make a refactor pass.
22
+ - Do not modify tests merely to make a refactor pass.
23
23
  - Format touched files with the project's own formatter — detect it first (see Principle 2); never run a formatter the project has not adopted.
24
24
  - Run `mate cap index --tokensave` after code changes.
25
25
  - Never commit, push, or create a pull request unless the user explicitly asks.
26
26
 
27
- ## When to Use
28
-
29
- - After a feature is working and tests pass, but the implementation feels heavier than it needs to be
30
- - During code review when readability or complexity issues are flagged
31
- - When you encounter deeply nested logic, long functions, or unclear names
32
- - When refactoring code written under time pressure
33
- - When consolidating related logic scattered across files
34
- - After merging changes that introduced duplication or inconsistency
35
-
36
- **When NOT to use:**
27
+ ## When NOT to Use
37
28
 
38
29
  - Code is already clean and readable — don't simplify for the sake of it
39
30
  - You don't understand what the code does yet — comprehend before you simplify
@@ -75,25 +66,29 @@ Simplification that breaks project consistency is not simplification — it's ch
75
66
 
76
67
  Detect the formatter before formatting anything — first match wins:
77
68
 
78
- | Signal in the repo | Formatter to run |
79
- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
80
- | `format` / `fmt` script in `package.json`, `Makefile`, `justfile`, `Taskfile.yml` | Run that script — it encodes the project's intent and needs no further detection |
81
- | `biome.json` / `biome.jsonc` | `biome format --write` |
82
- | `.oxfmtrc.json`, or `oxfmt` in devDependencies | `oxfmt` |
83
- | `dprint.json` / `.dprint.jsonc` | `dprint fmt` |
84
- | `.prettierrc*`, `prettier.config.*`, or a `prettier` key in `package.json` | `prettier --write` |
85
- | `rustfmt.toml`, or any Cargo crate | `cargo fmt` |
86
- | `[tool.ruff]` in `pyproject.toml` | `ruff format` |
87
- | `[tool.black]` in `pyproject.toml` | `black` |
88
- | Go module | `gofmt -w` (or `goimports -w` if already used) |
89
- | Only `.editorconfig`, or no signal at all | Do not format — match the surrounding style by hand |
69
+ | Signal in the repo | Formatter to run |
70
+ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
71
+ | `format` / `fmt` script in `package.json`, `Makefile`, `justfile`, `Taskfile.yml` | That script decides — narrow it to your files (see the rules below) |
72
+ | `biome.json` / `biome.jsonc` | `biome format --write` |
73
+ | `.oxfmtrc.json`, or `oxfmt` in devDependencies | `oxfmt` |
74
+ | `dprint.json` / `.dprint.jsonc` | `dprint fmt` |
75
+ | `.prettierrc*`, `prettier.config.*`, or a `prettier` key in `package.json` | `prettier --write` |
76
+ | `rustfmt.toml`, or any Cargo crate | `cargo fmt` |
77
+ | `[tool.ruff]` in `pyproject.toml` | `ruff format` |
78
+ | `[tool.black]` in `pyproject.toml` | `black` |
79
+ | Go module | `gofmt -w` (or `goimports -w` if already used) |
80
+ | Only `.editorconfig`, or no signal at all | Do not format — match the surrounding style by hand |
90
81
 
91
82
  Rules:
92
83
 
93
84
  - Invoke the project's pinned local binary through its package manager or runner, inferred from the lockfile (`bun`, `pnpm`, `yarn`, `npm`) — never a global install and never an `npx`-downloaded version, which may differ from the one that formatted the committed code.
85
+ - **A script decides the tool, not the paths.** Read the script to learn the tool, its config, and its flags, then run that tool on your files only. Scripts usually hard-code their own paths, so passing a file to them adds it to the run instead of narrowing it. If the script chains several steps, run only its formatting steps, each narrowed to your files — a lint `--fix` step is not formatting.
86
+ - In a monorepo, use the script from the nearest package manifest above the files that defines one — often only the repository root does.
87
+ - If a `format` script cannot be narrowed, do not run it: it rewrites files outside the scope, and reverting those with `git checkout` would also discard any uncommitted work in them. Match the surrounding style by hand and report it.
94
88
  - If several formatters are configured, the `format` script decides. If there is no script and the signals conflict, ask which is canonical instead of picking one.
95
89
  - Format only the files you changed. A repo-wide format pass is a separate change with its own diff.
96
- - If the formatter rewrites far more than the lines you touched, its config disagrees with the committed code. Stop, revert the formatting, and report it — do not fold that drift into a simplification change.
90
+ - Before running any formatter, save a copy of each file you are about to format to a temporary directory (`$TMPDIR`) — never inside the repository, where a backup can be committed. Git cannot tell a formatter's hunks apart from uncommitted work already in the file; the copy can.
91
+ - If the formatter rewrites far more than the lines you touched, its config disagrees with the committed code. Stop, restore the copies you saved — never `git checkout` the file, which would also discard uncommitted work — match the surrounding style by hand, and report it. Do not fold that drift into a simplification change.
97
92
 
98
93
  ### 3. Prefer Clarity Over Cleverness
99
94
 
@@ -137,6 +132,7 @@ Simplification has a failure mode: over-simplification. Watch for these traps:
137
132
  - **Combining unrelated logic** — two simple functions merged into one complex function is not simpler
138
133
  - **Removing "unnecessary" abstraction** — some abstractions exist for extensibility or testability, not complexity
139
134
  - **Optimizing for line count** — fewer lines is not the goal; easier comprehension is
135
+ - **Stripping return type annotations** — leave them; exported ones are contracts, and inference can silently widen the type
140
136
 
141
137
  ### 5. Scope to What Changed
142
138
 
@@ -160,6 +156,16 @@ BEFORE SIMPLIFYING, ANSWER:
160
156
 
161
157
  If you can't answer these, you're not ready to simplify. Read more context first.
162
158
 
159
+ **When no test exercises the scope**, the safety net that Step 3 relies on is missing. Pick one, and report the missing coverage either way:
160
+
161
+ - Write characterization tests first. They pin the current behavior, including its quirks, and are never edited later to fit the refactor.
162
+ - In a type-checked project, restrict the pass to changes the type checker verifies on its own, and leave every other candidate in the report:
163
+ - Rename locals, or remove unused locals whose initializer has no side effects. A call, `await`, `new`, or getter in the initializer can have one, and removing it changes behavior the checker cannot see.
164
+ - Skip a rename when the local also supplies an object key (`{ user }`), a JSX prop, or a string lookup — renaming it changes data, and the checker cannot see that.
165
+ - Unexport a symbol only after it clears every box of the pre-removal checklist. The checker catches a broken importer, but not a framework or config that resolves the symbol by name.
166
+
167
+ Without a type checker, only characterization tests remain.
168
+
163
169
  ### Step 2: Identify Simplification Opportunities
164
170
 
165
171
  #### Step 2a: Mechanical pre-scan (required)
@@ -181,7 +187,8 @@ PRE-SCAN THE REQUESTED SCOPE:
181
187
 
182
188
  Do not skip the pre-scan because the file "looks clean". Judgment applies to the
183
189
  candidates it produces, not to whether to produce them. Report candidates you
184
- deliberately leave alone, with the reason.
190
+ deliberately leave alone, with the reason. Every "report it" in this skill means an entry
191
+ in the final [Report](#report), under its bucket.
185
192
 
186
193
  **A pre-scan hit is a question, not a verdict.** These tools find symbols nothing
187
194
  _imports_; they cannot see symbols resolved by name — framework exports, reflective
@@ -292,11 +299,6 @@ design decision rather than a behavior-preserving edit. Both collide with Princi
292
299
  Describe the change and the affected files, then stop and let the user decide — the
293
300
  same treatment the prop-drilling case gets under React guidance.
294
301
 
295
- **When the pre-scan flags a symbol you cannot prove is unreferenced, leave it and say
296
- so.** An export you were unsure about and kept costs a line of explanation. An export
297
- you removed on a guess costs a production incident. Unverifiable candidates are
298
- reported, not acted on.
299
-
300
302
  ```
301
303
  BEFORE REMOVING ANY export, ALL MUST HOLD:
302
304
  [ ] Not framework-resolved (checked against the list above)
@@ -310,7 +312,7 @@ Any box unchecked → report the candidate, do not touch it.
310
312
 
311
313
  ### Step 3: Apply Changes Incrementally
312
314
 
313
- Make one simplification at a time. Run tests after each change. **Submit refactoring changes separately from feature or bug fix changes.** A PR that refactors and adds a feature is two PRs — split them.
315
+ Make one simplification at a time and run tests after each change, so a failure points to the change that caused it. **Submit refactoring changes separately from feature or bug fix changes.** A PR that refactors and adds a feature is two PRs — split them.
314
316
 
315
317
  ```
316
318
  FOR EACH SIMPLIFICATION:
@@ -322,9 +324,7 @@ FOR EACH SIMPLIFICATION:
322
324
  4. If either fails → revert and reconsider
323
325
  ```
324
326
 
325
- Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
326
-
327
- **The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods or AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review.
327
+ **The Rule of 500:** If a refactoring would touch more than 500 lines, stop and propose it — the scope, the approach (codemod or AST transform included), and the affected files — instead of applying it, unless the user explicitly asked for that scope. A change that size is no longer scoped to what changed (Principle 5), and manual edits at that scale are error-prone and exhausting to review.
328
328
 
329
329
  ### Step 4: Verify the Result
330
330
 
@@ -334,29 +334,40 @@ Then step back and evaluate the whole:
334
334
 
335
335
  ```
336
336
  COMPARE BEFORE AND AFTER:
337
- - Is the simplified version genuinely easier to understand?
338
- - Did you introduce any new patterns inconsistent with the codebase?
339
- - Is the diff clean and reviewable?
340
- - Would a teammate approve this change?
337
+ - Is the simplified version genuinely easier to understand and review?
338
+ - Did you introduce any pattern inconsistent with the surrounding code?
341
339
  ```
342
340
 
343
- If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds.
341
+ If either answer is wrong, revert. Not every simplification attempt succeeds.
342
+
343
+ ## Report
344
+
345
+ End every pass with one report. Every pre-scan candidate lands in exactly one bucket,
346
+ and each entry names the file, the candidate, and the reason. A candidate you could not
347
+ verify goes under **Unsure**, never into the code: an export kept on doubt costs a line
348
+ of explanation, one removed on a guess costs an incident.
349
+
350
+ **Group the noise, itemize the decisions.** Candidates under **Left alone on purpose**
351
+ that share a tool and a reason collapse into one line with a count and the threshold or
352
+ rule that dismissed them (for example, "14 complexity hits below nesting depth 3"). Every
353
+ candidate in the other buckets gets its own entry.
354
+
355
+ - **Applied** — what changed, and the check that proved it (type checker, tests)
356
+ - **Not applied — changes behavior** — what the fix would alter: ordering, concurrency,
357
+ mutation, error surface, or name resolution
358
+ - **Unsure** — what you could not verify, and which evidence is missing
359
+ - **Propose-only** — API reshapes and refactors past the Rule of 500: the proposed change
360
+ and the files it would touch
361
+ - **Left alone on purpose** — candidates not worth changing, with the reason
362
+
363
+ Close with anything that limited the pass: missing test coverage, or formatter drift you
364
+ reverted.
344
365
 
345
366
  ## Language-Specific Guidance
346
367
 
347
368
  ### TypeScript / JavaScript
348
369
 
349
370
  ```typescript
350
- // SIMPLIFY: Unnecessary async wrapper
351
- // Before
352
- async function getUser(id: string): Promise<User> {
353
- return await userService.findById(id);
354
- }
355
- // After
356
- function getUser(id: string): Promise<User> {
357
- return userService.findById(id);
358
- }
359
-
360
371
  // SIMPLIFY: Verbose conditional assignment
361
372
  // Before
362
373
  let displayName: string;
@@ -454,15 +465,12 @@ function UserBadge({ user }: Props) {
454
465
 
455
466
  ## Common Rationalizations
456
467
 
457
- | Rationalization | Reality |
458
- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
459
- | "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. |
460
- | "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
461
- | "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. |
462
- | "The types make it self-documenting" | Types document structure, not intent. A well-named function explains _why_ better than a type signature explains _what_. |
463
- | "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. |
464
- | "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. |
465
- | "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
468
+ | Rationalization | Reality |
469
+ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
470
+ | "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
471
+ | "This abstraction might be useful later" | Speculative abstractions are complexity without value. If nothing uses it now, remove it under the dead-code and export rules above. |
472
+ | "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's the residue of iteration. |
473
+ | "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
466
474
 
467
475
  ## Red Flags
468
476
 
@@ -471,36 +479,34 @@ function UserBadge({ user }: Props) {
471
479
  - Renaming things to match your preferences rather than project conventions
472
480
  - Removing error handling because "it makes the code cleaner"
473
481
  - Simplifying code you don't fully understand
474
- - Batching many simplifications into one large, hard-to-review commit
475
- - Refactoring code outside the scope of the current task without being asked
482
+ - Touching code outside the requested scope without being asked
476
483
  - Deleting an export because a tool reported it unused, without checking whether the
477
484
  framework resolves it by name (`page.tsx`, `route.ts`, stories, config-referenced files)
478
485
  - Acting on a pre-scan candidate you could not verify — report it instead
486
+ - Applying a propose-only row (module collapse, barrel deletion) without user sign-off
479
487
  - Treating a green test run as proof a visibility change was safe without a type check
480
488
  - Unexporting a symbol whose only importer is a test, then editing the test to match
481
- - Applying a propose-only row (module collapse, barrel deletion) without user sign-off
482
489
  - Trusting "the compiler would catch it" in a project the type checker does not cover
490
+ - Dropping `async` or `return await` as a "simplification" — it changes how errors and stack traces surface
483
491
 
484
492
  ## Verification
485
493
 
486
494
  After completing a simplification pass:
487
495
 
488
496
  - [ ] All existing tests pass without modification
497
+ - [ ] Type checker passes, if the project has one
489
498
  - [ ] Build succeeds with no new warnings
490
- - [ ] The project's own formatter was detected and run on the touched files — no formatter the project has not adopted was used
491
- - [ ] Formatting touched only the changed files (no repo-wide reformat mixed in)
499
+ - [ ] The project's own formatter ran on the touched files only
492
500
  - [ ] Linter passes (no style regressions)
493
501
  - [ ] Each simplification is a reviewable, incremental change
494
- - [ ] The diff is clean — no unrelated changes mixed in
502
+ - [ ] The diff holds nothing outside the requested scope
495
503
  - [ ] Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
496
504
  - [ ] No error handling was removed or weakened
497
505
  - [ ] No dead code was left behind (unused imports, unreachable branches)
498
- - [ ] The Step 2a pre-scan was run, and every candidate is either fixed or explained
499
- - [ ] Export surface matches actual consumers — nothing exported without a caller outside its file
500
- - [ ] Type checker passes — no unexport broke an importer
506
+ - [ ] Every removed `export` cleared the pre-removal checklist
501
507
  - [ ] No framework-resolved export was unexported, renamed, or deleted
502
- - [ ] Every removed `export` cleared all boxes of the pre-removal checklist
503
508
  - [ ] No test was edited to accommodate a visibility change
504
509
  - [ ] Propose-only findings were reported, not applied
510
+ - [ ] Every pre-scan candidate appears in the Report, itemized or counted in a grouped line
505
511
  - [ ] Behavior is bit-for-bit identical: same inputs, outputs, side effects, error paths
506
512
  - [ ] A teammate or review agent would approve the change as a net improvement
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: mate-apply-change
3
+ description: Implement a change on a recorded delivery branch, offering change/<change-name> instead of a protected branch. Builds on the OpenSpec apply workflow. Use when the user wants to implement, apply, or continue implementing a reviewed change.
4
+ allowed-tools: Bash(mate:*), Bash(openspec:*), Bash(git:*)
5
+ license: MIT
6
+ compatibility: Requires the mate CLI and the openspec capability enabled.
7
+ metadata:
8
+ author: mate
9
+ version: "1.0"
10
+ ---
11
+
12
+ # Mate Apply Change
13
+
14
+ The Apply change stage of the Delivery Path. Before any code changes, it records the
15
+ Working Repository branch the change is delivered through, so archive and publication
16
+ later know which merge to wait for. Then it runs the OpenSpec apply workflow.
17
+
18
+ ## Step 1: Read the branch and the record
19
+
20
+ In the Working Repository, read local Git state only:
21
+
22
+ ```bash
23
+ git symbolic-ref --quiet --short HEAD # current branch; fails when detached
24
+ git symbolic-ref --quiet --short refs/remotes/origin/HEAD # default branch
25
+ ```
26
+
27
+ Read the change's existing record without changing it:
28
+
29
+ ```bash
30
+ mate artifact link "<change-name>" --json
31
+ ```
32
+
33
+ ## Step 2: Settle the delivery branch
34
+
35
+ A branch is **protected** when it is the default branch or matches a configured
36
+ protected pattern; `mate artifact link` refuses a
37
+ protected branch unless it is recorded as a direct delivery.
38
+
39
+ - **A branch is already recorded** and it is the current branch → continue. When the
40
+ current branch differs, warn, name both branches, and ask before implementing
41
+ whether to switch to the recorded branch or record the current one.
42
+ - **On `change/<change-name>`** → record it without asking:
43
+ `mate artifact link "<change-name>" --branch "change/<change-name>" --json`.
44
+ - **On another unprotected branch** (a shared feature branch) → ask once whether this
45
+ change is delivered through it, then record it on confirmation.
46
+ - **Detached HEAD** → ask for the branch name, then record it.
47
+ - **On a protected branch** → do not implement there by default. First name every
48
+ local commit that is not on the remote (`git log --oneline HEAD --not --remotes`) and
49
+ leave them where they are; never move, reset, or rebase them. Then offer:
50
+ 1. **Create `change/<change-name>`** (default): `git switch -c change/<change-name>`;
51
+ uncommitted edits carry over. Record it.
52
+ 2. **Use an existing branch**: switch to the branch the user names and record it.
53
+ 3. **Work directly here** — only when the user explicitly chooses it. Record it as a
54
+ direct delivery: `mate artifact link "<change-name>" --branch "<branch>" --direct --json`.
55
+
56
+ Record the branch before writing any code. When `mate artifact link` refuses, report
57
+ its message and ask; never work around it.
58
+
59
+ When its result lists `warnings`, a `dependsOn` change is not implemented yet, so this
60
+ change would be built without the code it builds on. Report each warning and ask
61
+ whether to apply the dependency first or continue here.
62
+
63
+ ## Step 3: Apply
64
+
65
+ Read [references/openspec-apply-change.md](references/openspec-apply-change.md) and
66
+ follow it for the implementation. The PR need not exist yet; the branch is the delivery.
67
+ After implementation, the optional peers `/mate-show-me` and `/mate-simplify-code` may
68
+ run in any order, then `/mate-archive-change`. Name them as next steps; do not invoke
69
+ them.
70
+
71
+ ## Guardrails
72
+
73
+ - Never push, open a PR, or merge on the user's behalf.
74
+ - Never record a protected branch except as an explicit direct delivery.
75
+ - The forge token, when one is used by `mate artifact link`, is never printed or
76
+ written; do not read or echo `MATE_GIT_TOKEN`.