From 358e1ee1e4e561a77c816142736e692ac8ab6011 Mon Sep 17 00:00:00 2001 From: lidge-jun Date: Tue, 8 Sep 2026 19:36:57 +0900 Subject: [PATCH] docs(devlog): archive the 2.48.0 release train record --- devlog/_fin/260908_release_248/000_plan.md | 31 +++++++++++++++ devlog/_fin/260908_release_248/010_release.md | 16 ++++++++ .../_fin/260908_release_248/020_progress.md | 14 +++++++ .../030_wp2_regression_review.md | 39 +++++++++++++++++++ .../260908_release_248/040_wp3_promotion.md | 35 +++++++++++++++++ .../260908_release_248/050_wp4_publication.md | 35 +++++++++++++++++ 6 files changed, 170 insertions(+) create mode 100644 devlog/_fin/260908_release_248/000_plan.md create mode 100644 devlog/_fin/260908_release_248/010_release.md create mode 100644 devlog/_fin/260908_release_248/020_progress.md create mode 100644 devlog/_fin/260908_release_248/030_wp2_regression_review.md create mode 100644 devlog/_fin/260908_release_248/040_wp3_promotion.md create mode 100644 devlog/_fin/260908_release_248/050_wp4_publication.md diff --git a/devlog/_fin/260908_release_248/000_plan.md b/devlog/_fin/260908_release_248/000_plan.md new file mode 100644 index 0000000000..221302a72d --- /dev/null +++ b/devlog/_fin/260908_release_248/000_plan.md @@ -0,0 +1,31 @@ +# Release 2.48.0 plan + +Owner-authorized HOTL release train for OpenCodex 2.48.0. The owner asked for a regression check of `dev` against `main`, two promotion pull requests, merges into `main` and `preview`, and npm publication. The owner also forbade running the local test suite and required `--no-verify` for any push, so every verification claim in this unit rests on hosted CI at an exact SHA. Local typecheck, local `bun run test`, and local privacy scan are NOT RUN by instruction and are labeled that way wherever they would otherwise appear as evidence. + +## Candidate + +Release candidate: `7797586a8899c673eab48886a490e85b480c6d72` (`origin/dev` tip, 2.48.0 in package.json). + +Published baseline: `@bitkyc08/opencodex` `latest=2.47.0`, `preview=2.47.0-preview.20260908`. `origin/main` is `f7f890ff7` at 2.47.0; `origin/preview` is `3bef20677` at 2.47.0-preview.20260908. `dev` is 70 commits ahead of each. + +The candidate tip itself has no Cross-platform CI run because its only delta against `9ad218a9bdd34ee33004c35706d78396bf02eef2` is under `devlog/`, which the workflow's push path filter excludes. `git diff --name-only 9ad218a9b 7797586a8 -- . ':(exclude)devlog'` returns zero files, so `9ad218a9b` is the runtime-identical CI witness for the candidate: 19 successful check-runs, two deliberately skipped (`macos control`, the Windows shard placeholder). That equivalence is stated explicitly rather than assumed, because the promotion merge SHAs will carry their own push-event CI regardless. + +## Scope + +In scope: version metadata on the two promotion branches, promotion PRs into `preview` and `main`, merges, `release.yml` dispatch for preview and stable, and registry/tag verification. Also in scope: a PABCD repair cycle merged into `dev` if regression evidence shows a defect, followed by a repeat of the release verification. + +Out of scope: unrelated open PRs and issues, dev-version bumping beyond what the release requires, installed-service upgrades, account settings, and any change to branch protection or CI gates. + +## Work phases + +- wp1 — this roadmap. Pin the candidate, record the CI-equivalence argument and the promotion procedure. No product change. +- wp2 — regression verification of the candidate against `main` using hosted evidence only. +- wp3 — promotion branches and PRs, merged with exact-head CI. +- wp4 — npm preview and stable publication with registry verification. + +## Verification and outcomes + +Each promotion SHA needs its own successful push-event Cross-platform CI and Service lifecycle before any publish dispatch. Publication proof is npm dist-tags, the published `gitHead`, tarball integrity, provenance, and the GitHub tag and release. `enforce-target` is expected to reject both promotion PRs because its allowed bases contain only `dev`; that is the established authorized promotion exception and is reported as failing, never as passing. + +DONE requires both channels published and verified with `dev` still ahead. BLOCKED is a concrete external prerequisite or a failed gate with no safe remedy. A failing gate is repaired or remains a blocker; it is never weakened, and no check is disabled to hide it. + diff --git a/devlog/_fin/260908_release_248/010_release.md b/devlog/_fin/260908_release_248/010_release.md new file mode 100644 index 0000000000..9e1875d65f --- /dev/null +++ b/devlog/_fin/260908_release_248/010_release.md @@ -0,0 +1,16 @@ +# Release operation + +1. Pin candidate `7797586a8899c673eab48886a490e85b480c6d72` and record its CI witness `9ad218a9bdd34ee33004c35706d78396bf02eef2` (runtime-identical; devlog-only delta). Confirm published baseline tags and that `v2.48.0` and `v2.48.0-preview.*` are unused. + +2. Regression review of `origin/main..origin/dev`: 70 commits, 162 changed files, 25 under `src/`. Read the delta for release-blocking risk in routing, auth, credentials, release automation, and workflows. Hosted CI on the witness SHA is the mechanical evidence; the local suite is NOT RUN by owner instruction. + +3. Create two independent promotion branches from `origin/preview` and `origin/main`, merge the frozen candidate into each, resolve only the channel version conflict, and set `package.json` to `2.48.0-preview.20260908` on the preview branch and `2.48.0` on the main branch. The runtime tree on each branch must equal the candidate exactly apart from that one version line; prove it with `git diff` restricted to non-version paths. + +4. Push both branches with `--no-verify` (owner instruction), open template-complete PRs, and wait for each merge SHA's own push-event Cross-platform CI and Service lifecycle. `enforce-target` will fail on both by design; record it as the authorized promotion exception. + +5. Dispatch `release.yml` with `expected-sha` equal to the branch tip: dry-run first, then preview, then stable, serialized. Verify `npm view @bitkyc08/opencodex dist-tags`, published `gitHead`, tarball SHA-512, provenance, and the GitHub tag and release. Run a published-package smoke in an isolated home. + +6. Record the outcome in `090_delivery.md`, confirm `dev` remains ahead of both channels, and leave unrelated dirty files in the primary checkout untouched. + +Activation scenarios: a moved branch means refuse the dispatch and repin; a failed CI job means inspect and repair rather than rerun blindly; a post-publish smoke failure means inspect registry metadata before any retry, and never republish blindly. Rollback artifact `v2.47.0` stays published; no destructive rollback is planned. + diff --git a/devlog/_fin/260908_release_248/020_progress.md b/devlog/_fin/260908_release_248/020_progress.md new file mode 100644 index 0000000000..64ac908fa9 --- /dev/null +++ b/devlog/_fin/260908_release_248/020_progress.md @@ -0,0 +1,14 @@ +# Progress + +## wp1 — roadmap (this cycle) + +Candidate pinned at `7797586a8899c673eab48886a490e85b480c6d72`. CI witness `9ad218a9bdd34ee33004c35706d78396bf02eef2`: 19 successful check-runs, 2 deliberate skips. The delta between them is devlog-only, so the witness covers the candidate's runtime tree exactly. + +Roadmap committed as `38edcbf7c` on `codex/release-248-plan` in the dedicated worktree `/private/tmp/ocx-release-248`. The primary checkout keeps its pre-existing unrelated dirty files untouched. + +Local suite, typecheck, and privacy scan: NOT RUN by owner instruction. + +## wp2 — regression verification (next) + +Delta to review: 70 commits, 162 files, 25 under `src/`, ~2096 changed source lines against `origin/main`. + diff --git a/devlog/_fin/260908_release_248/030_wp2_regression_review.md b/devlog/_fin/260908_release_248/030_wp2_regression_review.md new file mode 100644 index 0000000000..3e2e50712f --- /dev/null +++ b/devlog/_fin/260908_release_248/030_wp2_regression_review.md @@ -0,0 +1,39 @@ +# wp2 — regression review of the candidate against main + +Reviewed `origin/main..origin/dev`: 70 commits, 162 files, 25 under `src/`, about 2096 changed source lines. The question this phase answers is narrow — does anything in that delta regress behavior that `main` currently ships? The local suite is NOT RUN by owner instruction, so the mechanical evidence is hosted CI and the argument below is a source read. + +## What changed, by risk + +Credential and quota handling carries the most weight. `src/codex/routing.ts` factors the background recovery settle path into `settleCooldownRecoveryLease` and adds a manual-reset claim/settle pair. The refactor moves `cooldownSource === "reset-derived"` and the scope restriction into the shared settle helper, which reads at first glance like a new restriction on the pre-existing background path. It is not: `claimDueCodexQuotaRecoveryProbes` already filters candidates to `(scope === undefined || scope === "shared")` with `cooldownSource === "reset-derived"`, so no claim that could previously settle successfully can reach the helper and fail those conditions. `tests/codex-integration/codex-cooldown-recovery.test.ts` and `codex-reset-credit-auto-redeem.test.ts` cover both paths. + +`src/codex/auth-api.ts` adds a `dispatchSequence` fence around WHAM usage publication so a slow in-flight response cannot overwrite a newer published quota. The added early returns hand back the cached account info rather than publishing, which is a strict narrowing of when stale data wins. + +`src/server/responses/core.ts` adds combo session recall for compaction triggers and a completion callback gate. The recall path is guarded on a bare model name, an actual `compaction_trigger` input item, no configured selector, and no resolvable combo id, so a request that previously routed by explicit selector still does. The previous-response error code changed from `invalid_request_error` to `previous_response_not_found`; that is a deliberate behavior change so Codex reconnects with full input instead of terminating the task, and it is the fix's whole point. + +`src/router.ts` and `src/providers/default-aliases.ts` extend alias-ownership so a provider's own configured name also claims an alias, not just an explicit `alias` field. This makes an ambiguous alias resolve to nothing rather than to the wrong provider — a correctness fix with a narrow blast radius. + +`src/config/atomic-write.ts` replaces `constants.O_WRONLY | O_CREAT | O_EXCL` with the `"wx"` flag string, which is the same semantics expressed portably; that was the point of the change on Windows. + +## Coverage + +Forty test files changed alongside the 25 source files, and every source area above has a focused test in the same domain directory. No source change in the delta arrived without paired coverage. + +## Hosted evidence + +Push-event run on `9ad218a9bdd34ee33004c35706d78396bf02eef2` (runtime-identical to the candidate): 19 successful check-runs, 2 skipped by design. + +Dispatched full-lane run [34206043085](https://github.com/lidge-jun/opencodex/actions/runs/34206043085) on the exact candidate `7797586a8899c673eab48886a490e85b480c6d72` with `lane=all`, which adds the six Windows shards and the unsharded macOS control that the push event does not run. + +## Verdict + +No regression identified against `main`. The delta is corrective, each risky path narrows rather than widens behavior, and the one intentional behavior change (the previous-response error code) is the documented fix. + + +## Full-lane CI outcome + +Run [34206043085](https://github.com/lidge-jun/opencodex/actions/runs/34206043085) on the exact candidate `7797586a8899c673eab48886a490e85b480c6d72` completed **success** after one rerun of a single job. + +The first attempt failed on `windows 3/6`: `provider outbound GET transport > proxy mode reaches one real proxy across outbound, connection-test, and model-discovery paths` timed out at its own 15s bound, and the spawned fixture child was killed (exit 143). That test file is not in the release delta — `git log origin/main..origin/dev -- tests/providers/provider-outbound.test.ts` is empty — and the same content passed `windows 3/6` in dispatch run 34198186409 ninety minutes earlier. Rerunning the failed job passed. The evidence points at cold-runner timing on a 15s child-spawn budget, not at anything the candidate changed. + +That timeout is a real fragility worth tightening later, but it is not a 2.48.0 regression and does not block this promotion. + diff --git a/devlog/_fin/260908_release_248/040_wp3_promotion.md b/devlog/_fin/260908_release_248/040_wp3_promotion.md new file mode 100644 index 0000000000..5ba9997eaf --- /dev/null +++ b/devlog/_fin/260908_release_248/040_wp3_promotion.md @@ -0,0 +1,35 @@ +# wp3 — promotion pull requests and merges + +Both promotions are on their channels. + +| Channel | PR | Merge SHA | Version | +|---|---|---|---| +| `preview` | [#4010](https://github.com/lidge-jun/opencodex/pull/4010) | `c71474e83c92be1f39e9d8c1fe0743307ce93387` | 2.48.0-preview.20260908 | +| `main` | [#4011](https://github.com/lidge-jun/opencodex/pull/4011) | `9a27e86992d7a014e0aa92c046199b9fac148201` | 2.48.0 | + +Candidate `7797586a8899c673eab48886a490e85b480c6d72` is an ancestor of both branches, verified with `git merge-base --is-ancestor` against freshly fetched refs. `git diff 7797586a8 origin/main` is empty: the main tree is byte-identical to the candidate, since the candidate already carried 2.48.0. The preview tree differs only in the channel version line. + +## Gate outcomes + +`enforce-target` failed on both, as expected and as documented in the PR bodies. Its allowed bases contain only `dev` and its one coded exception is a stacked child, so a release promotion cannot pass it. Both PRs were opened as drafts by that gate and were marked ready before the authorized admin merge. The failure is recorded as a failure; no check, protection, or target was altered. + +Every other check passed on both heads. + +## Flakes encountered, and why they are flakes + +`macos 1/2` on #4011 hung twice inside `tests/clients/client-connect.test.ts` after "connect transaction and offline disconnect > an unavailable config coordinator refuses before issuing any hub key", producing "killed 1 dangling process" and then a 20-minute job timeout. The same tree passed `macos 1/2` in candidate run 34206043085 and on #4010, and passed on the third attempt. Combined with the earlier `windows 3/6` timeout, both failures were child-process lifecycle timing on cold runners, in files outside the release delta. + +## Post-merge gates + +Preview `c71474e83`: Cross-platform CI success, Service lifecycle success. + +Main `9a27e8699`: Service lifecycle success, React Doctor success, Docs deploy success; Cross-platform CI observed in progress at the time of writing and must be green before the stable publish. + + +## Merge verification commands + +``` +git merge-base --is-ancestor 7797586a8 origin/preview # YES +git merge-base --is-ancestor 7797586a8 origin/main # YES +git diff --stat 7797586a8 origin/main # empty +``` diff --git a/devlog/_fin/260908_release_248/050_wp4_publication.md b/devlog/_fin/260908_release_248/050_wp4_publication.md new file mode 100644 index 0000000000..672c8e0b45 --- /dev/null +++ b/devlog/_fin/260908_release_248/050_wp4_publication.md @@ -0,0 +1,35 @@ +# wp4 — publication + +Both channels are published and verified. + +| Channel | Version | Source SHA | npm gitHead | +|---|---|---|---| +| `preview` | 2.48.0-preview.20260908 | `c71474e83c92be1f39e9d8c1fe0743307ce93387` | matches | +| `latest` | 2.48.0 | `9a27e86992d7a014e0aa92c046199b9fac148201` | matches | + +`npm view @bitkyc08/opencodex dist-tags` reports `{"latest":"2.48.0","preview":"2.48.0-preview.20260908"}`. GitHub releases `v2.48.0` and `v2.48.0-preview.20260908` exist at exactly those commits. Both publishes carry a signed provenance statement from GitHub Actions. + +Tarball integrity was checked independently: downloading `bitkyc08-opencodex-2.48.0.tgz` from the registry and hashing it locally yields `sha512-f2GmrBpUJYZ+bOT62VL1MWhNwIBkFz5JUVGrNPG+SAaWJheshmMsnHDoMyRIpyd5v50sK9uI0Ll4XZwI4PVjhA==`, identical to the `dist.integrity` npm reports and to the `integrity:` line in the publish log. The unpacked package declares version 2.48.0 and its `bin/ocx.mjs` launcher runs and correctly reports the Bun runtime requirement in an isolated `OPENCODEX_HOME`. + +## The dev-version gate + +The first stable dispatch failed at "Require dev to be ready for this release": `origin/dev` still carried 2.48.0, which does not outrank the version being released. That gate exists so `tests/ci-workflows/release-version-line.test.ts` does not go red on `dev` and on every pull request against it the moment a release ships. + +The repair was [#4019](https://github.com/lidge-jun/opencodex/pull/4019), a one-line `package.json` change moving `dev` to 2.49.0, with the version decided by `scripts/bump-dev-version.ts` rather than chosen by hand. It merged as `0372c43e663b25387a0a00b03b6a9ca9d4bf9048` with full CI green, after which the stable dispatch succeeded on the unchanged `main` SHA. + +## Registry propagation + +Both publishes reported "Your package is being processed" and the workflow's bounded six-attempt registry smoke ended `verification=pending` in each case. Neither was republished. Preview appeared in the registry roughly twelve minutes after acceptance, stable roughly seven; both were then verified by direct registry reads and by the independent tarball hash above. + +## Final branch state + +`dev` 2.49.0, `main` 2.48.0, `preview` 2.48.0-preview.20260908. `dev` remains ahead of both release channels. + + +## Verification commands + +``` +npm view @bitkyc08/opencodex dist-tags --json +npm view @bitkyc08/opencodex@2.48.0 dist.integrity dist.tarball --json +gh release view v2.48.0 --json tagName,targetCommitish +```