thinkpool-pair 0.7.218 → 0.7.220

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/bridge.mjs CHANGED
@@ -65,7 +65,7 @@ import { writeLaneArtifact, digestSlice, appendDigest, resumeLane } from './flow
65
65
  import { createFlowWorktree, worktreeSpec } from './flow-worktree.mjs'
66
66
  import { startPreview, stopAllPreviews, previews } from './flow-preview.mjs'
67
67
  import { ViewportManager, createViewportTools, sharedViewportBrowser } from './viewport.mjs'
68
- import { designPrompt, resolveDesignSource, syncRealtimeAuth, validateDesignRequest } from './design-edit.mjs'
68
+ import { designPrompt, resolveDesignSource, restoreDesignSources, syncRealtimeAuth, validateDesignRequest } from './design-edit.mjs'
69
69
  // FL-M9 — per-lane preview servers leak (one per done lane, never stopped until shutdown).
70
70
  // Lane previews are keyed `lane:<flowId>:<laneId>`; stop a whole flow's set when it assembles
71
71
  // (the assembled preview supersedes them) or when a lane is reverted.
@@ -1862,6 +1862,9 @@ function openStructured({ id, runtime = 'claude', model, effort, resume, log, co
1862
1862
  // they land on this session even after other terminals open/close.
1863
1863
  const mockupOutbox = ownerOutbox('sessions', id)
1864
1864
  entry.mockupWatcher = watchOutbox(mockupOutbox, () => id, true)
1865
+ const restoredDesigns = restoreDesignSources(mockupOutbox, cwd || process.cwd(), id)
1866
+ for (const record of restoredDesigns) designArtifacts.set(record.previewId, record)
1867
+ if (restoredDesigns.length) process.stderr.write(`\n ◆ restored ${restoredDesigns.length} Thinkpool Design artifact${restoredDesigns.length === 1 ? '' : 's'} (${id.slice(0, 8)}).\n`)
1865
1868
  // Visual QA runs in the bridge process, outside either agent runtime's sandbox.
1866
1869
  // It remains scoped to this lane's cwd and private mockup outbox.
1867
1870
  entry.viewport = new ViewportManager({ workspaceRoot: cwd || process.cwd(), ownerId: id, outbox: mockupOutbox })
@@ -21,7 +21,7 @@ import { sanitizeSession } from './transcript-sanitize.mjs'
21
21
  import { reviewGatePreToolDecision } from './flow-review-gate.mjs'
22
22
  import { crossPostNeedsCard } from './cross-terminal.mjs'
23
23
  import { correctContext } from './context-windows.mjs'
24
- import { THINKPOOL_REMOTE_DELIVERY_RULES } from './thinkpool-room-prompt.mjs'
24
+ import { THINKPOOL_DESIGN_DELIVERY_RULE, THINKPOOL_REMOTE_DELIVERY_RULES } from './thinkpool-room-prompt.mjs'
25
25
  import { stallDecision, stallEvent, isCompactTurn } from './turn-stall.mjs'
26
26
 
27
27
  // The caret-pulled SDK's real version (^0.3.x auto-upgrades on restart). Resolved
@@ -196,7 +196,8 @@ const MODES = new Set(['default', 'acceptEdits', 'plan', 'bypassPermissions'])
196
196
  // the bridge's roomContext callback — see roomReminder() inside startClaudeSession.
197
197
  const TP_ROOM_REMINDER = [
198
198
  'You are Claude in a ThinkPool Code room, driven live from a phone or browser — NOT a local terminal. Keep using the room\'s features.',
199
- 'ARTIFACTS: never hand the room a local path, a file:// URL, a localhost address, an `open …`/Preview reference, or "it\'s in ~/claude-shots/" — the room cannot see the host. Surface every image by reading the PNG into your turn so it renders inline; for HTML — mockups and mockup-iterate output included — use the $TP_MOCKUP_OUTBOX render helper (inline desktop+mobile card) and/or publish to a GitHub Pages URL and post that link.',
199
+ 'ARTIFACTS: never hand the room a local path, a file:// URL, a localhost address, an `open …`/Preview reference, or "it\'s in ~/claude-shots/" — the room cannot see the host. Surface every image by reading the PNG into your turn so it renders inline.',
200
+ THINKPOOL_DESIGN_DELIVERY_RULE,
200
201
  'REMOTE USER: the people here may have no terminal and no access to this host — never ask them to run a local command, open a local file, or check something on the machine. Anything host-side, YOU run, and show the result.',
201
202
  'SHOW, don\'t narrate: a picture of the result beats a wall of text on a phone — err toward more screenshots.',
202
203
  'ENSEMBLE: delegated work goes through the room — fan parallel work out with spawn_terminal (your own fresh lanes, visible and steerable by the people here), NOT the built-in invisible Task/Agent subagents; never hijack a busy sibling.',
package/design-edit.mjs CHANGED
@@ -48,6 +48,44 @@ export function resolveDesignSource(file, workspaceRoot) {
48
48
  return { previewId, revision, sourcePath, workspaceRoot: root, source }
49
49
  }
50
50
 
51
+ // Design provenance is intentionally host-only, but it must survive a bridge
52
+ // restart. Rebuild the in-memory registry from manifests already written by the
53
+ // trusted lane render workflow; do not re-upload or re-broadcast old cards.
54
+ export function restoreDesignSources(box, workspaceRoot, term, limit = 100) {
55
+ if (!box || !workspaceRoot || !term) return []
56
+ let files
57
+ try {
58
+ files = fs.readdirSync(box, { withFileTypes: true })
59
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.json') && !entry.name.endsWith('.receipt.json'))
60
+ .map((entry) => {
61
+ const file = path.join(box, entry.name)
62
+ return { file, mtimeMs: fs.statSync(file).mtimeMs }
63
+ })
64
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)
65
+ .slice(0, Math.max(0, limit))
66
+ } catch { return [] }
67
+ const restored = []
68
+ for (const { file } of files) {
69
+ try {
70
+ const manifest = JSON.parse(fs.readFileSync(file, 'utf8'))
71
+ if (!manifest?.source) continue
72
+ const record = resolveDesignSource(manifest.source, workspaceRoot)
73
+ if (!record) continue
74
+ Object.assign(record, {
75
+ term,
76
+ slug: String(manifest.slug || ''),
77
+ title: String(manifest.title || manifest.slug || ''),
78
+ desktop: manifest.desktop || null,
79
+ mobile: manifest.mobile || null,
80
+ })
81
+ const backupPath = path.join(box, '.design-revisions', `${record.revision}.html`)
82
+ if (fs.existsSync(backupPath)) record.backupPath = backupPath
83
+ restored.push(record)
84
+ } catch { /* stale or malformed manifests are ignored */ }
85
+ }
86
+ return restored
87
+ }
88
+
51
89
  function safeTarget(value) {
52
90
  if (!value || typeof value !== 'object') return null
53
91
  const rect = value.rect && typeof value.rect === 'object' ? {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.218",
3
+ "version": "0.7.220",
4
4
  "description": "Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -3,13 +3,15 @@
3
3
  // the first human turn in each fresh native thread. Keep the runtime-specific
4
4
  // orchestration rules in their own drivers — these are the cross-runtime truths
5
5
  // about where the people are and how finished work must reach them.
6
+ export const THINKPOOL_DESIGN_DELIVERY_RULE = 'THINKPOOL DESIGN (mandatory for HTML): save the editable HTML source in the workspace, then use the $TP_MOCKUP_OUTBOX render helper so the room receives a Thinkpool Design card with both desktop (1440×900) and mobile (390×844) previews. Never paste raw HTML into chat, send an .html file as the room deliverable, or substitute a bare URL or single screenshot for this card. A shareable browser URL may accompany the card, but never replaces it.'
7
+
6
8
  export const THINKPOOL_REMOTE_DELIVERY_RULES = Object.freeze([
7
9
  'REMOTE USER (authoritative default for ThinkPool Code rooms): unless a person explicitly says they are at the host machine, assume everyone driving this room is remote — possibly on a phone — with no terminal and no access to the host filesystem. Never ask them to run a local command, open a local file, or "go check" something on the machine. Anything host-side, you run yourself and show the result in the room. Only suggest actions they can actually do from the room UI or a browser.',
8
10
  'LINKS & ARTIFACTS: a local filesystem path, file:// URL, localhost/127.0.0.1 address, or host-only preview is useless to a remote room. Every link you surface must be reachable by the people in the room.',
9
- 'Whenever you produce HTML or shareable markup — a demo, mockup, preview, report, or page — publish it to a browser-renderable GitHub-shareable URL, normally GitHub Pages (or an equivalent URL that actually renders; raw.githubusercontent.com serves HTML as plain text). Give the room that shareable URL, never only a local path. If you cannot publish it, say so and ask how to proceed instead of falling back to a host-only path.',
11
+ 'Whenever you produce HTML or shareable markup — a demo, mockup, preview, report, or page — publish it to a browser-renderable GitHub-shareable URL, normally GitHub Pages (or an equivalent URL that actually renders; raw.githubusercontent.com serves HTML as plain text). Give the room that shareable URL in addition to the Thinkpool Design card, never instead of it and never only as a local path. If you cannot publish it, say so instead of falling back to a host-only path.',
10
12
  'SHOW VISUAL WORK: whenever you build, change, or fix anything visual — UI, page, HTML artifact, chart, diagram, or rendered result — capture a PNG and surface the image in your turn so it appears inline in the room; the room auto-uploads surfaced images. Prefer showing the result over describing it.',
11
13
  'BRIDGE PREVIEWS: for a built web UI, use preview_start (default root: dist), then preview_capture for exact desktop 1440x900 and mobile 390x844 PNGs, and preview_inspect when DOM text or selector geometry helps. Run the project build first and stop the preview server with preview_stop when done.',
12
- 'HTML PREVIEWS: when a mockup render helper is available through $TP_MOCKUP_OUTBOX, use it to surface the inline desktop-and-mobile preview card. Also publish the artifact and post its shareable browser URL. Never leave HTML viewable only on the host.',
14
+ THINKPOOL_DESIGN_DELIVERY_RULE,
13
15
  'VERIFY BEFORE CLAIMING: run or serve what you changed, observe it, and show the evidence in the room — the PNG, passing test output, or real response. If something could not be verified, say exactly what remains unverified.',
14
16
  ])
15
17