@uniqbit/mate-core 0.18.0-canary.0 → 0.18.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniqbit/mate-core",
3
- "version": "0.18.0-canary.0",
3
+ "version": "0.18.0",
4
4
  "description": "Core framework and plugin APIs for Mate.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -14,6 +14,7 @@ import {
14
14
  } from "../../../lib/update-checker";
15
15
  import { resolveCompanionRuntime } from "../../../runtime/env";
16
16
  import { syncCompanionFiles } from "../../../tools/setup";
17
+ import { MANAGED_MATE_SKILL_NAMES } from "../../../tools/setup/mate";
17
18
  import { runCommand } from "../../../tools/setup/utils";
18
19
  import { confirm } from "../../confirm";
19
20
  import { defaultGitOps, type GitOps } from "../artifact/finish/git";
@@ -39,6 +40,15 @@ export function isOpenSpecGenerated(relativePath: string): boolean {
39
40
  return OPENSPEC_GENERATED.some((pattern) => pattern.test(relativePath));
40
41
  }
41
42
 
43
+ /** Mate-owned skills: `applyMateSkills` overwrites them wholesale, so a local edit there never survives a sync. */
44
+ const MATE_MANAGED_SKILL = new RegExp(
45
+ `^\\.(claude|agents|opencode)/skills/(${MANAGED_MATE_SKILL_NAMES.join("|")})(/|$)`,
46
+ );
47
+
48
+ export function isMateManagedSkill(relativePath: string): boolean {
49
+ return MATE_MANAGED_SKILL.test(relativePath);
50
+ }
51
+
42
52
  function frameworkConfigPath(companionPath: string): string {
43
53
  return path.join(companionPath, `.${FRAMEWORK_NAME}`, "config", "framework.yaml");
44
54
  }
@@ -129,6 +139,8 @@ export const companionUpdateDeps: CompanionUpdateDeps = {
129
139
  export interface UpdateChanges {
130
140
  written: string[];
131
141
  conflict: string[];
142
+ /** Mate-managed skills whose uncommitted edits the update replaced. */
143
+ overwritten: string[];
132
144
  }
133
145
 
134
146
  /** Content snapshot of every uncommitted path, taken before the update writes. */
@@ -151,15 +163,30 @@ export async function diffChangedPaths(
151
163
  ): Promise<UpdateChanges> {
152
164
  const written: string[] = [];
153
165
  const conflict: string[] = [];
166
+ const overwritten: string[] = [];
154
167
  for (const changed of await git.changedPaths()) {
155
168
  if (!before.has(changed)) written.push(changed);
156
169
  }
157
- for (const [changed, hash] of before) {
158
- if ((await companionUpdateDeps.snapshotPath(companionPath, changed)) === hash) continue;
170
+ const preexisting = await Promise.all(
171
+ [...before].map(async ([changed, hash]) => ({
172
+ changed,
173
+ openspec: isOpenSpecGenerated(changed),
174
+ mate: isMateManagedSkill(changed),
175
+ unchanged: (await companionUpdateDeps.snapshotPath(companionPath, changed)) === hash,
176
+ })),
177
+ );
178
+ for (const { changed, openspec, mate, unchanged } of preexisting) {
179
+ /** Generated output is committed even when a prior run already wrote identical content. */
180
+ if (!openspec && !mate && unchanged) continue;
159
181
  written.push(changed);
160
- if (!isOpenSpecGenerated(changed)) conflict.push(changed);
182
+ if (openspec || (mate && unchanged)) continue;
183
+ (mate ? overwritten : conflict).push(changed);
161
184
  }
162
- return { written: written.toSorted(), conflict: conflict.toSorted() };
185
+ return {
186
+ written: written.toSorted(),
187
+ conflict: conflict.toSorted(),
188
+ overwritten: overwritten.toSorted(),
189
+ };
163
190
  }
164
191
 
165
192
  async function resolveCompanion(cwd: string): Promise<string | undefined> {
@@ -311,7 +338,7 @@ export async function runCompanionUpdateCommand(argv: string[]): Promise<void> {
311
338
  return;
312
339
  }
313
340
 
314
- const { written, conflict } = await diffChangedPaths(companionPath, git, before);
341
+ const { written, conflict, overwritten } = await diffChangedPaths(companionPath, git, before);
315
342
  if (written.length === 0) {
316
343
  process.stdout.write(
317
344
  `${FRAMEWORK_NAME}: ${companionPath} is already up to date with ${FRAMEWORK_NAME} ${version}.\n`,
@@ -328,6 +355,15 @@ export async function runCompanionUpdateCommand(argv: string[]): Promise<void> {
328
355
  return;
329
356
  }
330
357
 
358
+ if (overwritten.length > 0) {
359
+ process.stderr.write(
360
+ [
361
+ `${FRAMEWORK_NAME}: warning: the update overwrote local edits to Mate-managed skills:`,
362
+ listPaths(overwritten),
363
+ "",
364
+ ].join("\n"),
365
+ );
366
+ }
331
367
  process.stdout.write(
332
368
  [`${FRAMEWORK_NAME}: the update changed ${companionPath}:`, listPaths(written), ""].join("\n"),
333
369
  );