Repository navigation
fix(converter): hold parity with harbor 0.24.0's converters - #41
Merged
Merged
Conversation
harbor 0.24.0 (PyPI upload 2026-10-05T05:04:46Z) changes both converters atif-sql holds parity with: #3434 keeps Claude subagent ids on every ATIF step, #3467 records Codex structured tool outputs as text and images, and #2972 gives Codex web search calls an id. The ATIF models, the validator and RFC 0001 are byte-identical to 0.23.0. The workspace's seven-day cooldown admits 0.24.0 only from 2026-10-12T05:05Z, so harbor alone gets an exclude-newer-package exemption up to 2026-10-05T05:05:00Z, the instant its upload needs; the global window stays seven days. Delete the exemption in the next `uv lock --upgrade` after 2026-10-12, when the window reaches the release. `uv lock --upgrade-package harbor` moves harbor alone and adds semver 3.1.0, a new harbor dependency uploaded 2026-09-12; every other package stays where main locks it. uv 0.12.23 writes lockfile revision 5 on any re-resolution. The parity decisions for the three converter changes follow in the next commit; on this commit alone the oracle tests report them as failures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
harbor 0.24.0 changes three things the converters port. Each is decided here against the upstream diff. - harbor #3434 (6a410975), adopted: every step a Claude Code event becomes, its prompt, tool result and turn alike, carries `is_sidechain` and the event's `agentId` as `extra.agent_id`, right after `id`, through `_event_identity_extra`. harbor now reads `agentId`, so the oracle's one deliberate divergence (`steps[i].extra.agent_id` only in ours) is gone, and a snake_case `agent_id` key names no subagent, as in harbor. - harbor #3467 (d286d15d), adopted with one divergence: a Codex tool output that is a list of MCP content blocks or content items becomes its text parts joined by newlines rather than Python's str() of the list (5,124 such outputs in the 144 local rollouts); a non-string `output` is its JSON text; a JSON scalar keeps its raw text. An inline image, which harbor saves under `<logs_dir>/images/` and returns as content parts, is the blob placeholder the pre-pass writes for the same item, because the converter is pure and the corpus keeps attachments in its blob store. The oracle forgives exactly that content path, only when each placeholder names the bytes harbor saved (`_image_content_forgiven`). - harbor #2972 (7e042f6e), adopted: a Codex `web_search_call` keeps its item id, or gets `<api call>_web_search_<n>`, where its id was empty. `trial/sync_trajectory.py` (#3467) copies media for streamed trials and 536f533a (`CODEX_HOME` out of tmp, after 0.24.0) sets up the runtime home; neither touches a conversion. The vendored ATIF models, validator and RFC are byte-identical to 0.24.0's, so only their headers and `UPSTREAM_VERSION` move, which `meta.json` stamps as `harbor_version`. CONVERTER_SCHEMA_VERSION 7 re-converts the corpus for all of it; the digest is re-pinned. The goldens do not change: the synthetic fixtures exercise none of the three shapes, and the live oracle still matches them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Move the harbor oracle to 0.24.0 and hold parity with its converter changes
Branch
factory/2-harbor-0-24, two commits onorigin/main5d4efa3:36712c2 chore(deps): move the harbor oracle to 0.24.0 with a cooldown exemption793087b fix(converter): hold parity with harbor 0.24.0's convertersharbor 0.24.0 (PyPI upload 2026-10-05T05:04:46Z) leaves the ATIF models, the validator and RFC 0001 byte-identical to 0.23.0 (ATIF-v1.8 both sides) and changes the converters atif-sql ports. The lock bump surfaced three converter changes, one more than the plan named: harbor #2972 landed on 2026-09-12 after 0.23.0 was cut.
Parity decisions, one per upstream change
_event_identity_extraputsis_sidechainand the event'sagentIdon every step it becomes (prompt, tool result, turn), right afterid, harbor's key order. harbor readsagentIdnow, so the oracle's one deliberate divergence (steps[i].extra.agent_id: only in ours) is removed fromDELIBERATE_DIVERGENCES, and a snake_caseagent_idkey names no subagent, as in harbor.test_claude_code_conversion.py::TestSidechains::test_every_step_of_a_subagent_names_it(harbor's own #3434 test, two concurrent subagents),::test_snake_case_agent_id_is_not_an_identity,test_result_signals.py::TestSubagentAgentId::test_harbor_names_every_sidechain_step_the_same(replaces the test that required the divergence)str()of the list ("[{'type': 'input_text', ...}]"), 5,124 such outputs in the 144 local rollouts. After: text parts joined by\n, other blocks as JSON text, a non-stringoutputas JSON text, a JSON scalar as its raw text, remote and unreadable images as harbor's own[image: url]/[image omitted]. Divergence: an inline image harbor saves to<logs_dir>/images/codex_<sha16>.<ext>and returns as content parts becomes the blob placeholder the pre-pass writes for the same item, because the converter is pure and the corpus keeps attachments in its blob store. The oracle forgives only that content path, only when each placeholder's SHA-256 starts with harbor's file name digest, the media type matches, and every text part matches (harbor_oracle._image_content_forgiven).test_codex_conversion_port.py::TestStructuredToolOutput(13 cases, live cross-checked except the two inline-image ones),::test_harbor_differs_only_by_the_saved_image(exactly one diff path, forgiven, and a tampered digest is not),::test_an_inline_image_is_the_pre_pass_placeholder(raw and production paths give identical trajectories), 4 newtest_function_call_output_blob_shapesrowsweb_search_callkeeps its itemid, or gets<api call>_web_search_<n>, where its id was"".test_codex_conversion_port.py::TestToolCallShapes::test_web_search_call_gets_a_request_scoped_id_and_null_observation,::test_web_search_call_keeps_codexs_own_item_idtrial/sync_trajectory.py(#3467) and 536f533a (CODEX_HOMEout of tmp, main after 0.24.0)Cooldown
[tool.uv]getsexclude-newer-package = { harbor = "2026-10-05T05:05:00Z" }, the key shape in uv's settings reference (docs.astral.sh/uv/reference/settings, read 2026-10-08) for the mise-pinned uv 0.12.23; the globalexclude-newer = "7 days"is unchanged. The comment says to delete the exemption in the nextuv lock --upgradeafter 2026-10-12T05:05Z. Semgrepuv-missing-dependency-cooldown(rule fetched from semgrep/semgrep-rules develop) reports nothing on the branch'spyproject.tomland flags line 109 on a plantedexclude-newer = "3 days".Lock
uv lock --upgrade-package harbor: harbor 0.23.0 -> 0.24.0 and one added package, semver 3.1.0 (a new harbor 0.24.0 dependency, uploaded 2026-09-12, dev-only through harbor). No other package changes version. uv 0.12.23 writesrevision = 5(was 3) on any re-resolution, a backward-compatible lockfile revision.Converter version
CONVERTER_SCHEMA_VERSION6 -> 7 with a history line:UPSTREAM_VERSIONmoves to 0.24.0 (stamped asmeta.jsonharbor_version), and all three adoptions change artifact bytes. Digest re-pinned intest_converter_schema_version.py. The next materialize re-converts the whole corpus. The vendored files change only their header line (Vendored from harbor 0.24.0). Goldens are not re-frozen: the synthetic fixtures exercise none of the three shapes, andtest_goldensshows the 0.24.0 live oracle still matches them.Gates
test_harbor_oracle.pytest_parity_codex.pytest_parity_claude_code.pytest_parity_live.py(25 + 25 newest sessions)test_vendored_atif.pyATIF_PARITY_LIMIT=0)~/.claude/projectssessionsmise run checkmise run lock:checkmise run docs:install && mise run docs:gate(docs/CONTRACT.md changed)With harbor 0.24.0 and no converter change (commit 36712c2 alone), 5 tests fail: the web search port test, both live parity tests (22 of 25 Claude sessions on
extra.agent_id, 18 of 25 Codex rollouts on list content), the result-signals divergence test and the upstream version check. So 36712c2 is red on its own and 793087b is green; rebase-merging lands one red commit on main, squash-merging does not.Risks
tool_results.contentsee plain text instead of a Python repr). A query that matched the repr's'type': 'input_text'breaks.imageblock with inline data that reached production (none in the local corpus) becomes a placeholder whose bytes the blob store does not hold, becauseextract_codex_blobsliftsinput_imagedata URLs only.docs/insights,docs/architectureanddocs/diagramsstill name harbor 0.23.0 in passing; AGENTS.md, CONTRIBUTING.md, the converter README,docs/CONTRACT.mdand the package comments name 0.24.0.What to look at
packages/atif-converter/tests/harbor_oracle.py:_image_content_matchesis the only new forgiveness; check it cannot pass a changed text part.packages/atif-converter/src/atif_converter/domain/codex_conversion.py_parse_output_blobthrough_image_media_typeagainst harbor 0.24.0codex.pylines 611-766.exclude-newer-packageline in the firstuv lock --upgradeafter 2026-10-12.Lead review (2026-10-08)
uv.lockmoves harbor and adds semver 3.1.0 alone.mise run install:ciandmise run checkin a fresh worktree at793087b: green, 2396 passed, 1 skipped in 256 s, pyright 0 errors._image_content_matchesdirectly: a matching placeholder is forgiven; a changed text part, a wrong media type and a wrong SHA-256 are not.~/.codex/sessionscarries an MCPimageblock with inline data, so the dangling-placeholder risk above has no case today; a follow-up can lift those blocks inextract_codex_blobs.36712c2alone is red, so a rebase merge would land a red commit on main.🤖 Generated with Claude Code