@orkestrel/probe 0.0.11 → 0.0.12

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/bin/main.js CHANGED
@@ -6,7 +6,7 @@ try {
6
6
  new ProbeServer().start();
7
7
  } catch (error) {
8
8
  if (!isProbeError(error)) throw error;
9
- console.error(`[${error.origin}] ${error.code}: ${error.message.split(/\r?\n|\r/u).join(" ")}`);
9
+ console.error(`[${error.origin}] ${error.code}: ${error.message.split(/\r\n|\n/u).join(" ")}`);
10
10
  process.exitCode = 1;
11
11
  }
12
12
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","names":[],"sources":["../../src/bin/main.ts"],"sourcesContent":["import { isProbeError } from '@src/core'\nimport { ProbeServer } from '@src/server'\n\ntry {\n\tnew ProbeServer().start()\n} catch (error) {\n\tif (!isProbeError(error)) throw error\n\tconsole.error(`[${error.origin}] ${error.code}: ${error.message.split(/\\r?\\n|\\r/u).join(' ')}`)\n\tprocess.exitCode = 1\n}\n"],"mappings":";;;;AAGA,IAAI;CACH,IAAI,YAAY,CAAC,CAAC,MAAM;AACzB,SAAS,OAAO;CACf,IAAI,CAAC,aAAa,KAAK,GAAG,MAAM;CAChC,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,WAAW,CAAC,CAAC,KAAK,GAAG,GAAG;CAC9F,QAAQ,WAAW;AACpB"}
1
+ {"version":3,"file":"main.js","names":[],"sources":["../../src/bin/main.ts"],"sourcesContent":["import { isProbeError } from '@src/core'\nimport { ProbeServer } from '@src/server'\n\ntry {\n\tnew ProbeServer().start()\n} catch (error) {\n\tif (!isProbeError(error)) throw error\n\tconsole.error(`[${error.origin}] ${error.code}: ${error.message.split(/\\r\\n|\\n/u).join(' ')}`)\n\tprocess.exitCode = 1\n}\n"],"mappings":";;;;AAGA,IAAI;CACH,IAAI,YAAY,CAAC,CAAC,MAAM;AACzB,SAAS,OAAO;CACf,IAAI,CAAC,aAAa,KAAK,GAAG,MAAM;CAChC,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,UAAU,CAAC,CAAC,KAAK,GAAG,GAAG;CAC7F,QAAQ,WAAW;AACpB"}
@@ -134,6 +134,39 @@ var LINT_DEADLINE = 2e3;
134
134
  * ```
135
135
  */
136
136
  var PROBE_KEYS = 4096;
137
+ /**
138
+ * Names the specification lifetime the runtime stage replaces its resident Vitest service at.
139
+ *
140
+ * @remarks
141
+ * Vite retains one unresolved URL for every fresh specification path, so an inspection that writes
142
+ * a specification grows a map the resident service never releases. The stage replaces that service
143
+ * rather than deleting from each map it owns, and this is the count of specifications one service
144
+ * carries before the replacement. Any bound holds the retention flat, because the replacement
145
+ * releases everything the instance held; this value trades the cost of the replacement against how
146
+ * far the map grows between them. On 2026-08-20, over this package's own workspace on the host
147
+ * `guides/probe.md` § Cost names, two runs of 66 inspections put the crossing inspection at 480 ms
148
+ * and 269 ms against median inspections of 156 ms and 155 ms.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * PROBE_SPECIFICATIONS // 64
153
+ * ```
154
+ */
155
+ var PROBE_SPECIFICATIONS = 64;
156
+ /**
157
+ * Names the Vite plugin the runtime stage installs into a target workspace's Vitest configuration.
158
+ *
159
+ * @remarks
160
+ * The stage declares the plugin under this name and reads a configured project's plugin list for
161
+ * the same name to decide whether that project carries the overlay. One name feeds both, so a
162
+ * project the stage instrumented is never reported as a workspace project it could not reach.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * RUNTIME_PLUGIN // 'orkestrel-runtime-overlay'
167
+ * ```
168
+ */
169
+ var RUNTIME_PLUGIN = "orkestrel-runtime-overlay";
137
170
  //#endregion
138
171
  //#region src/core/errors.ts
139
172
  /**
@@ -191,7 +224,7 @@ var ProbeError = class extends Error {
191
224
  * condition all stay outside the type.
192
225
  *
193
226
  * @param value - The value to inspect
194
- * @returns True only for a `ProbeError` instance; false otherwise
227
+ * @returns True if the value is a `ProbeError` instance; false otherwise
195
228
  *
196
229
  * @example
197
230
  * ```ts
@@ -813,10 +846,12 @@ exports.PROBE_DEADLINE = PROBE_DEADLINE;
813
846
  exports.PROBE_ERROR_CODES = PROBE_ERROR_CODES;
814
847
  exports.PROBE_KEYS = PROBE_KEYS;
815
848
  exports.PROBE_PARTIES = PROBE_PARTIES;
849
+ exports.PROBE_SPECIFICATIONS = PROBE_SPECIFICATIONS;
816
850
  exports.PROBE_STAGES = PROBE_STAGES;
817
851
  exports.ProbeError = ProbeError;
818
852
  exports.RECEIPT_PREFIX = RECEIPT_PREFIX;
819
853
  exports.RECEIPT_SEPARATOR = RECEIPT_SEPARATOR;
854
+ exports.RUNTIME_PLUGIN = RUNTIME_PLUGIN;
820
855
  exports.computeReceipt = computeReceipt;
821
856
  exports.createDestroyedError = createDestroyedError;
822
857
  exports.formatCheck = formatCheck;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/shapers.ts"],"sourcesContent":["/**\n * Lists the stages a claim passes through, in the order a verdict reports them.\n *\n * @remarks\n * One list feeds the `Stage` type, the wire shape, the stage guard, and the receipt computation, so\n * a stage cannot be admitted by one and refused by another. The type derives from this list rather\n * than standing beside it, so a stage the list omits is a stage no member of the union names.\n *\n * @example\n * ```ts\n * PROBE_STAGES // ['type', 'lint', 'runtime']\n * ```\n */\nexport const PROBE_STAGES = Object.freeze(['type', 'lint', 'runtime'] as const)\n\n/**\n * Lists the parties that can own action on an issue or probe failure.\n *\n * @remarks\n * One list feeds the `Party` type and its guard, so a party cannot be admitted by one and refused\n * by another.\n *\n * @example\n * ```ts\n * PROBE_PARTIES // ['claimant', 'workspace', 'instrument']\n * ```\n */\nexport const PROBE_PARTIES = Object.freeze(['claimant', 'workspace', 'instrument'] as const)\n\n/**\n * Lists the conditions that can end a probe operation.\n *\n * @remarks\n * One list feeds the code union and the error guard, so a condition cannot be constructed by one\n * and refused by the other. The guard reads this list rather than the class, which is what lets it\n * refuse a lookalike carrying a condition this package never declared.\n *\n * @example\n * ```ts\n * PROBE_ERROR_CODES // ['refused', 'missing', 'malformed', 'destroyed', 'deadline']\n * ```\n */\nexport const PROBE_ERROR_CODES = Object.freeze([\n\t'refused',\n\t'missing',\n\t'malformed',\n\t'destroyed',\n\t'deadline',\n] as const)\n\n/**\n * Names the leading token every receipt carries.\n *\n * @remarks\n * A receipt travels away from the verdict that minted it — an agent pastes it into the promotion\n * action — so it names itself rather than relying on where it was found.\n *\n * @example\n * ```ts\n * const receipt =\n * \t'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * receipt.startsWith(RECEIPT_PREFIX) // true\n * ```\n */\nexport const RECEIPT_PREFIX = 'probe'\n\n/**\n * Names the character joining a receipt's tokens.\n *\n * @remarks\n * A project path can contain this character, so the project field goes last and a reader rejoins\n * every field from index 6 onward with this separator rather than expecting a fixed count.\n *\n * @example\n * ```ts\n * const receipt =\n * \t'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * receipt.split(RECEIPT_SEPARATOR).length // 7\n * ```\n */\nexport const RECEIPT_SEPARATOR = ':'\n\n/**\n * Names the default inspection deadline a `Probe` applies when its construction omits one.\n *\n * @remarks\n * `ProbeOptions.deadline` overrides this value per instance.\n *\n * @example\n * ```ts\n * PROBE_DEADLINE // 30_000\n * ```\n */\nexport const PROBE_DEADLINE = 30_000\n\n/**\n * Names the bound the lint stage holds over the lifecycle exchanges the protocol leaves to the\n * server: the `initialize` reply warming waits for and the `shutdown` reply ending waits for.\n *\n * @remarks\n * It does not reach the diagnostics an inspection waits for, which the caller's own signal bounds.\n * The transport's cooperative window is half of it, so a child that ignores its ending is\n * signalled and released inside the same bound rather than outliving the client's own wait for\n * the close. Measured 2026-08-27: the workspace `oxlint --lsp` answers `initialize` in 155 ms, so\n * this bound is more than ten times that reply.\n *\n * @example\n * ```ts\n * LINT_DEADLINE // 2_000\n * ```\n */\nexport const LINT_DEADLINE = 2_000\n\n/**\n * Names the total enumerable key bound `ProbeServer` applies to inbound metadata and to produced\n * tool content alike.\n *\n * @remarks\n * `@orkestrel/mcp`'s default leaf is sized for metadata: a verdict costs 38 keys empty and 11 more\n * for each issue a stage reports, so the default carries a verdict whose control refuses one\n * declaration and stops carrying the next one. A whole tool-call result carrying the record beside\n * its rendering costs 44 keys plus 11 for each issue, so this bound carries a record reporting up\n * to 368 issues. Past that the reply falls back to the rendered text, and past the 4 MiB content\n * bound to the receipt block.\n *\n * @example\n * ```ts\n * PROBE_KEYS // 4096\n * ```\n */\nexport const PROBE_KEYS = 4096\n","import type { Party, ProbeErrorCode, ProbeErrorContext, ProbeErrorOptions } from './types.js'\nimport { holds, isError } from '@orkestrel/contract'\nimport { PROBE_ERROR_CODES, PROBE_PARTIES } from './constants.js'\n\n/**\n * Reports one probe failure under stable ownership and condition axes.\n *\n * @remarks\n * Every failure raised while serving a claim arrives as one of these, so a consumer catching from\n * `prove`, from a stage, or from a workspace leaf branches on {@link Party} and\n * {@link ProbeErrorCode} rather than on message text. Narrow a caught value with\n * {@link isProbeError} before reading either member. A pure leaf called directly with a value\n * `isClaim` would refuse raises the host's own fault unchanged, because those leaves are written to\n * be total over a validated claim rather than over every value.\n *\n * @example\n * ```ts\n * const error = new ProbeError('Path escapes the workspace: ../secrets.env', {\n * \torigin: 'claimant',\n * \tcode: 'refused',\n * \tcontext: { path: '../secrets.env' },\n * })\n * error.origin // 'claimant'\n * error.code // 'refused'\n * error.context?.path // '../secrets.env'\n * ```\n */\nexport class ProbeError extends Error {\n\toverride readonly name = 'ProbeError'\n\treadonly origin: Party\n\treadonly code: ProbeErrorCode\n\treadonly context?: ProbeErrorContext\n\n\t/**\n\t * Creates one classified probe failure.\n\t *\n\t * @param message - Human-readable description of what failed\n\t * @param options - The ownership, condition, optional structured context, and optional cause\n\t */\n\tconstructor(message: string, options: ProbeErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\t// A global own-property brand rather than the constructor identity, because a consumer that\n\t\t// installs this package twice, or loads its ESM and CommonJS builds together, holds two\n\t\t// classes and `instanceof` refuses the other one's error.\n\t\tObject.defineProperty(this, Symbol.for('@orkestrel/probe.error'), { value: true })\n\t\tthis.origin = options.origin\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProbeError}.\n *\n * @remarks\n * Recognition combines the global own-property brand with the native `Error` base, the subclass\n * prototype, the fixed name, a party {@link PROBE_PARTIES} declares, and a condition\n * {@link PROBE_ERROR_CODES} declares. The brand carries recognition across duplicate installations\n * and across an ESM and a CommonJS copy of this package, where the two classes are different values.\n * A plain `Error`, a property-only lookalike, and a branded value carrying an undeclared origin or\n * condition all stay outside the type.\n *\n * @param value - The value to inspect\n * @returns True only for a `ProbeError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProbeError(createDestroyedError('probe')) // true\n * isProbeError(new Error('The probe has been destroyed')) // false\n * ```\n */\nexport function isProbeError(value: unknown): value is ProbeError {\n\tif (!isError(value)) return false\n\treturn holds(() => {\n\t\tif (Object.getPrototypeOf(value) === Error.prototype) return false\n\t\tif (value.name !== 'ProbeError' || !('origin' in value) || !('code' in value)) return false\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, Symbol.for('@orkestrel/probe.error'))\n\t\tif (descriptor?.value !== true) return false\n\t\tconst origin: unknown = value.origin\n\t\tconst code: unknown = value.code\n\t\treturn (\n\t\t\tPROBE_PARTIES.some((declared) => declared === origin) &&\n\t\t\tPROBE_ERROR_CODES.some((declared) => declared === code)\n\t\t)\n\t})\n}\n\n/**\n * Creates the failure raised when an instrument is used after it was torn down.\n *\n * @remarks\n * Every resident entity in this package refuses this way, so the subject names which one in the\n * message and the condition is the same for all of them. A caller that meets this builds a\n * replacement rather than retrying: teardown is permanent.\n *\n * @param subject - The torn-down entity, named as the message names it, such as `type stage`\n * @returns A typed teardown failure\n *\n * @example\n * ```ts\n * createDestroyedError('type stage').message // 'The type stage has been destroyed'\n * createDestroyedError('probe').code // 'destroyed'\n * ```\n */\nexport function createDestroyedError(subject: string): ProbeError {\n\treturn new ProbeError(`The ${subject} has been destroyed`, {\n\t\torigin: 'claimant',\n\t\tcode: 'destroyed',\n\t})\n}\n","import type { Guard } from '@orkestrel/contract'\nimport type {\n\tCase,\n\tCheck,\n\tClaim,\n\tControl,\n\tDraft,\n\tIssue,\n\tParty,\n\tProject,\n\tStage,\n\tToolchain,\n\tVerdict,\n} from './types.js'\nimport {\n\tandOf,\n\tarrayOf,\n\tisNonEmptyString,\n\tisNumber,\n\tisString,\n\tliteralOf,\n\trecordOf,\n} from '@orkestrel/contract'\nimport { isLSPRange } from '@orkestrel/lsp'\nimport { PROBE_PARTIES, PROBE_STAGES } from './constants.js'\n\n/**\n * Checks whether a value names a stage.\n *\n * @param value - The value to check\n * @returns True if the value is a stage name; false otherwise\n *\n * @example\n * ```ts\n * isStage('lint') // true\n * isStage('typecheck') // false\n * ```\n */\nexport const isStage: Guard<Stage> = literalOf(PROBE_STAGES)\n\n/**\n * Checks whether a value carries a proposed file's path and text.\n *\n * @remarks\n * Rejects an empty, absolute, or workspace-escaping path. A contained relative path may contain\n * `.` or may traverse to a parent that remains inside the workspace. Every stage resolves a file\n * by that path, so admitting an escape here would defer the refusal until a stage had already\n * accepted the draft. An `Issue` carries no such minimum because this package produces issues\n * rather than admits them.\n *\n * @param value - The value to check\n * @returns True if the value is a draft; false otherwise\n *\n * @example\n * ```ts\n * isDraft({ path: 'src/core/greeting.ts', text: 'export const GREETING = \"hi\"\\n' }) // true\n * isDraft({ path: '../../etc/hosts', text: '' }) // false\n * isDraft({ path: 'src/core/greeting.ts' }) // false\n * ```\n */\nexport const isDraft: Guard<Draft> = recordOf({\n\tpath: andOf<string>(isNonEmptyString, (path) => {\n\t\tif (/^(?:[\\\\/]|[A-Za-z]:)/.test(path)) return false\n\t\tlet depth = 0\n\t\tfor (const segment of path.split(/[\\\\/]+/)) {\n\t\t\tif (segment === '' || segment === '.') continue\n\t\t\tif (segment !== '..') {\n\t\t\t\tdepth += 1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (depth === 0) return false\n\t\t\tdepth -= 1\n\t\t}\n\t\treturn true\n\t}),\n\ttext: isString,\n})\n\n/**\n * Checks whether a value carries a claim's candidate drafts and its test.\n *\n * @param value - The value to check\n * @returns True if the value is a case; false otherwise\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: 'test(\"greets\", () => {})\\n' }\n * isCase({ files: [], test }) // true\n * ```\n */\nexport const isCase: Guard<Case> = recordOf({ files: arrayOf(isDraft), test: isDraft })\n\n/**\n * Checks whether a value carries a case plus the stage and reason it must fail for.\n *\n * @param value - The value to check\n * @returns True if the value is a control; false otherwise\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: 'test(\"greets\", () => {})\\n' }\n * isControl({ files: [], test, stage: 'type', reason: 'must not compile' }) // true\n * isControl({ files: [], test }) // false\n * ```\n */\nexport const isControl: Guard<Control> = recordOf({\n\tfiles: arrayOf(isDraft),\n\ttest: isDraft,\n\tstage: isStage,\n\treason: isNonEmptyString,\n})\n\n/**\n * Checks whether a value carries a project, a case, and a control.\n *\n * @remarks\n * Exact rather than open: a claim is this package's own record, so an unknown member is a caller\n * sending a contract this service does not implement rather than a wider caller it must tolerate.\n *\n * `CLAIM_SHAPE` is the wire contract's shape and this is the admission rule the tool enforces, and\n * the rule is strictly narrower than the shape. They agree on every member but `Draft.path`: the\n * shape constrains it to a non-empty string, while `isDraft` also refuses an absolute path\n * and one that traverses out of the workspace, so `../../etc/hosts` satisfies\n * `compileGuard(CLAIM_SHAPE)` and is refused here. `ProbeServer` advertises the shape and enforces\n * this rule, so it names the refused member rather than reporting only that the claim was invalid.\n *\n * @param value - The value to check\n * @returns True if the value is a claim; false otherwise\n *\n * @example\n * ```ts\n * isClaim({ project: 'tsconfig.json', case: subject, control }) // true\n * isClaim({ project: 'tsconfig.json', case: subject }) // false\n * ```\n */\nexport const isClaim: Guard<Claim> = recordOf({\n\tproject: isNonEmptyString,\n\tcase: isCase,\n\tcontrol: isControl,\n})\n\n/**\n * Checks whether a value names a party an issue carries.\n *\n * @param value - The value to check\n * @returns True if the value is a party; false otherwise\n *\n * @example\n * ```ts\n * isParty('claimant') // true\n * isParty('workspace') // true\n * isParty('instrument') // true\n * isParty('stage') // false\n * ```\n */\nexport const isParty: Guard<Party> = literalOf(PROBE_PARTIES)\n\n/**\n * Checks whether a value carries one message, its location, and the origin of the fault it names.\n *\n * @remarks\n * `origin` is required rather than optional. Every issue this package produces sets it, and a\n * receipt turns on it: a control's issue disproves the claim only when its origin names the\n * claimant.\n *\n * @param value - The value to check\n * @returns True if the value is an issue; false otherwise\n *\n * @example\n * ```ts\n * isIssue({ origin: 'claimant', path: 'src/core/greeting.ts', message: 'not assignable' }) // true\n * isIssue({ path: 'src/core/greeting.ts', message: 'not assignable' }) // false\n * ```\n */\nexport const isIssue: Guard<Issue> = recordOf(\n\t{ origin: isParty, path: isString, message: isString, range: isLSPRange },\n\t['range'],\n)\n\n/**\n * Checks whether a value carries one stage's outcome.\n *\n * @param value - The value to check\n * @returns True if the value is a check; false otherwise\n *\n * @example\n * ```ts\n * isCheck({ stage: 'lint', elapsed: 17, issues: [] }) // true\n * ```\n */\nexport const isCheck: Guard<Check> = recordOf({\n\tstage: isStage,\n\telapsed: isNumber,\n\tissues: arrayOf(isIssue),\n})\n\n/**\n * Checks whether a value names every resolved tool version.\n *\n * @param value - The value to check\n * @returns True if the value is a toolchain; false otherwise\n *\n * @example\n * ```ts\n * isToolchain({ typescript: '6.0.3', oxlint: '1.79.0', vitest: '4.1.11' }) // true\n * isToolchain({ typescript: '6.0.3' }) // false\n * ```\n */\nexport const isToolchain: Guard<Toolchain> = recordOf({\n\ttypescript: isString,\n\toxlint: isString,\n\tvitest: isString,\n})\n\n/**\n * Checks whether a value names one resolved TypeScript project and what it contained.\n *\n * @remarks\n * Rejects an empty path and an empty digest. A verdict names the project that judged it, so a\n * blank member here would report a project the type stage never applied.\n *\n * @param value - The value to check\n * @returns True if the value is a project; false otherwise\n *\n * @example\n * ```ts\n * isProject({ path: 'configs/src/tsconfig.core.json', digest: '3b674fdf121c85ef' }) // true\n * isProject({ path: 'configs/src/tsconfig.core.json', digest: '' }) // false\n * ```\n */\nexport const isProject: Guard<Project> = recordOf({\n\tpath: isNonEmptyString,\n\tdigest: isNonEmptyString,\n})\n\n/**\n * Checks whether a value carries a complete verdict.\n *\n * @remarks\n * Accepts any check count, because arity is the coordinator's obligation rather than this guard's:\n * a stage that could not start throws before a verdict is built, so a short list can only arrive\n * from a caller that assembled one by hand.\n *\n * @param value - The value to check\n * @returns True if the value is a verdict; false otherwise\n *\n * @example\n * ```ts\n * const basis = { id: '01J8Z0', digest: '6ca20c3b', toolchain, project, elapsed: 337 }\n * isVerdict({ ...basis, case: [], control: [] }) // true\n * isVerdict({ ...basis, case: [] }) // false\n * ```\n */\nexport const isVerdict: Guard<Verdict> = recordOf(\n\t{\n\t\tid: isString,\n\t\tdigest: isString,\n\t\ttoolchain: isToolchain,\n\t\tproject: isProject,\n\t\treason: isNonEmptyString,\n\t\tcase: arrayOf(isCheck),\n\t\tcontrol: arrayOf(isCheck),\n\t\telapsed: isNumber,\n\t\treceipt: isString,\n\t},\n\t['reason', 'receipt'],\n)\n","import type { Check, Issue, Stage, Verdict } from './types.js'\nimport { PROBE_STAGES, RECEIPT_PREFIX, RECEIPT_SEPARATOR } from './constants.js'\n\n/**\n * Renders one tool message as a single line an agent can classify and locate.\n *\n * @remarks\n * `Issue.range` is stored zero-based, and this is the only place it is rendered, so the one-based\n * line an editor shows is derived here and nowhere else. The rendered location carries the line\n * alone: a reader opens a file at a line, and the column would widen every issue line in every\n * verdict for a precision that address does not use.\n *\n * @param issue - The message and location a stage reported\n * @returns The bracketed origin, location, and message, separated by spaces\n *\n * @example\n * ```ts\n * const located: Issue = {\n * \torigin: 'claimant',\n * \tpath: 'src/core/greeting.ts',\n * \tmessage: 'not assignable',\n * \trange: { start: { line: 0, character: 6 }, end: { line: 0, character: 13 } },\n * }\n * const whole: Issue = {\n * \torigin: 'claimant',\n * \tpath: 'src/core/greeting.ts',\n * \tmessage: 'not assignable',\n * }\n * formatIssue(located) // '[claimant] src/core/greeting.ts:1 not assignable'\n * formatIssue(whole) // '[claimant] src/core/greeting.ts not assignable'\n * ```\n */\nexport function formatIssue(issue: Issue): string {\n\tconst range = issue.range\n\tconst where = range === undefined ? issue.path : `${issue.path}:${range.start.line + 1}`\n\treturn `[${issue.origin}] ${where} ${issue.message}`\n}\n\n/**\n * Renders one stage's outcome as its summary line followed by every message it reported.\n *\n * @remarks\n * A clean stage renders one line. The count appears even when it is zero, because that line is\n * what shows a reader the stage ran; a silent stage and a skipped stage read the same.\n *\n * @param check - The stage outcome to render\n * @returns The summary line, then one indented line per issue\n *\n * @example\n * ```ts\n * formatCheck({ stage: 'lint', elapsed: 17, issues: [] })\n * // 'lint: 0 issues (17 ms)'\n * ```\n */\nexport function formatCheck(check: Check): string {\n\tconst count = check.issues.length\n\tconst noun = count === 1 ? 'issue' : 'issues'\n\tconst summary = `${check.stage}: ${count} ${noun} (${check.elapsed} ms)`\n\tconst lines = check.issues.map((issue) => ` ${formatIssue(issue)}`)\n\treturn [summary, ...lines].join('\\n')\n}\n\n/**\n * Renders the closing line a rendered verdict ends with: the receipt it earned, or its absence.\n *\n * @remarks\n * One implementation serves every rendering of that line, so the line a reader quotes off a whole\n * verdict and the line a bounded reply falls back to cannot drift apart.\n *\n * @param verdict - The verdict whose `receipt` decides the line\n * @returns `receipt <token>` when the verdict carries a receipt, and `no receipt` when it does not\n *\n * @example\n * ```ts\n * formatProof(proven)\n * // 'receipt probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * formatProof(disproven) // 'no receipt'\n * ```\n */\nexport function formatProof(verdict: Verdict): string {\n\treturn verdict.receipt === undefined ? 'no receipt' : `receipt ${verdict.receipt}`\n}\n\n/**\n * Renders the smallest text a verdict can travel as: what it judged, and how it ended.\n *\n * @remarks\n * A reply whose bounds refuse both the record and the whole rendering answers with this text, so it\n * carries what a reader cannot recompute — the call's identity, the claim's digest, and the\n * control's reason when the verdict carries one — and closes with the same line `formatVerdict`\n * closes with. Every line here is a line `formatVerdict` renders at the same position relative to\n * the ones around it, so a reader meets one shape whichever answer arrived.\n *\n * @param verdict - The verdict to render\n * @returns The identity and claim lines, the reason when present, then the closing receipt line\n *\n * @example\n * ```ts\n * formatReceipt(disproven).split('\\n')\n * // ['probe 88a5addc-7d33-40dc-9a5a-104b71f8787d (549 ms)', 'claim 6ca20c3bff623031d3955b9d1a76d71d', 'no receipt']\n * ```\n */\nexport function formatReceipt(verdict: Verdict): string {\n\tconst reason = verdict.reason === undefined ? [] : [`reason ${verdict.reason}`]\n\treturn [\n\t\t`probe ${verdict.id} (${verdict.elapsed} ms)`,\n\t\t`claim ${verdict.digest}`,\n\t\t...reason,\n\t\tformatProof(verdict),\n\t].join('\\n')\n}\n\n/**\n * Renders a whole verdict as the text an agent reads.\n *\n * @remarks\n * Every stage appears for both the case and the control, so no failing stage can be masked by an\n * earlier one. The closing line always states the receipt or its absence, so a reader never has to\n * infer from silence whether the claim was proven.\n *\n * The heading lines carry everything the receipt binds, each in the name-then-value form the\n * toolchain line established: the call's identity, the claim it answered, the tools that ran, and\n * the project that judged the candidates. A verdict carrying the control's reason renders it next,\n * before either phase's checks. A reader comparing two verdicts therefore reads what differed\n * without recomputing anything.\n *\n * @param verdict - The verdict to render\n * @returns The identity, claim, toolchain, project, and reason when present, then every case and\n * control stage, then the receipt line\n *\n * @example\n * ```ts\n * formatVerdict(verdict).split('\\n')[1] // 'claim 6ca20c3bff623031d3955b9d1a76d71d'\n * ```\n */\nexport function formatVerdict(verdict: Verdict): string {\n\tconst { typescript, oxlint, vitest } = verdict.toolchain\n\tconst tools = `toolchain typescript ${typescript}, oxlint ${oxlint}, vitest ${vitest}`\n\tconst project = `project ${verdict.project.path} ${verdict.project.digest}`\n\tconst reason = verdict.reason === undefined ? [] : [`reason ${verdict.reason}`]\n\treturn [\n\t\t`probe ${verdict.id} (${verdict.elapsed} ms)`,\n\t\t`claim ${verdict.digest}`,\n\t\ttools,\n\t\tproject,\n\t\t...reason,\n\t\t...verdict.case.map((check) => `case ${formatCheck(check)}`),\n\t\t...verdict.control.map((check) => `control ${formatCheck(check)}`),\n\t\tformatProof(verdict),\n\t].join('\\n')\n}\n\n/**\n * Computes the proof token a verdict carries, or returns nothing when the claim was not proven.\n *\n * @remarks\n * A receipt is minted on these conditions together: both phases report one check per stage, the\n * case carries no issue, the control carries at least one `origin: 'claimant'` issue\n * at the stage it declared, and every other control stage carries no claimant issue. A control\n * that fails somewhere else has falsified the instrument rather than the claim, so no receipt is\n * minted for it.\n *\n * Both phases owe every stage, not the case alone. `stayed` reads the control entries a verdict\n * carries, so a control that omits a stage entirely would otherwise read as a stage that stayed\n * clean, and the receipt would certify an inspection that never ran. `prove` records every stage\n * for both phases, so this condition refuses only a verdict a caller assembled by hand.\n *\n * The token names every condition the verdict was reached under, so a receipt read away from its\n * verdict still says what was judged and what judged it: the claim's digest, the stage the control\n * broke at, the tool versions, and the project the candidate drafts were checked against.\n * The call's identity is deliberately absent. It carries no integrity and it is the only value\n * stopping two honest runs of one claim from producing one comparable string, so leaving it out is\n * what makes \"re-run `prove` and compare tokens\" a verification a reader can perform.\n *\n * The project goes last, and its own path and digest are joined by `@`. Split the token on\n * `RECEIPT_SEPARATOR`, take fields 0 through 5, and rejoin the remainder with that separator to\n * read the project field; inside it the digest is everything after the final `@`. That rule stays\n * total for a workspace-relative project path containing either character.\n *\n * An `origin: 'instrument'` issue in either phase means the inspection did not complete and\n * refuses the receipt. A workspace issue in the control does not decide whether the claimant's\n * candidate broke, while one in the case still means that the case did not run clean.\n *\n * @param verdict - The verdict whose case and control checks decide the outcome\n * @param stage - The stage the claim's control declared it must fail at\n * @returns The receipt token, or `undefined` when any condition fails\n *\n * @example\n * ```ts\n * computeReceipt(proven, 'type')\n * // 'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * computeReceipt(proven, 'lint') // undefined\n * ```\n */\nexport function computeReceipt(verdict: Verdict, stage: Stage): string | undefined {\n\tconst ran = PROBE_STAGES.every(\n\t\t(name) =>\n\t\t\tverdict.case.filter((check) => check.stage === name).length === 1 &&\n\t\t\tverdict.control.filter((check) => check.stage === name).length === 1,\n\t)\n\tconst clean = verdict.case.every((check) => check.issues.length === 0)\n\tconst declared = verdict.control.find((check) => check.stage === stage)\n\tconst broke = declared?.issues.some((issue) => issue.origin === 'claimant') ?? false\n\tconst faulted =\n\t\tverdict.case.some((check) => check.issues.some((issue) => issue.origin === 'instrument')) ||\n\t\tverdict.control.some((check) => check.issues.some((issue) => issue.origin === 'instrument'))\n\tconst stayed = verdict.control.every(\n\t\t(check) => check.stage === stage || check.issues.every((issue) => issue.origin !== 'claimant'),\n\t)\n\tif (!ran || !clean || !broke || faulted || !stayed) return undefined\n\tconst { typescript, oxlint, vitest } = verdict.toolchain\n\treturn [\n\t\tRECEIPT_PREFIX,\n\t\tverdict.digest,\n\t\tstage,\n\t\t`typescript@${typescript}`,\n\t\t`oxlint@${oxlint}`,\n\t\t`vitest@${vitest}`,\n\t\t`${verdict.project.path}@${verdict.project.digest}`,\n\t].join(RECEIPT_SEPARATOR)\n}\n\n/**\n * Renders one generated specification: the caller's own test text, then the marker naming the\n * revision that wrote it.\n *\n * @remarks\n * The marker is what makes a file in a target workspace attributable to this package. A generated\n * specification carries text the caller supplied, so its name alone cannot separate it from a\n * developer's own file, and a sweep reading the name alone deletes that file. The marker goes last\n * so every line of the caller's text keeps the number a reported stack frame gives it, and the text\n * gains a terminating newline first so the marker is never appended to a line of the test.\n *\n * @param text - The caller's own test text\n * @param revision - The writing host's process id and a fresh UUID, joined by `-`\n * @returns The bytes the runtime stage writes for that revision\n *\n * @example\n * ```ts\n * formatSpecification(\"test('greets', () => {})\\n\", '4821-9f0c')\n * // \"test('greets', () => {})\\n// @orkestrel/probe generated specification 4821-9f0c\\n\"\n * ```\n */\nexport function formatSpecification(text: string, revision: string): string {\n\tconst body = text === '' || text.endsWith('\\n') ? text : `${text}\\n`\n\treturn `${body}// @orkestrel/probe generated specification ${revision}\\n`\n}\n\n/**\n * Checks whether one file's text is the generated specification written for one revision.\n *\n * @remarks\n * Reads the marker `formatSpecification` writes, taken from that function rather than restated, so\n * the writer and the reader cannot drift apart. An empty body renders the marker alone, which is\n * why the comparison is built from a call rather than from a second copy of the text.\n *\n * @param text - The file's full contents\n * @param revision - The revision the file's name declares\n * @returns True if the text ends with this package's marker for that revision; false otherwise\n *\n * @example\n * ```ts\n * matchesSpecification(formatSpecification('', '4821-9f0c'), '4821-9f0c') // true\n * matchesSpecification('export const NOTE = 1\\n', '4821-9f0c') // false\n * ```\n */\nexport function matchesSpecification(text: string, revision: string): boolean {\n\treturn text.endsWith(formatSpecification('', revision))\n}\n","import { arrayShape, literalShape, objectShape, stringShape } from '@orkestrel/contract'\nimport { PROBE_STAGES } from './constants.js'\n\n/**\n * Describes one proposed file a claim carries.\n *\n * @remarks\n * `path` is constrained to a non-empty string because every stage resolves a file by it, so an\n * empty path names no file. That minimum is the whole of the constraint here, and it is the one\n * place the wire contract is wider than what this package admits: `isDraft` enforces the same\n * minimum and also refuses an absolute path and one that traverses out of the workspace, which no\n * JSON Schema keyword can express. A caller that satisfies this shape can still be refused, and\n * `ProbeServer` names the member when it is.\n *\n * @example\n * ```ts\n * compileGuard(DRAFT_SHAPE)({ path: 'src/core/greeting.ts', text: '' }) // true\n * ```\n */\nexport const DRAFT_SHAPE = objectShape(\n\t{\n\t\tpath: stringShape({ min: 1, description: 'Workspace-relative path, which need not exist.' }),\n\t\ttext: stringShape({ description: \"The file's full contents.\" }),\n\t},\n\t{ description: 'One proposed file a claim carries.' },\n)\n\n/**\n * Describes the drafts a claim asserts about and the test that exercises them.\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: '' }\n * compileGuard(CASE_SHAPE)({ files: [], test }) // true\n * ```\n */\nexport const CASE_SHAPE = objectShape(\n\t{\n\t\tfiles: arrayShape(DRAFT_SHAPE, { description: 'The candidate drafts the test imports.' }),\n\t\ttest: DRAFT_SHAPE,\n\t},\n\t{ description: 'The drafts a claim asserts about, and the test that exercises them.' },\n)\n\n/**\n * Describes the negative control, which is a case plus where and why it must break.\n *\n * @remarks\n * Built from `CASE_SHAPE`'s own properties rather than a second copy of them, so the control and\n * the case cannot describe a draft differently.\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: '' }\n * compileGuard(CONTROL_SHAPE)({ files: [], test, stage: 'type', reason: 'must not compile' }) // true\n * ```\n */\nexport const CONTROL_SHAPE = objectShape(\n\t{\n\t\t...CASE_SHAPE.properties,\n\t\tstage: literalShape(PROBE_STAGES, { description: 'The stage this control must fail at.' }),\n\t\treason: stringShape({ min: 1, description: 'Why the control fails at that stage.' }),\n\t},\n\t{ description: 'A case that must fail, naming the stage where it must fail and why.' },\n)\n\n/**\n * Describes one claim and is the sole source of both the published tool schema and the guard\n * applied to an arriving claim.\n *\n * @remarks\n * The Model Context Protocol tool publishes `compileSchema(CLAIM_SHAPE)` and admits a call with\n * `isClaim`. Deriving the advertised schema from this one value is what stops the two from drifting\n * apart across a release on any member either can express. `isClaim` is narrower on the one member\n * neither a schema keyword nor this shape can carry — the containment rule on `Draft.path` — and\n * `validators.ts` names where.\n *\n * @example\n * ```ts\n * const schema = compileSchema(CLAIM_SHAPE)\n * const admits = compileGuard(CLAIM_SHAPE)\n * schema.type // 'object'\n * admits({ project: 'tsconfig.json' }) // false\n * ```\n */\nexport const CLAIM_SHAPE = objectShape(\n\t{\n\t\tproject: stringShape({\n\t\t\tmin: 1,\n\t\t\tdescription:\n\t\t\t\t'Workspace-relative TypeScript project the candidate drafts are checked against.',\n\t\t}),\n\t\tcase: CASE_SHAPE,\n\t\tcontrol: CONTROL_SHAPE,\n\t},\n\t{ description: 'One claim: the project, the case, and the control that must break.' },\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/shapers.ts"],"sourcesContent":["/**\n * Lists the stages a claim passes through, in the order a verdict reports them.\n *\n * @remarks\n * One list feeds the `Stage` type, the wire shape, the stage guard, and the receipt computation, so\n * a stage cannot be admitted by one and refused by another. The type derives from this list rather\n * than standing beside it, so a stage the list omits is a stage no member of the union names.\n *\n * @example\n * ```ts\n * PROBE_STAGES // ['type', 'lint', 'runtime']\n * ```\n */\nexport const PROBE_STAGES = Object.freeze(['type', 'lint', 'runtime'] as const)\n\n/**\n * Lists the parties that can own action on an issue or probe failure.\n *\n * @remarks\n * One list feeds the `Party` type and its guard, so a party cannot be admitted by one and refused\n * by another.\n *\n * @example\n * ```ts\n * PROBE_PARTIES // ['claimant', 'workspace', 'instrument']\n * ```\n */\nexport const PROBE_PARTIES = Object.freeze(['claimant', 'workspace', 'instrument'] as const)\n\n/**\n * Lists the conditions that can end a probe operation.\n *\n * @remarks\n * One list feeds the code union and the error guard, so a condition cannot be constructed by one\n * and refused by the other. The guard reads this list rather than the class, which is what lets it\n * refuse a lookalike carrying a condition this package never declared.\n *\n * @example\n * ```ts\n * PROBE_ERROR_CODES // ['refused', 'missing', 'malformed', 'destroyed', 'deadline']\n * ```\n */\nexport const PROBE_ERROR_CODES = Object.freeze([\n\t'refused',\n\t'missing',\n\t'malformed',\n\t'destroyed',\n\t'deadline',\n] as const)\n\n/**\n * Names the leading token every receipt carries.\n *\n * @remarks\n * A receipt travels away from the verdict that minted it — an agent pastes it into the promotion\n * action — so it names itself rather than relying on where it was found.\n *\n * @example\n * ```ts\n * const receipt =\n * \t'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * receipt.startsWith(RECEIPT_PREFIX) // true\n * ```\n */\nexport const RECEIPT_PREFIX = 'probe'\n\n/**\n * Names the character joining a receipt's tokens.\n *\n * @remarks\n * A project path can contain this character, so the project field goes last and a reader rejoins\n * every field from index 6 onward with this separator rather than expecting a fixed count.\n *\n * @example\n * ```ts\n * const receipt =\n * \t'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * receipt.split(RECEIPT_SEPARATOR).length // 7\n * ```\n */\nexport const RECEIPT_SEPARATOR = ':'\n\n/**\n * Names the default inspection deadline a `Probe` applies when its construction omits one.\n *\n * @remarks\n * `ProbeOptions.deadline` overrides this value per instance.\n *\n * @example\n * ```ts\n * PROBE_DEADLINE // 30_000\n * ```\n */\nexport const PROBE_DEADLINE = 30_000\n\n/**\n * Names the bound the lint stage holds over the lifecycle exchanges the protocol leaves to the\n * server: the `initialize` reply warming waits for and the `shutdown` reply ending waits for.\n *\n * @remarks\n * It does not reach the diagnostics an inspection waits for, which the caller's own signal bounds.\n * The transport's cooperative window is half of it, so a child that ignores its ending is\n * signalled and released inside the same bound rather than outliving the client's own wait for\n * the close. Measured 2026-08-27: the workspace `oxlint --lsp` answers `initialize` in 155 ms, so\n * this bound is more than ten times that reply.\n *\n * @example\n * ```ts\n * LINT_DEADLINE // 2_000\n * ```\n */\nexport const LINT_DEADLINE = 2_000\n\n/**\n * Names the total enumerable key bound `ProbeServer` applies to inbound metadata and to produced\n * tool content alike.\n *\n * @remarks\n * `@orkestrel/mcp`'s default leaf is sized for metadata: a verdict costs 38 keys empty and 11 more\n * for each issue a stage reports, so the default carries a verdict whose control refuses one\n * declaration and stops carrying the next one. A whole tool-call result carrying the record beside\n * its rendering costs 44 keys plus 11 for each issue, so this bound carries a record reporting up\n * to 368 issues. Past that the reply falls back to the rendered text, and past the 4 MiB content\n * bound to the receipt block.\n *\n * @example\n * ```ts\n * PROBE_KEYS // 4096\n * ```\n */\nexport const PROBE_KEYS = 4096\n\n/**\n * Names the specification lifetime the runtime stage replaces its resident Vitest service at.\n *\n * @remarks\n * Vite retains one unresolved URL for every fresh specification path, so an inspection that writes\n * a specification grows a map the resident service never releases. The stage replaces that service\n * rather than deleting from each map it owns, and this is the count of specifications one service\n * carries before the replacement. Any bound holds the retention flat, because the replacement\n * releases everything the instance held; this value trades the cost of the replacement against how\n * far the map grows between them. On 2026-08-20, over this package's own workspace on the host\n * `guides/probe.md` § Cost names, two runs of 66 inspections put the crossing inspection at 480 ms\n * and 269 ms against median inspections of 156 ms and 155 ms.\n *\n * @example\n * ```ts\n * PROBE_SPECIFICATIONS // 64\n * ```\n */\nexport const PROBE_SPECIFICATIONS = 64\n\n/**\n * Names the Vite plugin the runtime stage installs into a target workspace's Vitest configuration.\n *\n * @remarks\n * The stage declares the plugin under this name and reads a configured project's plugin list for\n * the same name to decide whether that project carries the overlay. One name feeds both, so a\n * project the stage instrumented is never reported as a workspace project it could not reach.\n *\n * @example\n * ```ts\n * RUNTIME_PLUGIN // 'orkestrel-runtime-overlay'\n * ```\n */\nexport const RUNTIME_PLUGIN = 'orkestrel-runtime-overlay'\n","import type { Party, ProbeErrorCode, ProbeErrorContext, ProbeErrorOptions } from './types.js'\nimport { holds, isError } from '@orkestrel/contract'\nimport { PROBE_ERROR_CODES, PROBE_PARTIES } from './constants.js'\n\n/**\n * Reports one probe failure under stable ownership and condition axes.\n *\n * @remarks\n * Every failure raised while serving a claim arrives as one of these, so a consumer catching from\n * `prove`, from a stage, or from a workspace leaf branches on {@link Party} and\n * {@link ProbeErrorCode} rather than on message text. Narrow a caught value with\n * {@link isProbeError} before reading either member. A pure leaf called directly with a value\n * `isClaim` would refuse raises the host's own fault unchanged, because those leaves are written to\n * be total over a validated claim rather than over every value.\n *\n * @example\n * ```ts\n * const error = new ProbeError('Path escapes the workspace: ../secrets.env', {\n * \torigin: 'claimant',\n * \tcode: 'refused',\n * \tcontext: { path: '../secrets.env' },\n * })\n * error.origin // 'claimant'\n * error.code // 'refused'\n * error.context?.path // '../secrets.env'\n * ```\n */\nexport class ProbeError extends Error {\n\toverride readonly name = 'ProbeError'\n\treadonly origin: Party\n\treadonly code: ProbeErrorCode\n\treadonly context?: ProbeErrorContext\n\n\t/**\n\t * Creates one classified probe failure.\n\t *\n\t * @param message - Human-readable description of what failed\n\t * @param options - The ownership, condition, optional structured context, and optional cause\n\t */\n\tconstructor(message: string, options: ProbeErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\t// A global own-property brand rather than the constructor identity, because a consumer that\n\t\t// installs this package twice, or loads its ESM and CommonJS builds together, holds two\n\t\t// classes and `instanceof` refuses the other one's error.\n\t\tObject.defineProperty(this, Symbol.for('@orkestrel/probe.error'), { value: true })\n\t\tthis.origin = options.origin\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProbeError}.\n *\n * @remarks\n * Recognition combines the global own-property brand with the native `Error` base, the subclass\n * prototype, the fixed name, a party {@link PROBE_PARTIES} declares, and a condition\n * {@link PROBE_ERROR_CODES} declares. The brand carries recognition across duplicate installations\n * and across an ESM and a CommonJS copy of this package, where the two classes are different values.\n * A plain `Error`, a property-only lookalike, and a branded value carrying an undeclared origin or\n * condition all stay outside the type.\n *\n * @param value - The value to inspect\n * @returns True if the value is a `ProbeError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProbeError(createDestroyedError('probe')) // true\n * isProbeError(new Error('The probe has been destroyed')) // false\n * ```\n */\nexport function isProbeError(value: unknown): value is ProbeError {\n\tif (!isError(value)) return false\n\treturn holds(() => {\n\t\tif (Object.getPrototypeOf(value) === Error.prototype) return false\n\t\tif (value.name !== 'ProbeError' || !('origin' in value) || !('code' in value)) return false\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, Symbol.for('@orkestrel/probe.error'))\n\t\tif (descriptor?.value !== true) return false\n\t\tconst origin: unknown = value.origin\n\t\tconst code: unknown = value.code\n\t\treturn (\n\t\t\tPROBE_PARTIES.some((declared) => declared === origin) &&\n\t\t\tPROBE_ERROR_CODES.some((declared) => declared === code)\n\t\t)\n\t})\n}\n\n/**\n * Creates the failure raised when an instrument is used after it was torn down.\n *\n * @remarks\n * Every resident entity in this package refuses this way, so the subject names which one in the\n * message and the condition is the same for all of them. A caller that meets this builds a\n * replacement rather than retrying: teardown is permanent.\n *\n * @param subject - The torn-down entity, named as the message names it, such as `type stage`\n * @returns A typed teardown failure\n *\n * @example\n * ```ts\n * createDestroyedError('type stage').message // 'The type stage has been destroyed'\n * createDestroyedError('probe').code // 'destroyed'\n * ```\n */\nexport function createDestroyedError(subject: string): ProbeError {\n\treturn new ProbeError(`The ${subject} has been destroyed`, {\n\t\torigin: 'claimant',\n\t\tcode: 'destroyed',\n\t})\n}\n","import type { Guard } from '@orkestrel/contract'\nimport type {\n\tCase,\n\tCheck,\n\tClaim,\n\tControl,\n\tDraft,\n\tIssue,\n\tParty,\n\tProject,\n\tStage,\n\tToolchain,\n\tVerdict,\n} from './types.js'\nimport {\n\tandOf,\n\tarrayOf,\n\tisNonEmptyString,\n\tisNumber,\n\tisString,\n\tliteralOf,\n\trecordOf,\n} from '@orkestrel/contract'\nimport { isLSPRange } from '@orkestrel/lsp'\nimport { PROBE_PARTIES, PROBE_STAGES } from './constants.js'\n\n/**\n * Checks whether a value names a stage.\n *\n * @param value - The value to check\n * @returns True if the value is a stage name; false otherwise\n *\n * @example\n * ```ts\n * isStage('lint') // true\n * isStage('typecheck') // false\n * ```\n */\nexport const isStage: Guard<Stage> = literalOf(PROBE_STAGES)\n\n/**\n * Checks whether a value carries a proposed file's path and text.\n *\n * @remarks\n * Rejects an empty, absolute, or workspace-escaping path. A contained relative path may contain\n * `.` or may traverse to a parent that remains inside the workspace. Every stage resolves a file\n * by that path, so admitting an escape here would defer the refusal until a stage had already\n * accepted the draft. An `Issue` carries no such minimum because this package produces issues\n * rather than admits them.\n *\n * @param value - The value to check\n * @returns True if the value is a draft; false otherwise\n *\n * @example\n * ```ts\n * isDraft({ path: 'src/core/greeting.ts', text: 'export const GREETING = \"hi\"\\n' }) // true\n * isDraft({ path: '../../etc/hosts', text: '' }) // false\n * isDraft({ path: 'src/core/greeting.ts' }) // false\n * ```\n */\nexport const isDraft: Guard<Draft> = recordOf({\n\tpath: andOf<string>(isNonEmptyString, (path) => {\n\t\tif (/^(?:[\\\\/]|[A-Za-z]:)/.test(path)) return false\n\t\tlet depth = 0\n\t\tfor (const segment of path.split(/[\\\\/]+/)) {\n\t\t\tif (segment === '' || segment === '.') continue\n\t\t\tif (segment !== '..') {\n\t\t\t\tdepth += 1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (depth === 0) return false\n\t\t\tdepth -= 1\n\t\t}\n\t\treturn true\n\t}),\n\ttext: isString,\n})\n\n/**\n * Checks whether a value carries a claim's candidate drafts and its test.\n *\n * @param value - The value to check\n * @returns True if the value is a case; false otherwise\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: 'test(\"greets\", () => {})\\n' }\n * isCase({ files: [], test }) // true\n * ```\n */\nexport const isCase: Guard<Case> = recordOf({ files: arrayOf(isDraft), test: isDraft })\n\n/**\n * Checks whether a value carries a case plus the stage and reason it must fail for.\n *\n * @param value - The value to check\n * @returns True if the value is a control; false otherwise\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: 'test(\"greets\", () => {})\\n' }\n * isControl({ files: [], test, stage: 'type', reason: 'must not compile' }) // true\n * isControl({ files: [], test }) // false\n * ```\n */\nexport const isControl: Guard<Control> = recordOf({\n\tfiles: arrayOf(isDraft),\n\ttest: isDraft,\n\tstage: isStage,\n\treason: isNonEmptyString,\n})\n\n/**\n * Checks whether a value carries a project, a case, and a control.\n *\n * @remarks\n * Exact rather than open: a claim is this package's own record, so an unknown member is a caller\n * sending a contract this service does not implement rather than a wider caller it must tolerate.\n *\n * `CLAIM_SHAPE` is the wire contract's shape and this is the admission rule the tool enforces, and\n * the rule is strictly narrower than the shape. They agree on every member but `Draft.path`: the\n * shape constrains it to a non-empty string, while `isDraft` also refuses an absolute path\n * and one that traverses out of the workspace, so `../../etc/hosts` satisfies\n * `compileGuard(CLAIM_SHAPE)` and is refused here. `ProbeServer` advertises the shape and enforces\n * this rule, so it names the refused member rather than reporting only that the claim was invalid.\n *\n * @param value - The value to check\n * @returns True if the value is a claim; false otherwise\n *\n * @example\n * ```ts\n * isClaim({ project: 'tsconfig.json', case: subject, control }) // true\n * isClaim({ project: 'tsconfig.json', case: subject }) // false\n * ```\n */\nexport const isClaim: Guard<Claim> = recordOf({\n\tproject: isNonEmptyString,\n\tcase: isCase,\n\tcontrol: isControl,\n})\n\n/**\n * Checks whether a value names a party an issue carries.\n *\n * @param value - The value to check\n * @returns True if the value is a party; false otherwise\n *\n * @example\n * ```ts\n * isParty('claimant') // true\n * isParty('workspace') // true\n * isParty('instrument') // true\n * isParty('stage') // false\n * ```\n */\nexport const isParty: Guard<Party> = literalOf(PROBE_PARTIES)\n\n/**\n * Checks whether a value carries one message, its location, and the origin of the fault it names.\n *\n * @remarks\n * `origin` is required rather than optional. Every issue this package produces sets it, and a\n * receipt turns on it: a control's issue disproves the claim only when its origin names the\n * claimant.\n *\n * @param value - The value to check\n * @returns True if the value is an issue; false otherwise\n *\n * @example\n * ```ts\n * isIssue({ origin: 'claimant', path: 'src/core/greeting.ts', message: 'not assignable' }) // true\n * isIssue({ path: 'src/core/greeting.ts', message: 'not assignable' }) // false\n * ```\n */\nexport const isIssue: Guard<Issue> = recordOf(\n\t{ origin: isParty, path: isString, message: isString, range: isLSPRange },\n\t['range'],\n)\n\n/**\n * Checks whether a value carries one stage's outcome.\n *\n * @param value - The value to check\n * @returns True if the value is a check; false otherwise\n *\n * @example\n * ```ts\n * isCheck({ stage: 'lint', elapsed: 17, issues: [] }) // true\n * ```\n */\nexport const isCheck: Guard<Check> = recordOf({\n\tstage: isStage,\n\telapsed: isNumber,\n\tissues: arrayOf(isIssue),\n})\n\n/**\n * Checks whether a value names every resolved tool version.\n *\n * @param value - The value to check\n * @returns True if the value is a toolchain; false otherwise\n *\n * @example\n * ```ts\n * isToolchain({ typescript: '6.0.3', oxlint: '1.79.0', vitest: '4.1.11' }) // true\n * isToolchain({ typescript: '6.0.3' }) // false\n * ```\n */\nexport const isToolchain: Guard<Toolchain> = recordOf({\n\ttypescript: isString,\n\toxlint: isString,\n\tvitest: isString,\n})\n\n/**\n * Checks whether a value names one resolved TypeScript project and what it contained.\n *\n * @remarks\n * Rejects an empty path and an empty digest. A verdict names the project that judged it, so a\n * blank member here would report a project the type stage never applied.\n *\n * @param value - The value to check\n * @returns True if the value is a project; false otherwise\n *\n * @example\n * ```ts\n * isProject({ path: 'configs/src/tsconfig.core.json', digest: '3b674fdf121c85ef' }) // true\n * isProject({ path: 'configs/src/tsconfig.core.json', digest: '' }) // false\n * ```\n */\nexport const isProject: Guard<Project> = recordOf({\n\tpath: isNonEmptyString,\n\tdigest: isNonEmptyString,\n})\n\n/**\n * Checks whether a value carries a complete verdict.\n *\n * @remarks\n * Accepts any check count, because arity is the coordinator's obligation rather than this guard's:\n * a stage that could not start throws before a verdict is built, so a short list can only arrive\n * from a caller that assembled one by hand.\n *\n * @param value - The value to check\n * @returns True if the value is a verdict; false otherwise\n *\n * @example\n * ```ts\n * const basis = { id: '01J8Z0', digest: '6ca20c3b', toolchain, project, elapsed: 337 }\n * isVerdict({ ...basis, case: [], control: [] }) // true\n * isVerdict({ ...basis, case: [] }) // false\n * ```\n */\nexport const isVerdict: Guard<Verdict> = recordOf(\n\t{\n\t\tid: isString,\n\t\tdigest: isString,\n\t\ttoolchain: isToolchain,\n\t\tproject: isProject,\n\t\treason: isNonEmptyString,\n\t\tcase: arrayOf(isCheck),\n\t\tcontrol: arrayOf(isCheck),\n\t\telapsed: isNumber,\n\t\treceipt: isString,\n\t},\n\t['reason', 'receipt'],\n)\n","import type { Check, Issue, Stage, Verdict } from './types.js'\nimport { PROBE_STAGES, RECEIPT_PREFIX, RECEIPT_SEPARATOR } from './constants.js'\n\n/**\n * Renders one tool message as a single line an agent can classify and locate.\n *\n * @remarks\n * `Issue.range` is stored zero-based, and this is the only place it is rendered, so the one-based\n * line an editor shows is derived here and nowhere else. The rendered location carries the line\n * alone: a reader opens a file at a line, and the column would widen every issue line in every\n * verdict for a precision that address does not use.\n *\n * @param issue - The message and location a stage reported\n * @returns The bracketed origin, location, and message, separated by spaces\n *\n * @example\n * ```ts\n * const located: Issue = {\n * \torigin: 'claimant',\n * \tpath: 'src/core/greeting.ts',\n * \tmessage: 'not assignable',\n * \trange: { start: { line: 0, character: 6 }, end: { line: 0, character: 13 } },\n * }\n * const whole: Issue = {\n * \torigin: 'claimant',\n * \tpath: 'src/core/greeting.ts',\n * \tmessage: 'not assignable',\n * }\n * formatIssue(located) // '[claimant] src/core/greeting.ts:1 not assignable'\n * formatIssue(whole) // '[claimant] src/core/greeting.ts not assignable'\n * ```\n */\nexport function formatIssue(issue: Issue): string {\n\tconst range = issue.range\n\tconst where = range === undefined ? issue.path : `${issue.path}:${range.start.line + 1}`\n\treturn `[${issue.origin}] ${where} ${issue.message}`\n}\n\n/**\n * Renders one stage's outcome as its summary line followed by every message it reported.\n *\n * @remarks\n * A clean stage renders one line. The count appears even when it is zero, because that line is\n * what shows a reader the stage ran; a silent stage and a skipped stage read the same.\n *\n * @param check - The stage outcome to render\n * @returns The summary line, then one indented line per issue\n *\n * @example\n * ```ts\n * formatCheck({ stage: 'lint', elapsed: 17, issues: [] })\n * // 'lint: 0 issues (17 ms)'\n * ```\n */\nexport function formatCheck(check: Check): string {\n\tconst count = check.issues.length\n\tconst noun = count === 1 ? 'issue' : 'issues'\n\tconst summary = `${check.stage}: ${count} ${noun} (${check.elapsed} ms)`\n\tconst lines = check.issues.map((issue) => ` ${formatIssue(issue)}`)\n\treturn [summary, ...lines].join('\\n')\n}\n\n/**\n * Renders the closing line a rendered verdict ends with: the receipt it earned, or its absence.\n *\n * @remarks\n * One implementation serves every rendering of that line, so the line a reader quotes off a whole\n * verdict and the line a bounded reply falls back to cannot drift apart.\n *\n * @param verdict - The verdict whose `receipt` decides the line\n * @returns `receipt <token>` when the verdict carries a receipt, and `no receipt` when it does not\n *\n * @example\n * ```ts\n * formatProof(proven)\n * // 'receipt probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * formatProof(disproven) // 'no receipt'\n * ```\n */\nexport function formatProof(verdict: Verdict): string {\n\treturn verdict.receipt === undefined ? 'no receipt' : `receipt ${verdict.receipt}`\n}\n\n/**\n * Renders the smallest text a verdict can travel as: what it judged, and how it ended.\n *\n * @remarks\n * A reply whose bounds refuse both the record and the whole rendering answers with this text, so it\n * carries what a reader cannot recompute — the call's identity, the claim's digest, and the\n * control's reason when the verdict carries one — and closes with the same line `formatVerdict`\n * closes with. Every line here is a line `formatVerdict` renders at the same position relative to\n * the ones around it, so a reader meets one shape whichever answer arrived.\n *\n * @param verdict - The verdict to render\n * @returns The identity and claim lines, the reason when present, then the closing receipt line\n *\n * @example\n * ```ts\n * formatReceipt(disproven).split('\\n')\n * // ['probe 88a5addc-7d33-40dc-9a5a-104b71f8787d (549 ms)', 'claim 6ca20c3bff623031d3955b9d1a76d71d', 'no receipt']\n * ```\n */\nexport function formatReceipt(verdict: Verdict): string {\n\tconst reason = verdict.reason === undefined ? [] : [`reason ${verdict.reason}`]\n\treturn [\n\t\t`probe ${verdict.id} (${verdict.elapsed} ms)`,\n\t\t`claim ${verdict.digest}`,\n\t\t...reason,\n\t\tformatProof(verdict),\n\t].join('\\n')\n}\n\n/**\n * Renders a whole verdict as the text an agent reads.\n *\n * @remarks\n * Every stage appears for both the case and the control, so no failing stage can be masked by an\n * earlier one. The closing line always states the receipt or its absence, so a reader never has to\n * infer from silence whether the claim was proven.\n *\n * The heading lines carry everything the receipt binds, each in the name-then-value form the\n * toolchain line established: the call's identity, the claim it answered, the tools that ran, and\n * the project that judged the candidates. A verdict carrying the control's reason renders it next,\n * before either phase's checks. A reader comparing two verdicts therefore reads what differed\n * without recomputing anything.\n *\n * @param verdict - The verdict to render\n * @returns The identity, claim, toolchain, project, and reason when present, then every case and\n * control stage, then the receipt line\n *\n * @example\n * ```ts\n * formatVerdict(verdict).split('\\n')[1] // 'claim 6ca20c3bff623031d3955b9d1a76d71d'\n * ```\n */\nexport function formatVerdict(verdict: Verdict): string {\n\tconst { typescript, oxlint, vitest } = verdict.toolchain\n\tconst tools = `toolchain typescript ${typescript}, oxlint ${oxlint}, vitest ${vitest}`\n\tconst project = `project ${verdict.project.path} ${verdict.project.digest}`\n\tconst reason = verdict.reason === undefined ? [] : [`reason ${verdict.reason}`]\n\treturn [\n\t\t`probe ${verdict.id} (${verdict.elapsed} ms)`,\n\t\t`claim ${verdict.digest}`,\n\t\ttools,\n\t\tproject,\n\t\t...reason,\n\t\t...verdict.case.map((check) => `case ${formatCheck(check)}`),\n\t\t...verdict.control.map((check) => `control ${formatCheck(check)}`),\n\t\tformatProof(verdict),\n\t].join('\\n')\n}\n\n/**\n * Computes the proof token a verdict carries, or returns nothing when the claim was not proven.\n *\n * @remarks\n * A receipt is minted on these conditions together: both phases report one check per stage, the\n * case carries no issue, the control carries at least one `origin: 'claimant'` issue\n * at the stage it declared, and every other control stage carries no claimant issue. A control\n * that fails somewhere else has falsified the instrument rather than the claim, so no receipt is\n * minted for it.\n *\n * Both phases owe every stage, not the case alone. `stayed` reads the control entries a verdict\n * carries, so a control that omits a stage entirely would otherwise read as a stage that stayed\n * clean, and the receipt would certify an inspection that never ran. `prove` records every stage\n * for both phases, so this condition refuses only a verdict a caller assembled by hand.\n *\n * The token names every condition the verdict was reached under, so a receipt read away from its\n * verdict still says what was judged and what judged it: the claim's digest, the stage the control\n * broke at, the tool versions, and the project the candidate drafts were checked against.\n * The call's identity is deliberately absent. It carries no integrity and it is the only value\n * stopping two honest runs of one claim from producing one comparable string, so leaving it out is\n * what makes \"re-run `prove` and compare tokens\" a verification a reader can perform.\n *\n * The project goes last, and its own path and digest are joined by `@`. Split the token on\n * `RECEIPT_SEPARATOR`, take fields 0 through 5, and rejoin the remainder with that separator to\n * read the project field; inside it the digest is everything after the final `@`. That rule stays\n * total for a workspace-relative project path containing either character.\n *\n * An `origin: 'instrument'` issue in either phase means the inspection did not complete and\n * refuses the receipt. A workspace issue in the control does not decide whether the claimant's\n * candidate broke, while one in the case still means that the case did not run clean.\n *\n * @param verdict - The verdict whose case and control checks decide the outcome\n * @param stage - The stage the claim's control declared it must fail at\n * @returns The receipt token, or `undefined` when any condition fails\n *\n * @example\n * ```ts\n * computeReceipt(proven, 'type')\n * // 'probe:6ca20c3bff623031d3955b9d1a76d71d:type:typescript@6.0.3:oxlint@1.79.0:vitest@4.1.11:configs/src/tsconfig.core.json@3b674fdf121c85efb9ed1bab25ceeec8'\n * computeReceipt(proven, 'lint') // undefined\n * ```\n */\nexport function computeReceipt(verdict: Verdict, stage: Stage): string | undefined {\n\tconst ran = PROBE_STAGES.every(\n\t\t(name) =>\n\t\t\tverdict.case.filter((check) => check.stage === name).length === 1 &&\n\t\t\tverdict.control.filter((check) => check.stage === name).length === 1,\n\t)\n\tconst clean = verdict.case.every((check) => check.issues.length === 0)\n\tconst declared = verdict.control.find((check) => check.stage === stage)\n\tconst broke = declared?.issues.some((issue) => issue.origin === 'claimant') ?? false\n\tconst faulted =\n\t\tverdict.case.some((check) => check.issues.some((issue) => issue.origin === 'instrument')) ||\n\t\tverdict.control.some((check) => check.issues.some((issue) => issue.origin === 'instrument'))\n\tconst stayed = verdict.control.every(\n\t\t(check) => check.stage === stage || check.issues.every((issue) => issue.origin !== 'claimant'),\n\t)\n\tif (!ran || !clean || !broke || faulted || !stayed) return undefined\n\tconst { typescript, oxlint, vitest } = verdict.toolchain\n\treturn [\n\t\tRECEIPT_PREFIX,\n\t\tverdict.digest,\n\t\tstage,\n\t\t`typescript@${typescript}`,\n\t\t`oxlint@${oxlint}`,\n\t\t`vitest@${vitest}`,\n\t\t`${verdict.project.path}@${verdict.project.digest}`,\n\t].join(RECEIPT_SEPARATOR)\n}\n\n/**\n * Renders one generated specification: the caller's own test text, then the marker naming the\n * revision that wrote it.\n *\n * @remarks\n * The marker is what makes a file in a target workspace attributable to this package. A generated\n * specification carries text the caller supplied, so its name alone cannot separate it from a\n * developer's own file, and a sweep reading the name alone deletes that file. The marker goes last\n * so every line of the caller's text keeps the number a reported stack frame gives it, and the text\n * gains a terminating newline first so the marker is never appended to a line of the test.\n *\n * @param text - The caller's own test text\n * @param revision - The writing host's process id and a fresh UUID, joined by `-`\n * @returns The bytes the runtime stage writes for that revision\n *\n * @example\n * ```ts\n * formatSpecification(\"test('greets', () => {})\\n\", '4821-9f0c')\n * // \"test('greets', () => {})\\n// @orkestrel/probe generated specification 4821-9f0c\\n\"\n * ```\n */\nexport function formatSpecification(text: string, revision: string): string {\n\tconst body = text === '' || text.endsWith('\\n') ? text : `${text}\\n`\n\treturn `${body}// @orkestrel/probe generated specification ${revision}\\n`\n}\n\n/**\n * Checks whether one file's text is the generated specification written for one revision.\n *\n * @remarks\n * Reads the marker `formatSpecification` writes, taken from that function rather than restated, so\n * the writer and the reader cannot drift apart. An empty body renders the marker alone, which is\n * why the comparison is built from a call rather than from a second copy of the text.\n *\n * @param text - The file's full contents\n * @param revision - The revision the file's name declares\n * @returns True if the text ends with this package's marker for that revision; false otherwise\n *\n * @example\n * ```ts\n * matchesSpecification(formatSpecification('', '4821-9f0c'), '4821-9f0c') // true\n * matchesSpecification('export const NOTE = 1\\n', '4821-9f0c') // false\n * ```\n */\nexport function matchesSpecification(text: string, revision: string): boolean {\n\treturn text.endsWith(formatSpecification('', revision))\n}\n","import { arrayShape, literalShape, objectShape, stringShape } from '@orkestrel/contract'\nimport { PROBE_STAGES } from './constants.js'\n\n/**\n * Describes one proposed file a claim carries.\n *\n * @remarks\n * `path` is constrained to a non-empty string because every stage resolves a file by it, so an\n * empty path names no file. That minimum is the whole of the constraint here, and it is the one\n * place the wire contract is wider than what this package admits: `isDraft` enforces the same\n * minimum and also refuses an absolute path and one that traverses out of the workspace, which no\n * JSON Schema keyword can express. A caller that satisfies this shape can still be refused, and\n * `ProbeServer` names the member when it is.\n *\n * @example\n * ```ts\n * compileGuard(DRAFT_SHAPE)({ path: 'src/core/greeting.ts', text: '' }) // true\n * ```\n */\nexport const DRAFT_SHAPE = objectShape(\n\t{\n\t\tpath: stringShape({ min: 1, description: 'Workspace-relative path, which need not exist.' }),\n\t\ttext: stringShape({ description: \"The file's full contents.\" }),\n\t},\n\t{ description: 'One proposed file a claim carries.' },\n)\n\n/**\n * Describes the drafts a claim asserts about and the test that exercises them.\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: '' }\n * compileGuard(CASE_SHAPE)({ files: [], test }) // true\n * ```\n */\nexport const CASE_SHAPE = objectShape(\n\t{\n\t\tfiles: arrayShape(DRAFT_SHAPE, { description: 'The candidate drafts the test imports.' }),\n\t\ttest: DRAFT_SHAPE,\n\t},\n\t{ description: 'The drafts a claim asserts about, and the test that exercises them.' },\n)\n\n/**\n * Describes the negative control, which is a case plus where and why it must break.\n *\n * @remarks\n * Built from `CASE_SHAPE`'s own properties rather than a second copy of them, so the control and\n * the case cannot describe a draft differently.\n *\n * @example\n * ```ts\n * const test = { path: 'tests/src/core/greeting.test.ts', text: '' }\n * compileGuard(CONTROL_SHAPE)({ files: [], test, stage: 'type', reason: 'must not compile' }) // true\n * ```\n */\nexport const CONTROL_SHAPE = objectShape(\n\t{\n\t\t...CASE_SHAPE.properties,\n\t\tstage: literalShape(PROBE_STAGES, { description: 'The stage this control must fail at.' }),\n\t\treason: stringShape({ min: 1, description: 'Why the control fails at that stage.' }),\n\t},\n\t{ description: 'A case that must fail, naming the stage where it must fail and why.' },\n)\n\n/**\n * Describes one claim and is the sole source of both the published tool schema and the guard\n * applied to an arriving claim.\n *\n * @remarks\n * The Model Context Protocol tool publishes `compileSchema(CLAIM_SHAPE)` and admits a call with\n * `isClaim`. Deriving the advertised schema from this one value is what stops the two from drifting\n * apart across a release on any member either can express. `isClaim` is narrower on the one member\n * neither a schema keyword nor this shape can carry — the containment rule on `Draft.path` — and\n * `validators.ts` names where.\n *\n * @example\n * ```ts\n * const schema = compileSchema(CLAIM_SHAPE)\n * const admits = compileGuard(CLAIM_SHAPE)\n * schema.type // 'object'\n * admits({ project: 'tsconfig.json' }) // false\n * ```\n */\nexport const CLAIM_SHAPE = objectShape(\n\t{\n\t\tproject: stringShape({\n\t\t\tmin: 1,\n\t\t\tdescription:\n\t\t\t\t'Workspace-relative TypeScript project the candidate drafts are checked against.',\n\t\t}),\n\t\tcase: CASE_SHAPE,\n\t\tcontrol: CONTROL_SHAPE,\n\t},\n\t{ description: 'One claim: the project, the case, and the control that must break.' },\n)\n"],"mappings":";;;;;;;;;;;;;;;;;AAaA,IAAa,eAAe,OAAO,OAAO;CAAC;CAAQ;CAAQ;AAAS,CAAU;;;;;;;;;;;;;AAc9E,IAAa,gBAAgB,OAAO,OAAO;CAAC;CAAY;CAAa;AAAY,CAAU;;;;;;;;;;;;;;AAe3F,IAAa,oBAAoB,OAAO,OAAO;CAC9C;CACA;CACA;CACA;CACA;AACD,CAAU;;;;;;;;;;;;;;;AAgBV,IAAa,iBAAiB;;;;;;;;;;;;;;;AAgB9B,IAAa,oBAAoB;;;;;;;;;;;;AAajC,IAAa,iBAAiB;;;;;;;;;;;;;;;;;AAkB9B,IAAa,gBAAgB;;;;;;;;;;;;;;;;;;AAmB7B,IAAa,aAAa;;;;;;;;;;;;;;;;;;;AAoB1B,IAAa,uBAAuB;;;;;;;;;;;;;;AAepC,IAAa,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;AC1I9B,IAAa,aAAb,cAAgC,MAAM;CACrC,OAAyB;CACzB;CACA;CACA;;;;;;;CAQA,YAAY,SAAiB,SAA4B;EACxD,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,CAAC;EAI1D,OAAO,eAAe,MAAM,OAAO,IAAI,wBAAwB,GAAG,EAAE,OAAO,KAAK,CAAC;EACjF,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,QAAQ;EACpB,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;CAC3D;AACD;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,aAAa,OAAqC;CACjE,IAAI,EAAA,GAAC,oBAAA,QAAA,CAAQ,KAAK,GAAG,OAAO;CAC5B,QAAA,GAAO,oBAAA,MAAA,OAAY;EAClB,IAAI,OAAO,eAAe,KAAK,MAAM,MAAM,WAAW,OAAO;EAC7D,IAAI,MAAM,SAAS,gBAAgB,EAAE,YAAY,UAAU,EAAE,UAAU,QAAQ,OAAO;EAEtF,IADmB,OAAO,yBAAyB,OAAO,OAAO,IAAI,wBAAwB,CACzF,CAAA,EAAY,UAAU,MAAM,OAAO;EACvC,MAAM,SAAkB,MAAM;EAC9B,MAAM,OAAgB,MAAM;EAC5B,OACC,cAAc,MAAM,aAAa,aAAa,MAAM,KACpD,kBAAkB,MAAM,aAAa,aAAa,IAAI;CAExD,CAAC;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,qBAAqB,SAA6B;CACjE,OAAO,IAAI,WAAW,OAAO,QAAQ,sBAAsB;EAC1D,QAAQ;EACR,MAAM;CACP,CAAC;AACF;;;;;;;;;;;;;;;ACxEA,IAAa,WAAA,GAAwB,oBAAA,UAAA,CAAU,YAAY;;;;;;;;;;;;;;;;;;;;;AAsB3D,IAAa,WAAA,GAAwB,oBAAA,SAAA,CAAS;CAC7C,OAAA,GAAM,oBAAA,MAAA,CAAc,oBAAA,mBAAmB,SAAS;EAC/C,IAAI,uBAAuB,KAAK,IAAI,GAAG,OAAO;EAC9C,IAAI,QAAQ;EACZ,KAAK,MAAM,WAAW,KAAK,MAAM,QAAQ,GAAG;GAC3C,IAAI,YAAY,MAAM,YAAY,KAAK;GACvC,IAAI,YAAY,MAAM;IACrB,SAAS;IACT;GACD;GACA,IAAI,UAAU,GAAG,OAAO;GACxB,SAAS;EACV;EACA,OAAO;CACR,CAAC;CACD,MAAM,oBAAA;AACP,CAAC;;;;;;;;;;;;;AAcD,IAAa,UAAA,GAAsB,oBAAA,SAAA,CAAS;CAAE,QAAA,GAAO,oBAAA,QAAA,CAAQ,OAAO;CAAG,MAAM;AAAQ,CAAC;;;;;;;;;;;;;;AAetF,IAAa,aAAA,GAA4B,oBAAA,SAAA,CAAS;CACjD,QAAA,GAAO,oBAAA,QAAA,CAAQ,OAAO;CACtB,MAAM;CACN,OAAO;CACP,QAAQ,oBAAA;AACT,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AAyBD,IAAa,WAAA,GAAwB,oBAAA,SAAA,CAAS;CAC7C,SAAS,oBAAA;CACT,MAAM;CACN,SAAS;AACV,CAAC;;;;;;;;;;;;;;;AAgBD,IAAa,WAAA,GAAwB,oBAAA,UAAA,CAAU,aAAa;;;;;;;;;;;;;;;;;;AAmB5D,IAAa,WAAA,GAAwB,oBAAA,SAAA,CACpC;CAAE,QAAQ;CAAS,MAAM,oBAAA;CAAU,SAAS,oBAAA;CAAU,OAAO,eAAA;AAAW,GACxE,CAAC,OAAO,CACT;;;;;;;;;;;;AAaA,IAAa,WAAA,GAAwB,oBAAA,SAAA,CAAS;CAC7C,OAAO;CACP,SAAS,oBAAA;CACT,SAAA,GAAQ,oBAAA,QAAA,CAAQ,OAAO;AACxB,CAAC;;;;;;;;;;;;;AAcD,IAAa,eAAA,GAAgC,oBAAA,SAAA,CAAS;CACrD,YAAY,oBAAA;CACZ,QAAQ,oBAAA;CACR,QAAQ,oBAAA;AACT,CAAC;;;;;;;;;;;;;;;;;AAkBD,IAAa,aAAA,GAA4B,oBAAA,SAAA,CAAS;CACjD,MAAM,oBAAA;CACN,QAAQ,oBAAA;AACT,CAAC;;;;;;;;;;;;;;;;;;;AAoBD,IAAa,aAAA,GAA4B,oBAAA,SAAA,CACxC;CACC,IAAI,oBAAA;CACJ,QAAQ,oBAAA;CACR,WAAW;CACX,SAAS;CACT,QAAQ,oBAAA;CACR,OAAA,GAAM,oBAAA,QAAA,CAAQ,OAAO;CACrB,UAAA,GAAS,oBAAA,QAAA,CAAQ,OAAO;CACxB,SAAS,oBAAA;CACT,SAAS,oBAAA;AACV,GACA,CAAC,UAAU,SAAS,CACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1OA,SAAgB,YAAY,OAAsB;CACjD,MAAM,QAAQ,MAAM;CACpB,MAAM,QAAQ,UAAU,KAAA,IAAY,MAAM,OAAO,GAAG,MAAM,KAAK,GAAG,MAAM,MAAM,OAAO;CACrF,OAAO,IAAI,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM;AAC5C;;;;;;;;;;;;;;;;;AAkBA,SAAgB,YAAY,OAAsB;CACjD,MAAM,QAAQ,MAAM,OAAO;CAC3B,MAAM,OAAO,UAAU,IAAI,UAAU;CAGrC,OAAO,CAAC,GAFW,MAAM,MAAM,IAAI,MAAM,GAAG,KAAK,IAAI,MAAM,QAAQ,OAElD,GADH,MAAM,OAAO,KAAK,UAAU,KAAK,YAAY,KAAK,GAC5C,CAAK,CAAC,CAAC,KAAK,IAAI;AACrC;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,YAAY,SAA0B;CACrD,OAAO,QAAQ,YAAY,KAAA,IAAY,eAAe,WAAW,QAAQ;AAC1E;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cAAc,SAA0B;CACvD,MAAM,SAAS,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,CAAC,UAAU,QAAQ,QAAQ;CAC9E,OAAO;EACN,SAAS,QAAQ,GAAG,IAAI,QAAQ,QAAQ;EACxC,SAAS,QAAQ;EACjB,GAAG;EACH,YAAY,OAAO;CACpB,CAAC,CAAC,KAAK,IAAI;AACZ;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,cAAc,SAA0B;CACvD,MAAM,EAAE,YAAY,QAAQ,WAAW,QAAQ;CAC/C,MAAM,QAAQ,wBAAwB,WAAW,WAAW,OAAO,WAAW;CAC9E,MAAM,UAAU,WAAW,QAAQ,QAAQ,KAAK,GAAG,QAAQ,QAAQ;CACnE,MAAM,SAAS,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,CAAC,UAAU,QAAQ,QAAQ;CAC9E,OAAO;EACN,SAAS,QAAQ,GAAG,IAAI,QAAQ,QAAQ;EACxC,SAAS,QAAQ;EACjB;EACA;EACA,GAAG;EACH,GAAG,QAAQ,KAAK,KAAK,UAAU,QAAQ,YAAY,KAAK,GAAG;EAC3D,GAAG,QAAQ,QAAQ,KAAK,UAAU,WAAW,YAAY,KAAK,GAAG;EACjE,YAAY,OAAO;CACpB,CAAC,CAAC,KAAK,IAAI;AACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,SAAgB,eAAe,SAAkB,OAAkC;CAClF,MAAM,MAAM,aAAa,OACvB,SACA,QAAQ,KAAK,QAAQ,UAAU,MAAM,UAAU,IAAI,CAAC,CAAC,WAAW,KAChE,QAAQ,QAAQ,QAAQ,UAAU,MAAM,UAAU,IAAI,CAAC,CAAC,WAAW,CACrE;CACA,MAAM,QAAQ,QAAQ,KAAK,OAAO,UAAU,MAAM,OAAO,WAAW,CAAC;CAErE,MAAM,QADW,QAAQ,QAAQ,MAAM,UAAU,MAAM,UAAU,KACnD,CAAA,EAAU,OAAO,MAAM,UAAU,MAAM,WAAW,UAAU,KAAK;CAC/E,MAAM,UACL,QAAQ,KAAK,MAAM,UAAU,MAAM,OAAO,MAAM,UAAU,MAAM,WAAW,YAAY,CAAC,KACxF,QAAQ,QAAQ,MAAM,UAAU,MAAM,OAAO,MAAM,UAAU,MAAM,WAAW,YAAY,CAAC;CAC5F,MAAM,SAAS,QAAQ,QAAQ,OAC7B,UAAU,MAAM,UAAU,SAAS,MAAM,OAAO,OAAO,UAAU,MAAM,WAAW,UAAU,CAC9F;CACA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,WAAW,CAAC,QAAQ,OAAO,KAAA;CAC3D,MAAM,EAAE,YAAY,QAAQ,WAAW,QAAQ;CAC/C,OAAO;EACN;EACA,QAAQ;EACR;EACA,cAAc;EACd,UAAU;EACV,UAAU;EACV,GAAG,QAAQ,QAAQ,KAAK,GAAG,QAAQ,QAAQ;CAC5C,CAAC,CAAC,KAAA,GAAsB;AACzB;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,oBAAoB,MAAc,UAA0B;CAE3E,OAAO,GADM,SAAS,MAAM,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,KAAK,IAClD,8CAA8C,SAAS;AACvE;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,qBAAqB,MAAc,UAA2B;CAC7E,OAAO,KAAK,SAAS,oBAAoB,IAAI,QAAQ,CAAC;AACvD;;;;;;;;;;;;;;;;;;;ACzPA,IAAa,eAAA,GAAc,oBAAA,YAAA,CAC1B;CACC,OAAA,GAAM,oBAAA,YAAA,CAAY;EAAE,KAAK;EAAG,aAAa;CAAiD,CAAC;CAC3F,OAAA,GAAM,oBAAA,YAAA,CAAY,EAAE,aAAa,4BAA4B,CAAC;AAC/D,GACA,EAAE,aAAa,qCAAqC,CACrD;;;;;;;;;;AAWA,IAAa,cAAA,GAAa,oBAAA,YAAA,CACzB;CACC,QAAA,GAAO,oBAAA,WAAA,CAAW,aAAa,EAAE,aAAa,yCAAyC,CAAC;CACxF,MAAM;AACP,GACA,EAAE,aAAa,sEAAsE,CACtF;;;;;;;;;;;;;;AAeA,IAAa,iBAAA,GAAgB,oBAAA,YAAA,CAC5B;CACC,GAAG,WAAW;CACd,QAAA,GAAO,oBAAA,aAAA,CAAa,cAAc,EAAE,aAAa,uCAAuC,CAAC;CACzF,SAAA,GAAQ,oBAAA,YAAA,CAAY;EAAE,KAAK;EAAG,aAAa;CAAuC,CAAC;AACpF,GACA,EAAE,aAAa,sEAAsE,CACtF;;;;;;;;;;;;;;;;;;;;AAqBA,IAAa,eAAA,GAAc,oBAAA,YAAA,CAC1B;CACC,UAAA,GAAS,oBAAA,YAAA,CAAY;EACpB,KAAK;EACL,aACC;CACF,CAAC;CACD,MAAM;CACN,SAAS;AACV,GACA,EAAE,aAAa,qEAAqE,CACrF"}
@@ -29,9 +29,9 @@ import { StringShape } from '@orkestrel/contract';
29
29
  * ```
30
30
  */
31
31
  export declare interface Case {
32
- /** The candidate drafts the test imports, in the order the claim supplies them. */
32
+ /** Holds the candidate drafts the test imports, in the order the claim supplies them. */
33
33
  readonly files: readonly Draft[];
34
- /** The test that exercises those drafts. */
34
+ /** Holds the test that exercises those drafts. */
35
35
  readonly test: Draft;
36
36
  }
37
37
 
@@ -68,11 +68,11 @@ export declare const CASE_SHAPE: ObjectShape<{
68
68
  * ```
69
69
  */
70
70
  export declare interface Check {
71
- /** The stage that produced this outcome. */
71
+ /** Names the stage that produced this outcome. */
72
72
  readonly stage: Stage;
73
- /** Milliseconds the stage took. */
73
+ /** Holds the milliseconds the stage took. */
74
74
  readonly elapsed: number;
75
- /** Every message the stage's tool reported, in the tool's own order. */
75
+ /** Holds every message the stage's tool reported, in the tool's own order. */
76
76
  readonly issues: readonly Issue[];
77
77
  }
78
78
 
@@ -114,11 +114,14 @@ export declare interface Check {
114
114
  * ```
115
115
  */
116
116
  export declare interface Claim {
117
- /** Workspace-relative path of the TypeScript project the candidate drafts are checked against. */
117
+ /**
118
+ * Names the workspace-relative path of the TypeScript project the candidate drafts are checked
119
+ * against.
120
+ */
118
121
  readonly project: string;
119
- /** The drafts and test the claim asserts about. */
122
+ /** Holds the drafts and test the claim asserts about. */
120
123
  readonly case: Case;
121
- /** The negative control that must break, and where. */
124
+ /** Holds the negative control that must break, and where. */
122
125
  readonly control: Control;
123
126
  }
124
127
 
@@ -233,9 +236,9 @@ export declare function computeReceipt(verdict: Verdict, stage: Stage): string |
233
236
  * ```
234
237
  */
235
238
  export declare interface Control extends Case {
236
- /** The stage this control must report issues at. */
239
+ /** Names the stage this control must report issues at. */
237
240
  readonly stage: Stage;
238
- /** Why the control fails there, in the claimant's own words. */
241
+ /** Explains why the control fails there, in the claimant's own words. */
239
242
  readonly reason: string;
240
243
  }
241
244
 
@@ -298,9 +301,9 @@ export declare function createDestroyedError(subject: string): ProbeError;
298
301
  * ```
299
302
  */
300
303
  export declare interface Draft {
301
- /** Workspace-relative path the stages resolve the text against. */
304
+ /** Names the workspace-relative path the stages resolve the text against. */
302
305
  readonly path: string;
303
- /** The file's full contents. */
306
+ /** Holds the file's full contents. */
304
307
  readonly text: string;
305
308
  }
306
309
 
@@ -598,7 +601,7 @@ export declare const isParty: Guard<Party>;
598
601
  * condition all stay outside the type.
599
602
  *
600
603
  * @param value - The value to inspect
601
- * @returns True only for a `ProbeError` instance; false otherwise
604
+ * @returns True if the value is a `ProbeError` instance; false otherwise
602
605
  *
603
606
  * @example
604
607
  * ```ts
@@ -680,13 +683,15 @@ export declare const isStage: Guard<Stage>;
680
683
  * ```
681
684
  */
682
685
  export declare interface Issue {
683
- /** The party that must act on this message. */
686
+ /** Names the party that must act on this message. */
684
687
  readonly origin: Party;
685
- /** Workspace-relative path this message is reported against. */
688
+ /** Names the workspace-relative path this message is reported against. */
686
689
  readonly path: string;
687
- /** The diagnostic or failure message. */
690
+ /** Holds the diagnostic or failure message. */
688
691
  readonly message: string;
689
- /** Zero-based UTF-16 span the tool reported, or absent when it reported no location. */
692
+ /**
693
+ * Holds the zero-based UTF-16 span the tool reported, or is absent when it reported no location.
694
+ */
690
695
  readonly range?: LSPRange;
691
696
  }
692
697
 
@@ -837,6 +842,26 @@ export declare const PROBE_KEYS = 4096;
837
842
  */
838
843
  export declare const PROBE_PARTIES: readonly ["claimant", "workspace", "instrument"];
839
844
 
845
+ /**
846
+ * Names the specification lifetime the runtime stage replaces its resident Vitest service at.
847
+ *
848
+ * @remarks
849
+ * Vite retains one unresolved URL for every fresh specification path, so an inspection that writes
850
+ * a specification grows a map the resident service never releases. The stage replaces that service
851
+ * rather than deleting from each map it owns, and this is the count of specifications one service
852
+ * carries before the replacement. Any bound holds the retention flat, because the replacement
853
+ * releases everything the instance held; this value trades the cost of the replacement against how
854
+ * far the map grows between them. On 2026-08-20, over this package's own workspace on the host
855
+ * `guides/probe.md` § Cost names, two runs of 66 inspections put the crossing inspection at 480 ms
856
+ * and 269 ms against median inspections of 156 ms and 155 ms.
857
+ *
858
+ * @example
859
+ * ```ts
860
+ * PROBE_SPECIFICATIONS // 64
861
+ * ```
862
+ */
863
+ export declare const PROBE_SPECIFICATIONS = 64;
864
+
840
865
  /**
841
866
  * Lists the stages a claim passes through, in the order a verdict reports them.
842
867
  *
@@ -919,20 +944,20 @@ export declare type ProbeErrorCode = (typeof PROBE_ERROR_CODES)[number];
919
944
  * ```
920
945
  */
921
946
  export declare interface ProbeErrorContext {
922
- /** The stage the failure belongs to, when one stage owns it. */
947
+ /** Names the stage the failure belongs to, when one stage owns it. */
923
948
  readonly stage?: Stage;
924
949
  /**
925
- * The path involved, spelled as the refusing operation named it: workspace-relative for an
950
+ * Names the path involved, spelled as the refusing operation named it: workspace-relative for an
926
951
  * input a caller supplied, absolute for a file this package resolved.
927
952
  */
928
953
  readonly path?: string;
929
- /** The workspace-relative TypeScript project involved, for a project failure. */
954
+ /** Names the workspace-relative TypeScript project involved, for a project failure. */
930
955
  readonly project?: string;
931
- /** The installed package name involved, for a workspace toolchain failure. */
956
+ /** Identifies the installed package involved, for a workspace toolchain failure. */
932
957
  readonly name?: string;
933
- /** Milliseconds the expired budget allowed, for a deadline failure. */
958
+ /** Holds the milliseconds the expired budget allowed, for a deadline failure. */
934
959
  readonly deadline?: number;
935
- /** The rejected value, for an input the guards refused. */
960
+ /** Holds the rejected value, for an input the guards refused. */
936
961
  readonly value?: unknown;
937
962
  }
938
963
 
@@ -954,13 +979,13 @@ export declare interface ProbeErrorContext {
954
979
  * ```
955
980
  */
956
981
  export declare interface ProbeErrorOptions {
957
- /** The party that must act on this failure. */
982
+ /** Names the party that must act on this failure. */
958
983
  readonly origin: Party;
959
- /** The condition that ended the operation. */
984
+ /** Names the condition that ended the operation. */
960
985
  readonly code: ProbeErrorCode;
961
- /** Structured detail about the failure. */
986
+ /** Holds structured detail about the failure. */
962
987
  readonly context?: ProbeErrorContext;
963
- /** The underlying fault, when one ended the operation. */
988
+ /** Holds the underlying fault, when one ended the operation. */
964
989
  readonly cause?: unknown;
965
990
  }
966
991
 
@@ -982,13 +1007,16 @@ export declare interface ProbeErrorOptions {
982
1007
  * ```
983
1008
  */
984
1009
  export declare type ProbeEventMap = {
985
- /** The boot control reported red and the instrument has begun answering calls. */
1010
+ /** Fires when the boot control has reported red and the instrument has begun answering calls. */
986
1011
  readonly arm: readonly [toolchain: Toolchain];
987
- /** A claim was answered. */
1012
+ /** Fires when a claim is answered. */
988
1013
  readonly prove: readonly [verdict: Verdict];
989
- /** The coordinator's deadline fired at one stage and that stage was replaced before this event. */
1014
+ /** Fires after the coordinator's deadline fired at one stage and that stage was replaced. */
990
1015
  readonly expire: readonly [claim: Claim];
991
- /** A fault surfaced for observation, once per fault, including a rejected arming attempt. */
1016
+ /**
1017
+ * Fires when a fault surfaces for observation, once per fault, including a rejected arming
1018
+ * attempt.
1019
+ */
992
1020
  readonly error: readonly [error: unknown];
993
1021
  };
994
1022
 
@@ -1012,9 +1040,9 @@ export declare type ProbeEventMap = {
1012
1040
  * ```
1013
1041
  */
1014
1042
  export declare interface ProbeInterface {
1015
- /** Observation surface for arming, answers, deadline expiry, and faults. */
1043
+ /** Publishes arming, answers, deadline expiry, and faults for observation. */
1016
1044
  readonly emitter: EmitterInterface<ProbeEventMap>;
1017
- /** The tool versions resolved from the workspace at construction. */
1045
+ /** Names the tool versions resolved from the workspace at construction. */
1018
1046
  readonly toolchain: Toolchain;
1019
1047
  /**
1020
1048
  * Answers one claim with every stage's evidence.
@@ -1064,15 +1092,15 @@ export declare interface ProbeInterface {
1064
1092
  * ```
1065
1093
  */
1066
1094
  export declare interface ProbeOptions {
1067
- /** Initial listeners, wired at construction. */
1095
+ /** Declares the initial listeners, wired at construction. */
1068
1096
  readonly on?: EmitterHooks<ProbeEventMap>;
1069
- /** Handler for a listener throw. */
1097
+ /** Holds the handler for a listener throw. */
1070
1098
  readonly error?: EmitterErrorHandler;
1071
- /** Target workspace root. Default: the current working directory. */
1099
+ /** Names the target workspace root. Default: the current working directory. */
1072
1100
  readonly workspace?: string;
1073
1101
  /**
1074
- * Milliseconds one active stage inspection may take; an expired stage is replaced. Default:
1075
- * 30,000 ms.
1102
+ * Holds the milliseconds one active stage inspection may take; an expired stage is replaced.
1103
+ * Default: 30,000 ms.
1076
1104
  */
1077
1105
  readonly deadline?: number;
1078
1106
  }
@@ -1096,9 +1124,12 @@ export declare interface ProbeOptions {
1096
1124
  * ```
1097
1125
  */
1098
1126
  export declare interface Project {
1099
- /** Resolved workspace-relative path of the project file the type stage applied. */
1127
+ /** Names the resolved workspace-relative path of the project file the type stage applied. */
1100
1128
  readonly path: string;
1101
- /** Digest of that project's resolved compiler options, workspace-relative and key-sorted. */
1129
+ /**
1130
+ * Holds the digest of that project's resolved compiler options, workspace-relative and
1131
+ * key-sorted.
1132
+ */
1102
1133
  readonly digest: string;
1103
1134
  }
1104
1135
 
@@ -1134,6 +1165,21 @@ export declare const RECEIPT_PREFIX = "probe";
1134
1165
  */
1135
1166
  export declare const RECEIPT_SEPARATOR = ":";
1136
1167
 
1168
+ /**
1169
+ * Names the Vite plugin the runtime stage installs into a target workspace's Vitest configuration.
1170
+ *
1171
+ * @remarks
1172
+ * The stage declares the plugin under this name and reads a configured project's plugin list for
1173
+ * the same name to decide whether that project carries the overlay. One name feeds both, so a
1174
+ * project the stage instrumented is never reported as a workspace project it could not reach.
1175
+ *
1176
+ * @example
1177
+ * ```ts
1178
+ * RUNTIME_PLUGIN // 'orkestrel-runtime-overlay'
1179
+ * ```
1180
+ */
1181
+ export declare const RUNTIME_PLUGIN = "orkestrel-runtime-overlay";
1182
+
1137
1183
  /**
1138
1184
  * Names an inspection a claim passes through, derived from {@link PROBE_STAGES}.
1139
1185
  *
@@ -1162,11 +1208,11 @@ export declare type Stage = (typeof PROBE_STAGES)[number];
1162
1208
  * ```
1163
1209
  */
1164
1210
  export declare interface Toolchain {
1165
- /** Resolved `typescript` version the type stage ran. */
1211
+ /** Names the resolved `typescript` version the type stage ran. */
1166
1212
  readonly typescript: string;
1167
- /** Resolved `oxlint` version the lint stage ran. */
1213
+ /** Names the resolved `oxlint` version the lint stage ran. */
1168
1214
  readonly oxlint: string;
1169
- /** Resolved `vitest` version the runtime stage ran. */
1215
+ /** Names the resolved `vitest` version the runtime stage ran. */
1170
1216
  readonly vitest: string;
1171
1217
  }
1172
1218
 
@@ -1231,26 +1277,26 @@ export declare interface Toolchain {
1231
1277
  * ```
1232
1278
  */
1233
1279
  export declare interface Verdict {
1234
- /** The revision identity this verdict was produced for, fresh per call. */
1280
+ /** Names the revision identity this verdict was produced for, fresh per call. */
1235
1281
  readonly id: string;
1236
- /** Digest of the case and control this verdict answers. */
1282
+ /** Holds the digest of the case and control this verdict answers. */
1237
1283
  readonly digest: string;
1238
- /** The tool versions that produced it. */
1284
+ /** Names the tool versions that produced it. */
1239
1285
  readonly toolchain: Toolchain;
1240
- /** The TypeScript project the candidate drafts were judged against. */
1286
+ /** Names the TypeScript project the candidate drafts were judged against. */
1241
1287
  readonly project: Project;
1242
1288
  /**
1243
- * The claimant's explanation for the selected control, when the verdict came from a claim. Part
1244
- * of the control, so it enters `digest` and through it the receipt token.
1289
+ * Holds the claimant's explanation for the selected control, when the verdict came from a claim.
1290
+ * Part of the control, so it enters `digest` and through it the receipt token.
1245
1291
  */
1246
1292
  readonly reason?: string;
1247
- /** One outcome per stage for the claim's case. */
1293
+ /** Holds one outcome per stage for the claim's case. */
1248
1294
  readonly case: readonly Check[];
1249
- /** One outcome per stage for the claim's control. */
1295
+ /** Holds one outcome per stage for the claim's control. */
1250
1296
  readonly control: readonly Check[];
1251
- /** Milliseconds the whole call took, including both the case and the control. */
1297
+ /** Holds the milliseconds the whole call took, including both the case and the control. */
1252
1298
  readonly elapsed: number;
1253
- /** The proof token, absent when either phase reports an instrument failure. */
1299
+ /** Holds the proof token, absent when either phase reports an instrument failure. */
1254
1300
  readonly receipt?: string;
1255
1301
  }
1256
1302