@remixhq/claude-plugin 0.1.14 → 0.1.15
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/.claude-plugin/plugin.json +1 -1
- package/agents/remix-collab.md +2 -0
- package/dist/hook-post-collab.cjs +3 -3
- package/dist/hook-post-collab.cjs.map +1 -1
- package/dist/hook-stop-collab.cjs +7 -4
- package/dist/hook-stop-collab.cjs.map +1 -1
- package/dist/hook-user-prompt.cjs +3 -3
- package/dist/hook-user-prompt.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.cjs +36 -6
- package/dist/mcp-server.cjs.map +1 -1
- package/package.json +3 -3
- package/skills/identity-and-scope-routing/SKILL.md +4 -0
- package/skills/init-or-remix/SKILL.md +8 -3
package/agents/remix-collab.md
CHANGED
|
@@ -33,6 +33,8 @@ When appropriate:
|
|
|
33
33
|
- use `remix_collab_init` to bind the current repo
|
|
34
34
|
- use `remix_collab_remix` to start from an existing app lineage
|
|
35
35
|
- use `remix_collab_checkout` to continue work on an existing app id without creating a fork
|
|
36
|
+
- when helping the user choose an app, prefer scoped or membership-oriented discovery first: use `organizationId` / `projectId` when known, or use `ownership` with `accessScope="explicit_member"` when the user means “apps I can work on”
|
|
37
|
+
- reserve `accessScope="all_readable"` for explicit public or broad readable discovery, not as the default work-oriented app picker
|
|
36
38
|
- use memory summary/search/timeline tools before repo inspection when historical context or reasoning is needed
|
|
37
39
|
- use the explicit change-step diff tool only after you already know which `changeStepId` matters
|
|
38
40
|
- use `remix_collab_finalize_turn` as the final turn recorder
|
|
@@ -351,7 +351,7 @@ async function markPendingTurnConsultedMemory(sessionId) {
|
|
|
351
351
|
// package.json
|
|
352
352
|
var package_default = {
|
|
353
353
|
name: "@remixhq/claude-plugin",
|
|
354
|
-
version: "0.1.
|
|
354
|
+
version: "0.1.15",
|
|
355
355
|
description: "Claude Code plugin for Remix collaboration workflows",
|
|
356
356
|
homepage: "https://github.com/RemixDotOne/remix-claude-plugin",
|
|
357
357
|
license: "MIT",
|
|
@@ -382,8 +382,8 @@ var package_default = {
|
|
|
382
382
|
prepack: "npm run build"
|
|
383
383
|
},
|
|
384
384
|
dependencies: {
|
|
385
|
-
"@remixhq/core": "^0.1.
|
|
386
|
-
"@remixhq/mcp": "^0.1.
|
|
385
|
+
"@remixhq/core": "^0.1.10",
|
|
386
|
+
"@remixhq/mcp": "^0.1.10"
|
|
387
387
|
},
|
|
388
388
|
devDependencies: {
|
|
389
389
|
"@types/node": "^25.4.0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hook-post-collab.ts","../src/hook-diagnostics.ts","../src/hook-state.ts","../package.json","../src/metadata.ts","../src/hook-utils.ts","../node_modules/@remixhq/core/dist/chunk-GEHSFPCD.js"],"sourcesContent":["import { appendHookDiagnosticsEvent } from \"./hook-diagnostics.js\";\nimport { markPendingTurnConsultedMemory, markTouchedRepoManuallyRecorded, markTouchedRepoObservedWrite, upsertTouchedRepo } from \"./hook-state.js\";\nimport {\n didToolSucceed,\n extractAssistantResponse,\n extractBashCommand,\n extractFinalizeTurnMode,\n extractString,\n extractToolName,\n extractToolInput,\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 hasManualFullTurnPayload(payload: Record<string, unknown>): boolean {\n const toolInput = extractToolInput(payload);\n return Boolean(extractString(toolInput, [\"prompt\"]) && extractAssistantResponse(payload));\n}\n\nfunction getManualRecordingScope(payload: Record<string, unknown>, toolName: string): \"change_step\" | \"full_turn\" | null {\n if (/remix_collab_finalize_turn$/i.test(toolName)) {\n return \"full_turn\";\n }\n if (/remix_collab_(add|add_change_step)$/i.test(toolName)) {\n return hasManualFullTurnPayload(payload) ? \"full_turn\" : \"change_step\";\n }\n if (/remix_collab_(record_turn|record_no_diff_turn)$/i.test(toolName)) {\n return \"full_turn\";\n }\n return null;\n}\n\nfunction didFinalizeTurnRecordRemoteChange(payload: Record<string, unknown>, toolName: string): boolean {\n if (!/remix_collab_finalize_turn$/i.test(toolName)) {\n return false;\n }\n return extractFinalizeTurnMode(payload) === \"changed_turn\";\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\nexport async function runHookPostCollab(payload: Record<string, unknown>): Promise<void> {\n const sessionId = typeof payload.session_id === \"string\" && payload.session_id.trim() ? payload.session_id.trim() : null;\n const toolName = normalizeHookToolName(extractToolName(payload));\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"payload_received\",\n result: \"start\",\n toolName,\n fields: {\n hasSessionId: Boolean(sessionId),\n hasToolName: Boolean(toolName),\n },\n });\n\n if (!sessionId || !toolName) {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"payload_validation\",\n result: \"skip\",\n reason: !sessionId ? \"missing_session_id\" : \"missing_tool_name\",\n toolName,\n });\n return;\n }\n\n const toolSucceeded = didToolSucceed(payload);\n const remoteChangeRecordedButSyncFailed =\n (isRemoteChangeRecordingToolName(toolName) || /remix_collab_finalize_turn$/i.test(toolName)) &&\n isRemoteChangeRecordedButLocalSyncFailed(payload);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"tool_classified\",\n result: \"info\",\n toolName,\n fields: {\n toolSucceeded,\n remoteChangeRecordedButSyncFailed,\n isMemoryTool: isMemoryToolName(toolName),\n isRepoMutationTool: isRepoMutationToolName(toolName),\n isShellTool: isShellToolName(toolName),\n isStructuredLocalWriteTool: isStructuredLocalWriteToolName(toolName),\n isStructuredLocalReadTool: isStructuredLocalReadToolName(toolName),\n },\n });\n if (!toolSucceeded && !remoteChangeRecordedButSyncFailed) {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"tool_result_gate\",\n result: \"skip\",\n reason: \"tool_failed_or_skipped\",\n toolName,\n });\n return;\n }\n\n if (toolSucceeded && isMemoryToolName(toolName)) {\n await markPendingTurnConsultedMemory(sessionId);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"memory_marked_consulted\",\n result: \"success\",\n toolName,\n });\n }\n\n const manualRecordingScope = getManualRecordingScope(payload, 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) || didFinalizeTurnRecordRemoteChange(payload, toolName)\n : remoteChangeRecordedButSyncFailed,\n });\n }\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"repo_marked_from_tool_cwd\",\n result: \"success\",\n toolName,\n repoRoot: targetRepo.repoRoot,\n fields: {\n hasObservedWrite: isRepoMutationToolName(toolName),\n manualRecordingScope,\n remoteChangeRecordedButSyncFailed,\n },\n });\n } else {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"repo_marked_from_tool_cwd\",\n result: \"skip\",\n reason: \"repo_not_bound_from_tool_cwd\",\n toolName,\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 await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"shell_repo_marked\",\n result: \"success\",\n toolName,\n repoRoot: targetRepo.repoRoot,\n fields: {\n hasObservedWrite,\n bashCommandLength: bashCommand?.length ?? 0,\n },\n });\n } else {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"shell_repo_marked\",\n result: \"skip\",\n reason: \"repo_not_bound_from_shell_cwd\",\n toolName,\n });\n }\n }\n\n if (toolSucceeded && (isStructuredLocalWriteToolName(toolName) || isStructuredLocalReadToolName(toolName))) {\n const touchedPaths = extractToolPathTargets(payload, toolName);\n const touchedRepos = await resolveTouchedBoundReposFromPaths(touchedPaths);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"path_targets_resolved\",\n result: touchedRepos.length > 0 ? \"info\" : \"skip\",\n reason: touchedRepos.length > 0 ? null : \"no_bound_repos_from_paths\",\n toolName,\n fields: {\n touchedPathCount: touchedPaths.length,\n boundRepoCount: touchedRepos.length,\n },\n });\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 await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"path_repo_marked\",\n result: \"success\",\n toolName,\n repoRoot: repo.repoRoot,\n fields: {\n hasObservedWrite: isStructuredLocalWriteToolName(toolName),\n },\n });\n }\n }\n\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"completed\",\n result: \"success\",\n toolName,\n });\n}\n\nasync function main(): Promise<void> {\n const payload = await readJsonStdin();\n await runHookPostCollab(payload);\n}\n\nmain().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n void appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n stage: \"unhandled_error\",\n result: \"error\",\n reason: \"exception\",\n message,\n });\n process.stderr.write(`${message}\\n`);\n process.exitCode = 0;\n});\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { getPendingTurnStateRootPath, listPendingTurnStateSummaries, type PendingTurnStateSummary } from \"./hook-state.js\";\nimport { pluginMetadata } from \"./metadata.js\";\n\ntype HookDiagnosticsResult = \"start\" | \"info\" | \"skip\" | \"success\" | \"error\";\ntype HookDiagnosticsFieldValue = string | number | boolean | null;\n\nexport type HookDiagnosticsEvent = {\n ts: string;\n hook: string;\n pluginVersion: string;\n pid: number;\n sessionId: string | null;\n turnId: string | null;\n stage: string;\n result: HookDiagnosticsResult;\n reason: string | null;\n toolName: string | null;\n repoRoot: string | null;\n message: string | null;\n fields: Record<string, HookDiagnosticsFieldValue>;\n};\n\nexport type HookDiagnosticsReport = {\n logPath: string;\n stateRoot: string;\n recentEvents: HookDiagnosticsEvent[];\n pendingStates: PendingTurnStateSummary[];\n};\n\nconst DEFAULT_EVENT_LIMIT = 50;\nconst MAX_EVENT_LIMIT = 200;\nconst MAX_LOG_BYTES = 512 * 1024;\n\nfunction resolveClaudeRoot(): string {\n const configured = process.env.CLAUDE_CONFIG_DIR?.trim();\n return configured || path.join(os.homedir(), \".claude\");\n}\n\nfunction resolvePluginDataDirName(): string {\n return `${pluginMetadata.pluginId}-${pluginMetadata.pluginId}`;\n}\n\nexport function getHookDiagnosticsDirPath(): string {\n const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_DIAGNOSTICS_DIR?.trim();\n return configured || path.join(resolveClaudeRoot(), \"plugins\", \"data\", resolvePluginDataDirName());\n}\n\nexport function getHookDiagnosticsLogPath(): string {\n return path.join(getHookDiagnosticsDirPath(), \"hooks.ndjson\");\n}\n\nfunction clampEventLimit(limit?: number): number {\n if (typeof limit !== \"number\" || !Number.isFinite(limit)) return DEFAULT_EVENT_LIMIT;\n return Math.max(1, Math.min(MAX_EVENT_LIMIT, Math.trunc(limit)));\n}\n\nfunction toFieldValue(value: unknown): HookDiagnosticsFieldValue | undefined {\n if (value === null) return null;\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"boolean\") return value;\n return undefined;\n}\n\nfunction normalizeFields(fields?: Record<string, unknown>): Record<string, HookDiagnosticsFieldValue> {\n if (!fields) return {};\n const normalizedEntries = Object.entries(fields)\n .map(([key, value]) => {\n const normalized = toFieldValue(value);\n return normalized === undefined ? null : ([key, normalized] as const);\n })\n .filter((entry): entry is readonly [string, HookDiagnosticsFieldValue] => entry !== null);\n return Object.fromEntries(normalizedEntries);\n}\n\nasync function rotateLogIfNeeded(logPath: string): Promise<void> {\n const stat = await fs.stat(logPath).catch(() => null);\n if (!stat || stat.size < MAX_LOG_BYTES) {\n return;\n }\n\n const rotatedPath = `${logPath}.1`;\n await fs.rm(rotatedPath, { force: true }).catch(() => undefined);\n await fs.rename(logPath, rotatedPath).catch(() => undefined);\n}\n\nexport function summarizeText(value: string | null | undefined): {\n present: boolean;\n length: number;\n sha256Prefix: string | null;\n} {\n if (typeof value !== \"string\" || !value.trim()) {\n return {\n present: false,\n length: 0,\n sha256Prefix: null,\n };\n }\n\n const trimmed = value.trim();\n return {\n present: true,\n length: trimmed.length,\n sha256Prefix: createHash(\"sha256\").update(trimmed).digest(\"hex\").slice(0, 12),\n };\n}\n\nexport async function appendHookDiagnosticsEvent(params: {\n hook: string;\n sessionId?: string | null;\n turnId?: string | null;\n stage: string;\n result: HookDiagnosticsResult;\n reason?: string | null;\n toolName?: string | null;\n repoRoot?: string | null;\n message?: string | null;\n fields?: Record<string, unknown>;\n}): Promise<void> {\n try {\n const logPath = getHookDiagnosticsLogPath();\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n await rotateLogIfNeeded(logPath);\n const event: HookDiagnosticsEvent = {\n ts: new Date().toISOString(),\n hook: params.hook,\n pluginVersion: pluginMetadata.version,\n pid: process.pid,\n sessionId: params.sessionId?.trim() || null,\n turnId: params.turnId?.trim() || null,\n stage: params.stage.trim(),\n result: params.result,\n reason: params.reason?.trim() || null,\n toolName: params.toolName?.trim() || null,\n repoRoot: params.repoRoot?.trim() || null,\n message: params.message?.trim() || null,\n fields: normalizeFields(params.fields),\n };\n await fs.appendFile(logPath, `${JSON.stringify(event)}\\n`, \"utf8\");\n } catch {\n // Diagnostics are best-effort and must never break hook execution.\n }\n}\n\nasync function readEventsFromFile(filePath: string): Promise<HookDiagnosticsEvent[]> {\n const raw = await fs.readFile(filePath, \"utf8\").catch(() => null);\n if (!raw) return [];\n return raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .flatMap((line) => {\n try {\n const parsed = JSON.parse(line) as HookDiagnosticsEvent;\n return parsed && typeof parsed === \"object\" ? [parsed] : [];\n } catch {\n return [];\n }\n });\n}\n\nexport async function readRecentHookDiagnosticsEvents(limit?: number): Promise<HookDiagnosticsEvent[]> {\n const eventLimit = clampEventLimit(limit);\n const logPath = getHookDiagnosticsLogPath();\n const [rotated, current] = await Promise.all([readEventsFromFile(`${logPath}.1`), readEventsFromFile(logPath)]);\n return [...rotated, ...current].slice(-eventLimit);\n}\n\nexport async function readHookDiagnosticsReport(limit?: number): Promise<HookDiagnosticsReport> {\n const [recentEvents, pendingStates] = await Promise.all([\n readRecentHookDiagnosticsEvents(limit),\n listPendingTurnStateSummaries(),\n ]);\n\n return {\n logPath: getHookDiagnosticsLogPath(),\n stateRoot: getPendingTurnStateRootPath(),\n recentEvents,\n pendingStates,\n };\n}\n","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\nexport type PendingTouchedRepoSummary = {\n repoRoot: string;\n projectId: string | null;\n currentAppId: string | null;\n upstreamAppId: string | null;\n lastTouchedAt: string;\n lastObservedWriteAt: string | null;\n touchedBy: string[];\n hasObservedWrite: boolean;\n manuallyRecorded: boolean;\n manualRecordingScope: ManualRecordingScope | null;\n stopAttempted: boolean;\n stopRecorded: boolean;\n stopRecordedMode: RepoRecordMode | null;\n recordingFailureMessage: string | null;\n recordingFailureHint: string | null;\n recordingFailedAt: string | null;\n};\n\nexport type PendingTurnStateSummary = {\n sessionId: string;\n turnId: string;\n initialCwd: string | null;\n submittedAt: string;\n consultedMemory: boolean;\n promptLength: number;\n touchedRepoCount: number;\n turnFailureMessage: string | null;\n turnFailureHint: string | null;\n turnFailedAt: string | null;\n touchedRepos: PendingTouchedRepoSummary[];\n};\n\nfunction stateRoot(): string {\n const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();\n return configured || 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 await fs.mkdir(stateRoot(), { recursive: true });\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\nfunction summarizeTouchedRepo(repo: TouchedRepoState): PendingTouchedRepoSummary {\n return {\n repoRoot: repo.repoRoot,\n projectId: repo.projectId,\n currentAppId: repo.currentAppId,\n upstreamAppId: repo.upstreamAppId,\n lastTouchedAt: repo.lastTouchedAt,\n lastObservedWriteAt: repo.lastObservedWriteAt,\n touchedBy: [...repo.touchedBy],\n hasObservedWrite: repo.hasObservedWrite,\n manuallyRecorded: repo.manuallyRecorded,\n manualRecordingScope: repo.manualRecordingScope,\n stopAttempted: repo.stopAttempted,\n stopRecorded: repo.stopRecorded,\n stopRecordedMode: repo.stopRecordedMode,\n recordingFailureMessage: repo.recordingFailureMessage,\n recordingFailureHint: repo.recordingFailureHint,\n recordingFailedAt: repo.recordingFailedAt,\n };\n}\n\nfunction summarizePendingTurnState(state: PendingTurnState): PendingTurnStateSummary {\n const touchedRepos = Object.values(state.touchedRepos)\n .sort((a, b) => a.repoRoot.localeCompare(b.repoRoot))\n .map((repo) => summarizeTouchedRepo(repo));\n return {\n sessionId: state.sessionId,\n turnId: state.turnId,\n initialCwd: state.initialCwd,\n submittedAt: state.submittedAt,\n consultedMemory: state.consultedMemory,\n promptLength: state.prompt.length,\n touchedRepoCount: touchedRepos.length,\n turnFailureMessage: state.turnFailureMessage,\n turnFailureHint: state.turnFailureHint,\n turnFailedAt: state.turnFailedAt,\n touchedRepos,\n };\n}\n\nexport function getPendingTurnStateRootPath(): string {\n return stateRoot();\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 listPendingTurnStateSummaries(): Promise<PendingTurnStateSummary[]> {\n const root = stateRoot();\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => []);\n const sessionIds = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".json\"))\n .map((entry) => entry.name.replace(/\\.json$/, \"\"))\n .sort((a, b) => a.localeCompare(b));\n const states = await Promise.all(sessionIds.map((sessionId) => loadPendingTurnState(sessionId)));\n return states\n .filter((state): state is PendingTurnState => state !== null)\n .sort((a, b) => b.submittedAt.localeCompare(a.submittedAt))\n .map((state) => summarizePendingTurnState(state));\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","{\n \"name\": \"@remixhq/claude-plugin\",\n \"version\": \"0.1.14\",\n \"description\": \"Claude Code plugin for Remix collaboration workflows\",\n \"homepage\": \"https://github.com/RemixDotOne/remix-claude-plugin\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/RemixDotOne/remix-claude-plugin.git\"\n },\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \".claude-plugin/plugin.json\",\n \".mcp.json\",\n \"skills\",\n \"hooks\",\n \"agents\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"postbuild\": \"node -e \\\"const fs=require('node:fs'); for (const p of ['dist/mcp-server.cjs','dist/hook-pre-git.cjs','dist/hook-user-prompt.cjs','dist/hook-post-collab.cjs','dist/hook-stop-collab.cjs']) fs.chmodSync(p, 0o755);\\\"\",\n \"dev\": \"tsx src/mcp-server.ts\",\n \"typecheck\": \"tsc -p tsconfig.json --noEmit\",\n \"prepack\": \"npm run build\"\n },\n \"dependencies\": {\n \"@remixhq/core\": \"^0.1.9\",\n \"@remixhq/mcp\": \"^0.1.9\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.4.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\"\n }\n}\n","import pkg from \"../package.json\";\n\nexport const pluginMetadata = {\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n pluginId: \"remix\",\n agentName: \"remix-collab\",\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\nfunction extractToolStructuredData(payload: Record<string, unknown>): Record<string, unknown> | null {\n const toolResponse = extractToolResponse(payload);\n const structuredContent = getNestedRecord(toolResponse?.structuredContent) ?? getNestedRecord(payload.structuredContent);\n return (\n getNestedRecord(toolResponse?.data) ??\n getNestedRecord(structuredContent?.data) ??\n structuredContent\n );\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(extractToolStructuredData(payload) ?? {}, candidateKeys) ??\n extractString(extractToolInput(payload), candidateKeys)\n );\n}\n\nexport function extractFinalizeTurnMode(payload: Record<string, unknown>): \"changed_turn\" | \"no_diff_turn\" | null {\n const mode =\n extractString(extractToolStructuredData(payload) ?? {}, [\"mode\"]) ??\n extractString(extractToolResponse(payload) ?? {}, [\"mode\"]) ??\n extractString(payload, [\"mode\"]);\n if (mode === \"changed_turn\" || mode === \"no_diff_turn\") {\n return mode;\n }\n return null;\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"],"mappings":"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","names":["import_node_crypto","import_promises","import_node_os","import_node_path","path","os","fs","fs","path","os","fs","fs","path","import_promises","import_node_path","import_promises","path2","fs2","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/hook-post-collab.ts","../src/hook-diagnostics.ts","../src/hook-state.ts","../package.json","../src/metadata.ts","../src/hook-utils.ts","../node_modules/@remixhq/core/dist/chunk-GEHSFPCD.js"],"sourcesContent":["import { appendHookDiagnosticsEvent } from \"./hook-diagnostics.js\";\nimport { markPendingTurnConsultedMemory, markTouchedRepoManuallyRecorded, markTouchedRepoObservedWrite, upsertTouchedRepo } from \"./hook-state.js\";\nimport {\n didToolSucceed,\n extractAssistantResponse,\n extractBashCommand,\n extractFinalizeTurnMode,\n extractString,\n extractToolName,\n extractToolInput,\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 hasManualFullTurnPayload(payload: Record<string, unknown>): boolean {\n const toolInput = extractToolInput(payload);\n return Boolean(extractString(toolInput, [\"prompt\"]) && extractAssistantResponse(payload));\n}\n\nfunction getManualRecordingScope(payload: Record<string, unknown>, toolName: string): \"change_step\" | \"full_turn\" | null {\n if (/remix_collab_finalize_turn$/i.test(toolName)) {\n return \"full_turn\";\n }\n if (/remix_collab_(add|add_change_step)$/i.test(toolName)) {\n return hasManualFullTurnPayload(payload) ? \"full_turn\" : \"change_step\";\n }\n if (/remix_collab_(record_turn|record_no_diff_turn)$/i.test(toolName)) {\n return \"full_turn\";\n }\n return null;\n}\n\nfunction didFinalizeTurnRecordRemoteChange(payload: Record<string, unknown>, toolName: string): boolean {\n if (!/remix_collab_finalize_turn$/i.test(toolName)) {\n return false;\n }\n return extractFinalizeTurnMode(payload) === \"changed_turn\";\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\nexport async function runHookPostCollab(payload: Record<string, unknown>): Promise<void> {\n const sessionId = typeof payload.session_id === \"string\" && payload.session_id.trim() ? payload.session_id.trim() : null;\n const toolName = normalizeHookToolName(extractToolName(payload));\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"payload_received\",\n result: \"start\",\n toolName,\n fields: {\n hasSessionId: Boolean(sessionId),\n hasToolName: Boolean(toolName),\n },\n });\n\n if (!sessionId || !toolName) {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"payload_validation\",\n result: \"skip\",\n reason: !sessionId ? \"missing_session_id\" : \"missing_tool_name\",\n toolName,\n });\n return;\n }\n\n const toolSucceeded = didToolSucceed(payload);\n const remoteChangeRecordedButSyncFailed =\n (isRemoteChangeRecordingToolName(toolName) || /remix_collab_finalize_turn$/i.test(toolName)) &&\n isRemoteChangeRecordedButLocalSyncFailed(payload);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"tool_classified\",\n result: \"info\",\n toolName,\n fields: {\n toolSucceeded,\n remoteChangeRecordedButSyncFailed,\n isMemoryTool: isMemoryToolName(toolName),\n isRepoMutationTool: isRepoMutationToolName(toolName),\n isShellTool: isShellToolName(toolName),\n isStructuredLocalWriteTool: isStructuredLocalWriteToolName(toolName),\n isStructuredLocalReadTool: isStructuredLocalReadToolName(toolName),\n },\n });\n if (!toolSucceeded && !remoteChangeRecordedButSyncFailed) {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"tool_result_gate\",\n result: \"skip\",\n reason: \"tool_failed_or_skipped\",\n toolName,\n });\n return;\n }\n\n if (toolSucceeded && isMemoryToolName(toolName)) {\n await markPendingTurnConsultedMemory(sessionId);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"memory_marked_consulted\",\n result: \"success\",\n toolName,\n });\n }\n\n const manualRecordingScope = getManualRecordingScope(payload, 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) || didFinalizeTurnRecordRemoteChange(payload, toolName)\n : remoteChangeRecordedButSyncFailed,\n });\n }\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"repo_marked_from_tool_cwd\",\n result: \"success\",\n toolName,\n repoRoot: targetRepo.repoRoot,\n fields: {\n hasObservedWrite: isRepoMutationToolName(toolName),\n manualRecordingScope,\n remoteChangeRecordedButSyncFailed,\n },\n });\n } else {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"repo_marked_from_tool_cwd\",\n result: \"skip\",\n reason: \"repo_not_bound_from_tool_cwd\",\n toolName,\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 await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"shell_repo_marked\",\n result: \"success\",\n toolName,\n repoRoot: targetRepo.repoRoot,\n fields: {\n hasObservedWrite,\n bashCommandLength: bashCommand?.length ?? 0,\n },\n });\n } else {\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"shell_repo_marked\",\n result: \"skip\",\n reason: \"repo_not_bound_from_shell_cwd\",\n toolName,\n });\n }\n }\n\n if (toolSucceeded && (isStructuredLocalWriteToolName(toolName) || isStructuredLocalReadToolName(toolName))) {\n const touchedPaths = extractToolPathTargets(payload, toolName);\n const touchedRepos = await resolveTouchedBoundReposFromPaths(touchedPaths);\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"path_targets_resolved\",\n result: touchedRepos.length > 0 ? \"info\" : \"skip\",\n reason: touchedRepos.length > 0 ? null : \"no_bound_repos_from_paths\",\n toolName,\n fields: {\n touchedPathCount: touchedPaths.length,\n boundRepoCount: touchedRepos.length,\n },\n });\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 await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"path_repo_marked\",\n result: \"success\",\n toolName,\n repoRoot: repo.repoRoot,\n fields: {\n hasObservedWrite: isStructuredLocalWriteToolName(toolName),\n },\n });\n }\n }\n\n await appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n sessionId,\n stage: \"completed\",\n result: \"success\",\n toolName,\n });\n}\n\nasync function main(): Promise<void> {\n const payload = await readJsonStdin();\n await runHookPostCollab(payload);\n}\n\nmain().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n void appendHookDiagnosticsEvent({\n hook: \"PostToolUse\",\n stage: \"unhandled_error\",\n result: \"error\",\n reason: \"exception\",\n message,\n });\n process.stderr.write(`${message}\\n`);\n process.exitCode = 0;\n});\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { getPendingTurnStateRootPath, listPendingTurnStateSummaries, type PendingTurnStateSummary } from \"./hook-state.js\";\nimport { pluginMetadata } from \"./metadata.js\";\n\ntype HookDiagnosticsResult = \"start\" | \"info\" | \"skip\" | \"success\" | \"error\";\ntype HookDiagnosticsFieldValue = string | number | boolean | null;\n\nexport type HookDiagnosticsEvent = {\n ts: string;\n hook: string;\n pluginVersion: string;\n pid: number;\n sessionId: string | null;\n turnId: string | null;\n stage: string;\n result: HookDiagnosticsResult;\n reason: string | null;\n toolName: string | null;\n repoRoot: string | null;\n message: string | null;\n fields: Record<string, HookDiagnosticsFieldValue>;\n};\n\nexport type HookDiagnosticsReport = {\n logPath: string;\n stateRoot: string;\n recentEvents: HookDiagnosticsEvent[];\n pendingStates: PendingTurnStateSummary[];\n};\n\nconst DEFAULT_EVENT_LIMIT = 50;\nconst MAX_EVENT_LIMIT = 200;\nconst MAX_LOG_BYTES = 512 * 1024;\n\nfunction resolveClaudeRoot(): string {\n const configured = process.env.CLAUDE_CONFIG_DIR?.trim();\n return configured || path.join(os.homedir(), \".claude\");\n}\n\nfunction resolvePluginDataDirName(): string {\n return `${pluginMetadata.pluginId}-${pluginMetadata.pluginId}`;\n}\n\nexport function getHookDiagnosticsDirPath(): string {\n const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_DIAGNOSTICS_DIR?.trim();\n return configured || path.join(resolveClaudeRoot(), \"plugins\", \"data\", resolvePluginDataDirName());\n}\n\nexport function getHookDiagnosticsLogPath(): string {\n return path.join(getHookDiagnosticsDirPath(), \"hooks.ndjson\");\n}\n\nfunction clampEventLimit(limit?: number): number {\n if (typeof limit !== \"number\" || !Number.isFinite(limit)) return DEFAULT_EVENT_LIMIT;\n return Math.max(1, Math.min(MAX_EVENT_LIMIT, Math.trunc(limit)));\n}\n\nfunction toFieldValue(value: unknown): HookDiagnosticsFieldValue | undefined {\n if (value === null) return null;\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"boolean\") return value;\n return undefined;\n}\n\nfunction normalizeFields(fields?: Record<string, unknown>): Record<string, HookDiagnosticsFieldValue> {\n if (!fields) return {};\n const normalizedEntries = Object.entries(fields)\n .map(([key, value]) => {\n const normalized = toFieldValue(value);\n return normalized === undefined ? null : ([key, normalized] as const);\n })\n .filter((entry): entry is readonly [string, HookDiagnosticsFieldValue] => entry !== null);\n return Object.fromEntries(normalizedEntries);\n}\n\nasync function rotateLogIfNeeded(logPath: string): Promise<void> {\n const stat = await fs.stat(logPath).catch(() => null);\n if (!stat || stat.size < MAX_LOG_BYTES) {\n return;\n }\n\n const rotatedPath = `${logPath}.1`;\n await fs.rm(rotatedPath, { force: true }).catch(() => undefined);\n await fs.rename(logPath, rotatedPath).catch(() => undefined);\n}\n\nexport function summarizeText(value: string | null | undefined): {\n present: boolean;\n length: number;\n sha256Prefix: string | null;\n} {\n if (typeof value !== \"string\" || !value.trim()) {\n return {\n present: false,\n length: 0,\n sha256Prefix: null,\n };\n }\n\n const trimmed = value.trim();\n return {\n present: true,\n length: trimmed.length,\n sha256Prefix: createHash(\"sha256\").update(trimmed).digest(\"hex\").slice(0, 12),\n };\n}\n\nexport async function appendHookDiagnosticsEvent(params: {\n hook: string;\n sessionId?: string | null;\n turnId?: string | null;\n stage: string;\n result: HookDiagnosticsResult;\n reason?: string | null;\n toolName?: string | null;\n repoRoot?: string | null;\n message?: string | null;\n fields?: Record<string, unknown>;\n}): Promise<void> {\n try {\n const logPath = getHookDiagnosticsLogPath();\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n await rotateLogIfNeeded(logPath);\n const event: HookDiagnosticsEvent = {\n ts: new Date().toISOString(),\n hook: params.hook,\n pluginVersion: pluginMetadata.version,\n pid: process.pid,\n sessionId: params.sessionId?.trim() || null,\n turnId: params.turnId?.trim() || null,\n stage: params.stage.trim(),\n result: params.result,\n reason: params.reason?.trim() || null,\n toolName: params.toolName?.trim() || null,\n repoRoot: params.repoRoot?.trim() || null,\n message: params.message?.trim() || null,\n fields: normalizeFields(params.fields),\n };\n await fs.appendFile(logPath, `${JSON.stringify(event)}\\n`, \"utf8\");\n } catch {\n // Diagnostics are best-effort and must never break hook execution.\n }\n}\n\nasync function readEventsFromFile(filePath: string): Promise<HookDiagnosticsEvent[]> {\n const raw = await fs.readFile(filePath, \"utf8\").catch(() => null);\n if (!raw) return [];\n return raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .flatMap((line) => {\n try {\n const parsed = JSON.parse(line) as HookDiagnosticsEvent;\n return parsed && typeof parsed === \"object\" ? [parsed] : [];\n } catch {\n return [];\n }\n });\n}\n\nexport async function readRecentHookDiagnosticsEvents(limit?: number): Promise<HookDiagnosticsEvent[]> {\n const eventLimit = clampEventLimit(limit);\n const logPath = getHookDiagnosticsLogPath();\n const [rotated, current] = await Promise.all([readEventsFromFile(`${logPath}.1`), readEventsFromFile(logPath)]);\n return [...rotated, ...current].slice(-eventLimit);\n}\n\nexport async function readHookDiagnosticsReport(limit?: number): Promise<HookDiagnosticsReport> {\n const [recentEvents, pendingStates] = await Promise.all([\n readRecentHookDiagnosticsEvents(limit),\n listPendingTurnStateSummaries(),\n ]);\n\n return {\n logPath: getHookDiagnosticsLogPath(),\n stateRoot: getPendingTurnStateRootPath(),\n recentEvents,\n pendingStates,\n };\n}\n","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\nexport type PendingTouchedRepoSummary = {\n repoRoot: string;\n projectId: string | null;\n currentAppId: string | null;\n upstreamAppId: string | null;\n lastTouchedAt: string;\n lastObservedWriteAt: string | null;\n touchedBy: string[];\n hasObservedWrite: boolean;\n manuallyRecorded: boolean;\n manualRecordingScope: ManualRecordingScope | null;\n stopAttempted: boolean;\n stopRecorded: boolean;\n stopRecordedMode: RepoRecordMode | null;\n recordingFailureMessage: string | null;\n recordingFailureHint: string | null;\n recordingFailedAt: string | null;\n};\n\nexport type PendingTurnStateSummary = {\n sessionId: string;\n turnId: string;\n initialCwd: string | null;\n submittedAt: string;\n consultedMemory: boolean;\n promptLength: number;\n touchedRepoCount: number;\n turnFailureMessage: string | null;\n turnFailureHint: string | null;\n turnFailedAt: string | null;\n touchedRepos: PendingTouchedRepoSummary[];\n};\n\nfunction stateRoot(): string {\n const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();\n return configured || 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 await fs.mkdir(stateRoot(), { recursive: true });\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\nfunction summarizeTouchedRepo(repo: TouchedRepoState): PendingTouchedRepoSummary {\n return {\n repoRoot: repo.repoRoot,\n projectId: repo.projectId,\n currentAppId: repo.currentAppId,\n upstreamAppId: repo.upstreamAppId,\n lastTouchedAt: repo.lastTouchedAt,\n lastObservedWriteAt: repo.lastObservedWriteAt,\n touchedBy: [...repo.touchedBy],\n hasObservedWrite: repo.hasObservedWrite,\n manuallyRecorded: repo.manuallyRecorded,\n manualRecordingScope: repo.manualRecordingScope,\n stopAttempted: repo.stopAttempted,\n stopRecorded: repo.stopRecorded,\n stopRecordedMode: repo.stopRecordedMode,\n recordingFailureMessage: repo.recordingFailureMessage,\n recordingFailureHint: repo.recordingFailureHint,\n recordingFailedAt: repo.recordingFailedAt,\n };\n}\n\nfunction summarizePendingTurnState(state: PendingTurnState): PendingTurnStateSummary {\n const touchedRepos = Object.values(state.touchedRepos)\n .sort((a, b) => a.repoRoot.localeCompare(b.repoRoot))\n .map((repo) => summarizeTouchedRepo(repo));\n return {\n sessionId: state.sessionId,\n turnId: state.turnId,\n initialCwd: state.initialCwd,\n submittedAt: state.submittedAt,\n consultedMemory: state.consultedMemory,\n promptLength: state.prompt.length,\n touchedRepoCount: touchedRepos.length,\n turnFailureMessage: state.turnFailureMessage,\n turnFailureHint: state.turnFailureHint,\n turnFailedAt: state.turnFailedAt,\n touchedRepos,\n };\n}\n\nexport function getPendingTurnStateRootPath(): string {\n return stateRoot();\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 listPendingTurnStateSummaries(): Promise<PendingTurnStateSummary[]> {\n const root = stateRoot();\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => []);\n const sessionIds = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".json\"))\n .map((entry) => entry.name.replace(/\\.json$/, \"\"))\n .sort((a, b) => a.localeCompare(b));\n const states = await Promise.all(sessionIds.map((sessionId) => loadPendingTurnState(sessionId)));\n return states\n .filter((state): state is PendingTurnState => state !== null)\n .sort((a, b) => b.submittedAt.localeCompare(a.submittedAt))\n .map((state) => summarizePendingTurnState(state));\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","{\n \"name\": \"@remixhq/claude-plugin\",\n \"version\": \"0.1.15\",\n \"description\": \"Claude Code plugin for Remix collaboration workflows\",\n \"homepage\": \"https://github.com/RemixDotOne/remix-claude-plugin\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/RemixDotOne/remix-claude-plugin.git\"\n },\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \".claude-plugin/plugin.json\",\n \".mcp.json\",\n \"skills\",\n \"hooks\",\n \"agents\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"postbuild\": \"node -e \\\"const fs=require('node:fs'); for (const p of ['dist/mcp-server.cjs','dist/hook-pre-git.cjs','dist/hook-user-prompt.cjs','dist/hook-post-collab.cjs','dist/hook-stop-collab.cjs']) fs.chmodSync(p, 0o755);\\\"\",\n \"dev\": \"tsx src/mcp-server.ts\",\n \"typecheck\": \"tsc -p tsconfig.json --noEmit\",\n \"prepack\": \"npm run build\"\n },\n \"dependencies\": {\n \"@remixhq/core\": \"^0.1.10\",\n \"@remixhq/mcp\": \"^0.1.10\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.4.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\"\n }\n}\n","import pkg from \"../package.json\";\n\nexport const pluginMetadata = {\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n pluginId: \"remix\",\n agentName: \"remix-collab\",\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\nfunction extractToolStructuredData(payload: Record<string, unknown>): Record<string, unknown> | null {\n const toolResponse = extractToolResponse(payload);\n const structuredContent = getNestedRecord(toolResponse?.structuredContent) ?? getNestedRecord(payload.structuredContent);\n return (\n getNestedRecord(toolResponse?.data) ??\n getNestedRecord(structuredContent?.data) ??\n structuredContent\n );\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(extractToolStructuredData(payload) ?? {}, candidateKeys) ??\n extractString(extractToolInput(payload), candidateKeys)\n );\n}\n\nexport function extractFinalizeTurnMode(payload: Record<string, unknown>): \"changed_turn\" | \"no_diff_turn\" | null {\n const mode =\n extractString(extractToolStructuredData(payload) ?? {}, [\"mode\"]) ??\n extractString(extractToolResponse(payload) ?? {}, [\"mode\"]) ??\n extractString(payload, [\"mode\"]);\n if (mode === \"changed_turn\" || mode === \"no_diff_turn\") {\n return mode;\n }\n return null;\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"],"mappings":"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","names":["import_node_crypto","import_promises","import_node_os","import_node_path","path","os","fs","fs","path","os","fs","fs","path","import_promises","import_node_path","import_promises","path2","fs2","path","fs"]}
|
|
@@ -8873,7 +8873,7 @@ async function collabRecordTurn(params) {
|
|
|
8873
8873
|
return unwrapResponseObject(resp, "collab turn");
|
|
8874
8874
|
}
|
|
8875
8875
|
|
|
8876
|
-
// node_modules/@remixhq/core/dist/chunk-
|
|
8876
|
+
// node_modules/@remixhq/core/dist/chunk-B5S3PUIR.js
|
|
8877
8877
|
async function readJsonSafe(res) {
|
|
8878
8878
|
const ct = res.headers.get("content-type") ?? "";
|
|
8879
8879
|
if (!ct.toLowerCase().includes("application/json")) return null;
|
|
@@ -8987,6 +8987,9 @@ function createApiClient(config, opts) {
|
|
|
8987
8987
|
const qs = new URLSearchParams();
|
|
8988
8988
|
if (params?.projectId) qs.set("projectId", params.projectId);
|
|
8989
8989
|
if (params?.organizationId) qs.set("organizationId", params.organizationId);
|
|
8990
|
+
if (params?.ownership) qs.set("ownership", params.ownership);
|
|
8991
|
+
if (params?.accessScope) qs.set("accessScope", params.accessScope);
|
|
8992
|
+
if (params?.createdBy) qs.set("createdBy", params.createdBy);
|
|
8990
8993
|
if (params?.forked) qs.set("forked", params.forked);
|
|
8991
8994
|
if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
|
|
8992
8995
|
if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
|
|
@@ -33522,7 +33525,7 @@ async function clearPendingTurnState(sessionId) {
|
|
|
33522
33525
|
// package.json
|
|
33523
33526
|
var package_default = {
|
|
33524
33527
|
name: "@remixhq/claude-plugin",
|
|
33525
|
-
version: "0.1.
|
|
33528
|
+
version: "0.1.15",
|
|
33526
33529
|
description: "Claude Code plugin for Remix collaboration workflows",
|
|
33527
33530
|
homepage: "https://github.com/RemixDotOne/remix-claude-plugin",
|
|
33528
33531
|
license: "MIT",
|
|
@@ -33553,8 +33556,8 @@ var package_default = {
|
|
|
33553
33556
|
prepack: "npm run build"
|
|
33554
33557
|
},
|
|
33555
33558
|
dependencies: {
|
|
33556
|
-
"@remixhq/core": "^0.1.
|
|
33557
|
-
"@remixhq/mcp": "^0.1.
|
|
33559
|
+
"@remixhq/core": "^0.1.10",
|
|
33560
|
+
"@remixhq/mcp": "^0.1.10"
|
|
33558
33561
|
},
|
|
33559
33562
|
devDependencies: {
|
|
33560
33563
|
"@types/node": "^25.4.0",
|