@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.
@@ -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 CORTEX_ALLOWED_TOOLS permission
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 CORTEX_ALLOWED_TOOLS) {
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
 
@@ -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
- /** C1 sets this true. Until then the notice is inert, so building it now changes nothing for the
20
- * people currently on @latest. Flipping this constant IS the C1 release. */
21
- export const RENAME_NOTICE_ACTIVE = false
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.96",
3
+ "version": "0.9.98",
4
4
  "description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
5
5
  "type": "module",
6
6
  "bin": {