@arbiterforge/ca-pi 0.15.8 → 0.15.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.
Files changed (27) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/plugins/ca-pi/CHANGELOG.md +42 -0
  4. package/plugins/ca-pi/extensions/codearbiter-child.js +2 -2
  5. package/plugins/ca-pi/extensions/codearbiter.js +33 -23
  6. package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-amd64 +0 -0
  7. package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-arm64 +0 -0
  8. package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-amd64 +0 -0
  9. package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-arm64 +0 -0
  10. package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-amd64.exe +0 -0
  11. package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-arm64.exe +0 -0
  12. package/plugins/ca-pi/helpers/artifacts/release.json +6 -6
  13. package/plugins/ca-pi/hooks/_artifactauthoritylib.py +473 -34
  14. package/plugins/ca-pi/hooks/_artifactlib.py +78 -5
  15. package/plugins/ca-pi/hooks/_bashguardlib.py +9 -8
  16. package/plugins/ca-pi/hooks/_hooklib.py +1 -1
  17. package/plugins/ca-pi/hooks/_host.py +1 -1
  18. package/plugins/ca-pi/hooks/_sensitivelib.py +28 -14
  19. package/plugins/ca-pi/hooks/artifact-authority-hook.py +1 -0
  20. package/plugins/ca-pi/hooks/artifact-authority.py +5 -0
  21. package/plugins/ca-pi/hooks/git-enforce.py +7 -6
  22. package/plugins/ca-pi/hooks/hostapi.py +1 -1
  23. package/plugins/ca-pi/includes/artifacts.md +56 -1
  24. package/plugins/ca-pi/includes/pi-host-notes.md +1 -1
  25. package/plugins/ca-pi/includes/security-gate-record.md +5 -3
  26. package/plugins/ca-pi/package.json +1 -1
  27. package/plugins/ca-pi/skills/ca-doctor/SKILL.md +1 -1
package/README.md CHANGED
@@ -10,7 +10,7 @@ project context. You decide. codeArbiter enforces.
10
10
  <img alt="Claude Code plugin" src="https://img.shields.io/badge/Claude_Code-plugin-d97757">
11
11
  <img alt="Codex plugin" src="https://img.shields.io/badge/OpenAI_Codex-plugin-10a37f">
12
12
  <img alt="Pi Feature Forge preview" src="https://img.shields.io/badge/ca--pi-Feature_Forge_preview-d97757">
13
- <img alt="version 2.23.1" src="https://img.shields.io/badge/version-2.23.1-2b7489">
13
+ <img alt="version 2.23.4" src="https://img.shields.io/badge/version-2.23.4-2b7489">
14
14
  <img alt="core lanes" src="https://img.shields.io/badge/core_lanes-18-555">
15
15
  <img alt="skills" src="https://img.shields.io/badge/skills-22-555">
16
16
  <img alt="agents" src="https://img.shields.io/badge/agents-20-555">
@@ -183,7 +183,7 @@ Replace `<version>` with the numeric suffix from the chosen tag while retaining
183
183
  it is a partial install that cannot author typed HTML specs and plans; use the npm channel for
184
184
  that.
185
185
 
186
- Pi 0.84.1 is the supported host for this release line. Generated aliases use `/ca-*`;
186
+ Pi 1.0.0 is the supported host for this release line. Generated aliases use `/ca-*`;
187
187
  `/skill:ca-*` is the host-native fallback. Every `ca-pi-v*` tag is also published to npm as
188
188
  `npm:@arbiterforge/ca-pi` with provenance (ADR-0029); the pinned Git tag remains the reproducible
189
189
  install. The [Pi runbook](./docs/pi-parity-testing.md) covers isolated install, trust, verification,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbiterforge/ca-pi",
3
- "version": "0.15.8",
3
+ "version": "0.15.12",
4
4
  "license": "AGPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,6 +4,48 @@ All notable changes to `ca-pi` are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.15.12] - 2026-10-03
8
+
9
+ ### Fixed
10
+
11
+ - Shared authority library: recovering an already-abandoned oversized review now reports
12
+ `request was already abandoned` instead of a misleading binding failure. Carries the Claude
13
+ Code 2.1.286 review-correlation fix (tagged `resolvedModel`, `SubagentHandback` reports),
14
+ which applies only to the Claude host.
15
+ - The crypto/secret commit gate (H-09b/H-10b) no longer expires a recorded pass after 30 minutes.
16
+ A pass now stays valid for exactly the lines it reviewed, in the files it reviewed them in,
17
+ like the migration gate; any new, changed, or moved sensitive line still blocks until reviewed.
18
+
19
+ ## [0.15.11] - 2026-10-03
20
+
21
+ ### Changed
22
+
23
+ - Synchronize the shared kernel's explicit completion-review evidence contract.
24
+ This does not enable the unsupported Pi native review-authority path.
25
+
26
+ ## [0.15.10] - 2026-10-03
27
+
28
+ ### Changed
29
+
30
+ - Promote the verified Pi host window through exact Pi 1.0.0. Pi 1.0.0 closes the
31
+ undici advisories present in 0.84.1; the brace-expansion advisories it still pins
32
+ were already present in 0.84.1 and are recorded as accepted under ADR-0041.
33
+
34
+ ### Fixed
35
+
36
+ - Child dispatch no longer degrades on Pi 1.0.0: the runner accepts the 1.0.0 JSON
37
+ wire (`message_update` usage, named `toolcall_start`, `deferred` completion).
38
+ - `/ca-doctor` validates the Pi 1.0.0 CLI at its declared `dist/bundle/cli.js` bin.
39
+
40
+ ## [0.15.9] - 2026-10-03
41
+
42
+ ### Fixed
43
+
44
+ - Named verification now supports a root npm script delegating once to a uniquely
45
+ selected workspace runner. The declared root command remains intact, both npm
46
+ argument boundaries are honored, and every inspected manifest is retained in
47
+ launch provenance. Unsupported or ambiguous delegation fails before execution.
48
+
7
49
  ## [0.15.8] - 2026-09-27
8
50
 
9
51
  ### Fixed
@@ -629,7 +629,7 @@ function resolvePythonCommand(platform = process.platform, probe = systemPythonP
629
629
  }
630
630
 
631
631
  // src/compatibility.ts
632
- var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["0.84.1"]);
632
+ var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["1.0.0"]);
633
633
  var MINIMUM_NODE = [22, 19, 0];
634
634
  var SEMVER_PREFIX = /^(\d+)\.(\d+)\.(\d+)(?:$|[-+])/u;
635
635
  function atLeast(version, minimum) {
@@ -644,7 +644,7 @@ function atLeast(version, minimum) {
644
644
  }
645
645
  function compatibilityDirection(input) {
646
646
  if (!SUPPORTED_PI_VERSIONS.has(input.piVersion)) {
647
- return "codeArbiter requires Pi 0.84.1; install a supported Pi version and run /ca-doctor.";
647
+ return "codeArbiter requires Pi 1.0.0; install a supported Pi version and run /ca-doctor.";
648
648
  }
649
649
  if (!atLeast(input.nodeVersion, MINIMUM_NODE)) {
650
650
  return "codeArbiter requires Node >=22.19.0 for Pi; upgrade Node and run /ca-doctor.";
@@ -2,7 +2,7 @@
2
2
  var define_CODEARBITER_PI_PERMISSION_POLICY_SURFACES_default = { "ca-plan": "planning-write", codearbiter_background_bash: "background-launch" };
3
3
 
4
4
  // <define:__CODEARBITER_PI_SKILL_EXPANSION_FINGERPRINTS__>
5
- var define_CODEARBITER_PI_SKILL_EXPANSION_FINGERPRINTS_default = { "0.84.1": "12632f365440b07d5183cff871d889b796a3c711b6b49df20f95d9bc198d6c51" };
5
+ var define_CODEARBITER_PI_SKILL_EXPANSION_FINGERPRINTS_default = { "1.0.0": "12632f365440b07d5183cff871d889b796a3c711b6b49df20f95d9bc198d6c51" };
6
6
 
7
7
  // <define:__CODEARBITER_PI_TOOL_CLASSES__>
8
8
  var define_CODEARBITER_PI_TOOL_CLASSES_default = { bash: "EXEC", codearbiter_background_bash: "EXEC", codearbiter_dispatch: "EXEC", codearbiter_farm_preview: "EXEC", write: "WRITE", edit: "EDIT", read: "READ" };
@@ -16,7 +16,7 @@ import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from
16
16
  import { types as utilTypes9 } from "node:util";
17
17
 
18
18
  // src/compatibility.ts
19
- var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["0.84.1"]);
19
+ var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["1.0.0"]);
20
20
  var MINIMUM_NODE = [22, 19, 0];
21
21
  var SEMVER_PREFIX = /^(\d+)\.(\d+)\.(\d+)(?:$|[-+])/u;
22
22
  function atLeast(version, minimum) {
@@ -31,7 +31,7 @@ function atLeast(version, minimum) {
31
31
  }
32
32
  function compatibilityDirection(input) {
33
33
  if (!SUPPORTED_PI_VERSIONS.has(input.piVersion)) {
34
- return "codeArbiter requires Pi 0.84.1; install a supported Pi version and run /ca-doctor.";
34
+ return "codeArbiter requires Pi 1.0.0; install a supported Pi version and run /ca-doctor.";
35
35
  }
36
36
  if (!atLeast(input.nodeVersion, MINIMUM_NODE)) {
37
37
  return "codeArbiter requires Node >=22.19.0 for Pi; upgrade Node and run /ca-doctor.";
@@ -6881,10 +6881,10 @@ async function collectPiDoctorInput(dependencies) {
6881
6881
  var REMEDIATION = {
6882
6882
  package: "Reinstall ca-pi from the approved pinned Git tag, then restart Pi.",
6883
6883
  trust: "Run /trust in Pi, inspect the project, grant trust only if you accept it, then start a new session.",
6884
- version: "Upgrade Pi to 0.84.1 and Node to >=22.19.0, then restart Pi.",
6884
+ version: "Upgrade Pi to 1.0.0 and Node to >=22.19.0, then restart Pi.",
6885
6885
  python: "Upgrade or install Python 3, then run /ca-doctor again.",
6886
6886
  core: "Reinstall ca-pi to restore the generated shared core, then run /ca-doctor again.",
6887
- commands: "Remove conflicting command owners or run Pi 0.84.1, then restart Pi and run /ca-doctor.",
6887
+ commands: "Remove conflicting command owners or run Pi 1.0.0, then restart Pi and run /ca-doctor.",
6888
6888
  bridge: "Reinstall ca-pi and Python 3, then run /ca-doctor again.",
6889
6889
  child: "Reinstall ca-pi if the hardened child artifact is missing or tampered, then run /ca-doctor again.",
6890
6890
  "ambient-marker": "Remove CODEARBITER_SUBAGENT from the parent environment and restart Pi.",
@@ -6913,7 +6913,7 @@ function diagnosePi(input) {
6913
6913
  const packageHealthy = input.package.declared && input.package.name === "@arbiterforge/ca-pi" && existsSync(input.package.root) && existsSync(input.package.extensionPath) && samePath2(input.package.extensionPath, expectedExtension) && canonicallyInside(input.package.extensionPath, input.package.root);
6914
6914
  const trustHealthy = input.trust.inspected && (!input.trust.required || input.trust.projectTrusted);
6915
6915
  const waitingForTrust = input.trust.required && !input.trust.projectTrusted;
6916
- const versionHealthy = input.runtime.piVersion === "0.84.1" && atLeast(input.runtime.nodeVersion, [22, 19, 0]);
6916
+ const versionHealthy = input.runtime.piVersion === "1.0.0" && atLeast(input.runtime.nodeVersion, [22, 19, 0]);
6917
6917
  const piBelowMinimum = !atLeast(input.runtime.piVersion, [0, 80, 5]);
6918
6918
  const supportedExpansion = input.commands.expansionVerifiedVersions.includes(input.runtime.piVersion);
6919
6919
  const expectedDoctorSkill = resolve9(input.package.root, "skills", "ca-doctor", "SKILL.md");
@@ -6924,7 +6924,7 @@ function diagnosePi(input) {
6924
6924
  resolve9(input.package.root, "extensions", "codearbiter-child.js")
6925
6925
  ) && canonicallyInside(input.child.path, input.package.root) && existsSync(input.child.path);
6926
6926
  const coreHealthy = input.core.present && existsSync(input.core.bridgeScript) && samePath2(input.core.bridgeScript, resolve9(input.package.root, "hooks", "pi-bridge.py")) && canonicallyInside(input.core.bridgeScript, input.package.root);
6927
- const runtimeIdentityHealthy = existsSync(input.runtime.cliEntry) && existsSync(input.runtime.moduleEntry) && canonicallyInside(input.runtime.cliEntry, input.runtime.packageRoot) && canonicallyInside(input.runtime.moduleEntry, input.runtime.packageRoot) && samePath2(input.runtime.cliEntry, resolve9(input.runtime.packageRoot, "dist", "cli.js")) && samePath2(input.runtime.moduleEntry, resolve9(input.runtime.packageRoot, "dist", "index.js"));
6927
+ const runtimeIdentityHealthy = existsSync(input.runtime.cliEntry) && existsSync(input.runtime.moduleEntry) && canonicallyInside(input.runtime.cliEntry, input.runtime.packageRoot) && canonicallyInside(input.runtime.moduleEntry, input.runtime.packageRoot) && samePath2(input.runtime.cliEntry, resolve9(input.runtime.packageRoot, "dist", "bundle", "cli.js")) && samePath2(input.runtime.moduleEntry, resolve9(input.runtime.packageRoot, "dist", "index.js"));
6928
6928
  const mutators = ["bash", "write", "edit"];
6929
6929
  const wrapperHealthy = input.finalArguments.wrapperSourcePath !== void 0 && existsSync(input.finalArguments.wrapperSourcePath) && samePath2(input.finalArguments.wrapperSourcePath, expectedExtension) && mutators.every((name) => input.finalArguments.activeTools?.includes(name) === true) && mutators.every((name) => {
6930
6930
  const path = input.finalArguments.toolSources?.[name];
@@ -7034,7 +7034,7 @@ function diagnosePi(input) {
7034
7034
  {
7035
7035
  id: "active-dispatch",
7036
7036
  state: "degraded",
7037
- message: "Supported Pi 0.84.1 public extension APIs cannot submit this deterministic self-test through the active dispatcher; the wrapper self-test does not exercise active dispatch.",
7037
+ message: "Supported Pi 1.0.0 public extension APIs cannot submit this deterministic self-test through the active dispatcher; the wrapper self-test does not exercise active dispatch.",
7038
7038
  remediation: REMEDIATION["active-dispatch"]
7039
7039
  }
7040
7040
  ];
@@ -8296,17 +8296,17 @@ function validContentBlock(value, kind) {
8296
8296
  case "text":
8297
8297
  return exactKeys4(value, ["type", "text", "textSignature"], ["type", "text"]) && boundedString2(value.text) && (value.textSignature === void 0 || boundedString2(value.textSignature));
8298
8298
  case "image":
8299
- return kind !== "assistant" && exactKeys4(value, ["type", "data", "mimeType"]) && boundedString2(value.data) && boundedString2(value.mimeType);
8299
+ return (kind === "user" || kind === "toolResult") && exactKeys4(value, ["type", "data", "mimeType"]) && boundedString2(value.data) && boundedString2(value.mimeType);
8300
8300
  case "thinking":
8301
8301
  return kind === "assistant" && exactKeys4(value, ["type", "thinking", "thinkingSignature", "redacted"], ["type", "thinking"]) && boundedString2(value.thinking) && (value.thinkingSignature === void 0 || boundedString2(value.thinkingSignature)) && (value.redacted === void 0 || typeof value.redacted === "boolean");
8302
8302
  case "toolCall":
8303
- return kind === "assistant" && exactKeys4(value, ["type", "id", "name", "arguments", "thoughtSignature"], ["type", "id", "name", "arguments"]) && boundedString2(value.id) && boundedString2(value.name) && validOpaqueJson(value.arguments) && (value.thoughtSignature === void 0 || boundedString2(value.thoughtSignature));
8303
+ return kind === "assistant" && exactKeys4(value, ["type", "id", "name", "arguments", "thoughtSignature", "namespace"], ["type", "id", "name", "arguments"]) && boundedString2(value.id) && boundedString2(value.name) && validOpaqueJson(value.arguments) && (value.thoughtSignature === void 0 || boundedString2(value.thoughtSignature)) && (value.namespace === void 0 || boundedString2(value.namespace));
8304
8304
  default:
8305
8305
  return false;
8306
8306
  }
8307
8307
  }
8308
8308
  function validContent(value, kind) {
8309
- if (kind === "user" && typeof value === "string") return boundedString2(value);
8309
+ if ((kind === "user" || kind === "system") && typeof value === "string") return boundedString2(value);
8310
8310
  return Array.isArray(value) && value.length <= MAX_JSON_ARRAY && value.every((block) => validContentBlock(block, kind));
8311
8311
  }
8312
8312
  function validUsage(value) {
@@ -8335,24 +8335,32 @@ function validDeferredHandle(value) {
8335
8335
  ["provider", "modelId", "api", "id"]
8336
8336
  ) && ["provider", "modelId", "api", "id"].every((key) => boundedString2(value[key])) && (value.expiresAt === void 0 || typeof value.expiresAt === "number" && Number.isFinite(value.expiresAt)) && (value.pollAfterMs === void 0 || typeof value.pollAfterMs === "number" && Number.isFinite(value.pollAfterMs)) && (value.data === void 0 || validOpaqueJson(value.data));
8337
8337
  }
8338
+ function validNestedCalls(value) {
8339
+ return isRecord(value) && exactKeys4(value, ["calls", "complete"]) && typeof value.complete === "boolean" && Array.isArray(value.calls) && value.calls.length <= MAX_JSON_ARRAY && value.calls.every((call) => isRecord(call) && exactKeys4(call, ["id", "name", "arguments", "argumentsBytes", "status", "durationMs", "error"], ["id", "name", "status"]) && boundedString2(call.id) && boundedString2(call.name) && (call.status === "ok" || call.status === "error" || call.status === "unfinished") && (call.arguments === void 0 || isRecord(call.arguments) && validOpaqueJson(call.arguments)) && (call.argumentsBytes === void 0 || typeof call.argumentsBytes === "number" && Number.isFinite(call.argumentsBytes)) && (call.durationMs === void 0 || typeof call.durationMs === "number" && Number.isFinite(call.durationMs)) && (call.error === void 0 || boundedString2(call.error)));
8340
+ }
8341
+ function validSystemMessage(value) {
8342
+ const sections = value.sections;
8343
+ return exactKeys4(value, ["role", "content", "sections", "toolsAdded", "toolsRemoved", "timestamp"], ["role", "content", "timestamp"]) && validContent(value.content, "system") && (sections === void 0 || isRecord(sections) && Object.keys(sections).length <= MAX_JSON_KEYS && Object.keys(sections).every((key) => boundedString2(key) && (sections[key] === null || boundedString2(sections[key])))) && (value.toolsAdded === void 0 || Array.isArray(value.toolsAdded) && value.toolsAdded.length <= MAX_JSON_ARRAY && value.toolsAdded.every((tool) => isRecord(tool) && boundedString2(tool.name) && validOpaqueJson(tool))) && (value.toolsRemoved === void 0 || Array.isArray(value.toolsRemoved) && value.toolsRemoved.length <= MAX_JSON_ARRAY && value.toolsRemoved.every((tool) => isRecord(tool) && exactKeys4(tool, ["name"]) && boundedString2(tool.name))) && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8344
+ }
8338
8345
  function validMessage(value) {
8339
8346
  if (!isRecord(value) || typeof value.role !== "string") return false;
8347
+ if (value.role === "system") return validSystemMessage(value);
8340
8348
  if (value.role === "user") {
8341
8349
  return exactKeys4(value, ["role", "content", "timestamp"]) && validContent(value.content, "user") && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8342
8350
  }
8343
8351
  if (value.role === "assistant") {
8344
8352
  return exactKeys4(
8345
8353
  value,
8346
- ["role", "content", "api", "provider", "model", "responseModel", "responseId", "diagnostics", "usage", "stopReason", "errorMessage", "rawStopReason", "deferred", "timestamp"],
8354
+ ["role", "content", "api", "provider", "model", "responseModel", "responseId", "providerThinkingLevel", "thinkingLevel", "diagnostics", "usage", "stopReason", "errorMessage", "rawStopReason", "deferred", "endTurn", "timestamp"],
8347
8355
  ["role", "content", "api", "provider", "model", "usage", "stopReason", "timestamp"]
8348
- ) && validContent(value.content, "assistant") && ["api", "provider", "model", "stopReason"].every((key) => typeof value[key] === "string") && (value.responseModel === void 0 || boundedString2(value.responseModel)) && (value.responseId === void 0 || boundedString2(value.responseId)) && (value.errorMessage === void 0 || boundedString2(value.errorMessage)) && (value.rawStopReason === void 0 || boundedString2(value.rawStopReason)) && (value.deferred === void 0 || validDeferredHandle(value.deferred)) && (value.diagnostics === void 0 || Array.isArray(value.diagnostics) && value.diagnostics.length <= MAX_JSON_ARRAY && value.diagnostics.every(validDiagnostic)) && validUsage(value.usage) && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8356
+ ) && validContent(value.content, "assistant") && ["api", "provider", "model", "stopReason"].every((key) => typeof value[key] === "string") && (value.responseModel === void 0 || boundedString2(value.responseModel)) && (value.responseId === void 0 || boundedString2(value.responseId)) && (value.errorMessage === void 0 || boundedString2(value.errorMessage)) && (value.rawStopReason === void 0 || boundedString2(value.rawStopReason)) && (value.providerThinkingLevel === void 0 || boundedString2(value.providerThinkingLevel)) && (value.thinkingLevel === void 0 || boundedString2(value.thinkingLevel)) && (value.endTurn === void 0 || typeof value.endTurn === "boolean") && (value.deferred === void 0 || validDeferredHandle(value.deferred)) && (value.diagnostics === void 0 || Array.isArray(value.diagnostics) && value.diagnostics.length <= MAX_JSON_ARRAY && value.diagnostics.every(validDiagnostic)) && validUsage(value.usage) && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8349
8357
  }
8350
8358
  if (value.role === "toolResult") {
8351
8359
  return exactKeys4(
8352
8360
  value,
8353
- ["role", "toolCallId", "toolName", "content", "details", "isError", "usage", "timestamp"],
8361
+ ["role", "toolCallId", "toolName", "content", "details", "isError", "usage", "nestedCalls", "timestamp"],
8354
8362
  ["role", "toolCallId", "toolName", "content", "isError", "timestamp"]
8355
- ) && typeof value.toolCallId === "string" && typeof value.toolName === "string" && validContent(value.content, "toolResult") && (value.details === void 0 || validOpaqueJson(value.details)) && (value.usage === void 0 || validUsage(value.usage)) && typeof value.isError === "boolean" && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8363
+ ) && typeof value.toolCallId === "string" && typeof value.toolName === "string" && validContent(value.content, "toolResult") && (value.details === void 0 || validOpaqueJson(value.details)) && (value.usage === void 0 || validUsage(value.usage)) && (value.nestedCalls === void 0 || validNestedCalls(value.nestedCalls)) && typeof value.isError === "boolean" && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
8356
8364
  }
8357
8365
  return false;
8358
8366
  }
@@ -8401,8 +8409,9 @@ function validAssistantEvent(value) {
8401
8409
  return exactWithOptionalPartial(["type"]);
8402
8410
  case "text_start":
8403
8411
  case "thinking_start":
8404
- case "toolcall_start":
8405
8412
  return exactWithOptionalPartial(["type", "contentIndex"]) && contentIndex();
8413
+ case "toolcall_start":
8414
+ return ("id" in value || "toolName" in value ? exactKeys4(value, ["type", "contentIndex", "id", "toolName"]) && boundedString2(value.id) && boundedString2(value.toolName) : exactWithOptionalPartial(["type", "contentIndex"])) && contentIndex();
8406
8415
  case "text_delta":
8407
8416
  case "thinking_delta":
8408
8417
  case "toolcall_delta":
@@ -8413,7 +8422,7 @@ function validAssistantEvent(value) {
8413
8422
  case "toolcall_end":
8414
8423
  return exactWithOptionalPartial(["type", "contentIndex", "toolCall"]) && contentIndex() && validContentBlock(value.toolCall, "assistant");
8415
8424
  case "done":
8416
- return exactKeys4(value, ["type", "reason", "message"]) && ["stop", "length", "toolUse"].includes(value.reason) && validMessage(value.message) && value.message.role === "assistant";
8425
+ return exactKeys4(value, ["type", "reason", "message"]) && ["stop", "length", "toolUse", "deferred"].includes(value.reason) && validMessage(value.message) && value.message.role === "assistant";
8417
8426
  case "error":
8418
8427
  return exactKeys4(value, ["type", "reason", "error"]) && ["aborted", "error"].includes(value.reason) && validMessage(value.error) && value.error.role === "assistant";
8419
8428
  default:
@@ -8435,7 +8444,8 @@ function parseChildJsonLine(line) {
8435
8444
  case "response":
8436
8445
  if (typeof record2.id !== "string" || record2.command !== "prompt" || typeof record2.success !== "boolean") invalidProtocol();
8437
8446
  if (record2.success === true) {
8438
- if (!exactKeys4(record2, ["type", "id", "command", "success"])) invalidProtocol();
8447
+ const data = record2.data;
8448
+ if (!exactKeys4(record2, ["type", "id", "command", "success", "data"], ["type", "id", "command", "success"]) || data !== void 0 && !(isRecord(data) && exactKeys4(data, ["disposition"]) && (data.disposition === "started" || data.disposition === "handled" || data.disposition === "queued"))) invalidProtocol();
8439
8449
  } else if (!exactKeys4(record2, ["type", "id", "command", "success", "error"]) || typeof record2.error !== "string") invalidProtocol();
8440
8450
  break;
8441
8451
  case "agent_start":
@@ -8454,16 +8464,16 @@ function parseChildJsonLine(line) {
8454
8464
  if (!exactKeys4(record2, ["type", "message"]) || !validMessage(record2.message) && !validPartialAssistantMessage(record2.message)) invalidProtocol();
8455
8465
  break;
8456
8466
  case "message_update":
8457
- if ("message" in record2 ? !exactKeys4(record2, ["type", "message", "assistantMessageEvent"]) || !validPartialAssistantMessage(record2.message) || !validAssistantEvent(record2.assistantMessageEvent) : !exactKeys4(record2, ["type", "assistantMessageEvent"]) || !validAssistantEvent(record2.assistantMessageEvent)) invalidProtocol();
8467
+ if ("message" in record2 ? !exactKeys4(record2, ["type", "message", "assistantMessageEvent"]) || !validPartialAssistantMessage(record2.message) || !validAssistantEvent(record2.assistantMessageEvent) : "usage" in record2 ? !exactKeys4(record2, ["type", "usage", "assistantMessageEvent"]) || !validUsage(record2.usage) || !validAssistantEvent(record2.assistantMessageEvent) : !exactKeys4(record2, ["type", "assistantMessageEvent"]) || !validAssistantEvent(record2.assistantMessageEvent)) invalidProtocol();
8458
8468
  break;
8459
8469
  case "tool_execution_start":
8460
- if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "args"]) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.args)) invalidProtocol();
8470
+ if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "args", "parentToolCallId"], ["type", "toolCallId", "toolName", "args"]) || record2.parentToolCallId !== void 0 && !boundedString2(record2.parentToolCallId) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.args)) invalidProtocol();
8461
8471
  break;
8462
8472
  case "tool_execution_update":
8463
- if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "args", "partialResult"]) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.args) || !validOpaqueJson(record2.partialResult)) invalidProtocol();
8473
+ if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "args", "partialResult", "parentToolCallId"], ["type", "toolCallId", "toolName", "args", "partialResult"]) || record2.parentToolCallId !== void 0 && !boundedString2(record2.parentToolCallId) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.args) || !validOpaqueJson(record2.partialResult)) invalidProtocol();
8464
8474
  break;
8465
8475
  case "tool_execution_end":
8466
- if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "result", "isError"]) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.result) || typeof record2.isError !== "boolean") invalidProtocol();
8476
+ if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "result", "isError", "parentToolCallId"], ["type", "toolCallId", "toolName", "result", "isError"]) || record2.parentToolCallId !== void 0 && !boundedString2(record2.parentToolCallId) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.result) || typeof record2.isError !== "boolean") invalidProtocol();
8467
8477
  break;
8468
8478
  case "extension_error":
8469
8479
  if (!exactKeys4(record2, ["type", "extensionPath", "event", "error"]) || typeof record2.extensionPath !== "string" || typeof record2.event !== "string" || typeof record2.error !== "string") invalidProtocol();
@@ -10588,7 +10598,7 @@ async function codeArbiterPi(pi) {
10588
10598
  activeTools: pi.getActiveTools(),
10589
10599
  allTools: pi.getAllTools(),
10590
10600
  expansionFingerprints,
10591
- childFingerprint: "22e5231b36a0af4a4202ced48a20e7dc9de435b6c6af985c6007bff96c5e04d1"
10601
+ childFingerprint: "86a08a0d5c29aa6693a07065f4ab2d6ad1d43293c65277cee944389886363d67"
10592
10602
  });
10593
10603
  const wrapperSelfTest = await runPiWrapperSelfTest({
10594
10604
  enabled: enabledForDoctor,
@@ -6,32 +6,32 @@
6
6
  "binaries": {
7
7
  "darwin/amd64": {
8
8
  "file": "ca-artifact-darwin-amd64",
9
- "sha256": "645fbde59c9db28a51d52dd7c975750f97613516c4003b7f4a3057359893687d",
9
+ "sha256": "2b2f735f123364bdc23adf937ba3088fe996ece9b36a20dce14491f12c0a02da",
10
10
  "native_tested": true
11
11
  },
12
12
  "darwin/arm64": {
13
13
  "file": "ca-artifact-darwin-arm64",
14
- "sha256": "390a6e9b65c2220bf52a6459eab4ec79283d4d560715a305280027f20e7a9d47",
14
+ "sha256": "cfd38fc1d52a41659d8c01e4668e595fac806bdc36162e87f0118605e17e666c",
15
15
  "native_tested": true
16
16
  },
17
17
  "linux/amd64": {
18
18
  "file": "ca-artifact-linux-amd64",
19
- "sha256": "65d39e119b446987ad8e8bdd592a1819165a95fe2c00ed887a1349a4fe692f86",
19
+ "sha256": "f73fb0e676f8bfd1222fdcaec7eeced54fe106f17dbf53aae50e86ac553bf1ce",
20
20
  "native_tested": true
21
21
  },
22
22
  "linux/arm64": {
23
23
  "file": "ca-artifact-linux-arm64",
24
- "sha256": "c5ae37567f9929b58beba88a3cd11e9e2de66bbb11a8f0fafbbae3bbcb0ba53f",
24
+ "sha256": "70852f1dbebc00a730a6cffc3835f17f45c3c7c8e0d554b4b9f0a248aecb6ecb",
25
25
  "native_tested": true
26
26
  },
27
27
  "windows/amd64": {
28
28
  "file": "ca-artifact-windows-amd64.exe",
29
- "sha256": "b381d900520c5024ec20c86333a29f007fb6f8a2737214c77916912836c3e762",
29
+ "sha256": "7048725daa508e7aeccaa0b531fe49b816bdd9e28f56127afe46b17eb1b4f582",
30
30
  "native_tested": true
31
31
  },
32
32
  "windows/arm64": {
33
33
  "file": "ca-artifact-windows-arm64.exe",
34
- "sha256": "ccf2ca3a3ed103d247baee0275a8ce2c62af050a6af46d39c4186d8fd8ff2872",
34
+ "sha256": "294b5bd3418979fb094bcc4f480d7284fdcdcd4e5e89f0459073d5315e243e66",
35
35
  "native_tested": true
36
36
  }
37
37
  }