agent-runtime-kit 0.5.4__tar.gz → 0.5.6__tar.gz

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 (83) hide show
  1. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/CHANGELOG.md +24 -0
  2. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/PKG-INFO +3 -3
  3. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/sdk-evolution-agent.md +16 -3
  4. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/cli.py +3 -1
  5. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/models.py +23 -0
  6. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/release_notes.py +194 -1
  7. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/report.py +13 -0
  8. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/snapshots.py +36 -0
  9. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/stages.py +31 -0
  10. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/pyproject.toml +3 -3
  11. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/compatibility.py +5 -5
  12. agent_runtime_kit-0.5.6/tests/_antigravity_workflow_probe.py +146 -0
  13. agent_runtime_kit-0.5.6/tests/test_antigravity_workflow_contract.py +46 -0
  14. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_sdk_evolution_agent.py +3 -2
  15. agent_runtime_kit-0.5.6/tests/test_sdk_evolution_alias_snapshots.py +57 -0
  16. agent_runtime_kit-0.5.6/tests/test_sdk_evolution_bundled_release_notes.py +220 -0
  17. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/.gitignore +0 -0
  18. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/LICENSE +0 -0
  19. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/README.md +0 -0
  20. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/api-stability.md +0 -0
  21. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/capability-matrix.md +0 -0
  22. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/live-smoke.md +0 -0
  23. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/providers.md +0 -0
  24. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/quickstart.md +0 -0
  25. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/recipes.md +0 -0
  26. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/sdk-evolution-agent-design.md +0 -0
  27. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/docs/task-control.md +0 -0
  28. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/README.md +0 -0
  29. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/__init__.py +0 -0
  30. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/basic_offline.py +0 -0
  31. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/diagnostics.py +0 -0
  32. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/events.py +0 -0
  33. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/provider_task.py +0 -0
  34. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/run_same_task.py +0 -0
  35. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/__init__.py +0 -0
  36. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/__main__.py +0 -0
  37. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/auth.py +0 -0
  38. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/behavior.py +0 -0
  39. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/collectors.py +0 -0
  40. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/current_state.py +0 -0
  41. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/events.py +0 -0
  42. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/inspection.py +0 -0
  43. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/pr.py +0 -0
  44. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/sdk_evolution_agent/schemas.py +0 -0
  45. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/examples/structured_output.py +0 -0
  46. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/__init__.py +0 -0
  47. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_control.py +0 -0
  48. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_errors.py +0 -0
  49. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_kit.py +0 -0
  50. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_runtime.py +0 -0
  51. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_schema.py +0 -0
  52. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/_types.py +0 -0
  53. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/__init__.py +0 -0
  54. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/_common.py +0 -0
  55. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/antigravity.py +0 -0
  56. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/claude.py +0 -0
  57. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/codex.py +0 -0
  58. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/adapters/diagnostics.py +0 -0
  59. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/events.py +0 -0
  60. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/py.typed +0 -0
  61. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/readiness.py +0 -0
  62. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/registry.py +0 -0
  63. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/support.py +0 -0
  64. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/testing/__init__.py +0 -0
  65. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/src/agent_runtime_kit/testing/fakes.py +0 -0
  66. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_adapter_common.py +0 -0
  67. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_adapter_protocol.py +0 -0
  68. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_antigravity_adapter.py +0 -0
  69. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_claude_adapter.py +0 -0
  70. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_codex_adapter.py +0 -0
  71. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_control.py +0 -0
  72. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_core.py +0 -0
  73. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_events.py +0 -0
  74. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_kit.py +0 -0
  75. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_live_smoke.py +0 -0
  76. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_mestre_compatibility.py +0 -0
  77. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_optional_dependencies.py +0 -0
  78. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_provider_diagnostics.py +0 -0
  79. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_readiness.py +0 -0
  80. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_schema.py +0 -0
  81. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_sdk_contract.py +0 -0
  82. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_sdk_evolution_docs.py +0 -0
  83. {agent_runtime_kit-0.5.4 → agent_runtime_kit-0.5.6}/tests/test_support.py +0 -0
@@ -5,6 +5,30 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 0.5.6 - 2026-11-08
9
+
10
+ ### Changed
11
+
12
+ - Updated the tested Claude Agent SDK to `0.2.179`, Antigravity to `0.1.23`,
13
+ and the exactly coupled Codex SDK and CLI to `0.167.0`. Raised the Codex
14
+ upper bound to `<0.168` after inspecting the exact candidate versions.
15
+
16
+ ### Fixed
17
+
18
+ - SDK evolution now collects official release notes for Claude's bundled CLI,
19
+ verifies its version against the inspected SDK distribution, and blocks on
20
+ incomplete or contradictory runtime evidence.
21
+ - Implementation snapshots distinguish a public class replaced by an alias
22
+ from a removed name, including in isolated candidate environments.
23
+
24
+ ## 0.5.5 - 2026-10-22
25
+
26
+ ### Changed
27
+
28
+ - Updated tested Claude Agent SDK from `0.2.168` to `0.2.172`, including bundled
29
+ Claude CLI `2.1.308`, after exact-version API and behavior checks. Codex SDK
30
+ and its exactly coupled CLI remain `0.163.0`; Antigravity remains `0.1.22`.
31
+
8
32
  ## 0.5.4 - 2026-10-18
9
33
 
10
34
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agent-runtime-kit
3
- Version: 0.5.4
3
+ Version: 0.5.6
4
4
  Summary: One typed runtime API for Claude, Codex, and Antigravity agent SDKs.
5
5
  Project-URL: Homepage, https://github.com/ebarti/agent-runtime-kit
6
6
  Project-URL: Repository, https://github.com/ebarti/agent-runtime-kit
@@ -23,13 +23,13 @@ Requires-Dist: tomli<3,>=2; python_version < '3.11'
23
23
  Provides-Extra: all
24
24
  Requires-Dist: claude-agent-sdk<0.3,>=0.2.87; extra == 'all'
25
25
  Requires-Dist: google-antigravity<0.2,>=0.1.2; extra == 'all'
26
- Requires-Dist: openai-codex<0.164,>=0.157.1; extra == 'all'
26
+ Requires-Dist: openai-codex<0.168,>=0.157.1; extra == 'all'
27
27
  Provides-Extra: antigravity
28
28
  Requires-Dist: google-antigravity<0.2,>=0.1.2; extra == 'antigravity'
29
29
  Provides-Extra: claude
30
30
  Requires-Dist: claude-agent-sdk<0.3,>=0.2.87; extra == 'claude'
31
31
  Provides-Extra: codex
32
- Requires-Dist: openai-codex<0.164,>=0.157.1; extra == 'codex'
32
+ Requires-Dist: openai-codex<0.168,>=0.157.1; extra == 'codex'
33
33
  Description-Content-Type: text/markdown
34
34
 
35
35
  # agent-runtime-kit
@@ -173,18 +173,31 @@ files and Python AST definitions, compares adjacent releases, and writes the
173
173
  result to `implementation_diffs.json`. History also includes the exact locked
174
174
  baseline and candidate when they fall outside the latest three releases, so
175
175
  the changes between the installed baseline and the recent releases remain
176
- visible. Claude probes construct permission, budget, session, MCP and schema
177
- options; Codex probes construct configuration and validated thread/turn wire
176
+ visible. Module-level capitalized alias assignments are fingerprinted alongside
177
+ class and function definitions, so replacing a class with an alias is
178
+ distinguished from deleting the name. These are static source observations,
179
+ not proof that a conditional assignment is present at runtime. Claude probes
180
+ construct permission, budget, session, MCP and schema options; Codex probes
181
+ construct configuration and validated thread/turn wire
178
182
  parameters, including permissions, reasoning effort and structured output.
179
183
  These checks complement real-adapter regression tests and live runtime checks;
180
184
  they do not establish behavior inside opaque executables.
181
- Source is never copied into the report;
185
+ Implementation source is never copied into the report;
182
186
  only paths, counts, sizes, and hashes are retained. Candidate inspection is
183
187
  opt-in because it executes freshly downloaded upstream code; historical
184
188
  inspection uses the same explicit consent. Without the flag, missing trend
185
189
  evidence is reported as `no-transition` rather than being replaced with
186
190
  dependency advice.
187
191
 
192
+ For a Claude SDK update, release evidence also covers its bundled Claude Code
193
+ CLI. The runner matches each SDK tag's CLI-version file against the fingerprint
194
+ of the exact inspected distribution, then records official CLI release notes
195
+ between the baseline and candidate. The SDK's own note status remains separate:
196
+ CLI notes do not turn an absent SDK changelog entry into a match. Missing or
197
+ contradictory version mappings, an incomplete release index, and missing CLI
198
+ release text block promotion. The CLI remains opaque even when its release
199
+ notes are available.
200
+
188
201
  ## Upstream Implementation Trends
189
202
 
190
203
  `direction_analysis.json` is an implementation-trend report. It answers what
@@ -237,7 +237,9 @@ async def run_agent(
237
237
  _progress("collecting release notes and executable behavior probes")
238
238
  release_notes = [
239
239
  to_jsonable(item)
240
- for item in collect_release_notes(evidence.get("packages", []), update_versions)
240
+ for item in collect_release_notes(
241
+ evidence.get("packages", []), update_versions, snapshots=snapshots
242
+ )
241
243
  ]
242
244
  behavior = to_jsonable(
243
245
  collect_behavior_evidence(
@@ -152,6 +152,28 @@ class ImplementationDiff:
152
152
  limitations: tuple[str, ...] = ()
153
153
 
154
154
 
155
+ @dataclass(frozen=True)
156
+ class BundledRuntimeRelease:
157
+ """An official release note for a runtime bundled inside an SDK."""
158
+
159
+ version: str
160
+ url: str
161
+ notes: str
162
+
163
+
164
+ @dataclass(frozen=True)
165
+ class BundledRuntimeEvidence:
166
+ """Provenance and release notes for an SDK's exact bundled runtime."""
167
+
168
+ name: str
169
+ from_version: str | None
170
+ to_version: str | None
171
+ status: str
172
+ sources: tuple[SourceRef, ...] = ()
173
+ releases: tuple[BundledRuntimeRelease, ...] = ()
174
+ unavailable_reason: str = ""
175
+
176
+
155
177
  @dataclass(frozen=True)
156
178
  class ReleaseNoteEvidence:
157
179
  """Release-note evidence collected for one package interval."""
@@ -164,6 +186,7 @@ class ReleaseNoteEvidence:
164
186
  summaries: tuple[str, ...] = ()
165
187
  checked_urls: tuple[str, ...] = ()
166
188
  unavailable_reason: str = ""
189
+ bundled_runtime: BundledRuntimeEvidence | None = None
167
190
 
168
191
 
169
192
  @dataclass(frozen=True)
@@ -2,7 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import ast
5
6
  import gzip
7
+ import hashlib
6
8
  import json
7
9
  import os
8
10
  import re
@@ -11,7 +13,15 @@ import urllib.parse
11
13
  import urllib.request
12
14
  from collections.abc import Callable, Mapping, Sequence
13
15
 
14
- from examples.sdk_evolution_agent.models import ReleaseNoteEvidence, SourceRef
16
+ from packaging.version import Version
17
+
18
+ from examples.sdk_evolution_agent.models import (
19
+ ApiSnapshot,
20
+ BundledRuntimeEvidence,
21
+ BundledRuntimeRelease,
22
+ ReleaseNoteEvidence,
23
+ SourceRef,
24
+ )
15
25
 
16
26
  ReleaseNoteFetcher = Callable[[str], str]
17
27
 
@@ -88,6 +98,7 @@ def collect_release_notes(
88
98
  update_versions: Mapping[str, str],
89
99
  *,
90
100
  fetcher: ReleaseNoteFetcher | None = None,
101
+ snapshots: Sequence[ApiSnapshot] | None = None,
91
102
  ) -> tuple[ReleaseNoteEvidence, ...]:
92
103
  """Collect primary-source release-note evidence for update candidates."""
93
104
 
@@ -219,6 +230,11 @@ def collect_release_notes(
219
230
  status = "unavailable"
220
231
  unavailable_reason = "no release-note source configured"
221
232
 
233
+ bundled_runtime = None
234
+ if name == "claude-agent-sdk" and snapshots is not None:
235
+ bundled_runtime = _collect_claude_bundled_runtime(
236
+ from_version, to_version, snapshots=snapshots, fetcher=fetcher
237
+ )
222
238
  evidence.append(
223
239
  ReleaseNoteEvidence(
224
240
  package=name,
@@ -229,11 +245,188 @@ def collect_release_notes(
229
245
  summaries=tuple(_dedupe(summaries)[:8]),
230
246
  checked_urls=tuple(checked_urls),
231
247
  unavailable_reason=unavailable_reason,
248
+ bundled_runtime=bundled_runtime,
232
249
  )
233
250
  )
234
251
  return tuple(evidence)
235
252
 
236
253
 
254
+ def _collect_claude_bundled_runtime(
255
+ from_version: str | None,
256
+ to_version: str,
257
+ *,
258
+ snapshots: Sequence[ApiSnapshot],
259
+ fetcher: ReleaseNoteFetcher,
260
+ ) -> BundledRuntimeEvidence:
261
+ """Resolve CLI versions from exact SDK snapshots, then collect their releases.
262
+
263
+ The upstream SDK tag is only accepted when its version file has
264
+ the same fingerprint as the inspected distribution. A release index or tag
265
+ that cannot be reconciled is evidence of a gap, not an empty changelog.
266
+ """
267
+
268
+ sources: list[SourceRef] = []
269
+ versions: list[str] = []
270
+ try:
271
+ for sdk_version in (from_version, to_version):
272
+ if not sdk_version or not re.fullmatch(r"[0-9A-Za-z][0-9A-Za-z.+-]*", sdk_version):
273
+ raise ValueError(f"invalid or missing Claude SDK version: {sdk_version!r}")
274
+ snapshot = next(
275
+ (
276
+ item
277
+ for item in snapshots
278
+ if item.package == "claude-agent-sdk"
279
+ and item.version == sdk_version
280
+ and not item.import_error
281
+ ),
282
+ None,
283
+ )
284
+ if snapshot is None:
285
+ raise ValueError(f"missing exact SDK snapshot for {sdk_version}")
286
+ version_file = next(
287
+ (
288
+ item
289
+ for item in snapshot.implementation_files
290
+ if item.path == "claude_agent_sdk/_cli_version.py"
291
+ ),
292
+ None,
293
+ )
294
+ if version_file is None:
295
+ raise ValueError(f"missing bundled CLI version fingerprint for SDK {sdk_version}")
296
+ url = (
297
+ "https://raw.githubusercontent.com/anthropics/claude-agent-sdk-python/"
298
+ f"v{urllib.parse.quote(sdk_version, safe='')}/src/claude_agent_sdk/_cli_version.py"
299
+ )
300
+ _progress(f"checking bundled Claude CLI version from SDK {sdk_version}")
301
+ try:
302
+ content = fetcher(url)
303
+ digest = hashlib.sha256(content.encode("utf-8")).hexdigest()
304
+ if digest != version_file.sha256:
305
+ raise ValueError(
306
+ f"bundled CLI version fingerprint mismatch for SDK {sdk_version}"
307
+ )
308
+ cli_version = _claude_cli_version(content)
309
+ except Exception as exc:
310
+ sources.append(
311
+ SourceRef(
312
+ kind="sdk-runtime-version",
313
+ label="Claude SDK bundled CLI version",
314
+ url=url,
315
+ version=sdk_version,
316
+ available=False,
317
+ note=str(exc),
318
+ )
319
+ )
320
+ raise
321
+ sources.append(
322
+ SourceRef(
323
+ kind="sdk-runtime-version",
324
+ label="Claude SDK bundled CLI version",
325
+ url=url,
326
+ version=sdk_version,
327
+ note="Source fingerprint matches the inspected SDK distribution.",
328
+ )
329
+ )
330
+ versions.append(cli_version)
331
+
332
+ baseline, candidate = (Version(value) for value in versions)
333
+ if candidate < baseline:
334
+ raise ValueError("candidate bundled CLI version is older than the baseline")
335
+ if candidate == baseline:
336
+ return BundledRuntimeEvidence(
337
+ "claude-code", versions[0], versions[1], "not-needed", tuple(sources)
338
+ )
339
+
340
+ releases: dict[Version, BundledRuntimeRelease] = {}
341
+ covered_baseline = False
342
+ for page in range(1, 6):
343
+ url = (
344
+ "https://api.github.com/repos/anthropics/claude-code/releases"
345
+ f"?per_page=100&page={page}"
346
+ )
347
+ _progress(f"checking bundled Claude CLI release notes, page {page}")
348
+ try:
349
+ rows = json.loads(fetcher(url))
350
+ if not isinstance(rows, list):
351
+ raise ValueError("release index is not a list")
352
+ except Exception as exc:
353
+ sources.append(
354
+ SourceRef(
355
+ kind="release-index",
356
+ label="Claude Code releases",
357
+ url=url,
358
+ available=False,
359
+ note=str(exc),
360
+ )
361
+ )
362
+ raise
363
+ sources.append(SourceRef(kind="release-index", label="Claude Code releases", url=url))
364
+ for row in rows:
365
+ if not isinstance(row, Mapping):
366
+ raise ValueError("release index contains a malformed entry")
367
+ if row.get("draft") or row.get("prerelease"):
368
+ continue
369
+ tag = str(row.get("tag_name") or "")
370
+ if not re.fullmatch(r"v?\d+\.\d+\.\d+", tag):
371
+ continue
372
+ release_version = Version(tag.lstrip("v"))
373
+ if release_version <= baseline:
374
+ covered_baseline = True
375
+ if baseline < release_version <= candidate:
376
+ release_url = f"https://github.com/anthropics/claude-code/releases/tag/{tag}"
377
+ release = BundledRuntimeRelease(
378
+ version=str(release_version),
379
+ url=release_url,
380
+ notes=str(row.get("body") or "").strip(),
381
+ )
382
+ if release_version in releases and releases[release_version] != release:
383
+ raise ValueError(f"contradictory CLI releases for {release_version}")
384
+ releases[release_version] = release
385
+ if covered_baseline or len(rows) < 100:
386
+ covered_baseline = True
387
+ break
388
+
389
+ missing = [str(version) for version, release in releases.items() if not release.notes]
390
+ problems = []
391
+ if not covered_baseline:
392
+ problems.append("release-index pagination did not reach the baseline")
393
+ if candidate not in releases:
394
+ problems.append(f"candidate CLI release {candidate} not found")
395
+ if missing:
396
+ problems.append("release notes missing for " + ", ".join(sorted(missing)))
397
+ return BundledRuntimeEvidence(
398
+ name="claude-code",
399
+ from_version=versions[0],
400
+ to_version=versions[1],
401
+ status="incomplete" if problems else "found",
402
+ sources=tuple(sources),
403
+ releases=tuple(releases[key] for key in sorted(releases)),
404
+ unavailable_reason="; ".join(problems),
405
+ )
406
+ except Exception as exc:
407
+ return BundledRuntimeEvidence(
408
+ name="claude-code",
409
+ from_version=versions[0] if versions else None,
410
+ to_version=versions[1] if len(versions) > 1 else None,
411
+ status="unavailable",
412
+ sources=tuple(sources),
413
+ unavailable_reason=str(exc),
414
+ )
415
+
416
+
417
+ def _claude_cli_version(content: str) -> str:
418
+ tree = ast.parse(content)
419
+ for node in tree.body:
420
+ if isinstance(node, ast.Assign) and any(
421
+ isinstance(target, ast.Name) and target.id == "__cli_version__"
422
+ for target in node.targets
423
+ ):
424
+ value = ast.literal_eval(node.value)
425
+ if isinstance(value, str) and re.fullmatch(r"\d+\.\d+\.\d+", value):
426
+ return value
427
+ raise ValueError("SDK bundled CLI version is missing or unsupported")
428
+
429
+
237
430
  def fetch_url_text(url: str) -> str:
238
431
  """Fetch a release-note source as text."""
239
432
 
@@ -154,6 +154,19 @@ def render_markdown_report(
154
154
  for item in release_notes
155
155
  if isinstance(item, dict) and item.get("to_version")
156
156
  ]
157
+ for item in release_notes:
158
+ if not isinstance(item, dict):
159
+ continue
160
+ bundled = item.get("bundled_runtime")
161
+ if isinstance(bundled, dict):
162
+ release_lines.append(
163
+ "- {name} (bundled): {status} ({from_version} -> {to_version})".format(
164
+ name=bundled.get("name"),
165
+ status=bundled.get("status"),
166
+ from_version=bundled.get("from_version"),
167
+ to_version=bundled.get("to_version"),
168
+ )
169
+ )
157
170
  behavior_summary = assess_behavior_payload(
158
171
  behavior,
159
172
  expectations=behavior_expectations_from_evidence(evidence),
@@ -584,6 +584,25 @@ def _definition_fingerprints(
584
584
  )
585
585
  )
586
586
  visit(child, (*parents, child.name))
587
+ elif (
588
+ not parents
589
+ and isinstance(child, (ast.Assign, ast.AnnAssign))
590
+ and isinstance(child.value, (ast.Name, ast.Attribute))
591
+ ):
592
+ targets = child.targets if isinstance(child, ast.Assign) else [child.target]
593
+ fingerprint = hashlib.sha256(
594
+ ast.dump(child, include_attributes=False).encode("utf-8")
595
+ ).hexdigest()
596
+ for target in targets:
597
+ if isinstance(target, ast.Name) and target.id[:1].isupper():
598
+ definitions.append(
599
+ ImplementationDefinition(
600
+ name=f"{path}:{target.id}",
601
+ kind="alias",
602
+ path=path,
603
+ sha256=fingerprint,
604
+ )
605
+ )
587
606
  else:
588
607
  visit(child, parents)
589
608
 
@@ -657,6 +676,23 @@ _SNAPSHOT_SCRIPT = textwrap.dedent(
657
676
  "sha256": fingerprint,
658
677
  })
659
678
  visit(child, (*parents, child.name))
679
+ elif (
680
+ not parents
681
+ and isinstance(child, (ast.Assign, ast.AnnAssign))
682
+ and isinstance(child.value, (ast.Name, ast.Attribute))
683
+ ):
684
+ targets = child.targets if isinstance(child, ast.Assign) else [child.target]
685
+ fingerprint = hashlib.sha256(
686
+ ast.dump(child, include_attributes=False).encode("utf-8")
687
+ ).hexdigest()
688
+ for target in targets:
689
+ if isinstance(target, ast.Name) and target.id[:1].isupper():
690
+ definitions.append({
691
+ "name": f"{path}:{target.id}",
692
+ "kind": "alias",
693
+ "path": path,
694
+ "sha256": fingerprint,
695
+ })
660
696
  else:
661
697
  visit(child, parents)
662
698
 
@@ -567,6 +567,35 @@ def with_release_note_guard(
567
567
  for item in release_notes
568
568
  if item.get("to_version") and item.get("status") == "unavailable"
569
569
  ]
570
+ for item in release_notes:
571
+ runtime = item.get("bundled_runtime")
572
+ if item.get("package") != "claude-agent-sdk" or not item.get("to_version"):
573
+ continue
574
+ if not isinstance(runtime, Mapping) or runtime.get("status") not in {
575
+ "found",
576
+ "not-needed",
577
+ }:
578
+ failed.append("claude-agent-sdk bundled claude-code")
579
+ elif runtime.get("status") == "not-needed" and (
580
+ not runtime.get("from_version")
581
+ or runtime.get("from_version") != runtime.get("to_version")
582
+ ):
583
+ failed.append("claude-agent-sdk bundled claude-code")
584
+ elif runtime.get("status") == "found":
585
+ releases = runtime.get("releases")
586
+ if (
587
+ not runtime.get("from_version")
588
+ or not runtime.get("to_version")
589
+ or not isinstance(releases, list)
590
+ or not any(
591
+ isinstance(release, Mapping)
592
+ and release.get("version") == runtime.get("to_version")
593
+ and isinstance(release.get("notes"), str)
594
+ and bool(release["notes"].strip())
595
+ for release in releases
596
+ )
597
+ ):
598
+ failed.append("claude-agent-sdk bundled claude-code")
570
599
  if not failed:
571
600
  return dict(architecture)
572
601
  result = dict(architecture)
@@ -970,6 +999,8 @@ def _stage_system_prompt(stage: str, schema: JsonSchema) -> str:
970
999
  "evidence, remains a hard blocker. Release-note status found "
971
1000
  "is direct release-note evidence. Status no-matching-version is source "
972
1001
  "coverage with explicit uncertainty, not unavailable evidence."
1002
+ " Bundled runtime release notes are separate from SDK release notes; "
1003
+ "unavailable or incomplete bundled-runtime evidence is a hard blocker."
973
1004
  )
974
1005
  if stage == "review":
975
1006
  prompt += " The review status must be exactly pass or reject."
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agent-runtime-kit"
7
- version = "0.5.4"
7
+ version = "0.5.6"
8
8
  description = "One typed runtime API for Claude, Codex, and Antigravity agent SDKs."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -48,12 +48,12 @@ dependencies = ["jsonschema>=4.18,<5", "tomli>=2,<3; python_version < '3.11'"]
48
48
  claude = ["claude-agent-sdk>=0.2.87,<0.3"]
49
49
  # 0.157.1 is the minimum SDK and CLI pair for native named profiles. Earlier
50
50
  # bundled CLIs do not enforce every profile rule needed by restricted runtimes.
51
- codex = ["openai-codex>=0.157.1,<0.164"]
51
+ codex = ["openai-codex>=0.157.1,<0.168"]
52
52
  antigravity = ["google-antigravity>=0.1.2,<0.2"]
53
53
  all = [
54
54
  "claude-agent-sdk>=0.2.87,<0.3",
55
55
  "google-antigravity>=0.1.2,<0.2",
56
- "openai-codex>=0.157.1,<0.164",
56
+ "openai-codex>=0.157.1,<0.168",
57
57
  ]
58
58
 
59
59
  [project.urls]
@@ -66,17 +66,17 @@ COMPATIBILITY_MANIFEST: tuple[RuntimeCompatibility, ...] = (
66
66
  package="claude-agent-sdk",
67
67
  module="claude_agent_sdk",
68
68
  version_specifier=">=0.2.87,<0.3",
69
- tested_version="0.2.168",
69
+ tested_version="0.2.179",
70
70
  ),
71
71
  RuntimeCompatibility(
72
72
  kind=AgentRuntimeKind.CODEX_AGENT_SDK,
73
73
  extra="codex",
74
74
  package="openai-codex",
75
75
  module="openai_codex",
76
- version_specifier=">=0.157.1,<0.164",
77
- tested_version="0.163.0",
76
+ version_specifier=">=0.157.1,<0.168",
77
+ tested_version="0.167.0",
78
78
  tested_runtime_dependencies=(
79
- PackageVersion(package="openai-codex-cli-bin", version="0.163.0"),
79
+ PackageVersion(package="openai-codex-cli-bin", version="0.167.0"),
80
80
  ),
81
81
  ),
82
82
  RuntimeCompatibility(
@@ -85,7 +85,7 @@ COMPATIBILITY_MANIFEST: tuple[RuntimeCompatibility, ...] = (
85
85
  package="google-antigravity",
86
86
  module="google.antigravity",
87
87
  version_specifier=">=0.1.2,<0.2",
88
- tested_version="0.1.22",
88
+ tested_version="0.1.23",
89
89
  ),
90
90
  )
91
91