prism-mcp-server 20.17.3 → 20.18.1

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/README.md CHANGED
@@ -42,6 +42,9 @@ A paid subscription adds cloud sync, higher model tiers, and team features throu
42
42
  offline last-good recovery.
43
43
  - **Hook-free startup** — MCP metadata and native instructions request Prism's
44
44
  startup context without requiring lifecycle hooks or a Prism-owned launcher.
45
+ Where a host offers hooks (Claude Code, Codex), `prism connect` adds two
46
+ small ones on top: mid-session prompt routing, and a post-compaction
47
+ re-injection of the protected-floor digest.
45
48
  - **Safe escalation and observability** — inference outcomes are explicit,
46
49
  reserved content remains fail-closed, and local/cloud usage is recorded for
47
50
  review.
@@ -83,14 +86,18 @@ behind it are in the
83
86
  Prism also ships as a plugin, which registers the MCP server and the startup
84
87
  skill for you.
85
88
 
86
- **Claude Code** from the community marketplace:
89
+ Both hosts install straight from this repository. There is nothing to host and
90
+ no server to run: the catalogue is the `.claude-plugin/marketplace.json` file
91
+ committed here, and your client clones it from GitHub.
92
+
93
+ **Claude Code:**
87
94
 
88
95
  ```bash
89
- /plugin marketplace add anthropics/claude-plugins-community
90
- /plugin install prism-coder@claude-community
96
+ claude plugin marketplace add dcostenco/prism-coder
97
+ claude plugin install prism-coder@prism
91
98
  ```
92
99
 
93
- **Codex** — this repository is itself a plugin marketplace:
100
+ **Codex:**
94
101
 
95
102
  ```bash
96
103
  codex plugin marketplace add dcostenco/prism-coder
@@ -138,6 +145,88 @@ or by re-enabling after each run.
138
145
  <details>
139
146
  <summary>Release history (optional)</summary>
140
147
 
148
+ ## What's New in v20.18.1
149
+
150
+ ### Task skills survive compaction and update in place
151
+
152
+ - **Prompt-routed task skills now return after compaction.** The hook restores
153
+ the three most recently active task skills alongside the protected-floor
154
+ digest, so a short follow-up such as `continue` keeps the workflow and visual
155
+ verification rules that governed the work before context was compacted.
156
+ - **A completed managed-skill sync refreshes active task rules on the next
157
+ prompt.** The hook compares the materialized generation on disk with its
158
+ per-session state, re-authorizes every restored name against the current
159
+ manifest, and injects the current bodies. A downgrade clears stale paid task
160
+ state; Prism-managed directories cannot use the user-owned local-skill
161
+ exception.
162
+ - **User-owned local skills now route with their actual body.** A local
163
+ `SKILL.md` remains usable while signed out, while an entitled platform body
164
+ takes precedence if both sources use the same name.
165
+ - **Codex hook context is anchored to the user's request.** Routed rules tell
166
+ the model to execute the preceding user request with the rules applied,
167
+ avoiding the trailing developer-context placement being mistaken for a new
168
+ task. The anchor and all restored content share the 9,800-character limit.
169
+ - **Hook version 5 enforces its command version.** A still-running host with a
170
+ trusted v4 command cannot execute the rewritten v5 script. After upgrading,
171
+ run `prism connect --refresh --no-models`; Codex must trust both new v5 hook
172
+ entries in `/hooks`. Restart the host if it has not reloaded the new hook
173
+ definitions. Once v5 is active, later skill-body generations refresh on the
174
+ next prompt without another host restart.
175
+ - State names are validated and bounded before they become CLI arguments, and
176
+ the two-call refresh paths fit inside the host's 15-second hook timeout.
177
+
178
+ ## What's New in v20.18.0
179
+
180
+ ### The protected floor rides the bootstrap — and survives compaction
181
+
182
+ - **`session_bootstrap` now inlines a digest of the protected floor** on
183
+ paid tiers at standard and deep depth: one inert line per rule, derived
184
+ from each skill's first paragraph (or its pinned `digest:`), plus its
185
+ section map, ~5.6K chars for the full floor. Small-context hosts such as
186
+ Codex were re-reading the sixteen SKILL.md files every session (median 8
187
+ re-reads / 36KB, worst 823 / 5.1MB in rollout logs) because the bootstrap
188
+ only *named* them. The digest is paid for on top of the context budget, so
189
+ the ledger/handoff share at every depth is byte-identical to before. Quick
190
+ depth stays names-only — the opt-out.
191
+ - **A second hook re-injects the digest after compaction.** `prism connect`
192
+ registers the prism-route script on `SessionStart` matched to `compact`
193
+ (Claude Code and Codex); it runs `prism floor-digest`, which applies the
194
+ same tier and depth decisions as the bootstrap, and adds nothing on
195
+ startup/resume/clear. Hosts without hooks (Gemini, Cursor) still get the
196
+ digest on every bootstrap. **Codex: UNVERIFIED against a live compaction.**
197
+ The hook is registered and the script accepts the documented payload
198
+ spellings, but no Codex compaction has been observed end-to-end; on a
199
+ payload it does not recognise it re-injects nothing rather than something
200
+ wrong. If the digest comes from a generation whose skill files never
201
+ finished syncing, the re-injected block carries the same STALE warning the
202
+ bootstrap shows.
203
+ - **Codex trust is reported honestly after a hook rewrite.** Approvals are
204
+ keyed by definition hash, so a rewritten `hooks.json` — this release adds
205
+ the SessionStart entry — voids prior trust: connect prints AWAITING TRUST
206
+ for both entries instead of a green ✓ for a hook Codex would silently skip,
207
+ and trust recorded for an older hook version is never mistaken for current.
208
+ - **A host config that no longer parses is left alone.** If
209
+ `~/.claude/settings.json` or `~/.codex/hooks.json` exists but is not valid
210
+ JSON, connect keeps it byte-identical, registers no hook there, and says so
211
+ — it no longer replaces the file with a minimal hooks-only one. The npm
212
+ postinstall notice says the same, instead of asking you to trust a Codex
213
+ hook it never registered.
214
+ - Fixed: a symptom-routed skill whose closing frontmatter fence is its last
215
+ line was inlined with its YAML (triggers included) as if it were the rule.
216
+ - Fixed: a digest line that crosses into a new section keeps that section's
217
+ heading in front of it — whatever opened the section (an H2, a mid-document
218
+ H1, an empty heading, a setext underline) — so "Delegate to" / "Do NOT
219
+ delegate" rules cannot read with the wrong polarity once joined. A skill
220
+ file on disk is used only when it digests: empty, cut off inside its
221
+ frontmatter, or frontmatter-only files fall back to the stored copy instead
222
+ of rendering YAML as the rule.
223
+ - Fixed: on Windows, a Codex hook approval is recognised even though Codex
224
+ stores the path with escaped backslashes.
225
+ - The publish gate now refuses release notes that run *ahead* of the package
226
+ version (CHANGELOG, README, translated READMEs) — reading the newest
227
+ version on the heading line, so a `v20.17.3 – v20.18.0` range counts as
228
+ 20.18.0, and surviving a typographic apostrophe or a BOM.
229
+
141
230
  ## What's New in v20.17.3
142
231
 
143
232
  - **A plugin install can no longer enable the prompt-routing hook.** The
@@ -579,8 +668,8 @@ the host's final verification responsibility are unchanged.
579
668
  materializes entitled packages in the native `~/.agents/skills` directory
580
669
  before the command exits. Codex therefore sees the current skillset on its
581
670
  first launch instead of requiring a second restart. Prism rechecks the same
582
- snapshot at MCP startup, session load, and every five minutes—without host
583
- lifecycle hooks.
671
+ snapshot at MCP startup, session load, and every five minutes—skill delivery
672
+ never depends on a host lifecycle hook.
584
673
 
585
674
  On the first user turn, Prism's native skill, MCP metadata, and managed host
586
675
  instructions request one `session_bootstrap({})` call. Prism then uses the
@@ -613,7 +702,10 @@ sections from `~/CLAUDE.md`, preserves every other instruction, and installs a
613
702
  small ownership-marked native block that selects `session_bootstrap({})` on the
614
703
  first turn. User hooks, custom instruction sections, and near matches remain
615
704
  untouched; native skills and server-side reminders preserve those Prism
616
- features without host lifecycle hooks. Because hosts expose no native
705
+ features without depending on host lifecycle hooks. On Claude Code and Codex
706
+ connect additionally registers the prism-route script twice: on every prompt
707
+ (mid-session skill routing) and on `SessionStart` matched to `compact` only
708
+ (post-compaction protected-floor digest). Because hosts expose no native
617
709
  session-end callback, handoff at shutdown is instruction-driven rather than a
618
710
  guaranteed lifecycle event.
619
711
 
@@ -1376,27 +1468,32 @@ Prism works alongside these tools — use whichever fits your workflow.
1376
1468
 
1377
1469
  ### Web IDE — Prism Coder
1378
1470
 
1379
- A browser-based IDE at [synalux.ai/coder](https://synalux.ai/coder). Import any GitHub repo and get:
1471
+ Open [synalux.ai/coder](https://synalux.ai/coder), sign in, connect GitHub, and import a repository you can access. Select a branch, open a file, edit, and save back to GitHub.
1380
1472
 
1381
- - **Monaco editor** with multi-tab, split view, syntax highlighting, and VS Code keybindings
1382
- - **In-browser Node.js** via WebContainer (your code runs in the browser sandbox, not on a server)
1383
- - **Integrated terminal** — WebContainer shell in-browser; optional server PTY via WebSocket when connected to a dev server
1384
- - **AI Agent Mode** — describe a task and the agent creates files, runs type-checks, and verifies
1385
- - **Source control** — commit, branch, push/pull, stash, blame, tag management
1386
- - **Live Share** — real-time collaborative editing with session links
1387
- - **Node.js debugger** via Chrome DevTools Protocol
1388
- - **Tasks runner** (VS Code `tasks.json` compatible), **Problems panel** (Monaco diagnostics)
1389
- - **12-language i18n** — full UI localization
1473
+ - **Monaco editor** multiple tabs, split view, syntax highlighting, and familiar VS Code keybindings.
1474
+ - **GitHub editing** branch selection, file saves, history, and conflict protection. If a file changes remotely, a conflicting save keeps your local draft for recovery. Binary renames preserve bytes, and Unicode paths are supported.
1475
+ - **AI Agent Mode** — describe a task, review proposed file changes, apply selected changes, and save on an isolated agent branch. Rollback discards that branch and returns to your previous work.
1476
+ - **Live Share** — start a session and share its invite with repository members for synchronized edits and labeled remote cursors. First-party signaling is enabled on the hosted IDE.
1477
+ - **In-browser Node.js and terminal** — WebContainer runs package scripts and previews when the browser supports its runtime. The optional server PTY and Node.js debugger require a connected development server.
1478
+ - **Tasks and diagnostics** — a `tasks.json` runner and a Problems panel for Monaco diagnostics; localized interface strings are available in 12 languages.
1390
1479
 
1391
- <p align="center">
1392
- <img src="docs/screenshots/agent-mode.png" alt="Prism Coder IDE — Agent Mode creating a component with auto-fix and type-checking" width="500" />
1393
- </p>
1480
+ **Production session, September 8, 2026.** The following screenshots were captured from the live IDE using a private test repository. The session exercised GitHub import/save, conflict recovery, binary rename, Unicode files, Agent review/apply/save/rollback, and Live Share text and cursors in both directions.
1394
1481
 
1395
- <p align="center">
1396
- <img src="docs/screenshots/collaboration.png" alt="Prism Coder IDE — Live Share with team members and real-time cursor tracking" width="500" />
1397
- </p>
1482
+ **Review an Agent proposal before applying it.** The diff below proposes a new `add(a, b)` function. Selected changes were then applied and the exact file was saved to the agent branch; rollback was checked afterward.
1483
+
1484
+ ![Live Coder Agent diff showing a proposed add function and Apply selected changes](docs/screenshots/coder-agent-diff-20260908.png)
1485
+
1486
+ **Keep your draft when a remote edit conflicts.** The status bar reports the conflict while the unsaved local edit remains in the editor. Draft recovery was also checked after reloading.
1487
+
1488
+ ![Coder file editor retaining an unsaved draft with a remote-change conflict message](docs/screenshots/coder-conflict-draft-20260908.png)
1489
+
1490
+ **See collaborators' edits and cursors.** The host receives the guest's edit and cursor in the first capture. The guest receives the host's return edit and cursor in the second. These captures show two Safari tabs using the same authorized account; separate-user and cross-device connections were not covered by this run.
1491
+
1492
+ ![Live Share host with two participants and the guest cursor on a synchronized edit](docs/screenshots/coder-liveshare-host-20260908.png)
1493
+
1494
+ ![Live Share guest receiving the host return edit and labeled remote cursor](docs/screenshots/coder-liveshare-guest-20260908.png)
1398
1495
 
1399
- Standard+ plans get cloud AI and higher rate limits. Free tier works with local Ollama. Code execution uses the in-browser WebContainer by default; Live Share and the optional PTY terminal connect to external servers when explicitly enabled.
1496
+ **Runtime requirements.** Chrome or Edge is recommended for WebContainer package installation, tests, and previews; see [WebContainer browser support](https://developer.stackblitz.com/platform/webcontainers/browser-support). Safari editing and the workflows shown above were exercised, but npm installation still failed in this Safari session. Successful editing does not establish successful code execution. Agent test and type-check execution also depends on the runtime. Cloud AI requires the applicable plan and configured service; local Ollama requires an explicit connection.
1400
1497
 
1401
1498
  ### VS Code Extension — Synalux
1402
1499
 
package/dist/cli.js CHANGED
@@ -348,10 +348,16 @@ program
348
348
  const { ensurePromptRouteHook } = await import('./promptRouteHostHook.js');
349
349
  for (const r of ensurePromptRouteHook({ hosts: hookHosts, mode: 'explicit' })) {
350
350
  const state = r.script === 'unchanged' && r.config === 'unchanged' ? 'up to date' : 'installed';
351
- if (r.host === 'codex' && r.codexApproval === 'pending-or-unknown') {
351
+ if (r.config === 'skipped-unparseable') {
352
+ // The file was left byte-identical on purpose: replacing
353
+ // it would have wiped the operator's own settings along
354
+ // with the syntax error.
355
+ console.log(`⚠ ${r.host}: ${r.configPath} is not valid JSON — prism-route hooks NOT registered; fix the file and re-run prism connect`);
356
+ }
357
+ else if (r.host === 'codex' && r.codexApproval === 'pending-or-unknown') {
352
358
  // Codex silently skips untrusted hooks — a green "installed"
353
359
  // here would be the "configured and inert" lie.
354
- console.log(`⚠ codex: prism-route hook ${state}, AWAITING TRUST — run codex, then /hooks, and trust the entry ending prism-route/on_prompt.py`);
360
+ console.log(`⚠ codex: prism-route hook ${state}, AWAITING TRUST — run codex, then /hooks, and trust BOTH entries ending prism-route/on_prompt.py (UserPromptSubmit and SessionStart)`);
355
361
  }
356
362
  else if (r.host === 'codex' && r.codexApproval === 'state-present-unverifiable') {
357
363
  // Approvals are keyed by definition hash, whose algorithm is
@@ -362,7 +368,7 @@ program
362
368
  console.log(`− codex: prism-route hook ${state}; trust state exists but is not verifiable from here — confirm once in /hooks`);
363
369
  }
364
370
  else {
365
- console.log(`✓ ${r.host}: prism-route prompt hook ${state} (${r.scriptPath})`);
371
+ console.log(`✓ ${r.host}: prism-route hooks ${state} — prompt routing + post-compaction floor (${r.scriptPath})`);
366
372
  }
367
373
  }
368
374
  }
@@ -525,7 +531,11 @@ program
525
531
  const shaped = result.names.length > 0
526
532
  ? reshapeForInlineBudget(result, HOOK_INLINE_SAFE_CHARS, writeRouteOffload)
527
533
  : { text: '' };
528
- const payload = JSON.stringify({ names: result.names, text: result.names.length > 0 ? shaped.text : '' });
534
+ const payload = JSON.stringify({
535
+ names: result.names,
536
+ alreadyLoaded: result.alreadyLoaded,
537
+ text: result.names.length > 0 ? shaped.text : '',
538
+ });
529
539
  await new Promise((resolveWrite) => process.stdout.write(payload + '\n', () => resolveWrite()));
530
540
  }
531
541
  catch {
@@ -540,6 +550,68 @@ program
540
550
  process.exit(0);
541
551
  }
542
552
  });
553
+ // Re-inject the most recently active task skills after the host discards its
554
+ // transcript, or immediately after a new managed manifest reaches disk. Names
555
+ // are re-authorized against the cached manifest before any body is returned.
556
+ program
557
+ .command('reinject-skills')
558
+ .description('Render previously active, still-entitled skills for the host hook.')
559
+ .requiredOption('--names <names>', 'Comma-separated skill names from the hook session state')
560
+ .option('--budget <chars>', 'Maximum inline characters', String(9_800))
561
+ .action(async (options) => {
562
+ try {
563
+ const names = options.names.split(',').map((name) => name.trim()).filter(Boolean);
564
+ const requestedBudget = Number.parseInt(options.budget ?? '', 10);
565
+ const { runNamedSkillRouteFromCache } = await import('./tools/ledgerHandlers.js');
566
+ const { reshapeForInlineBudget, HOOK_INLINE_SAFE_CHARS } = await import('./tools/promptRouteHandler.js');
567
+ const budget = Number.isFinite(requestedBudget)
568
+ ? Math.max(256, Math.min(HOOK_INLINE_SAFE_CHARS, requestedBudget))
569
+ : HOOK_INLINE_SAFE_CHARS;
570
+ const result = await runNamedSkillRouteFromCache(names);
571
+ const shaped = result.names.length > 0
572
+ ? reshapeForInlineBudget(result, budget, writeRouteOffload)
573
+ : { text: '' };
574
+ const payload = JSON.stringify({ ok: true, names: result.names, text: result.names.length > 0 ? shaped.text : '' });
575
+ await new Promise((resolveWrite) => process.stdout.write(payload + '\n', () => resolveWrite()));
576
+ }
577
+ catch {
578
+ await new Promise((resolveWrite) => process.stdout.write('{"ok":false,"names":[],"text":""}\n', () => resolveWrite()));
579
+ }
580
+ finally {
581
+ try {
582
+ await closeStorage();
583
+ }
584
+ catch { /* exit anyway */ }
585
+ process.exit(0);
586
+ }
587
+ });
588
+ // ── floor-digest ──────────────────────────────────────────────
589
+ // Called by the same hook on SessionStart with source "compact": the host
590
+ // just discarded the bootstrap along with the rest of the transcript, and
591
+ // this is the protected floor coming back in one line per rule. Same
592
+ // contract as route-prompt — exit 0, one JSON line, cached DB and the local
593
+ // skills root only. Fires once per compaction, never per prompt.
594
+ program
595
+ .command('floor-digest')
596
+ .description('Print the protected-floor digest as {names, text} JSON. Used by the prism-route host hook after a context compaction.')
597
+ .action(async () => {
598
+ try {
599
+ const { renderProtectedFloorDigestForHook } = await import('./tools/ledgerHandlers.js');
600
+ const result = await renderProtectedFloorDigestForHook();
601
+ const payload = JSON.stringify({ names: result.names, text: result.text });
602
+ await new Promise((resolveWrite) => process.stdout.write(payload + '\n', () => resolveWrite()));
603
+ }
604
+ catch {
605
+ await new Promise((resolveWrite) => process.stdout.write('{"names":[],"text":""}\n', () => resolveWrite()));
606
+ }
607
+ finally {
608
+ try {
609
+ await closeStorage();
610
+ }
611
+ catch { /* exit anyway */ }
612
+ process.exit(0);
613
+ }
614
+ });
543
615
  program
544
616
  .command('load <project>')
545
617
  .description('Load session context for a project (same output as session_load_context MCP tool)')
@@ -23,9 +23,16 @@ try {
23
23
  // approval impossible to miss. Approval is per hook-version, not per
24
24
  // release: it recurs only when the hook script itself changes.
25
25
  const codex = results.find((r) => r.host === "codex");
26
- if (codex && codex.codexApproval === "pending-or-unknown") {
26
+ if (codex && codex.config === "skipped-unparseable") {
27
+ // Nothing was registered, so there is nothing to trust: telling the
28
+ // operator to press t in /hooks would send them looking for an entry
29
+ // that does not exist. The file was left byte-identical on purpose.
30
+ console.error(`\n[prism] Codex ${codex.configPath} is not valid JSON — prism-route hooks NOT registered.\n` +
31
+ "[prism] Fix the file, then run: prism connect --host codex\n");
32
+ }
33
+ else if (codex && codex.codexApproval === "pending-or-unknown") {
27
34
  console.error("\n[prism] Codex hook installed but NOT yet trusted — Codex silently skips it until you approve it once:\n" +
28
- "[prism] codex -> /hooks -> entry ending prism-route/on_prompt.py -> press t\n");
35
+ "[prism] codex -> /hooks -> BOTH entries ending prism-route/on_prompt.py (UserPromptSubmit + SessionStart) -> press t\n");
29
36
  }
30
37
  }
31
38
  catch {