@claudexor/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/adapter.d.ts +56 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +8 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/browser-mcp.d.ts +18 -0
  8. package/dist/browser-mcp.d.ts.map +1 -0
  9. package/dist/browser-mcp.js +32 -0
  10. package/dist/browser-mcp.js.map +1 -0
  11. package/dist/capabilities.d.ts +4 -0
  12. package/dist/capabilities.d.ts.map +1 -0
  13. package/dist/capabilities.js +8 -0
  14. package/dist/capabilities.js.map +1 -0
  15. package/dist/conformance.d.ts +25 -0
  16. package/dist/conformance.d.ts.map +1 -0
  17. package/dist/conformance.js +60 -0
  18. package/dist/conformance.js.map +1 -0
  19. package/dist/diff.d.ts +71 -0
  20. package/dist/diff.d.ts.map +1 -0
  21. package/dist/diff.js +325 -0
  22. package/dist/diff.js.map +1 -0
  23. package/dist/doctor.d.ts +7 -0
  24. package/dist/doctor.d.ts.map +1 -0
  25. package/dist/doctor.js +75 -0
  26. package/dist/doctor.js.map +1 -0
  27. package/dist/effort.d.ts +18 -0
  28. package/dist/effort.d.ts.map +1 -0
  29. package/dist/effort.js +49 -0
  30. package/dist/effort.js.map +1 -0
  31. package/dist/env-scope.d.ts +38 -0
  32. package/dist/env-scope.d.ts.map +1 -0
  33. package/dist/env-scope.js +139 -0
  34. package/dist/env-scope.js.map +1 -0
  35. package/dist/errors.d.ts +16 -0
  36. package/dist/errors.d.ts.map +1 -0
  37. package/dist/errors.js +17 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/inactivity.d.ts +31 -0
  40. package/dist/inactivity.d.ts.map +1 -0
  41. package/dist/inactivity.js +77 -0
  42. package/dist/inactivity.js.map +1 -0
  43. package/dist/index.d.ts +16 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +16 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/model.d.ts +23 -0
  48. package/dist/model.d.ts.map +1 -0
  49. package/dist/model.js +21 -0
  50. package/dist/model.js.map +1 -0
  51. package/dist/proc.d.ts +68 -0
  52. package/dist/proc.d.ts.map +1 -0
  53. package/dist/proc.js +283 -0
  54. package/dist/proc.js.map +1 -0
  55. package/dist/process-registry.d.ts +8 -0
  56. package/dist/process-registry.d.ts.map +1 -0
  57. package/dist/process-registry.js +20 -0
  58. package/dist/process-registry.js.map +1 -0
  59. package/dist/runloop.d.ts +35 -0
  60. package/dist/runloop.d.ts.map +1 -0
  61. package/dist/runloop.js +156 -0
  62. package/dist/runloop.js.map +1 -0
  63. package/dist/runtime-env.d.ts +16 -0
  64. package/dist/runtime-env.d.ts.map +1 -0
  65. package/dist/runtime-env.js +51 -0
  66. package/dist/runtime-env.js.map +1 -0
  67. package/package.json +40 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 joi-lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @claudexor/core
2
+
3
+ Internal package of [Claudexor](https://github.com/razzant/claudexor) — HarnessAdapter contract, process helpers, typed errors, and low-level execution utilities.
4
+
5
+ Published as part of the Claudexor toolchain; it follows the monorepo's
6
+ lockstep version and has no separate semver contract. Use the `claudexor`
7
+ CLI (or `@claudexor/cli`) as the supported entry point.
@@ -0,0 +1,56 @@
1
+ import type { AuthPreference, ConformanceReport, HarnessEvent, HarnessManifest, HarnessModel, HarnessRunSpec, InteractionAnswerSet, InteractionRequest } from "@claudexor/schema";
2
+ export interface DoctorSpec {
3
+ cwd: string;
4
+ /** Optional scoped env for probes that must mirror a concrete run route. */
5
+ env?: Record<string, string | null | undefined>;
6
+ /** Optional auth route preference for probes that must mirror a concrete run route. */
7
+ authPreference?: AuthPreference;
8
+ }
9
+ /**
10
+ * The contract every harness adapter implements. Adapters translate a native
11
+ * harness's I/O into typed Claudexor events — they never contain orchestration
12
+ * logic. External adapters may implement this as an in-tree HarnessAdapter implementation (the out-of-tree JSON-RPC bridge package was removed in v0.9).
13
+ */
14
+ export interface HarnessAdapter {
15
+ readonly id: string;
16
+ /** Detect installation/version/auth and declare capabilities. */
17
+ discover(): Promise<HarnessManifest>;
18
+ /** Probe capabilities and report which intents this adapter may play. */
19
+ doctor(spec: DoctorSpec): Promise<ConformanceReport>;
20
+ /** Run a task, streaming normalized events. */
21
+ run(spec: HarnessRunSpec): AsyncIterable<HarnessEvent>;
22
+ /** Optional dedicated review path (defaults to run with intent=review). */
23
+ review?(spec: HarnessRunSpec): AsyncIterable<HarnessEvent>;
24
+ /**
25
+ * Optional model enumeration. Only adapters that can HONESTLY list models
26
+ * implement this (e.g. raw-api via OpenAI-compatible `GET /v1/models`);
27
+ * native-CLI adapters that cannot enumerate simply omit it. Must fail soft
28
+ * (return [] on network/auth error) — never throw into a picker/consumer.
29
+ */
30
+ models?(spec?: DoctorSpec): Promise<HarnessModel[]>;
31
+ /** Optional cancellation. */
32
+ cancel?(sessionId: string): Promise<void>;
33
+ }
34
+ /** A registry of available adapters keyed by harness id. */
35
+ export type AdapterRegistry = Map<string, HarnessAdapter>;
36
+ /**
37
+ * Imperative answer channel for interactive harness sessions.
38
+ *
39
+ * The adapter calls `request()` when its native session raises a user
40
+ * question (e.g. Claude's AskUserQuestion via the stream-json control
41
+ * protocol) and BLOCKS that tool until the promise resolves:
42
+ * - resolved with answers -> the adapter delivers them into the live session;
43
+ * - resolved with null (timeout / decline / no listener) -> the adapter
44
+ * declines benignly and the model continues with assumptions.
45
+ *
46
+ * The channel is smuggled through `spec.extra` (duck-typed, same pattern as
47
+ * the abort signal) because HarnessRunSpec is a serializable schema shape.
48
+ */
49
+ export interface InteractionChannel {
50
+ request(req: InteractionRequest): Promise<InteractionAnswerSet | null>;
51
+ /** Number of questions currently awaiting an answer. Lets stream watchdogs
52
+ * treat waiting-on-user as legitimate silence instead of a wedged harness. */
53
+ pendingCount?(): number;
54
+ }
55
+ export declare function interactionChannelFromSpec(spec: HarnessRunSpec): InteractionChannel | undefined;
56
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAChD,uFAAuF;IACvF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,iEAAiE;IACjE,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAErC,yEAAyE;IACzE,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAErD,+CAA+C;IAC/C,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAEvD,2EAA2E;IAC3E,MAAM,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAE3D;;;;;OAKG;IACH,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEpD,6BAA6B;IAC7B,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,4DAA4D;AAC5D,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACvE;kFAC8E;IAC9E,YAAY,CAAC,IAAI,MAAM,CAAC;CACzB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS,CAK/F"}
@@ -0,0 +1,8 @@
1
+ export function interactionChannelFromSpec(spec) {
2
+ const channel = spec.extra?.["interactionChannel"];
3
+ if (!channel || typeof channel !== "object")
4
+ return undefined;
5
+ const candidate = channel;
6
+ return typeof candidate.request === "function" ? channel : undefined;
7
+ }
8
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AA0EA,MAAM,UAAU,0BAA0B,CAAC,IAAoB;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,oBAAoB,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,OAAO,OAAO,SAAS,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAE,OAA8B,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/F,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { BrowserToolSpec } from "@claudexor/schema";
2
+ /**
3
+ * Resolve a usable `npx` for spawning the Playwright browser MCP. Prefer the
4
+ * bundled node's npx (the daemon runs under the notarized node, so `npx` sits
5
+ * alongside `node`), fall back to PATH `npx`; an explicit env override wins for
6
+ * unusual layouts. Centralized so every adapter's browser injection agrees.
7
+ */
8
+ export declare function resolveNpxBin(): string;
9
+ /**
10
+ * The argv (after `npx`) that launches the Playwright MCP server for a run's
11
+ * BrowserToolSpec: an isolated profile, core+pdf capabilities, headed by default
12
+ * (a real visible window the user watches), and an output dir pointed at the run
13
+ * artifact tree so captures surface in the Canvas gallery. Adapters wrap this in
14
+ * their own MCP-injection flag (codex `-c mcp_servers.*` overrides, claude
15
+ * `--mcp-config` inline JSON).
16
+ */
17
+ export declare function playwrightMcpArgs(browser: BrowserToolSpec): string[];
18
+ //# sourceMappingURL=browser-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-mcp.d.ts","sourceRoot":"","sources":["../src/browser-mcp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CAKpE"}
@@ -0,0 +1,32 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ /**
4
+ * Resolve a usable `npx` for spawning the Playwright browser MCP. Prefer the
5
+ * bundled node's npx (the daemon runs under the notarized node, so `npx` sits
6
+ * alongside `node`), fall back to PATH `npx`; an explicit env override wins for
7
+ * unusual layouts. Centralized so every adapter's browser injection agrees.
8
+ */
9
+ export function resolveNpxBin() {
10
+ const override = process.env.CLAUDEXOR_NPX_BIN;
11
+ if (override)
12
+ return override;
13
+ const bundled = join(dirname(process.execPath), "npx");
14
+ return existsSync(bundled) ? bundled : "npx";
15
+ }
16
+ /**
17
+ * The argv (after `npx`) that launches the Playwright MCP server for a run's
18
+ * BrowserToolSpec: an isolated profile, core+pdf capabilities, headed by default
19
+ * (a real visible window the user watches), and an output dir pointed at the run
20
+ * artifact tree so captures surface in the Canvas gallery. Adapters wrap this in
21
+ * their own MCP-injection flag (codex `-c mcp_servers.*` overrides, claude
22
+ * `--mcp-config` inline JSON).
23
+ */
24
+ export function playwrightMcpArgs(browser) {
25
+ const args = ["-y", "@playwright/mcp@latest", "--isolated", "--caps=core,pdf"];
26
+ if (browser.headless)
27
+ args.push("--headless");
28
+ if (browser.output_dir)
29
+ args.push(`--output-dir=${browser.output_dir}`);
30
+ return args;
31
+ }
32
+ //# sourceMappingURL=browser-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-mcp.js","sourceRoot":"","sources":["../src/browser-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IACvD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAwB;IACxD,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,wBAAwB,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;IAC/E,IAAI,OAAO,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,UAAU;QAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { HarnessCapabilityProfile } from "@claudexor/schema";
2
+ export declare function needsScopedHomeKeychainBridge(profile: HarnessCapabilityProfile): boolean;
3
+ export declare function readonlyMechanism(profile: HarnessCapabilityProfile): string;
4
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAKxF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAE3E"}
@@ -0,0 +1,8 @@
1
+ export function needsScopedHomeKeychainBridge(profile) {
2
+ return (profile.isolation.supported_containment.includes("scoped_home_keychain_bridge") &&
3
+ profile.auth.credential_transports.some((t) => t.kind === "os_keychain" && t.relocatable_by.includes("HOME")));
4
+ }
5
+ export function readonlyMechanism(profile) {
6
+ return profile.access_control.readonly_mechanism;
7
+ }
8
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,6BAA6B,CAAC,OAAiC;IAC7E,OAAO,CACL,OAAO,CAAC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QAC/E,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAC9G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,OAAO,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC;AACnD,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Typed-event conformance stats for one parsed adapter stream. Shared by the
3
+ * per-adapter fixture parity tests: every adapter must emit schema-valid
4
+ * events, tool_results MUST carry a status (a statusless result is treated as
5
+ * dropped/diagnostic by the engine, never as ok), and streams that perform
6
+ * tool work must surface typed tool_call/tool_result pairs.
7
+ */
8
+ export interface StreamConformanceStats {
9
+ total: number;
10
+ started: number;
11
+ messages: number;
12
+ toolCalls: number;
13
+ toolResults: number;
14
+ statuslessToolResults: number;
15
+ errorToolResults: number;
16
+ deniedToolResults: number;
17
+ cancelledToolResults: number;
18
+ fileChanges: number;
19
+ usageEvents: number;
20
+ errors: number;
21
+ completed: number;
22
+ }
23
+ /** Validate every event against the HarnessEvent schema and aggregate stats. */
24
+ export declare function validateTypedStream(events: unknown[]): StreamConformanceStats;
25
+ //# sourceMappingURL=conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAsC7E"}
@@ -0,0 +1,60 @@
1
+ import { HarnessEvent } from "@claudexor/schema";
2
+ /** Validate every event against the HarnessEvent schema and aggregate stats. */
3
+ export function validateTypedStream(events) {
4
+ const stats = {
5
+ total: 0,
6
+ started: 0,
7
+ messages: 0,
8
+ toolCalls: 0,
9
+ toolResults: 0,
10
+ statuslessToolResults: 0,
11
+ errorToolResults: 0,
12
+ deniedToolResults: 0,
13
+ cancelledToolResults: 0,
14
+ fileChanges: 0,
15
+ usageEvents: 0,
16
+ errors: 0,
17
+ completed: 0,
18
+ };
19
+ for (const raw of events) {
20
+ const ev = HarnessEvent.parse(raw); // throws loudly on contract violations
21
+ stats.total += 1;
22
+ switch (ev.type) {
23
+ case "started":
24
+ stats.started += 1;
25
+ break;
26
+ case "message":
27
+ stats.messages += 1;
28
+ break;
29
+ case "tool_call":
30
+ stats.toolCalls += 1;
31
+ break;
32
+ case "tool_result":
33
+ stats.toolResults += 1;
34
+ if (!ev.tool?.status)
35
+ stats.statuslessToolResults += 1;
36
+ if (ev.tool?.status === "error")
37
+ stats.errorToolResults += 1;
38
+ if (ev.tool?.status === "denied")
39
+ stats.deniedToolResults += 1;
40
+ if (ev.tool?.status === "cancelled")
41
+ stats.cancelledToolResults += 1;
42
+ break;
43
+ case "file_change":
44
+ stats.fileChanges += 1;
45
+ break;
46
+ case "usage":
47
+ stats.usageEvents += 1;
48
+ break;
49
+ case "error":
50
+ stats.errors += 1;
51
+ break;
52
+ case "completed":
53
+ stats.completed += 1;
54
+ break;
55
+ default: break;
56
+ }
57
+ }
58
+ return stats;
59
+ }
60
+ //# sourceMappingURL=conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAyBjD,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,KAAK,GAA2B;QACpC,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,CAAC;QACd,qBAAqB,EAAE,CAAC;QACxB,gBAAgB,EAAE,CAAC;QACnB,iBAAiB,EAAE,CAAC;QACpB,oBAAoB,EAAE,CAAC;QACvB,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;KACb,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,uCAAuC;QAC3E,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC1C,KAAK,SAAS;gBAAE,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC3C,KAAK,WAAW;gBAAE,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC9C,KAAK,aAAa;gBAChB,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;gBACvB,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM;oBAAE,KAAK,CAAC,qBAAqB,IAAI,CAAC,CAAC;gBACvD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO;oBAAE,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC;gBAC7D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ;oBAAE,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;gBAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW;oBAAE,KAAK,CAAC,oBAAoB,IAAI,CAAC,CAAC;gBACrE,MAAM;YACR,KAAK,aAAa;gBAAE,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;gBAAC,MAAM;YAClD,KAAK,OAAO;gBAAE,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC5C,KAAK,OAAO;gBAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;gBAAC,MAAM;YACvC,KAAK,WAAW;gBAAE,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC9C,OAAO,CAAC,CAAC,MAAM;QACjB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The ONE quote-aware unified-diff header parser. Three divergent parsers
3
+ * used to read patches: a regex in the orchestrator's diffStats that
4
+ * missed git-quoted headers (non-ASCII/spaces → protected-path and
5
+ * NEEDS_HUMAN gates silently skipped those files), a line-scan in the
6
+ * delivery gate that read `--- `-prefixed CONTENT lines as paths (SQL
7
+ * comments → false apply refusals), and a header tokenizer in
8
+ * context/evidence that never decoded octal escapes. All three rebase here.
9
+ *
10
+ * Structural rules, not regex governance: file metadata (`---`/`+++`,
11
+ * `rename from/to`, `new/deleted file mode`, binary markers) is honored only
12
+ * in HEADER position — between a `diff --git` line and that file's first
13
+ * `@@` hunk — so patch CONTENT can never masquerade as structure.
14
+ *
15
+ * PLAIN unified diffs (GNU `diff -ruN`, the workspace's non-git in-place
16
+ * fallback) have no `diff --git` anchors, so a document that opens with a
17
+ * plain file header is parsed in PLAIN mode: a file entry opens only on the
18
+ * full structural triple — a `--- ` line immediately followed by a `+++ `
19
+ * line and an `@@` hunk header — which keeps deleted `-- sql` content lines
20
+ * from masquerading as file boundaries. Without this mode every non-git
21
+ * in-place diff summarized to zero files, silently blinding diffstat and
22
+ * protected-path/risk gating for that whole run class. Inside a git-anchored
23
+ * document the git rules above apply unchanged (never mixed per document).
24
+ * Plain-mode entries default to modified (GNU diff marks absent files with
25
+ * epoch timestamps, not `/dev/null`, so added/deleted classification is
26
+ * honored only for explicit `/dev/null` headers) — conservative for gating:
27
+ * every touched path is visible to policy.
28
+ */
29
+ export interface DiffFileEntry {
30
+ /** Pre-image path (null when the file is newly added). */
31
+ oldPath: string | null;
32
+ /** Post-image path (null when the file is deleted). */
33
+ newPath: string | null;
34
+ added: boolean;
35
+ deleted: boolean;
36
+ renamed: boolean;
37
+ /** Binary change (GIT binary patch payload or a bare "Binary files" stub). */
38
+ binary: boolean;
39
+ /** True when the binary change carries NO applyable payload (stub). */
40
+ binaryStub: boolean;
41
+ }
42
+ export interface UnifiedDiffSummary {
43
+ files: DiffFileEntry[];
44
+ additions: number;
45
+ deletions: number;
46
+ hunks: number;
47
+ }
48
+ /**
49
+ * Decode one git C-quoted path token: strips surrounding quotes and decodes
50
+ * `\ooo` octal byte escapes plus the standard single-char escapes, yielding
51
+ * the real on-disk path (utf8).
52
+ */
53
+ export declare function cUnquoteGitPath(raw: string): string;
54
+ export declare function parseUnifiedDiff(diff: string): UnifiedDiffSummary;
55
+ export interface DiffPathSummary {
56
+ paths: string[];
57
+ addedPaths: string[];
58
+ modifiedPaths: string[];
59
+ existingPaths: string[];
60
+ additions: number;
61
+ deletions: number;
62
+ }
63
+ /**
64
+ * Path-oriented projection of a unified diff for policy/risk gating and
65
+ * diffstat honesty: which files the patch touches, which are NEW vs
66
+ * pre-existing, and the +/- counts. Quote-aware via parseUnifiedDiff — a
67
+ * git-quoted header (non-ASCII, spaces) must never silently DROP a file
68
+ * from protected-path/NEEDS_HUMAN classification.
69
+ */
70
+ export declare function summarizeDiffPaths(diff: string): DiffPathSummary;
71
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,uDAAuD;IACvD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA+BnD;AAmDD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA6JjE;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA0BhE"}