@theronap/cortex-mcp 0.9.96 → 0.9.98
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/lib/editors/claude.mjs +8 -2
- package/lib/rename_notice.mjs +3 -3
- package/lib/skills.mjs +29 -0
- package/package.json +1 -1
package/lib/editors/claude.mjs
CHANGED
|
@@ -46,13 +46,19 @@ export const allowedToolsFor = (namespace) => ALLOWED_TOOL_NAMES.map((t) => `mcp
|
|
|
46
46
|
|
|
47
47
|
export const CORTEX_ALLOWED_TOOLS = allowedToolsFor('cortex')
|
|
48
48
|
|
|
49
|
+
/** C1 (ADR-0033 §5). Every seat is pre-authorized for BOTH tool namespaces, because a machine that
|
|
50
|
+
* has not yet flipped its config key still calls mcp__cortex__*, and one that has calls
|
|
51
|
+
* mcp__agnoclast__*. Additive and permanent for the duration of the migration: the old rules are
|
|
52
|
+
* never removed, so a machine can carry both and neither ordering can strand it at a prompt. */
|
|
53
|
+
export const MANAGED_ALLOWED_TOOLS = [...allowedToolsFor('cortex'), ...allowedToolsFor('agnoclast')]
|
|
54
|
+
|
|
49
55
|
/** Merge Agnoclast's Claude Code hooks into a ~/.claude/settings.json object. Pure + idempotent: drops
|
|
50
56
|
* any prior cortex entry (old token/path/version) from each hook array before appending the current
|
|
51
57
|
* one — capture (Stop), status + skills-repair + snapshot-context (SessionStart), hydrate
|
|
52
58
|
* (UserPromptSubmit). Also UNWIRES the retired PreCompact reminder from seats that still carry it.
|
|
53
59
|
* Commands carry NO inline token (each subcommand
|
|
54
60
|
* self-resolves it). Mirrors setup.mjs
|
|
55
|
-
* step 2 exactly; foreign hooks are never touched. Also merges the
|
|
61
|
+
* step 2 exactly; foreign hooks are never touched. Also merges the MANAGED_ALLOWED_TOOLS permission
|
|
56
62
|
* allowlist — additive-only: a user's own allow entries (even extra mcp__cortex__* ones) are never
|
|
57
63
|
* removed, and `deny` is never touched (a user deny always beats our allow). */
|
|
58
64
|
export function mergeClaudeSettings(existing, spec) {
|
|
@@ -142,7 +148,7 @@ export function mergeClaudeSettings(existing, spec) {
|
|
|
142
148
|
// ship via uninstall, and rebuilding would delete allows the user added by hand.
|
|
143
149
|
s.permissions = s.permissions && typeof s.permissions === 'object' ? s.permissions : {}
|
|
144
150
|
s.permissions.allow = Array.isArray(s.permissions.allow) ? s.permissions.allow : []
|
|
145
|
-
for (const rule of
|
|
151
|
+
for (const rule of MANAGED_ALLOWED_TOOLS) {
|
|
146
152
|
if (!s.permissions.allow.includes(rule)) s.permissions.allow.push(rule)
|
|
147
153
|
}
|
|
148
154
|
|
package/lib/rename_notice.mjs
CHANGED
|
@@ -16,9 +16,9 @@ import { NEW_KEY, OLD_KEY } from './migrate_key.mjs'
|
|
|
16
16
|
// OLD config key. Once `migrate-key` flips it, the condition is false and the message stops. That is
|
|
17
17
|
// "warn, then leave them alone" expressed as a condition rather than as a timer.
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
export const RENAME_NOTICE_ACTIVE =
|
|
19
|
+
/** ACTIVATED 2026-08-19 — this flip is the C1 release. Delete this module, its test, and the two
|
|
20
|
+
* lines that call it in doctor.mjs one release after C2 lands. */
|
|
21
|
+
export const RENAME_NOTICE_ACTIVE = true
|
|
22
22
|
|
|
23
23
|
/** PURE. The one-line warning, or null when it should stay quiet.
|
|
24
24
|
* `key` is which config key answered on this machine ('cortex' | 'agnoclast' | null). */
|
package/lib/skills.mjs
CHANGED
|
@@ -361,6 +361,35 @@ export async function runSkills(argv = []) {
|
|
|
361
361
|
if (argv[0] === 'push') return runSkillsPush(argv.slice(1))
|
|
362
362
|
|
|
363
363
|
const quiet = argv.includes('--quiet')
|
|
364
|
+
|
|
365
|
+
// ── C2 (ADR-0033 §5): move the MCP config key to its new name. ─────────────
|
|
366
|
+
// This runs from the SessionStart hook because that is the only channel that reaches every seat
|
|
367
|
+
// without asking anyone to do anything. It is safe here for two reasons that both matter:
|
|
368
|
+
//
|
|
369
|
+
// • It is SELF-GUARDING. runKeyMigration adds the new namespace's allow rules and re-reads them
|
|
370
|
+
// from disk BEFORE flipping the key, and aborts leaving the machine on the old name if they
|
|
371
|
+
// did not land. The C1 release already pre-authorized both namespaces, so on a seat that took
|
|
372
|
+
// C1 there is nothing left to add — but a seat that skipped C1 entirely is handled too, which
|
|
373
|
+
// is the whole reason the guard lives on the machine rather than in the release cadence.
|
|
374
|
+
// • It is idempotent and cheap after the first run: a state file read, then nothing.
|
|
375
|
+
//
|
|
376
|
+
// FAIL-SOFT, like every other hook step. A migration hiccup must never block a session from
|
|
377
|
+
// starting; the next SessionStart tries again.
|
|
378
|
+
try {
|
|
379
|
+
const { runKeyMigration } = await import('./migrate_key.mjs')
|
|
380
|
+
const res = runKeyMigration()
|
|
381
|
+
if (!quiet && res.status === 'migrated') {
|
|
382
|
+
process.stdout.write(` ✓ MCP config key moved ${res.from} → ${res.to}. Restart to load it under the new name.\n`)
|
|
383
|
+
}
|
|
384
|
+
if (res.status === 'aborted') {
|
|
385
|
+
// Loud on stderr even when quiet: an abort means the machine is INTENTIONALLY still on the old
|
|
386
|
+
// key, and a silent abort is indistinguishable from never having tried.
|
|
387
|
+
process.stderr.write(`agnoclast: key migration held off at "${res.step}" (${res.reason}) — still on the old name, will retry.\n`)
|
|
388
|
+
}
|
|
389
|
+
} catch (e) {
|
|
390
|
+
process.stderr.write(`agnoclast: key migration skipped (${e?.message ?? e}) — will retry next session.\n`)
|
|
391
|
+
}
|
|
392
|
+
|
|
364
393
|
if (!quiet) process.stdout.write('\nAgnoclast skills — installing managed skills…\n')
|
|
365
394
|
const r = installSkills({ quiet })
|
|
366
395
|
if (!quiet) {
|