@glasstrace/sdk 1.13.0 → 1.15.0
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/dist/{chunk-KOYZJN6G.js → chunk-3A25EBAC.js} +5 -2
- package/dist/chunk-3A25EBAC.js.map +1 -0
- package/dist/{chunk-VWZMG3W2.js → chunk-PSMSSLQY.js} +358 -7
- package/dist/chunk-PSMSSLQY.js.map +1 -0
- package/dist/cli/init.cjs +8 -5
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +3 -3
- package/dist/cli/mcp-add.cjs +5 -2
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +2 -2
- package/dist/cli/upgrade-instructions.cjs +5 -2
- package/dist/cli/upgrade-instructions.cjs.map +1 -1
- package/dist/cli/upgrade-instructions.js +2 -2
- package/dist/index.cjs +1016 -957
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -295
- package/dist/index.js.map +1 -1
- package/dist/node-entry.cjs +12 -5
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-KOYZJN6G.js.map +0 -1
- package/dist/chunk-VWZMG3W2.js.map +0 -1
package/dist/node-entry.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent-detection/detect.ts","../src/agent-detection/agent-instruction-text.ts","../src/agent-detection/configs.ts","../src/agent-detection/inject-all-targets.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { access, stat } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { constants } from \"node:fs\";\n\n/**\n * Describes an AI coding agent detected in a project.\n */\nexport interface DetectedAgent {\n name: \"claude\" | \"codex\" | \"gemini\" | \"cursor\" | \"windsurf\" | \"generic\";\n mcpConfigPath: string | null;\n infoFilePath: string | null;\n cliAvailable: boolean;\n registrationCommand: string | null;\n}\n\ntype AgentName = DetectedAgent[\"name\"];\n\ninterface AgentRule {\n name: AgentName;\n /** Paths relative to a search directory that indicate this agent is present. */\n markers: string[];\n /** Function to compute the MCP config path given the directory where markers were found. */\n mcpConfigPath: (markerDir: string) => string;\n /** Function to compute the info file path, or null. */\n infoFilePath: (markerDir: string) => string | null;\n /** CLI binary name to check in PATH, or null if no CLI exists. */\n cliBinary: string | null;\n /** Registration command template, or null. */\n registrationCommand: string | null;\n}\n\nconst AGENT_RULES: AgentRule[] = [\n {\n name: \"claude\",\n markers: [\".claude\", \"CLAUDE.md\"],\n mcpConfigPath: (dir) => join(dir, \".mcp.json\"),\n infoFilePath: (dir) => join(dir, \"CLAUDE.md\"),\n cliBinary: \"claude\",\n registrationCommand: \"npx glasstrace mcp add --agent claude\",\n },\n {\n name: \"codex\",\n // Codex 2026 default discovery is `AGENTS.override.md` → `AGENTS.md` →\n // opt-in `project_doc_fallback_filenames`; `codex.md` is NOT in the\n // default fallback list. Detection requires Codex-specific markers\n // (`codex.md` legacy, `.codex/` config dir) — `AGENTS.md` is NOT\n // included as a marker because the SDK now writes `AGENTS.md`\n // broadly via the multi-target dispatcher's companion writes; if\n // `AGENTS.md` were a Codex marker, every project with the SDK's\n // own companion AGENTS.md would re-classify as Codex on subsequent\n // detect runs and trigger unintended `.codex/config.toml` writes\n // (Codex P1 + Copilot P1 review of Wave 18 PR #274). The canonical\n // write destination remains AGENTS.md regardless of which marker\n // classified the project.\n markers: [\"codex.md\", \".codex\"],\n mcpConfigPath: (dir) => join(dir, \".codex\", \"config.toml\"),\n infoFilePath: (dir) => join(dir, \"AGENTS.md\"),\n cliBinary: \"codex\",\n registrationCommand: \"npx glasstrace mcp add --agent codex\",\n },\n {\n name: \"gemini\",\n markers: [\".gemini\", \"GEMINI.md\"],\n mcpConfigPath: (dir) => join(dir, \".gemini\", \"settings.json\"),\n infoFilePath: (dir) => join(dir, \"GEMINI.md\"),\n cliBinary: \"gemini\",\n registrationCommand: \"npx glasstrace mcp add --agent gemini\",\n },\n {\n name: \"cursor\",\n // `.cursor/rules/*.mdc` is the current canonical format per Cursor's\n // 2026 docs. `.cursorrules` (single file) is supported-but-deprecated\n // and stays as a transitional fallback that the multi-target write\n // helper writes unconditionally alongside the .mdc canonical.\n markers: [\".cursor\", \".cursorrules\"],\n mcpConfigPath: (dir) => join(dir, \".cursor\", \"mcp.json\"),\n infoFilePath: (dir) => join(dir, \".cursor\", \"rules\", \"glasstrace.mdc\"),\n cliBinary: null,\n registrationCommand: \"npx glasstrace mcp add --agent cursor\",\n },\n {\n name: \"windsurf\",\n // Windsurf's current canonical workspace-rules format is\n // `.windsurf/rules/*.md`. AGENTS.md is a parallel cross-tool\n // mechanism Windsurf also reads BUT is NOT included as a Windsurf\n // detection marker — the SDK writes `AGENTS.md` broadly via the\n // multi-target dispatcher's companion writes, so treating\n // `AGENTS.md` as a Windsurf marker would re-classify every\n // SDK-managed project as Windsurf and cause `glasstrace uninit`\n // to mutate the global `~/.codeium/windsurf/mcp_config.json` for\n // non-Windsurf projects (Codex P1 + Copilot P1 review of Wave 18\n // PR #274). The single-file `.windsurfrules` is the deprecated\n // legacy form — recognized as a marker so legacy projects classify\n // correctly, but the SDK no longer writes to it.\n markers: [\".windsurf\", \".windsurfrules\"],\n mcpConfigPath: () =>\n join(homedir(), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n infoFilePath: (dir) => join(dir, \".windsurf\", \"rules\", \"glasstrace.md\"),\n cliBinary: null,\n registrationCommand: \"npx glasstrace mcp add --agent windsurf\",\n },\n];\n\n/**\n * Checks whether a path exists and is accessible, following symlinks.\n * Returns false on permission errors or missing paths.\n *\n * @param mode - The access mode to check (defaults to R_OK for marker detection).\n */\nasync function pathExists(\n path: string,\n mode: number = constants.R_OK,\n): Promise<boolean> {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Finds the git root directory by walking up from the given path.\n * Returns the starting directory if no `.git` is found.\n */\nasync function findGitRoot(startDir: string): Promise<string> {\n let current = resolve(startDir);\n\n while (true) {\n if (await pathExists(join(current, \".git\"), constants.F_OK)) {\n return current;\n }\n const parent = dirname(current);\n if (parent === current) {\n // Reached filesystem root without finding .git\n break;\n }\n current = parent;\n }\n\n return resolve(startDir);\n}\n\n/**\n * Returns true if a CLI binary is available on PATH.\n * Uses `which` on Unix and `where` on Windows, via execFile (no shell injection).\n */\nfunction isCliAvailable(binary: string): Promise<boolean> {\n return new Promise((resolve) => {\n const command = process.platform === \"win32\" ? \"where\" : \"which\";\n execFile(command, [binary], (error) => {\n resolve(error === null);\n });\n });\n}\n\n/**\n * Detects AI coding agents present in a project by scanning for marker\n * files and directories. Walks up from projectRoot to the git root to\n * support monorepo layouts.\n *\n * Always includes a \"generic\" fallback entry.\n *\n * @param projectRoot - Absolute or relative path to the project directory.\n * @returns Array of detected agents, with generic always last.\n * @throws If projectRoot does not exist or is not a directory.\n */\nexport async function detectAgents(\n projectRoot: string,\n): Promise<DetectedAgent[]> {\n const resolvedRoot = resolve(projectRoot);\n\n // Validate projectRoot exists and is a directory\n let rootStat;\n try {\n rootStat = await stat(resolvedRoot);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n throw new Error(\n `projectRoot does not exist: ${resolvedRoot}` +\n (code ? ` (${code})` : \"\"),\n );\n }\n\n if (!rootStat.isDirectory()) {\n throw new Error(`projectRoot is not a directory: ${resolvedRoot}`);\n }\n\n const gitRoot = await findGitRoot(resolvedRoot);\n\n // Collect unique directories to search: projectRoot and every ancestor up to gitRoot\n const searchDirs: string[] = [];\n let current = resolvedRoot;\n while (true) {\n searchDirs.push(current);\n if (current === gitRoot) {\n break;\n }\n const parent = dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n const detected: DetectedAgent[] = [];\n const seenAgents = new Set<AgentName>();\n\n for (const rule of AGENT_RULES) {\n let foundDir: string | null = null;\n\n // Check each search directory for markers\n for (const dir of searchDirs) {\n let markerFound = false;\n for (const marker of rule.markers) {\n if (await pathExists(join(dir, marker))) {\n markerFound = true;\n break;\n }\n }\n if (markerFound) {\n foundDir = dir;\n break;\n }\n }\n\n if (foundDir === null) {\n continue;\n }\n\n if (seenAgents.has(rule.name)) {\n continue;\n }\n seenAgents.add(rule.name);\n\n // Determine info file path. Wave 18: dropped the prior path-exists\n // gate that nulled out infoFilePath when the file didn't pre-exist —\n // the DISC-1592 / DISC-1602 marker contract makes file creation safe\n // (idempotent in-place replacement on re-runs), and `inject.ts`'s\n // existing create-or-replace logic already handles missing-file\n // creation under the same marker contract. The gate was a safety\n // guard added BEFORE the marker contract existed; with the contract\n // soaked in production it became a gratuitous skip that left new\n // installs with no managed section.\n const infoFilePath = rule.infoFilePath(foundDir);\n\n const cliAvailable = rule.cliBinary\n ? await isCliAvailable(rule.cliBinary)\n : false;\n\n detected.push({\n name: rule.name,\n mcpConfigPath: rule.mcpConfigPath(foundDir),\n infoFilePath,\n cliAvailable,\n registrationCommand: rule.registrationCommand,\n });\n }\n\n // Always include generic fallback. Wave 18: write AGENTS.md as the\n // universal cross-tool fallback (per the agents.md spec governed by\n // the Agentic AI Foundation under the Linux Foundation; adopted by\n // Cursor, Codex, Claude Code, Copilot, Devin, Windsurf, and Gemini\n // CLI). Generic-detected projects (no per-agent markers) previously\n // got NO instruction injection at all.\n detected.push({\n name: \"generic\",\n mcpConfigPath: join(resolvedRoot, \".glasstrace\", \"mcp.json\"),\n infoFilePath: join(resolvedRoot, \"AGENTS.md\"),\n cliAvailable: false,\n registrationCommand: null,\n });\n\n return detected;\n}\n","/**\n * The text body the SDK injects into a user's agent-instruction file\n * (AGENTS.md, CLAUDE.md, GEMINI.md, .cursor/rules/glasstrace.mdc,\n * .windsurf/rules/glasstrace.md, plus legacy .cursorrules — Wave 18\n * expanded the canonical set per DISC-1782) between the\n * `<!-- glasstrace:mcp:start v=<sdkVersion> -->` ... `<!-- glasstrace:mcp:end -->`\n * managed-section markers.\n *\n * **Why this lives in its own module:** the text is the contract\n * between the SDK and the user's coding agent at runtime — what the\n * AI reads when it decides whether to call Glasstrace MCP and how to\n * use the returned evidence. It evolves on a different cadence from\n * the surrounding marker / version-stamp / per-agent-format\n * machinery in `configs.ts`. Keeping it in a sibling module means\n * future content edits are a single-file change and don't risk\n * disturbing the `configs.ts` rendering machinery (which carries the\n * SDK-050 / DISC-1592 / DISC-1602 marker contract that has soaked in\n * production and must not regress).\n *\n * **Vocabulary alignment:** every MCP tool name and response-field\n * name in the body below is verified against the current MCP server\n * contract maintained in the private `glasstrace-product` repo\n * (`shared/types/wire-mcp.ts` and `shared/types/agent-evidence.ts`\n * there); the SDK consumes the resulting wire format but does not\n * own the schema source of truth for those tool names and field\n * names. If the server-side MCP contract evolves (renames a field,\n * restructures `suggestedFollowups`, adds new tools, etc.), update\n * this module in lockstep with the protocol change so the\n * agent-instruction text never references fields that don't exist.\n *\n * **Wave 17 follow-up (2026-05-09, post-PR-998):** the\n * vocabulary-mismatch-recovery wave (DISC-1626 + 40 sibling DISCs,\n * shipped via `glasstrace-product` PR #998) added five fields to\n * the no-match envelope on `find_trace_candidates`'s\n * `CandidateDiagnosticSchema` and the sibling-tools'\n * `ToolDiagnosticSchema`: `windowActivity`, `humanReadable`,\n * `diagnosticValue`, `recommendedNextStep`, and `maxUsefulFollowups`.\n * The Workflow §4 below names `closeMatches` /\n * `recentRoutesSample` / `windowActivity` / `humanReadable` /\n * `recoveryActions` / `diagnosticValue` / `recommendedNextStep`\n * because each disambiguates a different reason for an empty\n * result — most notably, `windowActivity` carries the four-way\n * distinguisher between \"wrong vocabulary\", \"no traffic in window\",\n * \"captureConfig-blocked\", and \"no traces ever for this tenant\"\n * (per `wire-mcp.ts` `NoMatchWindowActivitySchema` /\n * DISC-1652 Amendment 1 / DISC-1654). Without `windowActivity`\n * the agent cannot distinguish a vocabulary miss from \"the SDK was\n * never registered for this tenant\" — they look identical at the\n * `closeMatches`-only layer.\n *\n * **Heuristic-first vs tool-first framing:** the body opens with\n * explicit \"Call Glasstrace FIRST when\" / \"SKIP Glasstrace when\"\n * rules so a frontier agent has a cheap pre-tool-call decision\n * heuristic it can apply BEFORE spending tokens on tool\n * consideration. The Workflow section then names\n * `find_trace_candidates` as the entry point and instructs the\n * agent to READ `closeMatches` / `recentRoutesSample` /\n * `recoveryActions` before pivoting to source — that is the\n * load-bearing recovery contract from MCP-025 / MCP-027 (codified\n * in `wire-mcp.ts` `ToolDiagnosticSchema` and `CandidateDiagnosticSchema`)\n * and is the failure mode the prior SDK-050 cost-aware decision\n * paragraph did not surface.\n */\n\n/**\n * The full agent-instruction body, returned as a markdown string.\n *\n * The body has NO endpoint URL inlined — frontier agents reach\n * Glasstrace via the MCP server name `glasstrace` configured in the\n * user's MCP config (`.glasstrace/mcp.json` or per-agent native\n * config), not by reading a URL out of the instruction file. Keeping\n * the URL out of the instruction text avoids drift between the\n * instruction file and the MCP config and keeps the body tight.\n *\n * Returns the body WITHOUT the surrounding markers — the caller\n * (`generateInfoSection` in `configs.ts`) wraps the body with the\n * version-stamped start/end markers per the SDK-050 / DISC-1592\n * marker contract.\n */\nexport function buildAgentInstructionBody(): string {\n return [\n \"\",\n \"## Glasstrace MCP — Runtime Debugging Evidence\",\n \"\",\n \"Glasstrace is connected via MCP (`glasstrace`). It captures runtime traces from this app and exposes them through tools that disambiguate bugs source alone cannot resolve.\",\n \"\",\n \"### Call Glasstrace FIRST when:\",\n \"- A value passed at runtime is suspect: wrong role, locale, timezone, template, tenant id, or any enum/config that branches downstream.\",\n \"- The bug is in a side-effect operation: email sent, calendar event created, webhook dispatched, queued job, `after()` callback.\",\n \"- The user reports a symptom but you do not yet know which code path actually executed.\",\n \"- You need to confirm a route or procedure ran in the relevant time window before doing a source dive.\",\n \"\",\n \"### SKIP Glasstrace when:\",\n \"- The bug is statically obvious from source (N+1 query, missing await, redundant query, type error, missing null check).\",\n \"- The change is a refactor whose correctness does not depend on runtime behavior.\",\n \"- You already have a precise traceId from another source.\",\n \"\",\n \"### Workflow\",\n \"1. Start with `find_trace_candidates`. Pass whatever route or procedure name is natural — the server normalizes vocabulary and, on miss, returns close matches and a sample of routes actually present in the window.\",\n \"2. Take the highest-confidence candidate's `suggestedFollowups` and pass them straight to `get_trace` or `get_root_cause`.\",\n \"3. For side-effect bugs, read `sideEffectSummary` in the `get_trace` / `get_root_cause` response. The allowlisted fields (`templateKey`, `providerOperation`, `role`, `locale`, `timezone`, `status`, `phase`) are the ones that disambiguate payload bugs.\",\n \"4. If a tool returns empty, READ the response's empty-result envelope before pivoting to source — each field disambiguates a different reason for the empty result:\",\n \" - `closeMatches` / `recentRoutesSample` — your filter vocabulary doesn't match server-side names; the server returns the closest known names + a sample of routes actually present.\",\n \" - `windowActivity` — load-bearing four-way distinguisher. `totalTracesInWindow === 0` AND `totalTracesInTenantEver > 0` means \\\"your time window missed the activity\\\"; `totalTracesInTenantEver === 0` means \\\"this tenant has never produced traces\\\" (SDK not registered, or never hit); `captureConfigBlocksRequest === true` means \\\"the SDK's capture config dropped this route\\\"; otherwise the empty result is a vocabulary miss — see `closeMatches`.\",\n \" - `humanReadable` — prose guidance written for the agent.\",\n \" - `recoveryActions` — concrete next-call shapes.\",\n \" - `diagnosticValue` / `recommendedNextStep` — whether to keep searching or stop.\",\n \" Empty results carry `notAbsenceProof: true` — they are never proof the bug did not occur.\",\n \"\",\n \"### Tools\",\n \"- `find_trace_candidates` — discovery, vocabulary-tolerant filter\",\n \"- `get_trace` — exact trace by `traceId`\",\n \"- `get_root_cause` — root-cause analysis for a `traceId`\",\n \"- `get_session_timeline` — events for a session\",\n \"- `get_latest_error` / `get_error_list` — recent server errors\",\n \"\",\n \"Side-effect evidence is allowlisted and compact by design. Fields you don't see may have been omitted by policy, not absent at runtime.\",\n \"\",\n ].join(\"\\n\");\n}\n","import type { DetectedAgent } from \"./detect.js\";\nimport { buildAgentInstructionBody } from \"./agent-instruction-text.js\";\n\n/**\n * Generates the MCP server configuration content for a given agent.\n *\n * The output is the full file content suitable for writing to the agent's\n * MCP config file. The bearer token is intentionally embedded here for\n * agents whose schemas inline the Authorization header — Codex is the\n * exception and uses `bearer_token_env_var` so the actual token never\n * appears in TOML.\n *\n * @param agent - The detected agent to generate config for.\n * @param endpoint - The Glasstrace MCP endpoint URL.\n * @param bearer - The credential to embed in the Authorization header\n * (anon key or dev key, depending on the project's resolved\n * credential source). Empty values throw.\n * @returns The formatted configuration string.\n * @throws If endpoint or bearer is empty.\n */\nexport function generateMcpConfig(\n agent: DetectedAgent,\n endpoint: string,\n bearer: string,\n): string {\n if (!endpoint || endpoint.trim() === \"\") {\n throw new Error(\"endpoint must not be empty\");\n }\n if (!bearer || bearer.trim() === \"\") {\n throw new Error(\"bearer must not be empty\");\n }\n\n switch (agent.name) {\n case \"claude\":\n return JSON.stringify(\n {\n mcpServers: {\n glasstrace: {\n type: \"http\",\n url: endpoint,\n headers: {\n Authorization: `Bearer ${bearer}`,\n },\n },\n },\n },\n null,\n 2,\n );\n\n case \"codex\": {\n // Escape TOML basic string special characters in the endpoint value.\n // TOML requires backslashes, quotes, and control characters to be escaped.\n const safeEndpoint = endpoint\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n return [\n \"[mcp_servers.glasstrace]\",\n `url = \"${safeEndpoint}\"`,\n `bearer_token_env_var = \"GLASSTRACE_API_KEY\"`,\n \"\",\n ].join(\"\\n\");\n }\n\n case \"gemini\":\n return JSON.stringify(\n {\n mcpServers: {\n glasstrace: {\n httpUrl: endpoint,\n headers: {\n Authorization: `Bearer ${bearer}`,\n },\n },\n },\n },\n null,\n 2,\n );\n\n case \"cursor\":\n return JSON.stringify(\n {\n mcpServers: {\n glasstrace: {\n type: \"http\",\n url: endpoint,\n headers: {\n Authorization: `Bearer ${bearer}`,\n },\n },\n },\n },\n null,\n 2,\n );\n\n case \"windsurf\":\n return JSON.stringify(\n {\n mcpServers: {\n glasstrace: {\n type: \"http\",\n url: endpoint,\n headers: {\n Authorization: `Bearer ${bearer}`,\n },\n },\n },\n },\n null,\n 2,\n );\n\n case \"generic\":\n return JSON.stringify(\n {\n mcpServers: {\n glasstrace: {\n type: \"http\",\n url: endpoint,\n headers: {\n Authorization: `Bearer ${bearer}`,\n },\n },\n },\n },\n null,\n 2,\n );\n\n default: {\n const _exhaustive: never = agent.name;\n throw new Error(`Unknown agent: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Strict pattern accepted as the value substituted into a `v=<sdkVersion>`\n * marker stamp. Covers the SDK's own published versions\n * (e.g. `1.4.0`, `0.0.0-canary-20260508120000`, `1.4.0+build.42`) without\n * admitting whitespace, angle-brackets, or terminal control sequences\n * that could be smuggled into the agent instruction file via a\n * malformed callsite.\n *\n * The stamp is the SDK semver string and nothing else (DISC-1592 / SDK-050\n * Required Semantics Item 1: \"the stamp encodes only the SDK semver\n * string ... it must not embed user-controlled or environment-derived\n * content\"). Reject anything outside this charset at the render site\n * rather than relying on the upstream `__SDK_VERSION__` define being\n * well-formed.\n */\nconst SDK_VERSION_STAMP_PATTERN = /^[A-Za-z0-9.+-]+$/;\n\n/**\n * Marker pair used to delimit the Glasstrace section in agent info files.\n */\ninterface MarkerPair {\n start: string;\n end: string;\n}\n\nfunction htmlMarkers(sdkVersion: string): MarkerPair {\n return {\n start: `<!-- glasstrace:mcp:start v=${sdkVersion} -->`,\n end: \"<!-- glasstrace:mcp:end -->\",\n };\n}\n\nfunction hashMarkers(sdkVersion: string): MarkerPair {\n return {\n start: `# glasstrace:mcp:start v=${sdkVersion}`,\n end: \"# glasstrace:mcp:end\",\n };\n}\n\n/**\n * Generates informational content for an agent's instruction file.\n *\n * This content is designed to be appended to or inserted into agent-specific\n * instruction files. Wave 18 expanded the canonical set to follow the\n * 2026 cross-tool standard governed by the Agentic AI Foundation under\n * the Linux Foundation: `AGENTS.md` is the universal write target,\n * with per-agent canonical files written alongside it where the agent\n * has a documented primary file (Claude Code → CLAUDE.md, Gemini CLI\n * → GEMINI.md, Cursor → `.cursor/rules/glasstrace.mdc` canonical +\n * `.cursorrules` transitional fallback). Codex / Windsurf / generic\n * resolve to AGENTS.md alone (Codex retired `codex.md`; Windsurf\n * supports both AGENTS.md and `.windsurf/rules/glasstrace.md`). The\n * managed section's content is identical across destinations — only\n * the marker shape differs (HTML comments for Markdown / `.md` /\n * `.mdc` targets; `.cursorrules` legacy uses hash-prefix markers\n * preserved from the SDK-050 contract for backward-compat with\n * already-rendered managed sections). It contains a\n * tight, agent-facing decision policy + workflow + tool list — no\n * endpoint URL, no auth tokens, no setup instructions (those live in\n * the user's MCP config and the SDK README; the agent reads this file\n * to decide WHEN to call Glasstrace MCP and HOW to use the returned\n * evidence).\n *\n * The rendered block opens with explicit \"Call Glasstrace FIRST when\"\n * / \"SKIP Glasstrace when\" decision rules so a frontier agent has a\n * cheap pre-tool-call heuristic it can apply BEFORE spending tokens\n * on tool consideration. The Workflow section names\n * `find_trace_candidates` as the discovery entry point and instructs\n * the agent to READ `closeMatches` / `recentRoutesSample` /\n * `recoveryActions` before pivoting to source — that is the\n * load-bearing recovery contract from MCP-025 / MCP-027 (codified\n * in the server-side MCP contract maintained in the private\n * `glasstrace-product` repo's `shared/types/wire-mcp.ts` —\n * `ToolDiagnosticSchema` / `CandidateDiagnosticSchema`) and it\n * prevents the bail-to-source failure mode that the prior SDK-050\n * cost-aware decision paragraph did not surface.\n *\n * The body itself lives in a sibling module\n * (`agent-instruction-text.ts`) so future content evolutions are a\n * single-file edit and don't disturb the marker / version-stamp /\n * per-agent-format machinery in this file.\n *\n * The start marker carries a `v=<sdkVersion>` stamp (DISC-1592 /\n * SDK-050) so a later `glasstrace upgrade-instructions` run — and\n * the SDK's stale-section warning at init — can detect that the\n * file was rendered by an older SDK and refresh the block.\n *\n * @param agent - The detected agent to generate info for.\n * @param endpoint - The Glasstrace MCP endpoint URL. (Validated for\n * non-emptiness here for backwards compatibility with the prior\n * SDK-050 contract; not currently inlined in the body — agents\n * reach Glasstrace via the MCP server name `glasstrace` configured\n * separately in `.glasstrace/mcp.json` or per-agent native config.)\n * @param sdkVersion - The SDK semver string to embed in the start marker\n * (e.g. `1.4.0`, `0.0.0-canary-20260508120000`). Must match\n * `[A-Za-z0-9.+\\-]+`; arbitrary or empty values throw.\n * @returns The formatted info section string, or empty string for agents without a supported info file format.\n * @throws If endpoint is empty, or if sdkVersion is empty or contains\n * characters outside the accepted stamp charset.\n */\nexport function generateInfoSection(\n agent: DetectedAgent,\n endpoint: string,\n sdkVersion: string,\n): string {\n if (!endpoint || endpoint.trim() === \"\") {\n throw new Error(\"endpoint must not be empty\");\n }\n if (!sdkVersion || sdkVersion.trim() === \"\") {\n throw new Error(\"sdkVersion must not be empty\");\n }\n if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {\n throw new Error(\n \"sdkVersion must match [A-Za-z0-9.+\\\\-]+ (semver-shaped, no whitespace, no angle brackets)\",\n );\n }\n\n const content = buildAgentInstructionBody();\n\n switch (agent.name) {\n case \"claude\":\n case \"codex\":\n case \"gemini\":\n case \"windsurf\":\n case \"generic\": {\n // All Markdown-family targets (CLAUDE.md, AGENTS.md, GEMINI.md,\n // .windsurf/rules/glasstrace.md) use the HTML comment marker\n // shape that has soaked in production via SDK-050 / DISC-1592 /\n // DISC-1602 since Wave 17 main / `@glasstrace/sdk@1.10.x`.\n const m = htmlMarkers(sdkVersion);\n return `${m.start}\\n${content}${m.end}\\n`;\n }\n\n case \"cursor\": {\n // Wave 18 routes Cursor to the canonical `.cursor/rules/\n // glasstrace.mdc` destination. `.mdc` is Markdown body + YAML\n // frontmatter delimited by `---` lines; the SDK's marker\n // contract carries through unchanged via HTML comments. The\n // legacy `.cursorrules` write (still produced by the\n // multi-target write helper as a transitional fallback) is\n // rendered via {@link generateInfoSectionForCursorrulesLegacy}\n // using hash-prefix markers preserved from SDK-050 for\n // backward-compat with already-rendered managed sections.\n const m = htmlMarkers(sdkVersion);\n return `${m.start}\\n${content}${m.end}\\n`;\n }\n\n default: {\n const _exhaustive: never = agent.name;\n throw new Error(`Unknown agent: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Renders the managed section for Cursor's legacy `.cursorrules` file\n * (transitional fallback companion to the canonical\n * `.cursor/rules/glasstrace.mdc` write).\n *\n * Uses hash-prefix markers preserved from the SDK-050 contract — pre-\n * Wave-18 SDK versions rendered `.cursorrules` with hash markers, so\n * the legacy file's already-rendered managed sections need to be\n * recognized and idempotently replaced by the new SDK. Switching to\n * HTML markers on `.cursorrules` would break in-place replacement for\n * existing users (the new SDK wouldn't find the old marker pair) and\n * append a duplicate section.\n *\n * Wave 18 writes `.cursorrules` UNCONDITIONALLY alongside the\n * `.cursor/rules/glasstrace.mdc` canonical (per Codex P2 review of\n * DISC-1782 v3 — mixed-version Cursor scenarios may have Agent mode\n * reading legacy rules inconsistently across versions, so a\n * conditional fallback is too narrow).\n */\nexport function generateInfoSectionForCursorrulesLegacy(\n endpoint: string,\n sdkVersion: string,\n): string {\n if (!endpoint || endpoint.trim() === \"\") {\n throw new Error(\"endpoint must not be empty\");\n }\n if (!sdkVersion || sdkVersion.trim() === \"\") {\n throw new Error(\"sdkVersion must not be empty\");\n }\n if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {\n throw new Error(\n \"sdkVersion must match [A-Za-z0-9.+\\\\-]+ (semver-shaped, no whitespace, no angle brackets)\",\n );\n }\n\n const content = buildAgentInstructionBody();\n const m = hashMarkers(sdkVersion);\n return `${m.start}\\n${content}${m.end}\\n`;\n}\n\n/**\n * Renders the managed section for Cursor's `.cursor/rules/\n * glasstrace.mdc` canonical destination.\n *\n * `.mdc` is Cursor's Markdown-extension format with YAML frontmatter\n * delimited by `---` lines (per cursor.com/docs/rules — frontmatter\n * supports `alwaysApply`, `globs`, `description`). The Glasstrace\n * managed section uses `alwaysApply: true` because it's a global\n * agent instruction the user's coding agent should consult on every\n * debugging task. The SDK's idempotent-replacement logic anchors on\n * the markers and does NOT touch the frontmatter — user\n * customizations to the frontmatter survive `upgrade-instructions`.\n *\n * Recon caveat (Wave 18 impl-time, 2026-05-10): Cursor's official\n * docs do not address whether `.mdc` parser preserves HTML comments.\n * This implementation defaults to HTML comment markers (consistent\n * with the SDK-050 contract for `CLAUDE.md` and other Markdown\n * targets which have soaked in production). If a Cursor version\n * strips HTML comments from `.mdc` body content, the marker contract\n * breaks; track via the wave's closeout-gate items.\n */\nexport function generateInfoSectionForCursorMdc(\n endpoint: string,\n sdkVersion: string,\n): string {\n if (!endpoint || endpoint.trim() === \"\") {\n throw new Error(\"endpoint must not be empty\");\n }\n if (!sdkVersion || sdkVersion.trim() === \"\") {\n throw new Error(\"sdkVersion must not be empty\");\n }\n if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {\n throw new Error(\n \"sdkVersion must match [A-Za-z0-9.+\\\\-]+ (semver-shaped, no whitespace, no angle brackets)\",\n );\n }\n\n const content = buildAgentInstructionBody();\n const m = htmlMarkers(sdkVersion);\n // YAML frontmatter goes ABOVE the managed section. The marker\n // contract anchors on the `<!-- glasstrace:mcp:start -->` ...\n // `<!-- glasstrace:mcp:end -->` markers; the frontmatter sits above\n // the section and is preserved across re-renders.\n return [\n \"---\",\n \"description: Glasstrace MCP runtime debugging tools — runtime evidence the agent reads when source alone cannot resolve a bug\",\n \"alwaysApply: true\",\n \"---\",\n \"\",\n `${m.start}\\n${content}${m.end}\\n`,\n ].join(\"\\n\");\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type { DetectedAgent } from \"./detect.js\";\nimport {\n generateInfoSection,\n generateInfoSectionForCursorMdc,\n generateInfoSectionForCursorrulesLegacy,\n} from \"./configs.js\";\nimport { findMarkerBoundaries } from \"./inject.js\";\n\n/**\n * Wave 18 multi-target write dispatcher.\n *\n * Per DISC-1782 (P1 design_correction, 2026-05-09): the SDK's\n * agent-instruction injection writes the Glasstrace MCP managed\n * section to deprecated/wrong/missing filenames for nearly every\n * supported agent except Claude Code, and never writes to the\n * cross-tool `AGENTS.md` standard governed by the Agentic AI\n * Foundation under the Linux Foundation. Wave 18 corrects this by\n * routing every detected agent through this multi-target helper,\n * which writes to:\n *\n * - Claude Code: CLAUDE.md (primary) + AGENTS.md (companion)\n * - Codex CLI: AGENTS.md (sole — `codex.md` retired)\n * - Gemini CLI: GEMINI.md (primary) + AGENTS.md (companion)\n * - Cursor: .cursor/rules/glasstrace.mdc (canonical)\n * + .cursorrules (transitional fallback, unconditional)\n * + AGENTS.md (companion)\n * - Windsurf: .windsurf/rules/glasstrace.md (workspace-rules)\n * + AGENTS.md (companion — Windsurf reads both)\n * - Generic: AGENTS.md (sole, universal cross-tool fallback)\n *\n * AGENTS.md is deduplicated across multi-agent detection: a project\n * with both `.claude/` and `.cursor/` markers will detect TWO agents\n * (Claude Code + Cursor) but produce ONE AGENTS.md write, not two.\n *\n * **Failure semantics: fail-loud-per-target, non-atomic, all error\n * classes.** If write-to-target-N fails for any reason — permission\n * denied (EACCES/EPERM), read-only filesystem (EROFS), disk full\n * (ENOSPC), path too long (ENAMETOOLONG, common on Windows with\n * deeply nested project paths), I/O error, etc. — log a per-target\n * stderr warning naming the target path and the error kind, and\n * CONTINUE to the remaining targets. This is the broadened\n * fail-loud policy from the wave's 350-pass adversarial review\n * (finding 350-O8) — the prior `isPermissionError` path covered only\n * permission-class errors. Atomic rollback across targets is\n * explicitly OUT OF SCOPE for Wave 18 (track via closeout-gate).\n *\n * **Silent on success.** Successful writes produce no stdout/stderr\n * output. Only failures emit warnings. The SDK runs at user-runtime\n * load and verbose per-write logging would constitute log spam\n * across the user base.\n *\n * **Marker contract preserved.** All targets use the SDK-050 /\n * DISC-1592 / DISC-1602 marker contract for idempotent in-place\n * replacement on re-runs. Markdown-family destinations (CLAUDE.md,\n * AGENTS.md, GEMINI.md, .windsurf/rules/glasstrace.md, the body of\n * .cursor/rules/glasstrace.mdc) use HTML comment markers; the legacy\n * .cursorrules destination uses hash-prefix markers preserved from\n * the SDK-050 contract for backward-compat with already-rendered\n * managed sections.\n *\n * @param agents - All detected agents (typically the result of\n * `detectAgents()`). The helper iterates each, dispatches to its\n * per-agent target set, and dedupes AGENTS.md across the iteration.\n * @param endpoint - The Glasstrace MCP endpoint URL (currently\n * validated for non-emptiness; not inlined in the body).\n * @param sdkVersion - The SDK semver string for the marker stamp.\n * @param projectRoot - The project root, used to compute companion\n * AGENTS.md path when the per-agent rule didn't already point at it.\n */\nexport async function injectAllTargets(\n agents: DetectedAgent[],\n endpoint: string,\n sdkVersion: string,\n projectRoot: string,\n): Promise<void> {\n // Track AGENTS.md paths we've already written to so multi-agent\n // detection doesn't write the same file twice. Keyed by absolute\n // path string (already resolved by `detect.ts`).\n const writtenAgentsMd = new Set<string>();\n\n for (const agent of agents) {\n const targets = computeTargets(agent, projectRoot);\n\n for (const target of targets) {\n // Skip a duplicate AGENTS.md if another agent in the same\n // detection already wrote to it.\n if (target.isAgentsMdCompanion) {\n if (writtenAgentsMd.has(target.path)) {\n continue;\n }\n writtenAgentsMd.add(target.path);\n }\n\n // For cursor-mdc, emit the YAML frontmatter ONLY when creating\n // the file from scratch — appending it verbatim to an existing\n // mdc that has no markers would produce a duplicate `---` block\n // mid-file and corrupt the rule shape (Codex P2 review of v4).\n // The marker contract anchors on the managed-section markers\n // alone; user-customized frontmatter above the managed section\n // is preserved across re-renders. The managed section itself\n // (markers + body, no frontmatter) is identical across all\n // three file states (create / append / in-place replace), so\n // the frontmatter is a \"create-only prefix\" handed to the write\n // helper separately.\n let createContent: string;\n let managedSectionOnly: string;\n if (target.kind === \"cursor-mdc\") {\n createContent = generateInfoSectionForCursorMdc(endpoint, sdkVersion);\n // Same body but without the frontmatter wrapper — used when\n // appending to an existing mdc that already has its own\n // frontmatter.\n managedSectionOnly = generateInfoSection(agent, endpoint, sdkVersion);\n } else if (target.kind === \"cursorrules-legacy\") {\n createContent = generateInfoSectionForCursorrulesLegacy(\n endpoint,\n sdkVersion,\n );\n managedSectionOnly = createContent;\n } else {\n createContent = generateInfoSection(agent, endpoint, sdkVersion);\n managedSectionOnly = createContent;\n }\n\n if (managedSectionOnly === \"\") continue;\n\n await writeManagedSectionToTarget(\n target.path,\n createContent,\n managedSectionOnly,\n );\n }\n }\n}\n\ninterface WriteTarget {\n path: string;\n /**\n * Discriminator the dispatcher uses to pick the right rendering:\n * - \"primary\": render via `generateInfoSection(agent, ...)` using\n * the agent's existing per-agent format dispatch.\n * - \"agents-md-companion\": same content as primary (htmlMarkers)\n * but written to a different file; rendered via the agent's own\n * dispatch (the configs.ts switch routes Markdown-family agents\n * to htmlMarkers, which is correct for AGENTS.md too).\n * - \"cursor-mdc\": render via `generateInfoSectionForCursorMdc` to\n * prepend YAML frontmatter.\n * - \"cursorrules-legacy\": render via\n * `generateInfoSectionForCursorrulesLegacy` with hash-prefix\n * markers preserved from the SDK-050 contract.\n */\n kind: \"primary\" | \"agents-md-companion\" | \"cursor-mdc\" | \"cursorrules-legacy\";\n isAgentsMdCompanion: boolean;\n}\n\n/**\n * Derive the agent's `foundDir` (the directory `detectAgents` resolved\n * the marker in, after walking up to the git root for monorepo\n * support) from `agent.infoFilePath`. The companion AGENTS.md write\n * AND the Cursor `.cursorrules` transitional fallback MUST resolve\n * against this foundDir, not against `projectRoot` — for monorepos\n * where the SDK is initialized in a subdirectory but the agent\n * markers live at the git root, `projectRoot` is the wrong parent\n * (Codex P2 review of v6).\n *\n * Returns null when `agent.infoFilePath` is null (defensive — Wave 18\n * AGENT_RULES wires every agent to a non-null `infoFilePath`, so in\n * practice this never returns null).\n */\nfunction foundDirFromAgent(agent: DetectedAgent): string | null {\n if (agent.infoFilePath === null) return null;\n switch (agent.name) {\n case \"claude\":\n case \"codex\":\n case \"gemini\":\n case \"generic\":\n // infoFilePath is `<foundDir>/<canonical-filename>` — one\n // dirname call gets to foundDir.\n return dirname(agent.infoFilePath);\n case \"cursor\":\n // infoFilePath is `<foundDir>/.cursor/rules/glasstrace.mdc` —\n // three dirname calls strip `.cursor/rules/glasstrace.mdc`.\n return dirname(dirname(dirname(agent.infoFilePath)));\n case \"windsurf\":\n // infoFilePath is `<foundDir>/.windsurf/rules/glasstrace.md` —\n // three dirname calls strip `.windsurf/rules/glasstrace.md`.\n return dirname(dirname(dirname(agent.infoFilePath)));\n }\n}\n\nfunction computeTargets(\n agent: DetectedAgent,\n projectRoot: string,\n): WriteTarget[] {\n const targets: WriteTarget[] = [];\n\n // Resolve the companion AGENTS.md (and Cursor `.cursorrules`\n // transitional fallback) against the agent's foundDir — the\n // directory `detectAgents` walked up to. Falls back to projectRoot\n // only when foundDir cannot be derived (defensive; should not\n // happen in Wave 18). Codex P2 review of v6.\n const foundDir = foundDirFromAgent(agent) ?? projectRoot;\n\n switch (agent.name) {\n case \"claude\": {\n // Primary: CLAUDE.md (per-agent canonical for Claude Code).\n // Companion: AGENTS.md (cross-tool universal write).\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"primary\",\n isAgentsMdCompanion: false,\n });\n }\n targets.push({\n path: join(foundDir, \"AGENTS.md\"),\n kind: \"agents-md-companion\",\n isAgentsMdCompanion: true,\n });\n return targets;\n }\n\n case \"codex\": {\n // For Codex, the per-agent canonical IS AGENTS.md (set in\n // detect.ts AGENT_RULES). No separate companion needed —\n // dedup logic ensures we don't double-write.\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"primary\",\n isAgentsMdCompanion: true,\n });\n }\n return targets;\n }\n\n case \"gemini\": {\n // Primary: GEMINI.md (default Gemini context.fileName).\n // Companion: AGENTS.md (Gemini supports it via opt-in).\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"primary\",\n isAgentsMdCompanion: false,\n });\n }\n targets.push({\n path: join(foundDir, \"AGENTS.md\"),\n kind: \"agents-md-companion\",\n isAgentsMdCompanion: true,\n });\n return targets;\n }\n\n case \"cursor\": {\n // Primary: .cursor/rules/glasstrace.mdc (canonical 2026 format).\n // Transitional: .cursorrules (legacy, written unconditionally\n // per Codex P2 review of DISC-1782 v3 — mixed-version Cursor\n // scenarios may have Agent mode reading legacy rules\n // inconsistently, so a conditional fallback is too narrow).\n // Companion: AGENTS.md (Cursor reads it as cross-tool standard).\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"cursor-mdc\",\n isAgentsMdCompanion: false,\n });\n // .cursorrules sits at foundDir — same parent as the\n // .cursor/rules/ subtree.\n targets.push({\n path: join(foundDir, \".cursorrules\"),\n kind: \"cursorrules-legacy\",\n isAgentsMdCompanion: false,\n });\n }\n targets.push({\n path: join(foundDir, \"AGENTS.md\"),\n kind: \"agents-md-companion\",\n isAgentsMdCompanion: true,\n });\n return targets;\n }\n\n case \"windsurf\": {\n // Primary: .windsurf/rules/glasstrace.md (active workspace-rules).\n // Companion: AGENTS.md (cross-tool parallel mechanism Windsurf\n // also reads — NOT a replacement for workspace-rules, per\n // windsurf.com/university docs).\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"primary\",\n isAgentsMdCompanion: false,\n });\n }\n targets.push({\n path: join(foundDir, \"AGENTS.md\"),\n kind: \"agents-md-companion\",\n isAgentsMdCompanion: true,\n });\n return targets;\n }\n\n case \"generic\": {\n // For generic, the infoFilePath set in detect.ts IS AGENTS.md.\n // Mark as companion so multi-agent dedup applies.\n if (agent.infoFilePath) {\n targets.push({\n path: agent.infoFilePath,\n kind: \"primary\",\n isAgentsMdCompanion: true,\n });\n }\n return targets;\n }\n\n default: {\n const _exhaustive: never = agent.name;\n throw new Error(`Unknown agent: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Write the managed section to a single target file with broadened\n * fail-loud-per-target semantics.\n *\n * Mirrors the create-or-replace logic in `inject.ts`'s\n * `injectInfoSection` but catches ALL write errors (not just\n * `EACCES`/`EPERM`/`EROFS`) and logs a per-error-class qualifier so\n * the user can distinguish permission failures from disk-full / path-\n * too-long / I/O failures.\n *\n * Accepts two content strings to handle the cursor-mdc case cleanly\n * (Codex P2 review of v4):\n *\n * - `createContent` — used ONLY when the target file does not\n * already exist. For cursor-mdc this includes the YAML\n * frontmatter wrapper (`--- ... ---`) ABOVE the managed section.\n * - `managedSectionOnly` — used when the target file already\n * exists, regardless of whether it carries existing markers.\n * For cursor-mdc this is the managed section without the\n * frontmatter, so appending it to an existing `.mdc` (which\n * already has its own frontmatter) does NOT produce a duplicate\n * `--- ... ---` block mid-file.\n *\n * For non-mdc targets the two strings are identical (the body\n * IS the full content).\n */\nasync function writeManagedSectionToTarget(\n filePath: string,\n createContent: string,\n managedSectionOnly: string,\n): Promise<void> {\n let existingContent: string | null = null;\n try {\n existingContent = await readFile(filePath, \"utf-8\");\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n emitTargetWarning(filePath, \"read\", err);\n return;\n }\n }\n\n // File does not exist — create with the full content (frontmatter\n // wrapper for cursor-mdc, or the managed section alone for other\n // targets).\n if (existingContent === null) {\n try {\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, createContent, \"utf-8\");\n } catch (err: unknown) {\n emitTargetWarning(filePath, \"write\", err);\n return;\n }\n return;\n }\n\n // File exists — check for markers. For both branches below we use\n // `managedSectionOnly` (NOT `createContent`) so we don't inject a\n // second YAML frontmatter block into a cursor-mdc file that\n // already has one. The user's existing frontmatter is preserved.\n const lines = existingContent.split(\"\\n\");\n const boundaries = findMarkerBoundaries(lines);\n\n let newContent: string;\n if (boundaries !== null) {\n const before = lines.slice(0, boundaries.startIdx);\n const after = lines.slice(boundaries.endIdx + 1);\n const contentWithoutTrailingNewline = managedSectionOnly.endsWith(\"\\n\")\n ? managedSectionOnly.slice(0, -1)\n : managedSectionOnly;\n newContent = [...before, contentWithoutTrailingNewline, ...after].join(\n \"\\n\",\n );\n } else {\n const separator = existingContent.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n newContent = existingContent + separator + managedSectionOnly;\n }\n\n try {\n await writeFile(filePath, newContent, \"utf-8\");\n } catch (err: unknown) {\n emitTargetWarning(filePath, \"write\", err);\n }\n}\n\n/**\n * Emit a per-target stderr warning with an error-class qualifier so\n * users can distinguish failure modes (permission vs disk-full vs\n * path-too-long etc.). No-op when stderr is unavailable (e.g., a\n * non-Node runtime, though the SDK is Node-only).\n */\nfunction emitTargetWarning(\n filePath: string,\n op: \"read\" | \"write\",\n err: unknown,\n): void {\n const code = (err as NodeJS.ErrnoException).code;\n let qualifier: string;\n switch (code) {\n case \"EACCES\":\n case \"EPERM\":\n qualifier = \"permission denied\";\n break;\n case \"EROFS\":\n qualifier = \"filesystem read-only\";\n break;\n case \"ENOSPC\":\n qualifier = \"disk full\";\n break;\n case \"ENAMETOOLONG\":\n qualifier = \"path too long\";\n break;\n case \"ENOTDIR\":\n qualifier = \"not a directory\";\n break;\n case \"EISDIR\":\n qualifier = \"is a directory\";\n break;\n default:\n qualifier = \"I/O error\";\n break;\n }\n try {\n process.stderr.write(\n `Warning: cannot ${op} info file ${filePath}: ${qualifier}\\n`,\n );\n } catch {\n // stderr unavailable — silently swallow per the SDK-050\n // never-throw-from-instrumentation invariant.\n }\n}\n"],"mappings":"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","names":["resolve","dirname","join","dirname","join"]}
|