@arbiterforge/ca-pi 0.17.3 → 0.17.5
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/README.md +2 -2
- package/package.json +1 -1
- package/plugins/ca-pi/CHANGELOG.md +24 -0
- package/plugins/ca-pi/extensions/codearbiter-child.js +2 -2
- package/plugins/ca-pi/extensions/codearbiter.js +21 -14
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-amd64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-arm64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/release.json +36 -36
- package/plugins/ca-pi/hooks/_artifactauthoritylib.py +95 -5
- package/plugins/ca-pi/hooks/_host.py +1 -1
- package/plugins/ca-pi/hooks/hostapi.py +1 -1
- package/plugins/ca-pi/includes/artifacts.md +22 -7
- package/plugins/ca-pi/includes/pi-host-notes.md +1 -1
- package/plugins/ca-pi/package.json +1 -1
- package/plugins/ca-pi/skills/ca-doctor/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ and durable 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.25.
|
|
13
|
+
<img alt="version 2.25.4" src="https://img.shields.io/badge/version-2.25.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 1.0
|
|
186
|
+
Pi 1.1.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
|
@@ -4,6 +4,30 @@ All notable changes to `ca-pi` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.17.5] - 2026-10-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Preserve the shared adapter's bounded native completion-review context
|
|
12
|
+
references and complete review-result prompt contract (#921).
|
|
13
|
+
- Fingerprint complete completion-review workspaces up to 1 GiB independently
|
|
14
|
+
of the 256 MiB selected verification-input budget. Preserve full content
|
|
15
|
+
hashing, freshness checks, and the 32 MiB member and 50,000 entry limits.
|
|
16
|
+
- Preserve the shared engine's distinct fresh-verification completion profile
|
|
17
|
+
and historical receipt validation. Pi verification and review authority remain
|
|
18
|
+
unsupported; this shared payload change does not enable those host seams.
|
|
19
|
+
|
|
20
|
+
## [0.17.4] - 2026-10-09
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Promote the verified Pi host window through exact Pi 1.1.0.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Accept Pi 1.1.0 execution timing fields and settlement outcomes without treating aborted child work as successful.
|
|
29
|
+
- Recognize Pi's renamed Azure provider while retaining parent-only provider credentials.
|
|
30
|
+
|
|
7
31
|
## [0.17.3] - 2026-10-09
|
|
8
32
|
|
|
9
33
|
### 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(["1.0
|
|
632
|
+
var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["1.1.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 1.0
|
|
647
|
+
return "codeArbiter requires Pi 1.1.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 = { "1.0
|
|
5
|
+
var define_CODEARBITER_PI_SKILL_EXPANSION_FINGERPRINTS_default = { "1.1.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(["1.0
|
|
19
|
+
var SUPPORTED_PI_VERSIONS = /* @__PURE__ */ new Set(["1.1.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 1.0
|
|
34
|
+
return "codeArbiter requires Pi 1.1.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 1.0
|
|
6884
|
+
version: "Upgrade Pi to 1.1.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 1.0
|
|
6887
|
+
commands: "Remove conflicting command owners or run Pi 1.1.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 === "1.0
|
|
6916
|
+
const versionHealthy = input.runtime.piVersion === "1.1.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");
|
|
@@ -7034,7 +7034,7 @@ function diagnosePi(input) {
|
|
|
7034
7034
|
{
|
|
7035
7035
|
id: "active-dispatch",
|
|
7036
7036
|
state: "degraded",
|
|
7037
|
-
message: "Supported Pi 1.0
|
|
7037
|
+
message: "Supported Pi 1.1.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
|
];
|
|
@@ -7806,6 +7806,7 @@ var PI_PROVIDER_ENV = Object.freeze({
|
|
|
7806
7806
|
"amazon-bedrock": ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_BEARER_TOKEN_BEDROCK", "AWS_REGION"],
|
|
7807
7807
|
"ant-ling": ["ANT_LING_API_KEY"],
|
|
7808
7808
|
anthropic: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"],
|
|
7809
|
+
azure: ["AZURE_OPENAI_API_KEY", "AZURE_OPENAI_BASE_URL", "AZURE_OPENAI_RESOURCE_NAME", "AZURE_OPENAI_API_VERSION", "AZURE_OPENAI_DEPLOYMENT_NAME_MAP"],
|
|
7809
7810
|
"azure-openai-responses": ["AZURE_OPENAI_API_KEY", "AZURE_OPENAI_BASE_URL", "AZURE_OPENAI_RESOURCE_NAME", "AZURE_OPENAI_API_VERSION", "AZURE_OPENAI_DEPLOYMENT_NAME_MAP"],
|
|
7810
7811
|
cerebras: ["CEREBRAS_API_KEY"],
|
|
7811
7812
|
"cloudflare-ai-gateway": ["CLOUDFLARE_API_KEY", "CLOUDFLARE_ACCOUNT_ID", "CLOUDFLARE_GATEWAY_ID"],
|
|
@@ -8351,16 +8352,16 @@ function validMessage(value) {
|
|
|
8351
8352
|
if (value.role === "assistant") {
|
|
8352
8353
|
return exactKeys4(
|
|
8353
8354
|
value,
|
|
8354
|
-
["role", "content", "api", "provider", "model", "responseModel", "responseId", "providerThinkingLevel", "thinkingLevel", "diagnostics", "usage", "stopReason", "errorMessage", "rawStopReason", "deferred", "endTurn", "timestamp"],
|
|
8355
|
+
["role", "content", "api", "provider", "model", "responseModel", "responseId", "providerThinkingLevel", "thinkingLevel", "diagnostics", "usage", "stopReason", "errorMessage", "rawStopReason", "deferred", "endTurn", "timestamp", "durationMs"],
|
|
8355
8356
|
["role", "content", "api", "provider", "model", "usage", "stopReason", "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);
|
|
8357
|
+
) && 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.durationMs === void 0 || typeof value.durationMs === "number" && Number.isFinite(value.durationMs) && value.durationMs >= 0) && (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);
|
|
8357
8358
|
}
|
|
8358
8359
|
if (value.role === "toolResult") {
|
|
8359
8360
|
return exactKeys4(
|
|
8360
8361
|
value,
|
|
8361
|
-
["role", "toolCallId", "toolName", "content", "details", "isError", "usage", "nestedCalls", "timestamp"],
|
|
8362
|
+
["role", "toolCallId", "toolName", "content", "details", "isError", "usage", "nestedCalls", "timestamp", "durationMs"],
|
|
8362
8363
|
["role", "toolCallId", "toolName", "content", "isError", "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);
|
|
8364
|
+
) && 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)) && (value.durationMs === void 0 || typeof value.durationMs === "number" && Number.isFinite(value.durationMs) && value.durationMs >= 0) && typeof value.isError === "boolean" && typeof value.timestamp === "number" && Number.isFinite(value.timestamp);
|
|
8364
8365
|
}
|
|
8365
8366
|
return false;
|
|
8366
8367
|
}
|
|
@@ -8449,10 +8450,12 @@ function parseChildJsonLine(line) {
|
|
|
8449
8450
|
} else if (!exactKeys4(record2, ["type", "id", "command", "success", "error"]) || typeof record2.error !== "string") invalidProtocol();
|
|
8450
8451
|
break;
|
|
8451
8452
|
case "agent_start":
|
|
8452
|
-
case "agent_settled":
|
|
8453
8453
|
case "turn_start":
|
|
8454
8454
|
if (!exactKeys4(record2, ["type"])) invalidProtocol();
|
|
8455
8455
|
break;
|
|
8456
|
+
case "agent_settled":
|
|
8457
|
+
if (!exactKeys4(record2, ["type", "aborted"]) || typeof record2.aborted !== "boolean") invalidProtocol();
|
|
8458
|
+
break;
|
|
8456
8459
|
case "agent_end":
|
|
8457
8460
|
if (!exactKeys4(record2, ["type", "messages", "willRetry"]) || !Array.isArray(record2.messages) || record2.messages.length > MAX_JSON_ARRAY || !record2.messages.every(validMessage) || typeof record2.willRetry !== "boolean") invalidProtocol();
|
|
8458
8461
|
break;
|
|
@@ -8473,7 +8476,7 @@ function parseChildJsonLine(line) {
|
|
|
8473
8476
|
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();
|
|
8474
8477
|
break;
|
|
8475
8478
|
case "tool_execution_end":
|
|
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();
|
|
8479
|
+
if (!exactKeys4(record2, ["type", "toolCallId", "toolName", "result", "isError", "parentToolCallId", "durationMs"], ["type", "toolCallId", "toolName", "result", "isError"]) || record2.parentToolCallId !== void 0 && !boundedString2(record2.parentToolCallId) || record2.durationMs !== void 0 && (typeof record2.durationMs !== "number" || !Number.isFinite(record2.durationMs) || record2.durationMs < 0) || typeof record2.toolCallId !== "string" || typeof record2.toolName !== "string" || !validOpaqueJson(record2.result) || typeof record2.isError !== "boolean") invalidProtocol();
|
|
8477
8480
|
break;
|
|
8478
8481
|
case "extension_error":
|
|
8479
8482
|
if (!exactKeys4(record2, ["type", "extensionPath", "event", "error"]) || typeof record2.extensionPath !== "string" || typeof record2.event !== "string" || typeof record2.error !== "string") invalidProtocol();
|
|
@@ -8773,6 +8776,10 @@ async function runPiChild(request, signal) {
|
|
|
8773
8776
|
finishFailure("protocol_error");
|
|
8774
8777
|
return;
|
|
8775
8778
|
}
|
|
8779
|
+
if (record2.aborted === true) {
|
|
8780
|
+
finishFailure("cancelled");
|
|
8781
|
+
return;
|
|
8782
|
+
}
|
|
8776
8783
|
phase = "complete";
|
|
8777
8784
|
endInput();
|
|
8778
8785
|
} else {
|
|
@@ -10598,7 +10605,7 @@ async function codeArbiterPi(pi) {
|
|
|
10598
10605
|
activeTools: pi.getActiveTools(),
|
|
10599
10606
|
allTools: pi.getAllTools(),
|
|
10600
10607
|
expansionFingerprints,
|
|
10601
|
-
childFingerprint: "
|
|
10608
|
+
childFingerprint: "98a945a0d55cc25f75a50bbe7c94cbea192b81f3db44fd9b3133d977a2973430"
|
|
10602
10609
|
});
|
|
10603
10610
|
const wrapperSelfTest = await runPiWrapperSelfTest({
|
|
10604
10611
|
enabled: enabledForDoctor,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -6,43 +6,43 @@
|
|
|
6
6
|
"binaries": {
|
|
7
7
|
"darwin/amd64": {
|
|
8
8
|
"file": "ca-artifact-darwin-amd64",
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "12a8a4b23da84cd672d03abe0c748310225e8bce47c5e8c8cbb3753e5acdbe57",
|
|
10
10
|
"native_tested": true
|
|
11
11
|
},
|
|
12
12
|
"darwin/arm64": {
|
|
13
13
|
"file": "ca-artifact-darwin-arm64",
|
|
14
|
-
"sha256": "
|
|
14
|
+
"sha256": "2107c247473c8a9cc7c422dd754d98fa6211cf7bec5b7ecdd85ba5d7db0676b0",
|
|
15
15
|
"native_tested": true
|
|
16
16
|
},
|
|
17
17
|
"linux/amd64": {
|
|
18
18
|
"file": "ca-artifact-linux-amd64",
|
|
19
|
-
"sha256": "
|
|
19
|
+
"sha256": "92e27501fd18ae805c6390b17b4f2335e97d69c3645c60b3267fb7869c624727",
|
|
20
20
|
"native_tested": true
|
|
21
21
|
},
|
|
22
22
|
"linux/arm64": {
|
|
23
23
|
"file": "ca-artifact-linux-arm64",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "1961df0bdf37fd6a7b3a6214b925cf9f3b2efe0e797c05151a43ee96d7df07b3",
|
|
25
25
|
"native_tested": true
|
|
26
26
|
},
|
|
27
27
|
"windows/amd64": {
|
|
28
28
|
"file": "ca-artifact-windows-amd64.exe",
|
|
29
|
-
"sha256": "
|
|
29
|
+
"sha256": "63def27bda36ed03c9f7e6898eaf2110badda2419950a8dcb91666c4e4bdd438",
|
|
30
30
|
"native_tested": true
|
|
31
31
|
},
|
|
32
32
|
"windows/arm64": {
|
|
33
33
|
"file": "ca-artifact-windows-arm64.exe",
|
|
34
|
-
"sha256": "
|
|
34
|
+
"sha256": "107e1a8fe971fe24ce8a274ce1188b15c9785e4f94b835dadde1918b8fed5c4b",
|
|
35
35
|
"native_tested": true
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"context_qualification": {
|
|
39
39
|
"darwin/amd64": {
|
|
40
|
-
"source_commit": "
|
|
40
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
41
41
|
"workflow": ".github/workflows/ci.yml",
|
|
42
|
-
"run_id": "
|
|
43
|
-
"binary_sha256": "
|
|
44
|
-
"observation_sha256": "
|
|
45
|
-
"module_sha256": "
|
|
42
|
+
"run_id": "38030208537",
|
|
43
|
+
"binary_sha256": "12a8a4b23da84cd672d03abe0c748310225e8bce47c5e8c8cbb3753e5acdbe57",
|
|
44
|
+
"observation_sha256": "cbfbaf744db2c79e4c71fd23903ff06b5284e7475b3f094a90711bb62eb6a39e",
|
|
45
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
46
46
|
"native_cases": [
|
|
47
47
|
"TestContextBoundedRender",
|
|
48
48
|
"TestContextDocumentContract",
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
]
|
|
54
54
|
},
|
|
55
55
|
"darwin/arm64": {
|
|
56
|
-
"source_commit": "
|
|
56
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
57
57
|
"workflow": ".github/workflows/ci.yml",
|
|
58
|
-
"run_id": "
|
|
59
|
-
"binary_sha256": "
|
|
60
|
-
"observation_sha256": "
|
|
61
|
-
"module_sha256": "
|
|
58
|
+
"run_id": "38030208537",
|
|
59
|
+
"binary_sha256": "2107c247473c8a9cc7c422dd754d98fa6211cf7bec5b7ecdd85ba5d7db0676b0",
|
|
60
|
+
"observation_sha256": "426035459f63029ddd368a2a1a9dc542aeaebd920ae0ed993c6bbe6d5ecc1aa5",
|
|
61
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
62
62
|
"native_cases": [
|
|
63
63
|
"TestContextBoundedRender",
|
|
64
64
|
"TestContextDocumentContract",
|
|
@@ -69,12 +69,12 @@
|
|
|
69
69
|
]
|
|
70
70
|
},
|
|
71
71
|
"linux/amd64": {
|
|
72
|
-
"source_commit": "
|
|
72
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
73
73
|
"workflow": ".github/workflows/ci.yml",
|
|
74
|
-
"run_id": "
|
|
75
|
-
"binary_sha256": "
|
|
76
|
-
"observation_sha256": "
|
|
77
|
-
"module_sha256": "
|
|
74
|
+
"run_id": "38030208537",
|
|
75
|
+
"binary_sha256": "92e27501fd18ae805c6390b17b4f2335e97d69c3645c60b3267fb7869c624727",
|
|
76
|
+
"observation_sha256": "50f326cc374cd2914c907ef1367e75dc4ac49ef3526cebfc220a08e9e0d9bac8",
|
|
77
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
78
78
|
"native_cases": [
|
|
79
79
|
"TestContextBoundedRender",
|
|
80
80
|
"TestContextDocumentContract",
|
|
@@ -85,12 +85,12 @@
|
|
|
85
85
|
]
|
|
86
86
|
},
|
|
87
87
|
"linux/arm64": {
|
|
88
|
-
"source_commit": "
|
|
88
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
89
89
|
"workflow": ".github/workflows/ci.yml",
|
|
90
|
-
"run_id": "
|
|
91
|
-
"binary_sha256": "
|
|
92
|
-
"observation_sha256": "
|
|
93
|
-
"module_sha256": "
|
|
90
|
+
"run_id": "38030208537",
|
|
91
|
+
"binary_sha256": "1961df0bdf37fd6a7b3a6214b925cf9f3b2efe0e797c05151a43ee96d7df07b3",
|
|
92
|
+
"observation_sha256": "59a46860f93ed22094e9de20f7d2753cf361411d9e5230fcaabde95275cd7092",
|
|
93
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
94
94
|
"native_cases": [
|
|
95
95
|
"TestContextBoundedRender",
|
|
96
96
|
"TestContextDocumentContract",
|
|
@@ -101,12 +101,12 @@
|
|
|
101
101
|
]
|
|
102
102
|
},
|
|
103
103
|
"windows/amd64": {
|
|
104
|
-
"source_commit": "
|
|
104
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
105
105
|
"workflow": ".github/workflows/ci.yml",
|
|
106
|
-
"run_id": "
|
|
107
|
-
"binary_sha256": "
|
|
108
|
-
"observation_sha256": "
|
|
109
|
-
"module_sha256": "
|
|
106
|
+
"run_id": "38030208537",
|
|
107
|
+
"binary_sha256": "63def27bda36ed03c9f7e6898eaf2110badda2419950a8dcb91666c4e4bdd438",
|
|
108
|
+
"observation_sha256": "ff372ee0e5f5bacc316909afc37c6b9b5442143385180dd7eb235eae725f25f5",
|
|
109
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
110
110
|
"native_cases": [
|
|
111
111
|
"TestContextBoundedRender",
|
|
112
112
|
"TestContextDocumentContract",
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
]
|
|
118
118
|
},
|
|
119
119
|
"windows/arm64": {
|
|
120
|
-
"source_commit": "
|
|
120
|
+
"source_commit": "ee70aa8851f2b96500e1b27085e3466ab222445d",
|
|
121
121
|
"workflow": ".github/workflows/ci.yml",
|
|
122
|
-
"run_id": "
|
|
123
|
-
"binary_sha256": "
|
|
124
|
-
"observation_sha256": "
|
|
125
|
-
"module_sha256": "
|
|
122
|
+
"run_id": "38030208537",
|
|
123
|
+
"binary_sha256": "107e1a8fe971fe24ce8a274ce1188b15c9785e4f94b835dadde1918b8fed5c4b",
|
|
124
|
+
"observation_sha256": "c6761f9845ea9f51281ceb31118dc526a0496a57fa606807bf6118478f2906b4",
|
|
125
|
+
"module_sha256": "a7600f74a743626c4569da0da7803e057ed1df33d0fab8b0581bd25e45d402ed",
|
|
126
126
|
"native_cases": [
|
|
127
127
|
"TestContextBoundedRender",
|
|
128
128
|
"TestContextDocumentContract",
|
|
@@ -82,6 +82,16 @@ REQUEST_LOCK_WAIT_SECONDS = 5.0
|
|
|
82
82
|
CLAUDE_JOIN_LOCK_WAIT_SECONDS = 30.0
|
|
83
83
|
MAX_OUTPUT = 8 << 20
|
|
84
84
|
MAX_DECISION = 65536
|
|
85
|
+
# Current native completion reviews retain the complete immutable context by
|
|
86
|
+
# exact reference instead of duplicating it in every mutable request state.
|
|
87
|
+
CONTEXT_STORAGE = "frozen-reference/0.1.0"
|
|
88
|
+
CONTEXT_REFERENCE = {"format": "codearbiter.evidence-context-reference/0.1.0"}
|
|
89
|
+
# The native canonical decoder already bounds each complete context at 8 MiB.
|
|
90
|
+
MAX_EVIDENCE_CONTEXT = 8 << 20
|
|
91
|
+
# ASCII canonical JSON can expand each input UTF-8 byte to at most six bytes.
|
|
92
|
+
# Reserve that closed decision budget plus 32 bounded 256-byte lifecycle slots
|
|
93
|
+
# (host identities, content-addressed locators, their keys and delimiters).
|
|
94
|
+
REVIEW_RESULT_RESERVE = 6 * MAX_DECISION + 32 * 256
|
|
85
95
|
MAX_COMPLETION_FILES = 16
|
|
86
96
|
MAX_COMPLETION_FILE_BYTES = 64 << 10
|
|
87
97
|
MAX_COMPLETION_TOTAL_BYTES = 256 << 10
|
|
@@ -404,9 +414,41 @@ def _request_lock(spool: Path, relative: Path, wait: float | None = None):
|
|
|
404
414
|
# Do not unlink: a peer may already be waiting on this same inode.
|
|
405
415
|
|
|
406
416
|
|
|
417
|
+
def _referenced_review_state(value: dict[str, Any]) -> dict[str, Any]:
|
|
418
|
+
if (value.get("context_storage") != CONTEXT_STORAGE
|
|
419
|
+
or value.get("codex_review_profile") != CODEX_NATIVE_V1
|
|
420
|
+
or value.get("host", "codex") != "codex"
|
|
421
|
+
or value.get("activity") not in REVIEW_ACTIVITIES
|
|
422
|
+
or "completion" not in value["context"] or "handback" in value):
|
|
423
|
+
raise AuthorityError("INVALID_AUTHORITY_STATE", "context reference is not a native completion review")
|
|
424
|
+
base = dict(value, state="ARMED", launch=None, observation_ref=None,
|
|
425
|
+
observation_sha256=None, receipt=None, recovery=None)
|
|
426
|
+
for field in ("payload", "authority_source"):
|
|
427
|
+
base.pop(field, None)
|
|
428
|
+
base["integrity_sha256"] = "0" * 64
|
|
429
|
+
stored_base = dict(base, context=CONTEXT_REFERENCE)
|
|
430
|
+
context = value["context"]
|
|
431
|
+
# Quality review additionally copies its exact task hashes into the result.
|
|
432
|
+
static_payload = {"input_sha256": context["input_sha256"],
|
|
433
|
+
"spec_sha256": context["spec_sha256"],
|
|
434
|
+
"completion_sha256": context["completion_sha256"]}
|
|
435
|
+
if value["activity"] == "spec_review":
|
|
436
|
+
static_payload["task_sha256"] = context["task_sha256"]
|
|
437
|
+
else:
|
|
438
|
+
static_payload.update(base_input_sha256=context["base_input_sha256"],
|
|
439
|
+
task_hashes=context["task_hashes"])
|
|
440
|
+
if len(_canonical(stored_base)) + len(_canonical(static_payload)) + REVIEW_RESULT_RESERVE > MAX_STATE:
|
|
441
|
+
raise AuthorityError("INVALID_AUTHORITY_STATE", "review result has no bounded lifecycle reserve")
|
|
442
|
+
return dict(value, context=CONTEXT_REFERENCE)
|
|
443
|
+
|
|
444
|
+
|
|
407
445
|
def _save(root: Path, value: dict[str, Any]) -> None:
|
|
408
446
|
expected = value.get("integrity_sha256")
|
|
409
447
|
updated = dict(value)
|
|
448
|
+
if "context_storage" in updated:
|
|
449
|
+
if _read_context(root, updated["context_ref"], updated["context_sha256"]) != updated["context"]:
|
|
450
|
+
raise AuthorityError("INVALID_EVIDENCE_CONTEXT", "stored review context changed")
|
|
451
|
+
updated = _referenced_review_state(updated)
|
|
410
452
|
updated["integrity_sha256"] = _integrity(updated)
|
|
411
453
|
legacy_abandonment = (
|
|
412
454
|
value["state"] == "ABANDONED"
|
|
@@ -468,7 +510,7 @@ def _load(
|
|
|
468
510
|
"authority_source", "dispatch_prompt", "review_contract_sha256",
|
|
469
511
|
"required_coverage", "wrapper", "command_bindings", "recovery",
|
|
470
512
|
"launch_envelope", "workspace_roots", "host", "codex_review_profile",
|
|
471
|
-
"handback",
|
|
513
|
+
"handback", "context_storage",
|
|
472
514
|
}
|
|
473
515
|
if (
|
|
474
516
|
not isinstance(value, dict)
|
|
@@ -496,6 +538,16 @@ def _load(
|
|
|
496
538
|
or value["activity"] not in REVIEW_ACTIVITIES
|
|
497
539
|
):
|
|
498
540
|
raise AuthorityError("INVALID_AUTHORITY_STATE", "Codex review profile is unsupported")
|
|
541
|
+
if "context_storage" in value:
|
|
542
|
+
if value["context"] != CONTEXT_REFERENCE:
|
|
543
|
+
raise AuthorityError("INVALID_AUTHORITY_STATE", "stored context reference is malformed")
|
|
544
|
+
value["context"] = _read_context(root, value["context_ref"], value["context_sha256"])
|
|
545
|
+
subject = value["context"].get("subject", {})
|
|
546
|
+
_validate_context(value["context"], subject.get("artifact_id"),
|
|
547
|
+
subject.get("record_id"), value["activity"])
|
|
548
|
+
_referenced_review_state(value)
|
|
549
|
+
elif value["context"] == CONTEXT_REFERENCE:
|
|
550
|
+
raise AuthorityError("INVALID_AUTHORITY_STATE", "context reference lacks its closed storage profile")
|
|
499
551
|
if len(raw) > MAX_STATE:
|
|
500
552
|
if recover_armed_review and value["state"] == "ABANDONED":
|
|
501
553
|
# Only an abandonment can have retained this; recovering it again is
|
|
@@ -526,13 +578,20 @@ def _validate_hash(value: Any, field: str) -> str:
|
|
|
526
578
|
return value
|
|
527
579
|
|
|
528
580
|
|
|
529
|
-
def _read_context(
|
|
581
|
+
def _read_context(
|
|
582
|
+
root: Path, context_ref: str, context_hash: str
|
|
583
|
+
) -> dict[str, Any]:
|
|
530
584
|
_validate_hash(context_hash, "context_sha256")
|
|
531
585
|
expected_ref = f".codearbiter/.artifacts/evidence-contexts/{context_hash}.json"
|
|
532
586
|
if context_ref != expected_ref:
|
|
533
587
|
raise AuthorityError("INVALID_EVIDENCE_CONTEXT", "context locator is not content addressed")
|
|
534
588
|
try:
|
|
535
|
-
|
|
589
|
+
path = root / expected_ref
|
|
590
|
+
_path_identity(path)
|
|
591
|
+
with path.open("rb") as stream:
|
|
592
|
+
raw = stream.read(MAX_EVIDENCE_CONTEXT + 1)
|
|
593
|
+
if len(raw) > MAX_EVIDENCE_CONTEXT:
|
|
594
|
+
raise ValueError("context exceeds the native canonical budget")
|
|
536
595
|
context = json.loads(raw.decode("utf-8"))
|
|
537
596
|
except (OSError, UnicodeError, ValueError) as exc:
|
|
538
597
|
raise AuthorityError("INVALID_EVIDENCE_CONTEXT", "context bytes are unavailable") from exc
|
|
@@ -1341,6 +1400,7 @@ def _dispatch_prompt(request: dict[str, Any], *, legacy_inline: bool = False) ->
|
|
|
1341
1400
|
if request.get("codex_review_profile") == CODEX_NATIVE_V1 else ""
|
|
1342
1401
|
)
|
|
1343
1402
|
completion = ""
|
|
1403
|
+
completion_fields = ""
|
|
1344
1404
|
if "completion" in context:
|
|
1345
1405
|
completion = (
|
|
1346
1406
|
"This explicit completion review assesses performed work against every selected task's "
|
|
@@ -1370,7 +1430,10 @@ def _dispatch_prompt(request: dict[str, Any], *, legacy_inline: bool = False) ->
|
|
|
1370
1430
|
"that support each conclusion. Missing or unreadable facts require status=missing and "
|
|
1371
1431
|
"decision=changes_requested. A passing decision requires every completion obligation "
|
|
1372
1432
|
"substantiated; a claimed coverage list is insufficient.\n"
|
|
1433
|
+
"Separate required task/obligation pairs: "
|
|
1434
|
+
+ json.dumps(sorted(_completion_obligations(context)), ensure_ascii=True) + ".\n"
|
|
1373
1435
|
)
|
|
1436
|
+
completion_fields = ", completion_sha256 (exact selected packet hash), completion_assessment (separate obligation rows)"
|
|
1374
1437
|
return (
|
|
1375
1438
|
f"[CODEARBITER_AUTHORITY_REQUEST:{request['request_id']}]\n"
|
|
1376
1439
|
f"Target repository: {request['repository']['path']}\n"
|
|
@@ -1384,7 +1447,8 @@ def _dispatch_prompt(request: dict[str, Any], *, legacy_inline: bool = False) ->
|
|
|
1384
1447
|
+ json.dumps(request["required_coverage"], ensure_ascii=True)
|
|
1385
1448
|
+ ". Fields: format, request_id, target_sha256, contract_sha256, decision "
|
|
1386
1449
|
"(pass or changes_requested), coverage (unique strings), findings (objects with "
|
|
1387
|
-
"severity, code, message), assessment (non-empty string)
|
|
1450
|
+
"severity, code, message), assessment (non-empty string)"
|
|
1451
|
+
+ completion_fields + ". Reply with the JSON "
|
|
1388
1452
|
"object only: no code fence and no other text."
|
|
1389
1453
|
)
|
|
1390
1454
|
|
|
@@ -1468,6 +1532,8 @@ def arm_request(
|
|
|
1468
1532
|
seed_value["host"] = host
|
|
1469
1533
|
if codex_review_profile is not None:
|
|
1470
1534
|
seed_value["codex_review_profile"] = CODEX_NATIVE_V1
|
|
1535
|
+
if completion_selection is not None:
|
|
1536
|
+
seed_value["context_storage"] = CONTEXT_STORAGE
|
|
1471
1537
|
seed = _canonical(seed_value)
|
|
1472
1538
|
request_id = _digest(seed)
|
|
1473
1539
|
request = {
|
|
@@ -1493,6 +1559,8 @@ def arm_request(
|
|
|
1493
1559
|
request["host"] = host
|
|
1494
1560
|
if codex_review_profile is not None:
|
|
1495
1561
|
request["codex_review_profile"] = CODEX_NATIVE_V1
|
|
1562
|
+
if completion_selection is not None:
|
|
1563
|
+
request["context_storage"] = CONTEXT_STORAGE
|
|
1496
1564
|
if activity in REVIEW_ACTIVITIES:
|
|
1497
1565
|
request["review_contract_sha256"], request["required_coverage"] = _review_binding(context)
|
|
1498
1566
|
request["dispatch_prompt"] = _dispatch_prompt(request)
|
|
@@ -2388,6 +2456,24 @@ def run_verification(
|
|
|
2388
2456
|
request["context"], request["context_ref"], request["context_sha256"],
|
|
2389
2457
|
):
|
|
2390
2458
|
raise AuthorityError("WORKSPACE_DRIFT", "repository content changed after arm")
|
|
2459
|
+
def normalized_workspace():
|
|
2460
|
+
result = client.call("evidence-context", {
|
|
2461
|
+
"artifact_id": request["context"]["subject"]["artifact_id"],
|
|
2462
|
+
"record_id": request["context"]["subject"]["record_id"],
|
|
2463
|
+
"activity": "verification",
|
|
2464
|
+
"verification_command_bindings": request["command_bindings"],
|
|
2465
|
+
})
|
|
2466
|
+
if (not isinstance(result, dict)
|
|
2467
|
+
or result.get("context_ref") != request["context_ref"]
|
|
2468
|
+
or result.get("context_sha256") != request["context_sha256"]
|
|
2469
|
+
or not isinstance(result.get("completion_workspace_after"), list)
|
|
2470
|
+
or not result["completion_workspace_after"]):
|
|
2471
|
+
raise AuthorityError("WORKSPACE_DRIFT", "engine completion closure is absent or changed context")
|
|
2472
|
+
return result["completion_workspace_after"]
|
|
2473
|
+
|
|
2474
|
+
# The engine alone normalizes validated native bookkeeping. Raw snapshots
|
|
2475
|
+
# still freeze every byte across the actual command execution interval.
|
|
2476
|
+
completion_workspace_before = normalized_workspace()
|
|
2391
2477
|
workspace_before = _workspace_snapshots(request["command_bindings"])
|
|
2392
2478
|
if workspace_before != wrapper.get("workspace_before"):
|
|
2393
2479
|
raise AuthorityError("WORKSPACE_DRIFT", "workspace changed after wrapper authorization")
|
|
@@ -2422,6 +2508,9 @@ def run_verification(
|
|
|
2422
2508
|
workspace_after = _workspace_snapshots(request["command_bindings"])
|
|
2423
2509
|
if workspace_after != workspace_before:
|
|
2424
2510
|
raise AuthorityError("WORKSPACE_DRIFT", "verification changed the frozen workspace")
|
|
2511
|
+
completion_workspace_after = normalized_workspace()
|
|
2512
|
+
if completion_workspace_after != completion_workspace_before:
|
|
2513
|
+
raise AuthorityError("WORKSPACE_DRIFT", "verification changed the normalized completion workspace")
|
|
2425
2514
|
final_context, final_ref, final_hash = _context(
|
|
2426
2515
|
root, client, request["context"]["subject"]["artifact_id"],
|
|
2427
2516
|
request["context"]["subject"]["record_id"], "verification",
|
|
@@ -2435,6 +2524,7 @@ def run_verification(
|
|
|
2435
2524
|
"command_bindings": request["command_bindings"],
|
|
2436
2525
|
"workspace_before": workspace_before,
|
|
2437
2526
|
"workspace_after": workspace_after,
|
|
2527
|
+
"completion_workspace_after": completion_workspace_after,
|
|
2438
2528
|
"commands": commands,
|
|
2439
2529
|
}
|
|
2440
2530
|
payload = {
|
|
@@ -2444,7 +2534,7 @@ def run_verification(
|
|
|
2444
2534
|
"commands": commands,
|
|
2445
2535
|
}
|
|
2446
2536
|
observation = _closed_observation(
|
|
2447
|
-
request, payload, "declared-command/0.
|
|
2537
|
+
request, payload, "declared-command/0.3.0", request["attempt"],
|
|
2448
2538
|
producer_result,
|
|
2449
2539
|
)
|
|
2450
2540
|
_observation(root, request, observation)
|
|
@@ -11,7 +11,7 @@ import hostapi # noqa: E402
|
|
|
11
11
|
class PiHost(hostapi.Host):
|
|
12
12
|
name = "pi"
|
|
13
13
|
adapter_name = "@arbiterforge/ca-pi"
|
|
14
|
-
adapter_version = "0.17.
|
|
14
|
+
adapter_version = "0.17.5"
|
|
15
15
|
update_target = "ca-pi"
|
|
16
16
|
update_tag_prefix = "ca-pi-v"
|
|
17
17
|
update_command = "pi update npm:@arbiterforge/ca-pi"
|
|
@@ -313,7 +313,7 @@ class Host:
|
|
|
313
313
|
|
|
314
314
|
name = "claude"
|
|
315
315
|
adapter_name = "ca"
|
|
316
|
-
adapter_version = "2.25.
|
|
316
|
+
adapter_version = "2.25.4"
|
|
317
317
|
|
|
318
318
|
# Update-notifier descriptor. Each independently versioned host overrides
|
|
319
319
|
# these three values in its per-plugin _host.py. Keeping the target,
|
|
@@ -287,9 +287,11 @@ options. Local executables shadowing nested npm are rejected.
|
|
|
287
287
|
Direct Node script entrypoints are also pinned. These launch-file bindings do
|
|
288
288
|
not establish transitive dependency closure for deliberately excluded inputs.
|
|
289
289
|
|
|
290
|
-
New observations use the closed `declared-command/0.
|
|
291
|
-
retain collector and launch-file identities
|
|
292
|
-
|
|
290
|
+
New observations use the closed `declared-command/0.3.0` producer profile to
|
|
291
|
+
retain collector and launch-file identities plus an engine-produced normalized
|
|
292
|
+
completion closure. Raw workspace fingerprints must still match before and
|
|
293
|
+
after command execution. Historical `0.1.0` and `0.2.0` bindings retain their
|
|
294
|
+
original contracts and cannot be relabelled as newer evidence.
|
|
293
295
|
|
|
294
296
|
For `spec_review` or `quality_review`, arm the corresponding activity without
|
|
295
297
|
workspace mappings and dispatch the returned `launch_envelope` unchanged to one
|
|
@@ -332,10 +334,13 @@ acceptance. Scope review uses validated task completion bindings. If verificatio
|
|
|
332
334
|
is rerun, obtain and record its completed task review before selecting that run
|
|
333
335
|
for scope review; do not infer equivalence between receipts.
|
|
334
336
|
|
|
335
|
-
Creating
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
337
|
+
Creating a completion context for a `0.3.0` verification recomputes the normalized
|
|
338
|
+
worktree closure bound during that verification. Only validated native outputs
|
|
339
|
+
and execution bookkeeping are normalized; their publication must not invalidate
|
|
340
|
+
unchanged source. Historical `0.2.0` verification retains its initial exact raw
|
|
341
|
+
fingerprint comparison. Later freshness checks allow native task-status and
|
|
342
|
+
execution bookkeeping updates in validated canonical artifacts while retaining
|
|
343
|
+
their normative content hashes.
|
|
339
344
|
Changes to task definitions, other HTML or other governance files still affect
|
|
340
345
|
freshness under the normal snapshot policy. The closure covers
|
|
341
346
|
tracked working-tree bytes and non-ignored untracked files, not ignored
|
|
@@ -349,6 +354,16 @@ the scope reaches `REVIEW`, reverify against one current source snapshot, run th
|
|
|
349
354
|
combined quality review, and use `accept-scope` once. Do not accept tasks
|
|
350
355
|
individually.
|
|
351
356
|
|
|
357
|
+
Current Codex native V1 completion reviews retain the full frozen context in
|
|
358
|
+
its immutable, content-addressed file and keep only its closed reference in
|
|
359
|
+
mutable request state. Loading validates the exact context locator, hash,
|
|
360
|
+
canonical bytes and review kind. The native context budget remains 8 MiB;
|
|
361
|
+
mutable request state remains bounded at 1 MiB. Before dispatch, the adapter
|
|
362
|
+
reserves the exact fixed result identities, six times the 64 KiB decision
|
|
363
|
+
budget for canonical JSON escaping, and 32 bounded 256-byte lifecycle slots.
|
|
364
|
+
A request without that capacity is refused before child launch. Historical
|
|
365
|
+
inline requests retain their existing limits and abandonment-only recovery.
|
|
366
|
+
|
|
352
367
|
An ARMED review that never launched can be abandoned through the adapter:
|
|
353
368
|
|
|
354
369
|
```sh
|
|
@@ -87,7 +87,7 @@ file maps those actions to Pi's extension API.
|
|
|
87
87
|
operator-launched Pi CLI, imported module, package root, and reported version.
|
|
88
88
|
It does not prove publisher authenticity. Verify the source separately with
|
|
89
89
|
`pi list` and `pi config`.
|
|
90
|
-
- The supported promotion target is exact Pi 1.0.
|
|
90
|
+
- The supported promotion target is exact Pi 1.1.0. The package is
|
|
91
91
|
published as `npm:@arbiterforge/ca-pi` on every `ca-pi-v*` tag (ADR-0029);
|
|
92
92
|
the pinned Git tag remains the reproducible install. A Pi-native embedded
|
|
93
93
|
farm worker is a future spike, not an installed dependency.
|
|
@@ -32,7 +32,7 @@ repository binary, mutate an artifact, or silently fall back to Markdown.
|
|
|
32
32
|
Pi bash wrapper. The exact shared-core `[H-03]` block is healthy and cannot stage files; execution
|
|
33
33
|
or a different block is unhealthy. This self-test does not traverse Pi's active dispatcher. Do not
|
|
34
34
|
rerun or respell it.
|
|
35
|
-
4. Its `active-dispatch` row remains degraded because supported Pi 1.0
|
|
35
|
+
4. Its `active-dispatch` row remains degraded because supported Pi 1.1.0 public extension
|
|
36
36
|
APIs cannot submit that deterministic call through the active dispatcher. PI-AC-28 remains blocked
|
|
37
37
|
until supported-version real-host promotion/CI evidence closes the gap.
|
|
38
38
|
5. Resolve Python once, run `<plugin-root>/hooks/doctor.py`, and present its mechanical report
|