@mnmal-ai/cortext-opencode 1.0.0-alpha.1 → 1.0.0-alpha.2

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/dist/plugin.js CHANGED
@@ -582,7 +582,7 @@ function releasesBehind(installed, plugin) {
582
582
  */
583
583
  function renderFragmentDrift(result) {
584
584
  switch (result.state) {
585
- case "missing": return "> ⚠️ **This repo has an agent identity but no conventions fragment.** `.claude/substrate-conventions.md` is absent, so the conventions every other onboarded repo reads are not in your context. Run `/substrate-setup` to install it and its `CLAUDE.md` import.\n";
585
+ case "missing": return "> ⚠️ **This repo has an agent identity but no conventions fragment.** `.claude/substrate-conventions.md` is absent, so the conventions every other onboarded repo reads are not in your context. Run `/substrate-setup` to install it and its `CLAUDE.local.md` import.\n";
586
586
  case "stale": {
587
587
  const behind = releasesBehind(result.installed.version, result.plugin.version);
588
588
  return `${behind === null ? "> ⚠️ **Conventions fragment is STALE.**" : `> 🛑 **Conventions fragment is STALE — ${behind}.** This warning has a steady state where it is read past every session; the distance is the reason not to.`} \`.claude/substrate-conventions.md\` is \`v${result.installed.version}+${result.installed.digest}\`; the plugin ships \`v${result.plugin.version}+${result.plugin.digest}\`. **The content differs** — the conventions in your context are not the ones this plugin defines, and a stale copy has previously taught retired frame keys that fail on first use.
@@ -2252,42 +2252,44 @@ function resolveImport(target, fromFile) {
2252
2252
  return `${fromFile.slice(0, fromFile.lastIndexOf("/"))}/${target}`;
2253
2253
  }
2254
2254
  /**
2255
- * Walk a CLAUDE.md's imports one level deep and return the ones that do not
2255
+ * Walk the imports of CLAUDE.md and CLAUDE.local.md one level deep and return the ones that do not
2256
2256
  * resolve, each with the file that declared it.
2257
2257
  *
2258
- * Returns `[]` when the root file itself is absent: a repo with no CLAUDE.md
2258
+ * Returns `[]` when both root files are absent: a repo with neither
2259
2259
  * is not a consumer, and is a different fact from one whose imports are
2260
2260
  * broken. Saying nothing there is the same call `fragmentDriftWarning` makes
2261
2261
  * about a repo that never onboarded.
2262
2262
  */
2263
2263
  function findDanglingImports({ cwd, readFile }) {
2264
- const root = `${cwd}/CLAUDE.md`;
2265
- const rootText = readFile(root);
2266
- if (rootText === null) return [];
2264
+ const roots = [`${cwd}/CLAUDE.md`, `${cwd}/CLAUDE.local.md`];
2267
2265
  const dangling = [];
2268
- const seen = /* @__PURE__ */ new Set([root]);
2269
- for (const target of parseImports(rootText)) {
2270
- const path = resolveImport(target, root);
2271
- if (seen.has(path)) continue;
2272
- seen.add(path);
2273
- const text = readFile(path);
2274
- if (text === null) {
2275
- dangling.push({
2276
- target,
2277
- path,
2278
- declaredIn: root
2279
- });
2280
- continue;
2281
- }
2282
- for (const nested of parseImports(text)) {
2283
- const nestedPath = resolveImport(nested, path);
2284
- if (seen.has(nestedPath)) continue;
2285
- seen.add(nestedPath);
2286
- if (readFile(nestedPath) === null) dangling.push({
2287
- target: nested,
2288
- path: nestedPath,
2289
- declaredIn: path
2290
- });
2266
+ const seen = new Set(roots);
2267
+ for (const root of roots) {
2268
+ const rootText = readFile(root);
2269
+ if (rootText === null) continue;
2270
+ for (const target of parseImports(rootText)) {
2271
+ const path = resolveImport(target, root);
2272
+ if (seen.has(path)) continue;
2273
+ seen.add(path);
2274
+ const text = readFile(path);
2275
+ if (text === null) {
2276
+ dangling.push({
2277
+ target,
2278
+ path,
2279
+ declaredIn: root
2280
+ });
2281
+ continue;
2282
+ }
2283
+ for (const nested of parseImports(text)) {
2284
+ const nestedPath = resolveImport(nested, path);
2285
+ if (seen.has(nestedPath)) continue;
2286
+ seen.add(nestedPath);
2287
+ if (readFile(nestedPath) === null) dangling.push({
2288
+ target: nested,
2289
+ path: nestedPath,
2290
+ declaredIn: path
2291
+ });
2292
+ }
2291
2293
  }
2292
2294
  }
2293
2295
  return dangling;
@@ -1,4 +1,4 @@
1
- <!-- substrate-conventions vsynoptic-1.0.0-alpha.1+99787976 — opencode skin; plugin-owned, do not edit. Edit your own AGENTS.md instead. Body is shared with the Claude skin's fragment (test/instructions-sync.test.ts enforces it). -->
1
+ <!-- substrate-conventions vsynoptic-1.0.0-alpha.2+99787976 — opencode skin; plugin-owned, do not edit. Edit your own AGENTS.md instead. Body is shared with the Claude skin's fragment (test/instructions-sync.test.ts enforces it). -->
2
2
 
3
3
  # Substrate interaction conventions
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnmal-ai/cortext-opencode",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "Cortext — the OpenCode skin: cold-start injection via experimental.chat.system.transform, bundling the @mnmal-ai/synoptic host into a committed dist artifact. Installed as an OpenCode plugin (\"plugin\": [\"@mnmal-ai/cortext-opencode\"]). Published to npm, not the Claude marketplace.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "access": "public"
26
26
  },
27
27
  "devDependencies": {
28
- "@mnmal-ai/synoptic": "1.0.0-alpha.1",
28
+ "@mnmal-ai/synoptic": "1.0.0-alpha.2",
29
29
  "@opencode-ai/plugin": "^1.18.35",
30
30
  "@opencode/plugin": "^2.0.24",
31
31
  "@types/node": "^26.6.4",