@arbiterforge/ca-pi 0.18.2 → 0.18.4

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 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.26.2" src="https://img.shields.io/badge/version-2.26.2-2b7489">
13
+ <img alt="version 2.26.4" src="https://img.shields.io/badge/version-2.26.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">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbiterforge/ca-pi",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "license": "AGPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,6 +4,18 @@ All notable changes to `ca-pi` are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.4] - 2026-10-13
8
+
9
+ ### Fixed
10
+
11
+ - Fix task reconciliation for Unicode text while preserving armed requests and prompt-route integrity.
12
+
13
+ ## [0.18.3] - 2026-10-13
14
+
15
+ ### Fixed
16
+
17
+ - Synchronize the shared authority adapter with the Codex runtime compatibility repair while preserving Pi's existing host contract.
18
+
7
19
  ## [0.18.2] - 2026-10-12
8
20
 
9
21
  ### Fixed
@@ -6,43 +6,43 @@
6
6
  "binaries": {
7
7
  "darwin/amd64": {
8
8
  "file": "ca-artifact-darwin-amd64",
9
- "sha256": "0641b0b8014cd8498ab81144e631d9712d3eb5224fcd2726e899149d7ade7175",
9
+ "sha256": "42f302c05c66b22294bff0bdacbd28d5373ddd64b447f087a4532cd99f0a1b6c",
10
10
  "native_tested": true
11
11
  },
12
12
  "darwin/arm64": {
13
13
  "file": "ca-artifact-darwin-arm64",
14
- "sha256": "9a8bb6a130c8fbd17f0bf20c7f6a9286440e86003ec41eef934fc882a7ae41ca",
14
+ "sha256": "adf818a92d6d45db8d13a4ec685b2e2e14ddd19d0978c3d820541c45ed5cd4d9",
15
15
  "native_tested": true
16
16
  },
17
17
  "linux/amd64": {
18
18
  "file": "ca-artifact-linux-amd64",
19
- "sha256": "c0638efca21039ada655c4ebc488c18500eeb0dbc730dd8cb76d878be8a0878e",
19
+ "sha256": "8090a552d8a40bd3d37075eb81005d4e2bc4cdefac3ecb04cef8d72ef00f64d5",
20
20
  "native_tested": true
21
21
  },
22
22
  "linux/arm64": {
23
23
  "file": "ca-artifact-linux-arm64",
24
- "sha256": "204f5f549aa2f75d16f194aba964b14a367c9992d5e0b4cc88c262999141251b",
24
+ "sha256": "0e65ced478bc490e80d6ab5323d307ceffdf42830709563cd6740ef5f35fb069",
25
25
  "native_tested": true
26
26
  },
27
27
  "windows/amd64": {
28
28
  "file": "ca-artifact-windows-amd64.exe",
29
- "sha256": "1976f22b63679478b1c1f4b5f6b13f1d9ae60c9602e4cbc420073626ce8c20d8",
29
+ "sha256": "687e362c216634b531371b4238d129a5f09df716d8cf73b6123f20d4c40c9d36",
30
30
  "native_tested": true
31
31
  },
32
32
  "windows/arm64": {
33
33
  "file": "ca-artifact-windows-arm64.exe",
34
- "sha256": "9d50c8a72029483fc425ac2a27c1f5bfd43362454cc1e8cc8eb28d33ec2fa0db",
34
+ "sha256": "bc4920311a4e3768439b9c35bd0aca77f1ab964011d7812dd8932fc7360527a0",
35
35
  "native_tested": true
36
36
  }
37
37
  },
38
38
  "context_qualification": {
39
39
  "darwin/amd64": {
40
- "source_commit": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
40
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
41
41
  "workflow": ".github/workflows/ci.yml",
42
- "run_id": "38289702788",
43
- "binary_sha256": "0641b0b8014cd8498ab81144e631d9712d3eb5224fcd2726e899149d7ade7175",
44
- "observation_sha256": "3c527a2e9eb02e95c49409e3d71d15632d6e7807a3f74fcc56f9b4808bbe2259",
45
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
42
+ "run_id": "38575955363",
43
+ "binary_sha256": "42f302c05c66b22294bff0bdacbd28d5373ddd64b447f087a4532cd99f0a1b6c",
44
+ "observation_sha256": "e03881ae6e4baf8095597869933ae43dd90b4e1c97bd56dbd83ec57535f6ad7f",
45
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
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": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
56
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
57
57
  "workflow": ".github/workflows/ci.yml",
58
- "run_id": "38289702788",
59
- "binary_sha256": "9a8bb6a130c8fbd17f0bf20c7f6a9286440e86003ec41eef934fc882a7ae41ca",
60
- "observation_sha256": "eba5853f45cc7866ff6dcb94059197f753c25f6295a6a45de748a04bf7e273b4",
61
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
58
+ "run_id": "38575955363",
59
+ "binary_sha256": "adf818a92d6d45db8d13a4ec685b2e2e14ddd19d0978c3d820541c45ed5cd4d9",
60
+ "observation_sha256": "053780b4155a329003e9d8402a90be022ac1750e5f1420ea46a5079931464fd6",
61
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
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": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
72
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
73
73
  "workflow": ".github/workflows/ci.yml",
74
- "run_id": "38289702788",
75
- "binary_sha256": "c0638efca21039ada655c4ebc488c18500eeb0dbc730dd8cb76d878be8a0878e",
76
- "observation_sha256": "87ac254be4179136dc1f0e02650182dddac6045b28bd2c2e19889abe1af26665",
77
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
74
+ "run_id": "38575955363",
75
+ "binary_sha256": "8090a552d8a40bd3d37075eb81005d4e2bc4cdefac3ecb04cef8d72ef00f64d5",
76
+ "observation_sha256": "e83da7b877c8e37761b826b6a45bee44e009066a66c18309d2f854ed0d94096b",
77
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
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": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
88
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
89
89
  "workflow": ".github/workflows/ci.yml",
90
- "run_id": "38289702788",
91
- "binary_sha256": "204f5f549aa2f75d16f194aba964b14a367c9992d5e0b4cc88c262999141251b",
92
- "observation_sha256": "9459a65d3dac40380fd15e853cf1e16d3d41f7e786c9c31a0de232b4a4b569f5",
93
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
90
+ "run_id": "38575955363",
91
+ "binary_sha256": "0e65ced478bc490e80d6ab5323d307ceffdf42830709563cd6740ef5f35fb069",
92
+ "observation_sha256": "dbaace14fca6456b29dbb71360fe9d2f0ab73738bad9c09486f0964358958a07",
93
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
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": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
104
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
105
105
  "workflow": ".github/workflows/ci.yml",
106
- "run_id": "38289702788",
107
- "binary_sha256": "1976f22b63679478b1c1f4b5f6b13f1d9ae60c9602e4cbc420073626ce8c20d8",
108
- "observation_sha256": "80800ef282ee480aaeafca21141ee23e2104e5f22948677d020768b7d6cce939",
109
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
106
+ "run_id": "38575955363",
107
+ "binary_sha256": "687e362c216634b531371b4238d129a5f09df716d8cf73b6123f20d4c40c9d36",
108
+ "observation_sha256": "575df189640f478ffdbc593f4a070c4e407b0f50b7787d20632eb3586bc16cee",
109
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
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": "e33bb87b30d4a3ac3286378ad9ec5bff70140392",
120
+ "source_commit": "045c0812888f20f4c843677cfb37b802e2084770",
121
121
  "workflow": ".github/workflows/ci.yml",
122
- "run_id": "38289702788",
123
- "binary_sha256": "9d50c8a72029483fc425ac2a27c1f5bfd43362454cc1e8cc8eb28d33ec2fa0db",
124
- "observation_sha256": "01a8e1b91794dbed3d618dc20dd7adf0dcc9597bf9c42e0ba14278197a384f74",
125
- "module_sha256": "4c2f7af945966dbe8e0b31459a87bc1f5ebc40de544a3c42508d824ef82eeb23",
122
+ "run_id": "38575955363",
123
+ "binary_sha256": "bc4920311a4e3768439b9c35bd0aca77f1ab964011d7812dd8932fc7360527a0",
124
+ "observation_sha256": "1b6574772d1e93c2cd59ff43d519e343d44926312cf4d90b840207b0a625d3f9",
125
+ "module_sha256": "e482ad7b0c9264711828ac8404c624517b893981b45712d70ead0fb0ef3b5522",
126
126
  "native_cases": [
127
127
  "TestContextBoundedRender",
128
128
  "TestContextDocumentContract",
@@ -117,7 +117,11 @@ CLAUDE_REVIEW_PROFILE = "claude-review/0.1.0"
117
117
  CODEX_REVIEW_PROFILE = "codex-review/0.1.0"
118
118
  CODEX_NATIVE_V1 = "codex-native-v1/0.145.0"
119
119
  CODEX_NATIVE_V2 = "codex-native-v2/0.162.0-alpha.2"
120
- CODEX_NATIVE_PROFILES = frozenset({CODEX_NATIVE_V1, CODEX_NATIVE_V2})
120
+ # This version identifies our evidence protocol, never the host release.
121
+ CODEX_NATIVE_PROTOCOL = "codex-native-collaboration/1.0.0"
122
+ CODEX_COLLABORATION_PROFILES = frozenset({CODEX_NATIVE_V2, CODEX_NATIVE_PROTOCOL})
123
+ CODEX_NATIVE_PROFILES = frozenset({CODEX_NATIVE_V1, *CODEX_COLLABORATION_PROFILES})
124
+ CODEX_RUNTIME_RE = re.compile(r"[0-9]+(?:\.[0-9]+){2}(?:[-+][0-9A-Za-z.+-]+)?", re.ASCII)
121
125
  CODEX_UUID_RE = re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
122
126
  CODEX_AGENT_PATH_RE = re.compile(r"/root(?:/[a-z0-9_]+)*")
123
127
  CODEX_STEERING_TOOLS = frozenset({
@@ -1179,7 +1183,7 @@ def _reject_overlapping_authority(session_id: str, turn_id: str) -> None:
1179
1183
  launch = request.get("launch") or {}
1180
1184
  if (
1181
1185
  request["state"] in {"LAUNCHING", "RUNNING"}
1182
- and request.get("codex_review_profile") != CODEX_NATIVE_V2
1186
+ and request.get("codex_review_profile") not in CODEX_COLLABORATION_PROFILES
1183
1187
  and launch.get("parent_session_id") == session_id
1184
1188
  and launch.get("parent_turn_id") == turn_id
1185
1189
  ):
@@ -1500,8 +1504,8 @@ def _dispatch_prompt(request: dict[str, Any], *, legacy_inline: bool = False) ->
1500
1504
  "these settings do not provide an OS sandbox.\n"
1501
1505
  if request.get("codex_review_profile") == CODEX_NATIVE_V1 else ""
1502
1506
  )
1503
- if request.get("codex_review_profile") == CODEX_NATIVE_V2:
1504
- profile = (f"Native review profile: {CODEX_NATIVE_V2}. This review was dispatched through "
1507
+ if request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES:
1508
+ profile = (f"Native review profile: {request['codex_review_profile']}. This review was dispatched through "
1505
1509
  "collaboration.spawn_agent with default role and fork_turns=none. Read-only conduct "
1506
1510
  "is cooperative; these settings do not provide an OS sandbox.\n")
1507
1511
  completion = ""
@@ -1600,7 +1604,7 @@ def arm_request(
1600
1604
  if host == "claude" and reviewer_model not in CLAUDE_REVIEWER_MODELS:
1601
1605
  raise AuthorityError("INVALID_AUTHORITY_REQUEST", "reviewer model is unsupported")
1602
1606
  if codex_review_profile is not None and (
1603
- codex_review_profile not in {"native-v1", "native-v2"} or host != "codex" or activity not in REVIEW_ACTIVITIES
1607
+ codex_review_profile not in {"native", "native-v1", "native-v2"} or host != "codex" or activity not in REVIEW_ACTIVITIES
1604
1608
  ):
1605
1609
  raise AuthorityError("INVALID_AUTHORITY_REQUEST", "Codex review profile is unsupported")
1606
1610
  completion_selection = None
@@ -1652,7 +1656,9 @@ def arm_request(
1652
1656
  if activity == "verification":
1653
1657
  seed_value["context_storage"] = CONTEXT_STORAGE
1654
1658
  if codex_review_profile is not None:
1655
- seed_value["codex_review_profile"] = CODEX_NATIVE_V1 if codex_review_profile == "native-v1" else CODEX_NATIVE_V2
1659
+ seed_value["codex_review_profile"] = {
1660
+ "native": CODEX_NATIVE_PROTOCOL, "native-v1": CODEX_NATIVE_V1, "native-v2": CODEX_NATIVE_V2,
1661
+ }[codex_review_profile]
1656
1662
  if completion_selection is not None:
1657
1663
  seed_value["context_storage"] = CONTEXT_STORAGE
1658
1664
  seed = _canonical(seed_value)
@@ -3043,6 +3049,16 @@ def _codex_v2_activity(event: dict[str, Any], request: dict[str, Any]) -> dict[s
3043
3049
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native activity for exact call is missing or ambiguous")
3044
3050
  activity = matches[0]
3045
3051
  item = activity["item"]
3052
+ if request.get("codex_review_profile") == CODEX_NATIVE_PROTOCOL:
3053
+ # Host records may gain non-authoritative fields. Retained evidence is
3054
+ # closed; required joins, bounds and duplicate-key rejection stay strict.
3055
+ activity = {key: activity[key] for key in (
3056
+ "type", "thread_id", "turn_id", "item", "started_at_ms", "completed_at_ms",
3057
+ ) if key in activity}
3058
+ item = {key: item[key] for key in (
3059
+ "type", "id", "kind", "agent_thread_id", "agent_path",
3060
+ ) if key in item}
3061
+ activity["item"] = item
3046
3062
  if (set(activity) != {"type", "thread_id", "turn_id", "item", "started_at_ms", "completed_at_ms"}
3047
3063
  or set(item) != {"type", "id", "kind", "agent_thread_id", "agent_path"}
3048
3064
  or activity["thread_id"] != anchor["parent_thread_id"] or activity["turn_id"] != launch["parent_turn_id"]
@@ -3054,6 +3070,10 @@ def _codex_v2_activity(event: dict[str, Any], request: dict[str, Any]) -> dict[s
3054
3070
  return activity
3055
3071
 
3056
3072
 
3073
+ def _codex_runtime_identity(value: Any) -> bool:
3074
+ return isinstance(value, str) and len(value) <= 128 and CODEX_RUNTIME_RE.fullmatch(value) is not None
3075
+
3076
+
3057
3077
  def _codex_v2_child(event: dict[str, Any]) -> dict[str, Any] | None:
3058
3078
  # Historical V1 lifecycle fixtures/hosts need no native rollout metadata.
3059
3079
  if event.get("transcript_path") is None:
@@ -3065,16 +3085,26 @@ def _codex_v2_child(event: dict[str, Any]) -> dict[str, Any] | None:
3065
3085
  # A V1 Start did not promise native metadata. V2 binding below requires
3066
3086
  # qualified metadata; missing/unsafe bytes still cannot pass V2.
3067
3087
  return None
3068
- if meta.get("cli_version") != "0.162.0-alpha.2":
3088
+ # Runtime identity is provenance; compatibility comes from the concrete
3089
+ # launch/activity/lifecycle protocol, not a release allowlist.
3090
+ if (not _codex_runtime_identity(meta.get("cli_version"))
3091
+ or not {"id", "parent_thread_id", "session_id", "agent_path"} <= set(meta)):
3092
+ # V1 metadata lacks collaboration fields. Its own lifecycle contract
3093
+ # remains sufficient; collaboration requests require this evidence at bind.
3094
+ return None
3095
+ try:
3096
+ identity = {"cli_version": meta["cli_version"], "thread_id": _codex_uuid(meta.get("id")),
3097
+ "parent_thread_id": _codex_uuid(meta.get("parent_thread_id")),
3098
+ "session_id": _host_id(meta.get("session_id"), "session_id"),
3099
+ "agent_path": meta.get("agent_path"), "metadata_sha256": _digest(raw)}
3100
+ except AuthorityError:
3101
+ # Optional metadata cannot impose collaboration prerequisites on V1.
3102
+ # A collaboration request will reject this absence at profile binding.
3069
3103
  return None
3070
- identity = {"cli_version": meta["cli_version"], "thread_id": _codex_uuid(meta.get("id")),
3071
- "parent_thread_id": _codex_uuid(meta.get("parent_thread_id")),
3072
- "session_id": _host_id(meta.get("session_id"), "session_id"),
3073
- "agent_path": meta.get("agent_path"), "metadata_sha256": _digest(raw)}
3074
3104
  if (identity["thread_id"] != event["agent_id"] or identity["session_id"] != event.get("session_id")
3075
3105
  or not isinstance(identity["agent_path"], str)
3076
3106
  or CODEX_AGENT_PATH_RE.fullmatch(identity["agent_path"]) is None):
3077
- raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native child metadata differs from its lifecycle")
3107
+ return None
3078
3108
  return identity
3079
3109
 
3080
3110
 
@@ -3085,7 +3115,11 @@ def _codex_v2_bind_child(request: dict[str, Any], child: dict[str, Any]) -> None
3085
3115
  or identity.get("thread_id") != launch["agent_id"]
3086
3116
  or identity.get("session_id") != launch["parent_session_id"]
3087
3117
  or identity.get("agent_path") != launch["task_name"]):
3088
- raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native V2 child runtime or parent association is unqualified")
3118
+ raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native collaboration requires child metadata bound to the exact parent/session/path/UUID")
3119
+ # Only new protocol requests admit differing runtime provenance.
3120
+ if (request.get("codex_review_profile") == CODEX_NATIVE_V2
3121
+ and identity.get("cli_version") != "0.162.0-alpha.2"):
3122
+ raise AuthorityError("UNSUPPORTED_HOST_SEAM", "historical native-v2 request requires its original runtime; arm a new native protocol request")
3089
3123
  launch["native_child"] = identity
3090
3124
 
3091
3125
 
@@ -3173,7 +3207,7 @@ def _read_codex_child(path: Path, agent_id: str, session_id: str) -> dict[str, A
3173
3207
  identity = value["native_v2"]
3174
3208
  if (not isinstance(identity, dict) or set(identity) != {
3175
3209
  "cli_version", "thread_id", "parent_thread_id", "session_id", "agent_path", "metadata_sha256"}
3176
- or identity.get("cli_version") != "0.162.0-alpha.2"
3210
+ or not _codex_runtime_identity(identity.get("cli_version"))
3177
3211
  or identity.get("thread_id") != agent_id or identity.get("session_id") != value["session_id"]
3178
3212
  or not isinstance(identity.get("parent_thread_id"), str)
3179
3213
  or CODEX_UUID_RE.fullmatch(identity["parent_thread_id"]) is None
@@ -3224,7 +3258,7 @@ def _codex_native_post(event: dict[str, Any], root: Path, request: dict[str, Any
3224
3258
 
3225
3259
 
3226
3260
  def _codex_native_post_join(event: dict[str, Any], root: Path, request: dict[str, Any]) -> dict[str, Any]:
3227
- expected_tool = "collaborationspawn_agent" if request.get("codex_review_profile") == CODEX_NATIVE_V2 else "spawn_agent"
3261
+ expected_tool = "collaborationspawn_agent" if request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES else "spawn_agent"
3228
3262
  if event.get("tool_name") != expected_tool:
3229
3263
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native review PostToolUse tool differs from its launch profile")
3230
3264
  if _canonical(event.get("tool_input")) != _canonical(request["launch_envelope"]):
@@ -3238,13 +3272,22 @@ def _codex_native_post_join(event: dict[str, Any], root: Path, request: dict[str
3238
3272
  except ValueError as exc:
3239
3273
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native-v1 spawn result is not strict JSON") from exc
3240
3274
  activity = None
3241
- if request.get("codex_review_profile") == CODEX_NATIVE_V2:
3242
- if (not isinstance(response, dict) or set(response) not in ({"task_name"}, {"task_name", "nickname"})
3275
+ if request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES:
3276
+ stable = request.get("codex_review_profile") == CODEX_NATIVE_PROTOCOL
3277
+ if (not isinstance(response, dict)
3278
+ or not stable and set(response) not in ({"task_name"}, {"task_name", "nickname"})
3243
3279
  or response.get("task_name") != request["codex_native_trace"]["agent_path"]
3244
3280
  or ("nickname" in response and (not isinstance(response["nickname"], str) or len(response["nickname"]) > 256))):
3245
- raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native-v2 spawn result fields or canonical task path differ")
3281
+ raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native collaboration spawn result fields or canonical task path differ")
3246
3282
  activity = _codex_v2_activity(event, request)
3247
3283
  agent_id = _codex_uuid(activity["item"]["agent_thread_id"])
3284
+ if stable:
3285
+ # Extra display metadata is inert, but an optional host identity
3286
+ # must agree with the independently observed native activity.
3287
+ identities = {"agent_id": agent_id, "thread_id": agent_id,
3288
+ "parent_thread_id": request["launch"]["parent_thread_id"]}
3289
+ if any(key in response and response[key] != expected for key, expected in identities.items()):
3290
+ raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native spawn result identity conflicts with its activity")
3248
3291
  elif (not isinstance(response, dict) or set(response) != {"agent_id", "nickname"}
3249
3292
  or (response["nickname"] is not None and (
3250
3293
  not isinstance(response["nickname"], str) or len(response["nickname"]) > 256))):
@@ -3269,7 +3312,7 @@ def _codex_native_post_join(event: dict[str, Any], root: Path, request: dict[str
3269
3312
  if activity is not None:
3270
3313
  launch.update(native_activity=activity, native_activity_sha256=_engine_digest(activity))
3271
3314
  if child["start"] is not None:
3272
- if request.get("codex_review_profile") == CODEX_NATIVE_V2:
3315
+ if request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES:
3273
3316
  _codex_v2_bind_child(request, child)
3274
3317
  launch.update(child_turn_id=child["start"]["turn_id"], agent_type="default")
3275
3318
  request["state"] = "RUNNING"
@@ -3363,7 +3406,7 @@ def _codex_native_lifecycle_join(event: dict[str, Any]) -> dict[str, Any] | None
3363
3406
  if name == "SubagentStart":
3364
3407
  if request["state"] != "LAUNCHING":
3365
3408
  _codex_native_refuse(root, request, "native reviewer start was repeated")
3366
- if request.get("codex_review_profile") == CODEX_NATIVE_V2:
3409
+ if request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES:
3367
3410
  _codex_v2_bind_child(request, child)
3368
3411
  launch.update(child_turn_id=event["turn_id"], agent_type="default")
3369
3412
  request["state"] = "RUNNING"
@@ -3419,7 +3462,7 @@ def _codex_native_steering(event: dict[str, Any]) -> None:
3419
3462
  _write_codex_child(path, child)
3420
3463
  for root, request in _registered_requests(strict=True):
3421
3464
  launch = request.get("launch") or {}
3422
- if (request.get("codex_review_profile") != CODEX_NATIVE_V2
3465
+ if (request.get("codex_review_profile") not in CODEX_COLLABORATION_PROFILES
3423
3466
  or request["state"] not in {"LAUNCHING", "RUNNING"}
3424
3467
  or launch.get("parent_session_id") != event.get("session_id")):
3425
3468
  continue
@@ -3470,11 +3513,11 @@ def observe_codex_hook(root: str | Path, event: dict[str, Any]) -> dict[str, Any
3470
3513
  message = tool_input.get("message") if isinstance(tool_input, dict) else None
3471
3514
  if isinstance(message, str) and message.startswith("[CODEARBITER_AUTHORITY_REQUEST:"):
3472
3515
  _, candidate = _registered_request(_request_id_from_prompt(message))
3473
- if candidate.get("codex_review_profile") != CODEX_NATIVE_V2:
3516
+ if candidate.get("codex_review_profile") not in CODEX_COLLABORATION_PROFILES:
3474
3517
  raise AuthorityError(
3475
3518
  "UNSUPPORTED_HOST_SEAM",
3476
- "Codex v2 requires a fresh qualified native-v2 request with direct activity UUID binding; "
3477
- "otherwise qualify native-v1 and arm a fresh request",
3519
+ "collaboration review requires a fresh native protocol request with direct activity UUID binding; "
3520
+ "historical requests cannot be relabelled",
3478
3521
  )
3479
3522
  else:
3480
3523
  turn_id = _host_id(event.get("turn_id"), "turn_id")
@@ -3508,7 +3551,7 @@ def observe_codex_hook(root: str | Path, event: dict[str, Any]) -> dict[str, Any
3508
3551
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "review request is not launchable")
3509
3552
  if _canonical(tool_input) != _canonical(request.get("launch_envelope")):
3510
3553
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "review launch envelope was changed")
3511
- is_v2 = request.get("codex_review_profile") == CODEX_NATIVE_V2
3554
+ is_v2 = request.get("codex_review_profile") in CODEX_COLLABORATION_PROFILES
3512
3555
  if is_v2 != (event["tool_name"] == "collaborationspawn_agent"):
3513
3556
  raise AuthorityError("UNSUPPORTED_HOST_SEAM", "native review profile differs from launch tool")
3514
3557
  _require_frozen_context(root, request)
@@ -3536,7 +3579,7 @@ def observe_codex_hook(root: str | Path, event: dict[str, Any]) -> dict[str, Any
3536
3579
  elif is_v2:
3537
3580
  anchor = _codex_v2_trace_anchor(event, tool_input["task_name"])
3538
3581
  request["codex_native_trace"] = anchor
3539
- request["launch"].update(codex_review_profile=CODEX_NATIVE_V2, child_turn_id=None,
3582
+ request["launch"].update(codex_review_profile=request["codex_review_profile"], child_turn_id=None,
3540
3583
  parent_thread_id=anchor["parent_thread_id"], task_name=anchor["agent_path"], fork_turns="none")
3541
3584
  else:
3542
3585
  request["launch"].update(task_name=tool_input["task_name"], fork_turns=tool_input["fork_turns"])
@@ -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.18.2"
14
+ adapter_version = "0.18.4"
15
15
  update_target = "ca-pi"
16
16
  update_tag_prefix = "ca-pi-v"
17
17
  update_command = "pi update npm:@arbiterforge/ca-pi"
@@ -498,7 +498,9 @@ def _consume_reconciliation_unlocked(
498
498
  raise ReconciliationError("reconciliation target changed after arming")
499
499
  payload = {"input_sha256": pending["input_sha256"], "assessment": pending["assessment"]}
500
500
  if pending["operation"] == "task-reconcile":
501
- payload.update(task_sha256=pending["record_sha256"], target_state=pending["target_state"])
501
+ # Marker/route integrity retains its legacy serialization; authority
502
+ # binds the rechecked record to the engine's canonical JSON digest.
503
+ payload.update(task_sha256=_artifactauthoritylib._engine_digest(record), target_state=pending["target_state"])
502
504
  event = {
503
505
  "kind": "reconciliation",
504
506
  "authority_kind": "user_workflow",
@@ -52,8 +52,8 @@ def main(argv=None) -> int:
52
52
  default="opus", help="Claude reviewer model pinned into the launch envelope",
53
53
  )
54
54
  arm.add_argument(
55
- "--codex-review-profile", choices=("native-v1", "native-v2"), default=None,
56
- help="select only after qualifying the actual registered native interface and lifecycle",
55
+ "--codex-review-profile", choices=("native", "native-v1", "native-v2"), default=None,
56
+ help="Codex reviews default to the collaboration evidence protocol; legacy profiles are explicit",
57
57
  )
58
58
  context_arm = sub.add_parser("arm-context")
59
59
  context_arm.add_argument("--root", required=True)
@@ -92,10 +92,7 @@ def main(argv=None) -> int:
92
92
  )
93
93
  if (host == "codex" and args.activity in _artifactauthoritylib.REVIEW_ACTIVITIES
94
94
  and args.codex_review_profile is None):
95
- raise _artifactauthoritylib.AuthorityError(
96
- "UNSUPPORTED_HOST_SEAM",
97
- "Codex review requires an explicit native-v1 or native-v2 profile after live interface qualification",
98
- )
95
+ args.codex_review_profile = "native"
99
96
  result = _artifactauthoritylib.arm_request(
100
97
  root, client, args.artifact_id, args.record_id, args.activity,
101
98
  workspace_roots=workspaces or None, host=host,
@@ -313,7 +313,7 @@ class Host:
313
313
 
314
314
  name = "claude"
315
315
  adapter_name = "ca"
316
- adapter_version = "2.26.2"
316
+ adapter_version = "2.26.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,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbiterforge/ca-pi",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "private": true,
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",