@remixhq/claude-plugin 0.1.8 → 0.1.10

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "remix",
3
3
  "description": "Remix collaboration workflows for Claude Code",
4
- "version": "0.1.8",
4
+ "version": "0.1.10",
5
5
  "author": {
6
6
  "name": "Remix"
7
7
  },
package/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "remix": {
4
4
  "command": "node",
5
- "args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp-server.js"],
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp-server.cjs"],
6
6
  "cwd": "${CLAUDE_PLUGIN_ROOT}"
7
7
  }
8
8
  }
@@ -1,27 +1,50 @@
1
1
  #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
2
25
 
3
26
  // src/hook-state.ts
4
- import fs from "fs/promises";
5
- import os from "os";
6
- import path from "path";
7
- import { randomUUID } from "crypto";
27
+ var import_promises = __toESM(require("fs/promises"), 1);
28
+ var import_node_os = __toESM(require("os"), 1);
29
+ var import_node_path = __toESM(require("path"), 1);
30
+ var import_node_crypto = require("crypto");
8
31
  function stateRoot() {
9
- return path.join(os.tmpdir(), "remix-claude-plugin-hooks");
32
+ return import_node_path.default.join(import_node_os.default.tmpdir(), "remix-claude-plugin-hooks");
10
33
  }
11
34
  function statePath(sessionId) {
12
- return path.join(stateRoot(), `${sessionId}.json`);
35
+ return import_node_path.default.join(stateRoot(), `${sessionId}.json`);
13
36
  }
14
37
  function stateLockPath(sessionId) {
15
- return path.join(stateRoot(), `${sessionId}.lock`);
38
+ return import_node_path.default.join(stateRoot(), `${sessionId}.lock`);
16
39
  }
17
40
  function stateLockMetaPath(sessionId) {
18
- return path.join(stateLockPath(sessionId), "owner.json");
41
+ return import_node_path.default.join(stateLockPath(sessionId), "owner.json");
19
42
  }
20
43
  async function writeJsonAtomic(filePath, value) {
21
- await fs.mkdir(path.dirname(filePath), { recursive: true });
44
+ await import_promises.default.mkdir(import_node_path.default.dirname(filePath), { recursive: true });
22
45
  const tmpPath = `${filePath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
23
- await fs.writeFile(tmpPath, JSON.stringify(value, null, 2) + "\n", "utf8");
24
- await fs.rename(tmpPath, filePath);
46
+ await import_promises.default.writeFile(tmpPath, JSON.stringify(value, null, 2) + "\n", "utf8");
47
+ await import_promises.default.rename(tmpPath, filePath);
25
48
  }
26
49
  var STATE_LOCK_WAIT_MS = 2e3;
27
50
  var STATE_LOCK_POLL_MS = 25;
@@ -31,7 +54,7 @@ async function sleep(ms) {
31
54
  await new Promise((resolve) => setTimeout(resolve, ms));
32
55
  }
33
56
  async function readStateLockMetadata(sessionId) {
34
- const raw = await fs.readFile(stateLockMetaPath(sessionId), "utf8").catch(() => null);
57
+ const raw = await import_promises.default.readFile(stateLockMetaPath(sessionId), "utf8").catch(() => null);
35
58
  if (!raw) return null;
36
59
  try {
37
60
  const parsed = JSON.parse(raw);
@@ -56,13 +79,13 @@ async function tryRemoveStaleStateLock(sessionId) {
56
79
  const metadata = await readStateLockMetadata(sessionId);
57
80
  const staleByHeartbeat = metadata && Date.now() - new Date(metadata.heartbeatAt).getTime() > STATE_LOCK_STALE_MS;
58
81
  if (staleByHeartbeat) {
59
- await fs.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
82
+ await import_promises.default.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
60
83
  return true;
61
84
  }
62
85
  if (!metadata) {
63
- const lockStat = await fs.stat(lockPath).catch(() => null);
86
+ const lockStat = await import_promises.default.stat(lockPath).catch(() => null);
64
87
  if (lockStat && Date.now() - lockStat.mtimeMs > STATE_LOCK_STALE_MS) {
65
- await fs.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
88
+ await import_promises.default.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
66
89
  return true;
67
90
  }
68
91
  }
@@ -73,8 +96,8 @@ async function acquireStateLock(sessionId) {
73
96
  const deadline = Date.now() + STATE_LOCK_WAIT_MS;
74
97
  while (true) {
75
98
  try {
76
- await fs.mkdir(lockPath);
77
- const ownerId = randomUUID();
99
+ await import_promises.default.mkdir(lockPath);
100
+ const ownerId = (0, import_node_crypto.randomUUID)();
78
101
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
79
102
  const metadata = {
80
103
  ownerId,
@@ -98,7 +121,7 @@ async function acquireStateLock(sessionId) {
98
121
  clearInterval(heartbeat);
99
122
  const currentMetadata = await readStateLockMetadata(sessionId);
100
123
  if (currentMetadata?.ownerId === ownerId) {
101
- await fs.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
124
+ await import_promises.default.rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
102
125
  }
103
126
  };
104
127
  } catch (error) {
@@ -156,6 +179,8 @@ function normalizeTouchedRepo(value, repoRoot) {
156
179
  manuallyRecorded: Boolean(parsed.manuallyRecorded),
157
180
  manuallyRecordedAt: normalizeString(parsed.manuallyRecordedAt),
158
181
  manuallyRecordedByTool: normalizeString(parsed.manuallyRecordedByTool),
182
+ manualRecordingScope: parsed.manualRecordingScope === "change_step" || parsed.manualRecordingScope === "full_turn" ? parsed.manualRecordingScope : null,
183
+ manualRemoteChangeRecordedAt: normalizeString(parsed.manualRemoteChangeRecordedAt),
159
184
  stopAttempted: Boolean(parsed.stopAttempted),
160
185
  stopRecorded: Boolean(parsed.stopRecorded),
161
186
  stopRecordedAt: normalizeString(parsed.stopRecordedAt),
@@ -186,6 +211,8 @@ function createTouchedRepo(params) {
186
211
  manuallyRecorded: false,
187
212
  manuallyRecordedAt: null,
188
213
  manuallyRecordedByTool: null,
214
+ manualRecordingScope: null,
215
+ manualRemoteChangeRecordedAt: null,
189
216
  stopAttempted: false,
190
217
  stopRecorded: false,
191
218
  stopRecordedAt: null,
@@ -206,7 +233,7 @@ async function updatePendingTurnState(sessionId, updater) {
206
233
  });
207
234
  }
208
235
  async function loadPendingTurnState(sessionId) {
209
- const raw = await fs.readFile(statePath(sessionId), "utf8").catch(() => null);
236
+ const raw = await import_promises.default.readFile(statePath(sessionId), "utf8").catch(() => null);
210
237
  if (!raw) return null;
211
238
  try {
212
239
  const parsed = JSON.parse(raw);
@@ -281,6 +308,10 @@ async function markTouchedRepoManuallyRecorded(sessionId, repoRoot, params) {
281
308
  current.manuallyRecorded = true;
282
309
  current.manuallyRecordedAt = (/* @__PURE__ */ new Date()).toISOString();
283
310
  current.manuallyRecordedByTool = normalizeString(params?.toolName) ?? current.manuallyRecordedByTool;
311
+ current.manualRecordingScope = params?.scope ?? current.manualRecordingScope;
312
+ if (params?.remoteChangeRecorded) {
313
+ current.manualRemoteChangeRecordedAt = current.manuallyRecordedAt;
314
+ }
284
315
  current.recordingFailureMessage = null;
285
316
  current.recordingFailureHint = null;
286
317
  current.recordingFailedAt = null;
@@ -298,18 +329,18 @@ async function markPendingTurnConsultedMemory(sessionId) {
298
329
  }
299
330
 
300
331
  // src/hook-utils.ts
301
- import fs3 from "fs/promises";
302
- import path3 from "path";
332
+ var import_promises3 = __toESM(require("fs/promises"), 1);
333
+ var import_node_path2 = __toESM(require("path"), 1);
303
334
 
304
335
  // node_modules/@remixhq/core/dist/chunk-FAZUMWBS.js
305
- import fs2 from "fs/promises";
306
- import path2 from "path";
336
+ var import_promises2 = __toESM(require("fs/promises"), 1);
337
+ var import_path = __toESM(require("path"), 1);
307
338
  function getCollabBindingPath(repoRoot) {
308
- return path2.join(repoRoot, ".remix", "config.json");
339
+ return import_path.default.join(repoRoot, ".remix", "config.json");
309
340
  }
310
341
  async function readCollabBinding(repoRoot) {
311
342
  try {
312
- const raw = await fs2.readFile(getCollabBindingPath(repoRoot), "utf8");
343
+ const raw = await import_promises2.default.readFile(getCollabBindingPath(repoRoot), "utf8");
313
344
  const parsed = JSON.parse(raw);
314
345
  if (parsed?.schemaVersion !== 1) return null;
315
346
  if (!parsed.projectId || !parsed.currentAppId || !parsed.upstreamAppId) return null;
@@ -356,6 +387,16 @@ function extractToolResponse(payload) {
356
387
  function extractToolName(payload) {
357
388
  return extractString(payload, ["tool_name", "toolName"]);
358
389
  }
390
+ function normalizeHookToolName(toolName) {
391
+ if (!toolName) return null;
392
+ const trimmed = toolName.trim();
393
+ if (!trimmed) return null;
394
+ const remixToolIndex = trimmed.toLowerCase().indexOf("remix_collab_");
395
+ if (remixToolIndex >= 0) {
396
+ return trimmed.slice(remixToolIndex);
397
+ }
398
+ return trimmed;
399
+ }
359
400
  function extractString(input, keys) {
360
401
  for (const key of keys) {
361
402
  const value = input[key];
@@ -378,15 +419,38 @@ function extractToolCwd(payload) {
378
419
  const toolInput = extractToolInput(payload);
379
420
  return extractString(toolInput, ["cwd"]) ?? extractString(payload, ["cwd"]);
380
421
  }
422
+ function extractBashCommand(payload) {
423
+ const toolInput = extractToolInput(payload);
424
+ return extractString(toolInput, ["command", "cmd", "bash_command", "bashCommand"]);
425
+ }
426
+ function extractToolErrorMessage(payload) {
427
+ const toolResponse = extractToolResponse(payload);
428
+ const toolError = getNestedRecord(toolResponse?.error) ?? getNestedRecord(payload.error);
429
+ return extractString(toolError ?? {}, ["message"]) ?? extractString(toolResponse ?? {}, ["errorMessage", "message"]) ?? extractString(payload, ["errorMessage"]);
430
+ }
431
+ function extractToolStatus(payload) {
432
+ const toolResponse = extractToolResponse(payload);
433
+ return extractString(toolResponse ?? {}, ["status", "state"]) ?? extractString(payload, ["status", "state"]);
434
+ }
381
435
  function didToolSucceed(payload) {
382
436
  const toolResponse = extractToolResponse(payload);
383
437
  const explicitSuccess = toolResponse ? extractBoolean(toolResponse, ["success", "ok"]) : null;
384
438
  if (explicitSuccess !== null) {
385
439
  return explicitSuccess;
386
440
  }
441
+ if (extractToolErrorMessage(payload)) {
442
+ return false;
443
+ }
444
+ const status = extractToolStatus(payload)?.toLowerCase();
445
+ if (status === "error" || status === "failed" || status === "failure") {
446
+ return false;
447
+ }
387
448
  const hookEventName = extractString(payload, ["hook_event_name", "hookEventName"]);
388
449
  return hookEventName === "PostToolUse";
389
450
  }
451
+ function isRemoteChangeRecordedButLocalSyncFailed(payload) {
452
+ return extractToolErrorMessage(payload) === "Change step succeeded remotely, but automatic local sync failed.";
453
+ }
390
454
  function collectStringPathValue(value) {
391
455
  if (typeof value === "string" && value.trim()) return [value.trim()];
392
456
  if (Array.isArray(value)) {
@@ -398,7 +462,7 @@ function collectPathTargetsFromObject(input, keys) {
398
462
  return keys.flatMap((key) => collectStringPathValue(input[key]));
399
463
  }
400
464
  function resolveCandidatePath(targetPath, baseDir) {
401
- return path3.isAbsolute(targetPath) ? path3.normalize(targetPath) : path3.resolve(baseDir, targetPath);
465
+ return import_node_path2.default.isAbsolute(targetPath) ? import_node_path2.default.normalize(targetPath) : import_node_path2.default.resolve(baseDir, targetPath);
402
466
  }
403
467
  function extractToolPathTargets(payload, toolName) {
404
468
  const name = (toolName ?? extractToolName(payload) ?? "").trim().toLowerCase();
@@ -410,16 +474,16 @@ function extractToolPathTargets(payload, toolName) {
410
474
  }
411
475
  async function findBoundRepo(startPath) {
412
476
  if (!startPath) return null;
413
- let current = path3.resolve(startPath);
414
- let stats = await fs3.stat(current).catch(() => null);
477
+ let current = import_node_path2.default.resolve(startPath);
478
+ let stats = await import_promises3.default.stat(current).catch(() => null);
415
479
  if (stats?.isFile()) {
416
- current = path3.dirname(current);
480
+ current = import_node_path2.default.dirname(current);
417
481
  }
418
482
  while (true) {
419
- const bindingPath = path3.join(current, ".remix", "config.json");
420
- const bindingStats = await fs3.stat(bindingPath).catch(() => null);
483
+ const bindingPath = import_node_path2.default.join(current, ".remix", "config.json");
484
+ const bindingStats = await import_promises3.default.stat(bindingPath).catch(() => null);
421
485
  if (bindingStats?.isFile()) return current;
422
- const parent = path3.dirname(current);
486
+ const parent = import_node_path2.default.dirname(current);
423
487
  if (parent === current) return null;
424
488
  current = parent;
425
489
  }
@@ -450,9 +514,6 @@ async function resolveBoundRepoFromToolCwd(payload) {
450
514
  }
451
515
 
452
516
  // src/hook-post-collab.ts
453
- function isRecordingToolName(toolName) {
454
- return /remix_collab_(add|add_change_step|record_turn|record_no_diff_turn)$/i.test(toolName);
455
- }
456
517
  function isRepoMutationToolName(toolName) {
457
518
  return /remix_collab_(add|add_change_step|sync_apply|approve_and_sync_target|sync_upstream|reconcile_apply)$/i.test(toolName);
458
519
  }
@@ -462,20 +523,80 @@ function isMemoryToolName(toolName) {
462
523
  function isStructuredLocalWriteToolName(toolName) {
463
524
  return /^(Edit|MultiEdit|Write|Delete|NotebookEdit)$/i.test(toolName);
464
525
  }
526
+ function isStructuredLocalReadToolName(toolName) {
527
+ return /^Read$/i.test(toolName);
528
+ }
529
+ function isShellToolName(toolName) {
530
+ return /^Bash$/i.test(toolName);
531
+ }
532
+ function isRemoteChangeRecordingToolName(toolName) {
533
+ return /remix_collab_(add|add_change_step)$/i.test(toolName);
534
+ }
535
+ function getManualRecordingScope(toolName) {
536
+ if (/remix_collab_add_change_step$/i.test(toolName)) {
537
+ return "change_step";
538
+ }
539
+ if (/remix_collab_(add|record_turn|record_no_diff_turn)$/i.test(toolName)) {
540
+ return "full_turn";
541
+ }
542
+ return null;
543
+ }
544
+ function isLikelyMutatingShellCommand(command) {
545
+ const normalized = command.trim().toLowerCase();
546
+ if (!normalized) return false;
547
+ const readOnlyPatterns = [
548
+ /^pwd(?:\s|$)/,
549
+ /^ls(?:\s|$)/,
550
+ /^dir(?:\s|$)/,
551
+ /^tree(?:\s|$)/,
552
+ /^rg(?:\s|$)/,
553
+ /^git status(?:\s|$)/,
554
+ /^git diff(?:\s|$)/,
555
+ /^git log(?:\s|$)/,
556
+ /^git show(?:\s|$)/,
557
+ /^git branch(?:\s|$)/,
558
+ /^git rev-parse(?:\s|$)/,
559
+ /^git remote(?:\s|$)/,
560
+ /^git ls-files(?:\s|$)/,
561
+ /^cat(?:\s|$)/,
562
+ /^sed -n(?:\s|$)/,
563
+ /^head(?:\s|$)/,
564
+ /^tail(?:\s|$)/
565
+ ];
566
+ const mutatingPatterns = [
567
+ /\|\s*tee(?:\s|$)/,
568
+ /(^|[^\w-])>>?(?=[^&]|$)/,
569
+ /\bgit\b(?:\s+-[^\s]+)*\s+(add|apply|checkout|cherry-pick|clean|mv|restore|revert|rm|stash|switch)\b/,
570
+ /\b(mv|cp|rm|mkdir|rmdir|touch|chmod|chown|ln|install)\b/,
571
+ /\b(sed|perl|ruby)\b.*\s-i(?:\s|$)/,
572
+ /\b(npm|pnpm|yarn|bun)\b\s+(install|add|remove|update|upgrade)\b/
573
+ ];
574
+ const segments = normalized.split(/&&|\|\||;|\n/).map((segment) => segment.trim()).filter(Boolean);
575
+ if (mutatingPatterns.some((pattern) => pattern.test(normalized))) {
576
+ return true;
577
+ }
578
+ if (segments.length > 0 && segments.every((segment) => readOnlyPatterns.some((pattern) => pattern.test(segment)))) {
579
+ return false;
580
+ }
581
+ return false;
582
+ }
465
583
  async function main() {
466
584
  const payload = await readJsonStdin();
467
585
  const sessionId = typeof payload.session_id === "string" && payload.session_id.trim() ? payload.session_id.trim() : null;
468
- const toolName = extractToolName(payload);
586
+ const toolName = normalizeHookToolName(extractToolName(payload));
469
587
  if (!sessionId || !toolName) {
470
588
  return;
471
589
  }
472
- if (!didToolSucceed(payload)) {
590
+ const toolSucceeded = didToolSucceed(payload);
591
+ const remoteChangeRecordedButSyncFailed = isRemoteChangeRecordingToolName(toolName) && isRemoteChangeRecordedButLocalSyncFailed(payload);
592
+ if (!toolSucceeded && !remoteChangeRecordedButSyncFailed) {
473
593
  return;
474
594
  }
475
- if (isMemoryToolName(toolName)) {
595
+ if (toolSucceeded && isMemoryToolName(toolName)) {
476
596
  await markPendingTurnConsultedMemory(sessionId);
477
597
  }
478
- if (isRepoMutationToolName(toolName) || isRecordingToolName(toolName)) {
598
+ const manualRecordingScope = getManualRecordingScope(toolName);
599
+ if (isRepoMutationToolName(toolName) || manualRecordingScope) {
479
600
  const targetRepo = await resolveBoundRepoFromToolCwd(payload);
480
601
  if (targetRepo) {
481
602
  await upsertTouchedRepo(sessionId, {
@@ -486,15 +607,37 @@ async function main() {
486
607
  touchedBy: toolName,
487
608
  hasObservedWrite: isRepoMutationToolName(toolName)
488
609
  });
489
- if (isRepoMutationToolName(toolName)) {
610
+ if (toolSucceeded && isRepoMutationToolName(toolName)) {
490
611
  await markTouchedRepoObservedWrite(sessionId, targetRepo.repoRoot, { toolName });
491
612
  }
492
- if (isRecordingToolName(toolName)) {
493
- await markTouchedRepoManuallyRecorded(sessionId, targetRepo.repoRoot, { toolName });
613
+ if (manualRecordingScope) {
614
+ await markTouchedRepoManuallyRecorded(sessionId, targetRepo.repoRoot, {
615
+ toolName,
616
+ scope: manualRecordingScope,
617
+ remoteChangeRecorded: toolSucceeded ? isRemoteChangeRecordingToolName(toolName) : remoteChangeRecordedButSyncFailed
618
+ });
619
+ }
620
+ }
621
+ }
622
+ if (toolSucceeded && isShellToolName(toolName)) {
623
+ const targetRepo = await resolveBoundRepoFromToolCwd(payload);
624
+ if (targetRepo) {
625
+ const bashCommand = extractBashCommand(payload);
626
+ const hasObservedWrite = bashCommand ? isLikelyMutatingShellCommand(bashCommand) : false;
627
+ await upsertTouchedRepo(sessionId, {
628
+ repoRoot: targetRepo.repoRoot,
629
+ projectId: targetRepo.projectId,
630
+ currentAppId: targetRepo.currentAppId,
631
+ upstreamAppId: targetRepo.upstreamAppId,
632
+ touchedBy: toolName,
633
+ hasObservedWrite
634
+ });
635
+ if (hasObservedWrite) {
636
+ await markTouchedRepoObservedWrite(sessionId, targetRepo.repoRoot, { toolName });
494
637
  }
495
638
  }
496
639
  }
497
- if (isStructuredLocalWriteToolName(toolName)) {
640
+ if (toolSucceeded && (isStructuredLocalWriteToolName(toolName) || isStructuredLocalReadToolName(toolName))) {
498
641
  const touchedRepos = await resolveTouchedBoundReposFromPaths(extractToolPathTargets(payload, toolName));
499
642
  for (const repo of touchedRepos) {
500
643
  await upsertTouchedRepo(sessionId, {
@@ -503,9 +646,11 @@ async function main() {
503
646
  currentAppId: repo.currentAppId,
504
647
  upstreamAppId: repo.upstreamAppId,
505
648
  touchedBy: toolName,
506
- hasObservedWrite: true
649
+ hasObservedWrite: isStructuredLocalWriteToolName(toolName)
507
650
  });
508
- await markTouchedRepoObservedWrite(sessionId, repo.repoRoot, { toolName });
651
+ if (isStructuredLocalWriteToolName(toolName)) {
652
+ await markTouchedRepoObservedWrite(sessionId, repo.repoRoot, { toolName });
653
+ }
509
654
  }
510
655
  }
511
656
  }
@@ -515,4 +660,4 @@ main().catch((error) => {
515
660
  `);
516
661
  process.exitCode = 0;
517
662
  });
518
- //# sourceMappingURL=hook-post-collab.js.map
663
+ //# sourceMappingURL=hook-post-collab.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hook-state.ts","../src/hook-utils.ts","../node_modules/@remixhq/core/dist/chunk-FAZUMWBS.js","../src/hook-post-collab.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\n\nimport type { TurnIntent } from \"./history-routing.js\";\n\nexport type RepoRecordMode = \"changed_turn\" | \"no_diff_turn\";\nexport type ManualRecordingScope = \"change_step\" | \"full_turn\";\n\nexport type TouchedRepoState = {\n repoRoot: string;\n projectId: string | null;\n currentAppId: string | null;\n upstreamAppId: string | null;\n firstTouchedAt: string;\n lastTouchedAt: string;\n lastObservedWriteAt: string | null;\n touchedBy: string[];\n hasObservedWrite: boolean;\n manuallyRecorded: boolean;\n manuallyRecordedAt: string | null;\n manuallyRecordedByTool: string | null;\n manualRecordingScope: ManualRecordingScope | null;\n manualRemoteChangeRecordedAt: string | null;\n stopAttempted: boolean;\n stopRecorded: boolean;\n stopRecordedAt: string | null;\n stopRecordedMode: RepoRecordMode | null;\n recordingFailureMessage: string | null;\n recordingFailureHint: string | null;\n recordingFailedAt: string | null;\n};\n\nexport type PendingTurnState = {\n sessionId: string;\n turnId: string;\n prompt: string;\n initialCwd: string | null;\n intent: TurnIntent;\n submittedAt: string;\n consultedMemory: boolean;\n touchedRepos: Record<string, TouchedRepoState>;\n turnFailureMessage: string | null;\n turnFailureHint: string | null;\n turnFailedAt: string | null;\n};\n\nfunction stateRoot(): string {\n return path.join(os.tmpdir(), \"remix-claude-plugin-hooks\");\n}\n\nfunction statePath(sessionId: string): string {\n return path.join(stateRoot(), `${sessionId}.json`);\n}\n\nfunction stateLockPath(sessionId: string): string {\n return path.join(stateRoot(), `${sessionId}.lock`);\n}\n\nfunction stateLockMetaPath(sessionId: string): string {\n return path.join(stateLockPath(sessionId), \"owner.json\");\n}\n\nasync function writeJsonAtomic(filePath: string, value: unknown): Promise<void> {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n const tmpPath = `${filePath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;\n await fs.writeFile(tmpPath, JSON.stringify(value, null, 2) + \"\\n\", \"utf8\");\n await fs.rename(tmpPath, filePath);\n}\n\nconst STATE_LOCK_WAIT_MS = 2_000;\nconst STATE_LOCK_POLL_MS = 25;\nconst STATE_LOCK_STALE_MS = 30_000;\nconst STATE_LOCK_HEARTBEAT_MS = 5_000;\n\ntype StateLockMetadata = {\n ownerId: string;\n pid: number;\n createdAt: string;\n heartbeatAt: string;\n};\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function readStateLockMetadata(sessionId: string): Promise<StateLockMetadata | null> {\n const raw = await fs.readFile(stateLockMetaPath(sessionId), \"utf8\").catch(() => null);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as Partial<StateLockMetadata>;\n if (\n typeof parsed.ownerId !== \"string\" ||\n typeof parsed.pid !== \"number\" ||\n typeof parsed.createdAt !== \"string\" ||\n typeof parsed.heartbeatAt !== \"string\"\n ) {\n return null;\n }\n return {\n ownerId: parsed.ownerId,\n pid: parsed.pid,\n createdAt: parsed.createdAt,\n heartbeatAt: parsed.heartbeatAt,\n };\n } catch {\n return null;\n }\n}\n\nasync function writeStateLockMetadata(sessionId: string, metadata: StateLockMetadata): Promise<void> {\n await writeJsonAtomic(stateLockMetaPath(sessionId), metadata);\n}\n\nasync function tryRemoveStaleStateLock(sessionId: string): Promise<boolean> {\n const lockPath = stateLockPath(sessionId);\n const metadata = await readStateLockMetadata(sessionId);\n const staleByHeartbeat =\n metadata && Date.now() - new Date(metadata.heartbeatAt).getTime() > STATE_LOCK_STALE_MS;\n if (staleByHeartbeat) {\n await fs.rm(lockPath, { recursive: true, force: true }).catch(() => undefined);\n return true;\n }\n\n if (!metadata) {\n const lockStat = await fs.stat(lockPath).catch(() => null);\n if (lockStat && Date.now() - lockStat.mtimeMs > STATE_LOCK_STALE_MS) {\n await fs.rm(lockPath, { recursive: true, force: true }).catch(() => undefined);\n return true;\n }\n }\n\n return false;\n}\n\nasync function acquireStateLock(sessionId: string): Promise<() => Promise<void>> {\n const lockPath = stateLockPath(sessionId);\n const deadline = Date.now() + STATE_LOCK_WAIT_MS;\n\n while (true) {\n try {\n await fs.mkdir(lockPath);\n const ownerId = randomUUID();\n const createdAt = new Date().toISOString();\n const metadata: StateLockMetadata = {\n ownerId,\n pid: process.pid,\n createdAt,\n heartbeatAt: createdAt,\n };\n await writeStateLockMetadata(sessionId, metadata);\n let released = false;\n const heartbeat = setInterval(() => {\n if (released) return;\n void writeStateLockMetadata(sessionId, {\n ...metadata,\n heartbeatAt: new Date().toISOString(),\n }).catch(() => undefined);\n }, STATE_LOCK_HEARTBEAT_MS);\n heartbeat.unref?.();\n\n return async () => {\n if (released) return;\n released = true;\n clearInterval(heartbeat);\n const currentMetadata = await readStateLockMetadata(sessionId);\n if (currentMetadata?.ownerId === ownerId) {\n await fs.rm(lockPath, { recursive: true, force: true }).catch(() => undefined);\n }\n };\n } catch (error) {\n const code = error && typeof error === \"object\" && \"code\" in error ? (error as { code?: unknown }).code : null;\n if (code !== \"EEXIST\") {\n throw error;\n }\n\n if (await tryRemoveStaleStateLock(sessionId)) {\n continue;\n }\n\n if (Date.now() >= deadline) {\n throw new Error(`Timed out acquiring hook state lock for session ${sessionId}.`);\n }\n await sleep(STATE_LOCK_POLL_MS);\n }\n }\n}\n\nasync function withStateLock<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const release = await acquireStateLock(sessionId);\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n\nfunction normalizeIntent(value: unknown): TurnIntent {\n return value === \"memory_first\" || value === \"collab_state\" || value === \"git_facts\" ? value : \"neutral\";\n}\n\nfunction normalizeString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return Array.from(\n new Set(\n value\n .filter((entry): entry is string => typeof entry === \"string\" && entry.trim().length > 0)\n .map((entry) => entry.trim()),\n ),\n );\n}\n\nfunction normalizeTouchedRepo(value: unknown, repoRoot: string): TouchedRepoState | null {\n if (!value || typeof value !== \"object\") return null;\n const parsed = value as Partial<TouchedRepoState>;\n const normalizedRepoRoot = normalizeString(parsed.repoRoot) ?? repoRoot.trim();\n if (!normalizedRepoRoot) return null;\n\n return {\n repoRoot: normalizedRepoRoot,\n projectId: normalizeString(parsed.projectId),\n currentAppId: normalizeString(parsed.currentAppId),\n upstreamAppId: normalizeString(parsed.upstreamAppId),\n firstTouchedAt: normalizeString(parsed.firstTouchedAt) ?? new Date().toISOString(),\n lastTouchedAt: normalizeString(parsed.lastTouchedAt) ?? new Date().toISOString(),\n lastObservedWriteAt: normalizeString(parsed.lastObservedWriteAt),\n touchedBy: normalizeStringArray(parsed.touchedBy),\n hasObservedWrite: Boolean(parsed.hasObservedWrite),\n manuallyRecorded: Boolean(parsed.manuallyRecorded),\n manuallyRecordedAt: normalizeString(parsed.manuallyRecordedAt),\n manuallyRecordedByTool: normalizeString(parsed.manuallyRecordedByTool),\n manualRecordingScope:\n parsed.manualRecordingScope === \"change_step\" || parsed.manualRecordingScope === \"full_turn\"\n ? parsed.manualRecordingScope\n : null,\n manualRemoteChangeRecordedAt: normalizeString(parsed.manualRemoteChangeRecordedAt),\n stopAttempted: Boolean(parsed.stopAttempted),\n stopRecorded: Boolean(parsed.stopRecorded),\n stopRecordedAt: normalizeString(parsed.stopRecordedAt),\n stopRecordedMode: parsed.stopRecordedMode === \"changed_turn\" || parsed.stopRecordedMode === \"no_diff_turn\" ? parsed.stopRecordedMode : null,\n recordingFailureMessage: normalizeString(parsed.recordingFailureMessage),\n recordingFailureHint: normalizeString(parsed.recordingFailureHint),\n recordingFailedAt: normalizeString(parsed.recordingFailedAt),\n };\n}\n\nfunction normalizeTouchedRepos(value: unknown): Record<string, TouchedRepoState> {\n if (!value || typeof value !== \"object\") return {};\n const entries = Object.entries(value as Record<string, unknown>)\n .map(([repoRoot, repo]) => normalizeTouchedRepo(repo, repoRoot))\n .filter((repo): repo is TouchedRepoState => repo !== null)\n .sort((a, b) => a.repoRoot.localeCompare(b.repoRoot));\n return Object.fromEntries(entries.map((repo) => [repo.repoRoot, repo]));\n}\n\nfunction createTouchedRepo(params: {\n repoRoot: string;\n projectId?: string | null;\n currentAppId?: string | null;\n upstreamAppId?: string | null;\n touchedBy?: string | null;\n hasObservedWrite?: boolean;\n}): TouchedRepoState {\n const now = new Date().toISOString();\n const touchedBy = params.touchedBy?.trim() ? [params.touchedBy.trim()] : [];\n return {\n repoRoot: params.repoRoot,\n projectId: normalizeString(params.projectId),\n currentAppId: normalizeString(params.currentAppId),\n upstreamAppId: normalizeString(params.upstreamAppId),\n firstTouchedAt: now,\n lastTouchedAt: now,\n lastObservedWriteAt: params.hasObservedWrite ? now : null,\n touchedBy,\n hasObservedWrite: Boolean(params.hasObservedWrite),\n manuallyRecorded: false,\n manuallyRecordedAt: null,\n manuallyRecordedByTool: null,\n manualRecordingScope: null,\n manualRemoteChangeRecordedAt: null,\n stopAttempted: false,\n stopRecorded: false,\n stopRecordedAt: null,\n stopRecordedMode: null,\n recordingFailureMessage: null,\n recordingFailureHint: null,\n recordingFailedAt: null,\n };\n}\n\nasync function updatePendingTurnState(\n sessionId: string,\n updater: (state: PendingTurnState) => void | boolean,\n): Promise<PendingTurnState | null> {\n return withStateLock(sessionId, async () => {\n const existing = await loadPendingTurnState(sessionId);\n if (!existing) return null;\n const result = updater(existing);\n if (result === false) return existing;\n await savePendingTurnState(existing);\n return existing;\n });\n}\n\nexport async function loadPendingTurnState(sessionId: string): Promise<PendingTurnState | null> {\n const raw = await fs.readFile(statePath(sessionId), \"utf8\").catch(() => null);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as Partial<PendingTurnState>;\n if (!parsed || typeof parsed !== \"object\") return null;\n if (typeof parsed.sessionId !== \"string\" || typeof parsed.turnId !== \"string\" || typeof parsed.prompt !== \"string\") {\n return null;\n }\n return {\n sessionId: parsed.sessionId,\n turnId: parsed.turnId,\n prompt: parsed.prompt,\n initialCwd: normalizeString(parsed.initialCwd),\n intent: normalizeIntent(parsed.intent),\n submittedAt: typeof parsed.submittedAt === \"string\" ? parsed.submittedAt : new Date().toISOString(),\n consultedMemory: Boolean(parsed.consultedMemory),\n touchedRepos: normalizeTouchedRepos(parsed.touchedRepos),\n turnFailureMessage: normalizeString(parsed.turnFailureMessage),\n turnFailureHint: normalizeString(parsed.turnFailureHint),\n turnFailedAt: normalizeString(parsed.turnFailedAt),\n };\n } catch {\n return null;\n }\n}\n\nexport async function savePendingTurnState(state: PendingTurnState): Promise<void> {\n await writeJsonAtomic(statePath(state.sessionId), state);\n}\n\nexport async function createPendingTurnState(params: {\n sessionId: string;\n prompt: string;\n initialCwd?: string | null;\n intent: TurnIntent;\n}): Promise<PendingTurnState> {\n return withStateLock(params.sessionId, async () => {\n const state: PendingTurnState = {\n sessionId: params.sessionId,\n turnId: randomUUID(),\n prompt: params.prompt,\n initialCwd: params.initialCwd?.trim() || null,\n intent: params.intent,\n submittedAt: new Date().toISOString(),\n consultedMemory: false,\n touchedRepos: {},\n turnFailureMessage: null,\n turnFailureHint: null,\n turnFailedAt: null,\n };\n await savePendingTurnState(state);\n return state;\n });\n}\n\nexport async function upsertTouchedRepo(\n sessionId: string,\n params: {\n repoRoot: string;\n projectId?: string | null;\n currentAppId?: string | null;\n upstreamAppId?: string | null;\n touchedBy?: string | null;\n hasObservedWrite?: boolean;\n },\n): Promise<TouchedRepoState | null> {\n const normalizedRepoRoot = params.repoRoot.trim();\n if (!normalizedRepoRoot) return null;\n const state = await updatePendingTurnState(sessionId, (existing) => {\n const current =\n existing.touchedRepos[normalizedRepoRoot] ??\n createTouchedRepo({\n repoRoot: normalizedRepoRoot,\n projectId: params.projectId,\n currentAppId: params.currentAppId,\n upstreamAppId: params.upstreamAppId,\n touchedBy: params.touchedBy,\n hasObservedWrite: params.hasObservedWrite,\n });\n\n current.projectId = normalizeString(params.projectId) ?? current.projectId;\n current.currentAppId = normalizeString(params.currentAppId) ?? current.currentAppId;\n current.upstreamAppId = normalizeString(params.upstreamAppId) ?? current.upstreamAppId;\n current.lastTouchedAt = new Date().toISOString();\n if (params.touchedBy?.trim() && !current.touchedBy.includes(params.touchedBy.trim())) {\n current.touchedBy = [...current.touchedBy, params.touchedBy.trim()].sort((a, b) => a.localeCompare(b));\n }\n if (params.hasObservedWrite) {\n current.hasObservedWrite = true;\n current.lastObservedWriteAt = new Date().toISOString();\n }\n existing.touchedRepos[normalizedRepoRoot] = current;\n });\n return state?.touchedRepos[normalizedRepoRoot] ?? null;\n}\n\nexport async function markTouchedRepoObservedWrite(\n sessionId: string,\n repoRoot: string,\n params?: { toolName?: string | null },\n): Promise<void> {\n await upsertTouchedRepo(sessionId, {\n repoRoot,\n touchedBy: params?.toolName ?? null,\n hasObservedWrite: true,\n });\n}\n\nexport async function markTouchedRepoManuallyRecorded(\n sessionId: string,\n repoRoot: string,\n params?: { toolName?: string | null; scope?: ManualRecordingScope | null; remoteChangeRecorded?: boolean },\n): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n const normalizedRepoRoot = repoRoot.trim();\n if (!normalizedRepoRoot) return false;\n const current =\n existing.touchedRepos[normalizedRepoRoot] ??\n createTouchedRepo({\n repoRoot: normalizedRepoRoot,\n touchedBy: params?.toolName ?? null,\n hasObservedWrite: false,\n });\n current.lastTouchedAt = new Date().toISOString();\n current.manuallyRecorded = true;\n current.manuallyRecordedAt = new Date().toISOString();\n current.manuallyRecordedByTool = normalizeString(params?.toolName) ?? current.manuallyRecordedByTool;\n current.manualRecordingScope = params?.scope ?? current.manualRecordingScope;\n if (params?.remoteChangeRecorded) {\n current.manualRemoteChangeRecordedAt = current.manuallyRecordedAt;\n }\n current.recordingFailureMessage = null;\n current.recordingFailureHint = null;\n current.recordingFailedAt = null;\n if (params?.toolName?.trim() && !current.touchedBy.includes(params.toolName.trim())) {\n current.touchedBy = [...current.touchedBy, params.toolName.trim()].sort((a, b) => a.localeCompare(b));\n }\n existing.touchedRepos[normalizedRepoRoot] = current;\n });\n}\n\nexport async function markPendingTurnConsultedMemory(sessionId: string): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n if (existing.consultedMemory) return false;\n existing.consultedMemory = true;\n });\n}\n\nexport async function markTouchedRepoStopAttempted(sessionId: string, repoRoot: string): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n const current = existing.touchedRepos[repoRoot];\n if (!current) return false;\n current.stopAttempted = true;\n current.lastTouchedAt = new Date().toISOString();\n });\n}\n\nexport async function markTouchedRepoStopRecorded(\n sessionId: string,\n repoRoot: string,\n params: {\n mode: RepoRecordMode;\n },\n): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n const current = existing.touchedRepos[repoRoot];\n if (!current) return false;\n current.stopAttempted = true;\n current.stopRecorded = true;\n current.stopRecordedAt = new Date().toISOString();\n current.stopRecordedMode = params.mode;\n current.recordingFailureMessage = null;\n current.recordingFailureHint = null;\n current.recordingFailedAt = null;\n current.lastTouchedAt = new Date().toISOString();\n });\n}\n\nexport async function markTouchedRepoRecordingFailure(\n sessionId: string,\n repoRoot: string,\n params: {\n message: string;\n hint?: string | null;\n },\n): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n const current = existing.touchedRepos[repoRoot];\n if (!current) return false;\n current.stopAttempted = true;\n current.recordingFailureMessage = params.message.trim();\n current.recordingFailureHint = params.hint?.trim() || null;\n current.recordingFailedAt = new Date().toISOString();\n current.lastTouchedAt = new Date().toISOString();\n });\n}\n\nexport async function markPendingTurnFailure(\n sessionId: string,\n params: {\n message: string;\n hint?: string | null;\n },\n): Promise<void> {\n await updatePendingTurnState(sessionId, (existing) => {\n existing.turnFailureMessage = params.message.trim();\n existing.turnFailureHint = params.hint?.trim() || null;\n existing.turnFailedAt = new Date().toISOString();\n });\n}\n\nexport async function listTouchedRepos(sessionId: string): Promise<TouchedRepoState[]> {\n const existing = await loadPendingTurnState(sessionId);\n if (!existing) return [];\n return Object.values(existing.touchedRepos).sort((a, b) => a.repoRoot.localeCompare(b.repoRoot));\n}\n\nexport async function clearPendingTurnState(sessionId: string): Promise<void> {\n await withStateLock(sessionId, async () => {\n await fs.rm(statePath(sessionId), { force: true }).catch(() => undefined);\n });\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readCollabBinding } from \"@remixhq/core/binding\";\n\ntype BindingSummary = {\n repoRoot: string;\n projectId: string | null;\n currentAppId: string | null;\n upstreamAppId: string | null;\n};\n\nexport async function readJsonStdin(): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n const raw = Buffer.concat(chunks).toString(\"utf8\").trim();\n if (!raw) return {};\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n\nfunction getNestedRecord(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" ? (value as Record<string, unknown>) : null;\n}\n\nexport function extractToolInput(payload: Record<string, unknown>): Record<string, unknown> {\n return getNestedRecord(payload.tool_input) ?? getNestedRecord(payload.toolInput) ?? payload;\n}\n\nexport function extractToolResponse(payload: Record<string, unknown>): Record<string, unknown> | null {\n return getNestedRecord(payload.tool_response) ?? getNestedRecord(payload.toolResponse);\n}\n\nexport function extractToolName(payload: Record<string, unknown>): string | null {\n return extractString(payload, [\"tool_name\", \"toolName\"]);\n}\n\nexport function normalizeHookToolName(toolName: string | null): string | null {\n if (!toolName) return null;\n const trimmed = toolName.trim();\n if (!trimmed) return null;\n\n const remixToolIndex = trimmed.toLowerCase().indexOf(\"remix_collab_\");\n if (remixToolIndex >= 0) {\n return trimmed.slice(remixToolIndex);\n }\n\n return trimmed;\n}\n\nexport function extractAssistantResponse(payload: Record<string, unknown>): string | null {\n const candidateKeys = [\n \"last_assistant_message\",\n \"lastAssistantMessage\",\n \"assistant_response\",\n \"assistantResponse\",\n \"assistant_message\",\n \"assistantMessage\",\n \"response\",\n \"message\",\n ];\n\n return (\n extractString(payload, candidateKeys) ??\n extractString(extractToolResponse(payload) ?? {}, candidateKeys) ??\n extractString(extractToolInput(payload), candidateKeys)\n );\n}\n\nexport function extractString(input: Record<string, unknown>, keys: string[]): string | null {\n for (const key of keys) {\n const value = input[key];\n if (typeof value === \"string\" && value.trim()) {\n return value.trim();\n }\n }\n return null;\n}\n\nexport function extractBoolean(input: Record<string, unknown>, keys: string[]): boolean | null {\n for (const key of keys) {\n const value = input[key];\n if (typeof value === \"boolean\") {\n return value;\n }\n }\n return null;\n}\n\nexport function extractToolCwd(payload: Record<string, unknown>): string | null {\n const toolInput = extractToolInput(payload);\n return extractString(toolInput, [\"cwd\"]) ?? extractString(payload, [\"cwd\"]);\n}\n\nexport function extractBashCommand(payload: Record<string, unknown>): string | null {\n const toolInput = extractToolInput(payload);\n return extractString(toolInput, [\"command\", \"cmd\", \"bash_command\", \"bashCommand\"]);\n}\n\nexport function extractToolErrorMessage(payload: Record<string, unknown>): string | null {\n const toolResponse = extractToolResponse(payload);\n const toolError = getNestedRecord(toolResponse?.error) ?? getNestedRecord(payload.error);\n return (\n extractString(toolError ?? {}, [\"message\"]) ??\n extractString(toolResponse ?? {}, [\"errorMessage\", \"message\"]) ??\n extractString(payload, [\"errorMessage\"])\n );\n}\n\nfunction extractToolStatus(payload: Record<string, unknown>): string | null {\n const toolResponse = extractToolResponse(payload);\n return (\n extractString(toolResponse ?? {}, [\"status\", \"state\"]) ??\n extractString(payload, [\"status\", \"state\"])\n );\n}\n\nexport function didToolSucceed(payload: Record<string, unknown>): boolean {\n const toolResponse = extractToolResponse(payload);\n const explicitSuccess = toolResponse ? extractBoolean(toolResponse, [\"success\", \"ok\"]) : null;\n if (explicitSuccess !== null) {\n return explicitSuccess;\n }\n\n if (extractToolErrorMessage(payload)) {\n return false;\n }\n\n const status = extractToolStatus(payload)?.toLowerCase();\n if (status === \"error\" || status === \"failed\" || status === \"failure\") {\n return false;\n }\n\n const hookEventName = extractString(payload, [\"hook_event_name\", \"hookEventName\"]);\n return hookEventName === \"PostToolUse\";\n}\n\nexport function isRemoteChangeRecordedButLocalSyncFailed(payload: Record<string, unknown>): boolean {\n return extractToolErrorMessage(payload) === \"Change step succeeded remotely, but automatic local sync failed.\";\n}\n\nfunction collectStringPathValue(value: unknown): string[] {\n if (typeof value === \"string\" && value.trim()) return [value.trim()];\n if (Array.isArray(value)) {\n return value.flatMap((entry) => collectStringPathValue(entry));\n }\n return [];\n}\n\nfunction collectPathTargetsFromObject(input: Record<string, unknown>, keys: string[]): string[] {\n return keys.flatMap((key) => collectStringPathValue(input[key]));\n}\n\nfunction resolveCandidatePath(targetPath: string, baseDir: string): string {\n return path.isAbsolute(targetPath) ? path.normalize(targetPath) : path.resolve(baseDir, targetPath);\n}\n\nexport function extractToolPathTargets(payload: Record<string, unknown>, toolName?: string | null): string[] {\n const name = (toolName ?? extractToolName(payload) ?? \"\").trim().toLowerCase();\n const toolInput = extractToolInput(payload);\n const baseDir = extractToolCwd(payload) ?? process.cwd();\n const baseKeys = [\"path\", \"paths\", \"file_path\", \"filePath\", \"target_file\", \"targetFile\", \"filename\"];\n\n const targets =\n name === \"notebookedit\"\n ? collectPathTargetsFromObject(toolInput, [\"target_notebook\", \"notebook_path\", \"notebookPath\", ...baseKeys])\n : collectPathTargetsFromObject(toolInput, baseKeys);\n\n return Array.from(new Set(targets.map((entry) => resolveCandidatePath(entry, baseDir))));\n}\n\nexport async function findBoundRepo(startPath: string | null): Promise<string | null> {\n if (!startPath) return null;\n let current = path.resolve(startPath);\n let stats = await fs.stat(current).catch(() => null);\n if (stats?.isFile()) {\n current = path.dirname(current);\n }\n\n while (true) {\n const bindingPath = path.join(current, \".remix\", \"config.json\");\n const bindingStats = await fs.stat(bindingPath).catch(() => null);\n if (bindingStats?.isFile()) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nexport async function resolveBoundRepoSummary(startPath: string | null): Promise<BindingSummary | null> {\n const repoRoot = await findBoundRepo(startPath);\n if (!repoRoot) return null;\n const binding = await readCollabBinding(repoRoot).catch(() => null);\n if (!binding) return null;\n return {\n repoRoot,\n projectId: binding.projectId,\n currentAppId: binding.currentAppId,\n upstreamAppId: binding.upstreamAppId,\n };\n}\n\nexport async function resolveTouchedBoundReposFromPaths(paths: string[]): Promise<BindingSummary[]> {\n const resolved = await Promise.all(paths.map((targetPath) => resolveBoundRepoSummary(targetPath)));\n const unique = new Map<string, BindingSummary>();\n for (const repo of resolved) {\n if (!repo) continue;\n unique.set(repo.repoRoot, repo);\n }\n return Array.from(unique.values()).sort((a, b) => a.repoRoot.localeCompare(b.repoRoot));\n}\n\nexport async function resolveBoundRepoFromToolCwd(payload: Record<string, unknown>): Promise<BindingSummary | null> {\n return resolveBoundRepoSummary(extractToolCwd(payload));\n}\n","import {\n RemixError\n} from \"./chunk-YZ34ICNN.js\";\n\n// src/infrastructure/binding/collabBindingStore.ts\nimport fs2 from \"fs/promises\";\nimport path2 from \"path\";\n\n// src/shared/fs.ts\nimport fs from \"fs/promises\";\nimport path from \"path\";\nasync function reserveDirectory(targetDir) {\n try {\n await fs.mkdir(targetDir);\n return targetDir;\n } catch (error) {\n if (error?.code === \"EEXIST\") {\n throw new RemixError(\"Output directory already exists.\", {\n exitCode: 2,\n hint: `Choose an empty destination path: ${targetDir}`\n });\n }\n throw error;\n }\n}\nasync function reserveAvailableDirPath(preferredDir) {\n const parent = path.dirname(preferredDir);\n const base = path.basename(preferredDir);\n for (let i = 1; i <= 1e3; i += 1) {\n const candidate = i === 1 ? preferredDir : path.join(parent, `${base}-${i}`);\n try {\n await fs.mkdir(candidate);\n return candidate;\n } catch (error) {\n if (error?.code === \"EEXIST\") continue;\n throw error;\n }\n }\n throw new RemixError(\"No available output directory name.\", {\n exitCode: 2,\n hint: `Tried ${base} through ${base}-1000 under ${parent}.`\n });\n}\nasync function writeJsonAtomic(filePath, value) {\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = `${filePath}.tmp-${Date.now()}`;\n await fs.writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`, \"utf8\");\n await fs.rename(tmp, filePath);\n}\n\n// src/infrastructure/binding/collabBindingStore.ts\nfunction getCollabBindingPath(repoRoot) {\n return path2.join(repoRoot, \".remix\", \"config.json\");\n}\nasync function readCollabBinding(repoRoot) {\n try {\n const raw = await fs2.readFile(getCollabBindingPath(repoRoot), \"utf8\");\n const parsed = JSON.parse(raw);\n if (parsed?.schemaVersion !== 1) return null;\n if (!parsed.projectId || !parsed.currentAppId || !parsed.upstreamAppId) return null;\n return {\n schemaVersion: 1,\n projectId: parsed.projectId,\n currentAppId: parsed.currentAppId,\n upstreamAppId: parsed.upstreamAppId,\n threadId: parsed.threadId ?? null,\n repoFingerprint: parsed.repoFingerprint ?? null,\n remoteUrl: parsed.remoteUrl ?? null,\n defaultBranch: parsed.defaultBranch ?? null,\n preferredBranch: parsed.preferredBranch ?? parsed.defaultBranch ?? null\n };\n } catch {\n return null;\n }\n}\nasync function writeCollabBinding(repoRoot, binding) {\n const filePath = getCollabBindingPath(repoRoot);\n await writeJsonAtomic(filePath, {\n schemaVersion: 1,\n ...binding\n });\n return filePath;\n}\n\nexport {\n reserveDirectory,\n reserveAvailableDirPath,\n getCollabBindingPath,\n readCollabBinding,\n writeCollabBinding\n};\n","import {\n markPendingTurnConsultedMemory,\n markTouchedRepoManuallyRecorded,\n markTouchedRepoObservedWrite,\n upsertTouchedRepo,\n} from \"./hook-state.js\";\nimport {\n didToolSucceed,\n extractBashCommand,\n extractToolName,\n extractToolPathTargets,\n isRemoteChangeRecordedButLocalSyncFailed,\n normalizeHookToolName,\n readJsonStdin,\n resolveBoundRepoFromToolCwd,\n resolveTouchedBoundReposFromPaths,\n} from \"./hook-utils.js\";\n\nfunction isRepoMutationToolName(toolName: string): boolean {\n return /remix_collab_(add|add_change_step|sync_apply|approve_and_sync_target|sync_upstream|reconcile_apply)$/i.test(toolName);\n}\n\nfunction isMemoryToolName(toolName: string): boolean {\n return /remix_collab_memory_(summary|search|timeline|change_step_diff)$/i.test(toolName);\n}\n\nfunction isStructuredLocalWriteToolName(toolName: string): boolean {\n return /^(Edit|MultiEdit|Write|Delete|NotebookEdit)$/i.test(toolName);\n}\n\nfunction isStructuredLocalReadToolName(toolName: string): boolean {\n return /^Read$/i.test(toolName);\n}\n\nfunction isShellToolName(toolName: string): boolean {\n return /^Bash$/i.test(toolName);\n}\n\nfunction isRemoteChangeRecordingToolName(toolName: string): boolean {\n return /remix_collab_(add|add_change_step)$/i.test(toolName);\n}\n\nfunction getManualRecordingScope(toolName: string): \"change_step\" | \"full_turn\" | null {\n if (/remix_collab_add_change_step$/i.test(toolName)) {\n return \"change_step\";\n }\n if (/remix_collab_(add|record_turn|record_no_diff_turn)$/i.test(toolName)) {\n return \"full_turn\";\n }\n return null;\n}\n\nfunction isLikelyMutatingShellCommand(command: string): boolean {\n const normalized = command.trim().toLowerCase();\n if (!normalized) return false;\n\n const readOnlyPatterns = [\n /^pwd(?:\\s|$)/,\n /^ls(?:\\s|$)/,\n /^dir(?:\\s|$)/,\n /^tree(?:\\s|$)/,\n /^rg(?:\\s|$)/,\n /^git status(?:\\s|$)/,\n /^git diff(?:\\s|$)/,\n /^git log(?:\\s|$)/,\n /^git show(?:\\s|$)/,\n /^git branch(?:\\s|$)/,\n /^git rev-parse(?:\\s|$)/,\n /^git remote(?:\\s|$)/,\n /^git ls-files(?:\\s|$)/,\n /^cat(?:\\s|$)/,\n /^sed -n(?:\\s|$)/,\n /^head(?:\\s|$)/,\n /^tail(?:\\s|$)/,\n ];\n\n const mutatingPatterns = [\n /\\|\\s*tee(?:\\s|$)/,\n /(^|[^\\w-])>>?(?=[^&]|$)/,\n /\\bgit\\b(?:\\s+-[^\\s]+)*\\s+(add|apply|checkout|cherry-pick|clean|mv|restore|revert|rm|stash|switch)\\b/,\n /\\b(mv|cp|rm|mkdir|rmdir|touch|chmod|chown|ln|install)\\b/,\n /\\b(sed|perl|ruby)\\b.*\\s-i(?:\\s|$)/,\n /\\b(npm|pnpm|yarn|bun)\\b\\s+(install|add|remove|update|upgrade)\\b/,\n ];\n\n const segments = normalized\n .split(/&&|\\|\\||;|\\n/)\n .map((segment) => segment.trim())\n .filter(Boolean);\n\n if (mutatingPatterns.some((pattern) => pattern.test(normalized))) {\n return true;\n }\n\n if (segments.length > 0 && segments.every((segment) => readOnlyPatterns.some((pattern) => pattern.test(segment)))) {\n return false;\n }\n\n return false;\n}\n\nasync function main(): Promise<void> {\n const payload = await readJsonStdin();\n const sessionId = typeof payload.session_id === \"string\" && payload.session_id.trim() ? payload.session_id.trim() : null;\n const toolName = normalizeHookToolName(extractToolName(payload));\n if (!sessionId || !toolName) {\n return;\n }\n\n const toolSucceeded = didToolSucceed(payload);\n const remoteChangeRecordedButSyncFailed =\n isRemoteChangeRecordingToolName(toolName) && isRemoteChangeRecordedButLocalSyncFailed(payload);\n if (!toolSucceeded && !remoteChangeRecordedButSyncFailed) {\n return;\n }\n\n if (toolSucceeded && isMemoryToolName(toolName)) {\n await markPendingTurnConsultedMemory(sessionId);\n }\n\n const manualRecordingScope = getManualRecordingScope(toolName);\n if (isRepoMutationToolName(toolName) || manualRecordingScope) {\n const targetRepo = await resolveBoundRepoFromToolCwd(payload);\n if (targetRepo) {\n await upsertTouchedRepo(sessionId, {\n repoRoot: targetRepo.repoRoot,\n projectId: targetRepo.projectId,\n currentAppId: targetRepo.currentAppId,\n upstreamAppId: targetRepo.upstreamAppId,\n touchedBy: toolName,\n hasObservedWrite: isRepoMutationToolName(toolName),\n });\n if (toolSucceeded && isRepoMutationToolName(toolName)) {\n await markTouchedRepoObservedWrite(sessionId, targetRepo.repoRoot, { toolName });\n }\n if (manualRecordingScope) {\n await markTouchedRepoManuallyRecorded(sessionId, targetRepo.repoRoot, {\n toolName,\n scope: manualRecordingScope,\n remoteChangeRecorded: toolSucceeded\n ? isRemoteChangeRecordingToolName(toolName)\n : remoteChangeRecordedButSyncFailed,\n });\n }\n }\n }\n\n if (toolSucceeded && isShellToolName(toolName)) {\n const targetRepo = await resolveBoundRepoFromToolCwd(payload);\n if (targetRepo) {\n const bashCommand = extractBashCommand(payload);\n const hasObservedWrite = bashCommand ? isLikelyMutatingShellCommand(bashCommand) : false;\n await upsertTouchedRepo(sessionId, {\n repoRoot: targetRepo.repoRoot,\n projectId: targetRepo.projectId,\n currentAppId: targetRepo.currentAppId,\n upstreamAppId: targetRepo.upstreamAppId,\n touchedBy: toolName,\n hasObservedWrite,\n });\n if (hasObservedWrite) {\n await markTouchedRepoObservedWrite(sessionId, targetRepo.repoRoot, { toolName });\n }\n }\n }\n\n if (toolSucceeded && (isStructuredLocalWriteToolName(toolName) || isStructuredLocalReadToolName(toolName))) {\n const touchedRepos = await resolveTouchedBoundReposFromPaths(extractToolPathTargets(payload, toolName));\n for (const repo of touchedRepos) {\n await upsertTouchedRepo(sessionId, {\n repoRoot: repo.repoRoot,\n projectId: repo.projectId,\n currentAppId: repo.currentAppId,\n upstreamAppId: repo.upstreamAppId,\n touchedBy: toolName,\n hasObservedWrite: isStructuredLocalWriteToolName(toolName),\n });\n if (isStructuredLocalWriteToolName(toolName)) {\n await markTouchedRepoObservedWrite(sessionId, repo.repoRoot, { toolName });\n }\n }\n }\n}\n\nmain().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${message}\\n`);\n process.exitCode = 0;\n});\n"],"mappings":"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","names":["path","os","fs","import_promises","import_node_path","import_promises","path2","fs2","path","fs"]}