Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
296 commits
Select commit Hold shift + click to select a range
82dbb1a
fix(codex): adopt pre-substrate homes into coordinator (#2612)
lidge-jun Aug 25, 2026
aacd652
fix(config): persist top-level deletion provenance (#2613)
lidge-jun Aug 25, 2026
4adfd23
fix: repair three regressions from the #2463/#1478 landings (#2614)
lidge-jun Aug 25, 2026
eca432d
feat(acceptance): disposable-host service acceptance and the uninstal…
lidge-jun Aug 25, 2026
e449974
fix(codex): show the five-hour quota on account cards (#2616) (#2620)
lidge-jun Aug 25, 2026
1a15d62
fix(responses): strip search_content_types on web_search for Muse Spa…
lidge-jun Aug 25, 2026
1a92d6b
fix: avoid creating Claude agents directory when disabled (#2619)
fflake33 Aug 25, 2026
5df97f8
devlog: record the owner-backlog closeout (#2624)
lidge-jun Aug 25, 2026
0523239
docs(responses): state the reasoning sanitizer's real rule and pin it…
olddonkey Aug 25, 2026
6f3b5af
docs: document promptCacheKey for custom openai-chat providers (#2541…
lidge-jun Aug 25, 2026
c6084fe
fix(codex): write the provenance ledger, bounded (#2622) (#2626)
lidge-jun Aug 25, 2026
74823a5
fix(codex): gate subagent fallback by account entitlement (#2623)
luvs01 Aug 25, 2026
8091f2e
fix(storage): bound the cold Codex log inspection and surface when it…
lidge-jun Aug 25, 2026
e6dba54
docs(responses): define semantic progress ownership (#2600) (#2628)
lidge-jun Aug 25, 2026
faf70c4
fix(subagents): carry entitlement into the recovery preview (#2509) (…
lidge-jun Aug 25, 2026
324c1aa
fix: catalog effort ladders, v2 pin precedence, and combo owned_by (#…
lidge-jun Aug 25, 2026
848a66d
fix: gate root skip-permissions bypass and ship the auto-review model…
lidge-jun Aug 25, 2026
303cc3c
fix(server): refuse requests after the package tree is replaced under…
lidge-jun Aug 25, 2026
1a39adc
test(runtime): pin the bundled Bun 1.4 version (#2633)
lidge-jun Aug 25, 2026
6ccb13c
fix(google): carry chat video input onto Gemini wire (#2458) (#2634)
lidge-jun Aug 25, 2026
87179e8
test(server): give the Daybreak compact case the server budget (#2635)
lidge-jun Aug 25, 2026
b5563d4
devlog: record the community bug sweep (#2636)
lidge-jun Aug 25, 2026
23a6348
devlog: terminal record for the backlog closeout loop (#2637)
lidge-jun Aug 25, 2026
8bfac71
feat(oauth): activate multi-account 429 failover on account presence …
lidge-jun Aug 26, 2026
0a0a882
fix(management): preserve the account-failover opt-out across a provi…
lidge-jun Aug 26, 2026
40ad1c7
devlog: quota-window and backlog roadmap (260826) (#2644)
lidge-jun Aug 26, 2026
12f5876
fix(codex): classify a sub-day quota header window as the 5h burst (P…
lidge-jun Aug 26, 2026
bf73afe
feat(gui): hide the Codex Spark quota by default behind a Codex Auth …
lidge-jun Aug 26, 2026
37909c6
devlog: record the third Spark projection found during wp2 (#2657)
lidge-jun Aug 26, 2026
815a38c
devlog: backlog triage - 18 stale PRs and 21 open issues (260826) (#2…
lidge-jun Aug 26, 2026
bae100a
ci: delete branches left behind by closed pull requests (#2664)
lidge-jun Aug 26, 2026
7181ebd
fix(gui): preserve CommandCode billing-period credits (#2660)
lidge-jun Aug 26, 2026
e821f95
fix(registry): retain verified CommandCode image capabilities (#2659)
lidge-jun Aug 26, 2026
538a602
test(update): give the launcher-recovery case a budget that contains …
lidge-jun Aug 26, 2026
01b5da9
feat(config): preserve scoped no-proxy bypasses (#2661)
lidge-jun Aug 26, 2026
6ebf925
devlog(260826_cursor_responses_gap): plan + seed-thread failure catalog
Aug 26, 2026
0c2a8e1
devlog(260826_cursor_responses_gap): probe campaign + gap summary dec…
Aug 26, 2026
6fd9eb0
devlog(260826_cursor_responses_gap): curl-phase probe evidence P1-P12…
Aug 26, 2026
b909384
devlog(260826_cursor_responses_gap): subagent fleet evidence S1/S2, s…
Aug 26, 2026
64e69b0
devlog(260826_cursor_responses_gap): severity-ranked gap summary G1-G9
Aug 26, 2026
ab3708b
devlog(260826_cursor_responses_gap): ultra/k3/1M research ledger
Aug 26, 2026
ed81489
devlog(260826_cursor_responses_gap): implementation decade docs 030-0…
Aug 26, 2026
773d774
fix(cursor): single-line call_id codec + response.in_progress parity
Aug 26, 2026
4d85df3
fix(cursor): suppress default native tool catalog for bare API callers
Aug 26, 2026
69a0b71
feat(cursor): commit tool-suspended checkpoints for external models
Aug 26, 2026
6efe59a
fix(cursor): quarantine catalog models whose runs always fail upstream
Aug 26, 2026
73cc275
test(lab): shift streaming-turn phase selector for response.in_progress
Aug 26, 2026
e0b6060
feat(cursor): ultra mode toggle (kimi-k3-1m) with Max Mode wire flag …
Aug 26, 2026
712778e
feat(cursor): serve-time blob integrity diagnostic for replay corruption
Aug 26, 2026
f1d6097
fix(cursor): forbid native-tool probing outright + checkpoint refusal…
Aug 26, 2026
37f600c
fix(cursor): expand tool-finalize grace for parallel multi-tool requests
Aug 26, 2026
f3bd8b3
devlog(260826_cursor_responses_gap): user-confirmed k3 1M exposure
Aug 26, 2026
ddecc67
fix(cursor): explain empty exec results + forbid native probing in co…
Aug 26, 2026
624f339
fix(cursor): silent-redirect framing for native-tool denial payloads
Aug 26, 2026
aee1cbd
fix(cursor): cover codex CLI native shell names in empty-result norma…
Aug 26, 2026
7be8ee0
devlog(260826_cursor_responses_gap): gap-8 codex exec QA evidence
Aug 26, 2026
ae3bcf9
devlog(260826_cursor_responses_gap): wire/NDJSON QA round (W1-W8)
Aug 26, 2026
9d73e06
fix(cursor): forbid tool-selection commentary + shell-redirection fil…
Aug 26, 2026
187dec5
devlog(260826_cursor_responses_gap): app-route QA re-probe results
Aug 26, 2026
35667bb
feat(cursor): repetition breaker for external-model replay priming
Aug 26, 2026
d9d84b3
devlog(260826_cursor_responses_gap): repetition breaker + final stack…
Aug 26, 2026
954f345
Merge pull request #2650 from lidge-jun/codex/cursor-gap-1
lidge-jun Aug 26, 2026
58f5a29
Merge pull request #2651 from lidge-jun/codex/cursor-gap-2
lidge-jun Aug 26, 2026
6503602
fix(cursor): guard external replay against [Tool Result] envelope ech…
Aug 26, 2026
db37bc2
fix(cursor): detect echoed tool-result envelope and retry once with c…
Aug 26, 2026
4433b7d
fix(cursor): arm envelope-echo sniffer for any external turn with rep…
Aug 26, 2026
1328245
docs(cursor): record QA round-2 probe results on patched service
Aug 26, 2026
a48f933
fix(cursor): reject invented native-tool failure commentary
Aug 26, 2026
0b84d67
docs(cursor): record gap-11 live routing QA
Aug 26, 2026
ab54fe6
fix(cursor): close routing-commentary review edge cases
Aug 26, 2026
01d3c5f
Merge pull request #2669 from lidge-jun/codex/cursor-gap-10
lidge-jun Aug 26, 2026
779b609
Merge pull request #2670 from lidge-jun/codex/cursor-gap-11
lidge-jun Aug 26, 2026
16006bd
fix(catalog): advertise Muse Spark image input on OpenCode Go
DevonGithub Aug 26, 2026
e278a67
test(muse): add docstring to helper
DevonGithub Aug 26, 2026
50b50e1
fix(responses): normalize canonical forward prompt envelope
Ingwannu Aug 26, 2026
140d014
fix(responses): normalize Posit continuations
Ingwannu Aug 26, 2026
c0533ce
fix(web-search): bound Exa response bodies
luvs01 Aug 26, 2026
6bce1d1
fix(web-search): preserve Exa body timeout classification
luvs01 Aug 26, 2026
2787104
fix(openai-chat): normalize $ref-with-siblings for Moonshot tool schemas
Aug 26, 2026
37e5dd5
Merge pull request #2676 from luvs01/fix/bound-exa-response-bodies
Ingwannu Aug 26, 2026
c0ae9fd
feat(gui): Codex Auth becomes Codex Set, with a working Prompt panel
lidge-jun Aug 26, 2026
d3ed063
fix(gui): show a failed prompt read, and lazy-mount both Codex Set pa…
lidge-jun Aug 26, 2026
5b2a9b9
test(gui): prove the stale-revision re-read is installed, not merely …
lidge-jun Aug 26, 2026
b7b6a58
feat(gui): render the whole prompt-layer taxonomy, with a read-only d…
lidge-jun Aug 26, 2026
c4c87c8
feat(codex): serve the prompt-layer state over /api/codex-prompt
lidge-jun Aug 26, 2026
b7fd788
fix(gui): make the layer-copy maps actually exhaustive, and finish th…
lidge-jun Aug 26, 2026
67549e8
fix(codex): close the prompt-route gaps an audit found
lidge-jun Aug 26, 2026
33e3d4d
fix(gui): finish the unknown-layer fallback, and make case 11 watch t…
lidge-jun Aug 26, 2026
21665f3
test(codex): make two prompt-route guards actually protective
lidge-jun Aug 26, 2026
6352ef7
fix(lifecycle): admit same-session reconnect turns
Aug 26, 2026
7e3132e
test(lifecycle): prove HTTP reconnect lane ownership
Aug 26, 2026
57fbc24
docs(gui): add Codex Set prompt-panel screenshots for the stack
Aug 26, 2026
b006642
fix(gui): latch the lazy mounts and keep the resource key private
Aug 26, 2026
d47e618
fix(gui): route the features link, and declare the endpoint's CLI parity
Aug 26, 2026
ba77ff8
test(providers): follow the Add Provider CTA to its renamed route
Aug 26, 2026
b9211c4
feat(gui): custom prompt layers, editable and reorderable, with a linter
lidge-jun Aug 26, 2026
02093a4
fix(gui): let a first run create its first custom layer
lidge-jun Aug 26, 2026
b01f249
fix(gui): close the write races the draft-preservation fix opened
lidge-jun Aug 26, 2026
ecff6f2
feat(gui): repair drift from the panel, and say where a refused adopt…
lidge-jun Aug 26, 2026
6fd7cbc
feat(gui): show the real prompt text, and let the dialog turn a layer…
lidge-jun Aug 26, 2026
f160524
feat(gui): five prompt presets, authored rather than copied
lidge-jun Aug 26, 2026
f0ecd0e
feat(gui): show what each layer costs, where the decision is made
lidge-jun Aug 26, 2026
7d5fbaf
fix(gui): make the preset picker disabled state real, and close it on…
lidge-jun Aug 26, 2026
0ade9c5
fix(codex): read the global Codex home only, and tell an empty file f…
lidge-jun Aug 26, 2026
8dc5a72
feat(gui): collapse the preset menu when there is nothing to choose from
lidge-jun Aug 26, 2026
c5ac161
fix(gui): drop measured text after a write, and stop implying a probe…
lidge-jun Aug 26, 2026
46c846b
fix(gui): use the dashboard toggle, not a raw checkbox, and record wh…
lidge-jun Aug 26, 2026
9150a90
fix(codex): map only tags proven by live output, and bound the AGENTS…
lidge-jun Aug 26, 2026
0fdb702
fix(gui): drop a lint suppression and type the test request bodies
Aug 26, 2026
dbce563
feat(gui): show the stack as an ordered stack, and split notices from…
lidge-jun Aug 26, 2026
db73385
fix(gui): latch lazy mounts and the picker's expansion during render
Aug 26, 2026
52a32b2
fix(gui): close an editor whose layer was deleted, and reorder from t…
lidge-jun Aug 26, 2026
726433d
fix(gui): keep the resource key private and query the real switch ele…
Aug 26, 2026
8f57039
fix(gui): let a layer body wrap instead of scrolling sideways
Aug 26, 2026
26ac561
test(gui): query the switch element the rows actually render
Aug 26, 2026
b7c47f5
fix(gui): check the probe response status before trusting its body
Aug 26, 2026
7efa4e1
fix(gui): define the navigation strings in the layer that uses them
Aug 26, 2026
f41650e
fix(gui): derive the layer-gone notice instead of writing it from an …
Aug 26, 2026
5b1d6a9
docs(codex): document the prompt-layer panel in eight locales
Aug 26, 2026
3462ef9
test(gui): allowlist the position label where its key now lives
Aug 26, 2026
cd71a1d
fix(gui): drop the duplicate navigation keys now defined a layer below
Aug 26, 2026
bdf21ff
devlog(260802): record why local green missed three CI rounds
Aug 26, 2026
299f472
fix(openai-chat): compose ref assertions and bound the schema walk
Aug 26, 2026
c066882
fix: normalize Azure Model Router tool schemas
Michael-Z-Freeman Aug 26, 2026
f64ef6d
fix: preserve tool function schema typing
Michael-Z-Freeman Aug 26, 2026
f583ae9
fix(codex): restart the npm wrapper that supervises the app-server
Aug 26, 2026
c07c9e4
Merge pull request #2678 from lidge-jun/codex/prompt-layers-route
lidge-jun Aug 26, 2026
a87083d
Merge pull request #2679 from lidge-jun/codex/prompt-layers-shell
lidge-jun Aug 26, 2026
bfcb7c2
Merge pull request #2680 from lidge-jun/codex/prompt-layers-authoring
lidge-jun Aug 26, 2026
186b8ef
Merge pull request #2681 from lidge-jun/codex/prompt-layers-realtext
lidge-jun Aug 26, 2026
94b5d94
Merge pull request #2682 from lidge-jun/codex/prompt-layers-docs
lidge-jun Aug 26, 2026
9e746d8
Merge pull request #2685 from lidge-jun/codex/restart-codex-npm-wrapper
lidge-jun Aug 26, 2026
90b7ed4
Merge pull request #2683 from lidge-jun/codex/session-lane-reconnect
lidge-jun Aug 26, 2026
6c70924
fix(openai-chat): compose shared properties and leave data keywords a…
Aug 26, 2026
8412fe1
Merge pull request #2677 from lidge-jun/codex/moonshot-ref-sibling-sc…
lidge-jun Aug 26, 2026
4c8814e
feat(providers): seed glm-5.3-flash across the GLM-5.2 catalogs
Aug 26, 2026
792ca96
ci: re-trigger Cross-platform CI after a runner startup_failure
Aug 26, 2026
3289312
fix(providers): glm-5.3-flash is a VLM, and drop Ox Alpha entirely
Aug 26, 2026
5d0a97b
Merge pull request #2687 from lidge-jun/codex/glm-53-flash-preseed
lidge-jun Aug 26, 2026
618809d
devlog(260827): review dev against main, and plan the base variants
Aug 26, 2026
83cf732
fix(cursor): survive a desktop executor that never reads stdin
Aug 26, 2026
866073e
test(providers): move two stale allowlist counts to what the registry…
Aug 26, 2026
5916df1
fix(server): stop a chmod from fencing the data plane behind 503
Aug 26, 2026
d66252e
fix(codex): require a dashboard session to rewrite the prompt stack
Aug 26, 2026
583f5a2
fix(codex): keep a BOM at byte 0, and roll back a refused write
Aug 26, 2026
59d9bc9
fix: stop deleting reused branches, and finish the glm-5.3-flash corr…
Aug 26, 2026
b0e893e
test(ci): import the cleanup helper without a lint suppression
Aug 26, 2026
f25dab8
test(providers): move two more assertions that pinned the incomplete …
Aug 26, 2026
bbfdd65
feat(codex): show the commit-attribution layer, and stop rows claimin…
Aug 26, 2026
f0c14b6
Merge pull request #2695 from lidge-jun/codex/desktop-exec-epipe
lidge-jun Aug 26, 2026
942cb04
Merge pull request #2689 from lidge-jun/codex/pkgtree-503-false-positive
lidge-jun Aug 26, 2026
9f7d709
Merge pull request #2691 from lidge-jun/codex/branch-cleanup-sha-guard
lidge-jun Aug 26, 2026
ee182a1
Merge pull request #2692 from lidge-jun/codex/git-attribution-layer
lidge-jun Aug 26, 2026
b715985
feat(codex): base-prompt variants, with a default that cannot be edited
Aug 26, 2026
71f1299
feat(gui): a real switch on base, and a swipeable variant picker
Aug 26, 2026
18b9393
test(gui): the base position label has no French to write
Aug 26, 2026
06e8e8a
docs(pr): screenshots of the base switch and the variant picker
Aug 26, 2026
a3f5335
docs(devlog): record the remote gate, including the locale check it c…
Aug 26, 2026
924efc9
Merge pull request #2707 from lidge-jun/codex/base-prompt-variants
lidge-jun Aug 26, 2026
183286d
docs: base prompt variants and commit attribution, in five locales
Aug 26, 2026
ab63ded
Merge pull request #2708 from lidge-jun/codex/base-variant-docs
lidge-jun Aug 26, 2026
094a25c
feat(gui): UX polish for the prompt-layer panel
Aug 27, 2026
e92f6c1
docs(pr): UX polish screenshots — panel with left accents and dialog …
Aug 27, 2026
87ce20c
test(gui): the dot indicator renders and follows the ring position
Aug 27, 2026
9b838d0
Merge pull request #2719 from lidge-jun/codex/prompt-ux-polish
lidge-jun Aug 27, 2026
c3ef630
docs(devlog): intake matrix and lane roadmap for the 260827 bug-PR me…
lidge-jun Aug 27, 2026
d1c3988
docs(devlog): fold A-gate audit corrections into the merge-round plan
lidge-jun Aug 27, 2026
90ef53f
docs(devlog): operative execution order for the merge round
lidge-jun Aug 27, 2026
2a9c18d
Merge pull request #2672 from Ingwannu/ingw/fix-responses-forward-sys…
lidge-jun Aug 27, 2026
e3b136f
Merge pull request #2674 from Ingwannu/ingw/fix-posit-responses-conti…
lidge-jun Aug 27, 2026
17aadf8
Merge pull request #2671 from DevonGithub/codex/muse-spark-vision
lidge-jun Aug 27, 2026
4a4df12
test(catalog): pin Muse image input against a text-only discovered row
lidge-jun Aug 27, 2026
2c85dd4
Merge pull request #2684 from Michael-Z-Freeman/fix/azure-model-route…
lidge-jun Aug 27, 2026
36ff16e
docs(devlog): fold audit round 2 into the merge-round plan
lidge-jun Aug 27, 2026
2feffbd
Merge pull request #2720 from lidge-jun/codex/l1-merge-round-260827
lidge-jun Aug 27, 2026
fefeb05
fix(responses): backfill missing status for strict decoders
lidge-jun Aug 27, 2026
e1e6ec0
fix(command-code): add reasoning effort ladders for three live models
lidge-jun Aug 27, 2026
7a28fa5
fix(xai): normalize Responses root tool schemas
olddonkey Aug 26, 2026
e2ca660
fix(xai): preserve oneOf exclusivity and bound schema flattening
olddonkey Aug 26, 2026
6877f64
fix(responses): treat a queued response as in_progress, not completed
lidge-jun Aug 27, 2026
7d49790
docs(devlog): record the status/created_at asymmetry found at the L3 …
lidge-jun Aug 27, 2026
45c3d31
fix(command-code): keep Ox Alpha out of the regenerated catalog fixture
lidge-jun Aug 27, 2026
8af9ff2
docs(responses): repair the backfill docblock left broken by the crea…
lidge-jun Aug 27, 2026
ad8ab4f
fix(command-code): stop claiming the effort ladders self-correct
lidge-jun Aug 27, 2026
b64de51
docs(devlog): record the L3 audit findings and dispositions
lidge-jun Aug 27, 2026
da1e8af
test(command-code): pin the broken profile-refresh path
lidge-jun Aug 27, 2026
0209234
fix(kiro): send Kiro's service profile for AWS Builder ID accounts
Aug 27, 2026
1241021
fix(kiro): key the Builder ID wire path off the resolver's own verdict
Aug 27, 2026
64c6d64
Merge pull request #2721 from lidge-jun/codex/l3-cherry-picks-260827
lidge-jun Aug 27, 2026
307d2e0
docs(devlog): record the L1 lane outcome
lidge-jun Aug 27, 2026
0f10e57
docs(devlog): point the plan's verification section at the real test …
Aug 27, 2026
cb9bb9b
fix(responses): bridge bare code-mode helper calls through exec
lidge-jun Aug 27, 2026
56be8f6
docs(devlog): plan the Kiro Responses text-control guard fix
lidge-jun Aug 27, 2026
524a294
test(kiro): pin non-structured Responses text controls
lidge-jun Aug 27, 2026
a0d1ebb
fix(kiro): reject only genuine structured output
lidge-jun Aug 27, 2026
ce52a00
docs(kiro): document Responses text control handling
lidge-jun Aug 27, 2026
314d41d
test(kiro): make the wire-absence assertion non-vacuous
lidge-jun Aug 27, 2026
cebe005
Merge pull request #2724 from lidge-jun/codex/l2-2663-code-mode-exec
lidge-jun Aug 27, 2026
669efd5
test(xai): pin the additionalProperties composition boundary
olddonkey Aug 27, 2026
6769db6
docs(devlog): record the L2 lane outcome and audit
lidge-jun Aug 27, 2026
3d986ef
Merge pull request #2690 from olddonkey/codex/fix-xai-responses-root-…
lidge-jun Aug 27, 2026
4c5adb2
docs(devlog): record the L4 lane outcome
lidge-jun Aug 27, 2026
77e0370
Merge pull request #2727 from lidge-jun/codex/l4-round-260827
lidge-jun Aug 27, 2026
3727207
docs(devlog): close the Kiro text-control unit
lidge-jun Aug 27, 2026
729f01e
docs(devlog): close out the 260827 bug-PR merge round
lidge-jun Aug 27, 2026
41fcc9f
Merge pull request #2728 from lidge-jun/codex/round-closeout-260827
lidge-jun Aug 27, 2026
70159d9
Merge pull request #2722 from lidge-jun/codex/kiro-builder-id-profile
lidge-jun Aug 27, 2026
7547c89
Merge pull request #2725 from lidge-jun/codex/kiro-text-control-guard
lidge-jun Aug 27, 2026
005c0dc
fix(scripts): restart proxy without setsid on macOS
lidge-jun Aug 27, 2026
056d299
Merge pull request #2735 from lidge-jun/codex/fix-ocx-restart-macos
lidge-jun Aug 27, 2026
4188f5a
docs(devlog): close macOS restart repair
lidge-jun Aug 27, 2026
06fa680
Merge pull request #2736 from lidge-jun/codex/close-ocx-restart-macos
lidge-jun Aug 27, 2026
b49c4dc
fix(server): keep source checkout live during edits
lidge-jun Aug 27, 2026
17577c9
Merge pull request #2737 from lidge-jun/codex/source-checkout-integrity
lidge-jun Aug 27, 2026
afe22b2
docs(devlog): hardening inventory and remediation roadmap for dev
lidge-jun Aug 27, 2026
9919438
docs(devlog): record the launcher-recovery flake as a real readiness …
lidge-jun Aug 27, 2026
e4a85d1
fix(release): stop dev from carrying a version behind its own releases
lidge-jun Aug 27, 2026
5dfee1a
Merge pull request #2738 from lidge-jun/codex/dev-hardening-inventory
lidge-jun Aug 27, 2026
a223a2b
fix(release): make the version-line guard bite on release commits and…
lidge-jun Aug 27, 2026
7297bc8
ci: fetch tags without cloning full history for the version-line check
lidge-jun Aug 27, 2026
ca3b379
Merge pull request #2739 from lidge-jun/codex/dev-version-line
lidge-jun Aug 27, 2026
7c87039
test(ci): pin fetch-tags on the jobs that run the suite
lidge-jun Aug 27, 2026
0343569
docs(devlog): correct the wp3 failover-identity severity from a secon…
lidge-jun Aug 27, 2026
b8ad97a
ci: fetch tags on the Windows suite leg too
lidge-jun Aug 27, 2026
a57b962
Merge pull request #2743 from lidge-jun/codex/pin-ci-fetch-tags
lidge-jun Aug 27, 2026
2c123e8
docs: stop shipping locale pages that state the opposite of the code
lidge-jun Aug 27, 2026
2fc97f7
docs: name the current native-exec control in the remaining four locales
lidge-jun Aug 27, 2026
4f81880
test: harden the README asset check against two false verdicts
lidge-jun Aug 27, 2026
95314c1
docs: finish the adapter-count sweep the first pass left half-done
lidge-jun Aug 27, 2026
802f04a
Merge pull request #2746 from lidge-jun/codex/locale-docs-contradictions
lidge-jun Aug 27, 2026
e6661f2
fix(gui): make doctor:gui agree with CI instead of being bypassed
lidge-jun Aug 27, 2026
9542b26
test(gui): lock the exhaustive-deps suppression against going inert
lidge-jun Aug 27, 2026
5000321
Merge pull request #2749 from lidge-jun/codex/doctor-gui-agrees-with-ci
lidge-jun Aug 27, 2026
af479e0
test(core): lock the two invariants AGENTS.md claims are enforced
lidge-jun Aug 27, 2026
9493095
docs(agents): name the activation enforcement, and stop tripping the …
lidge-jun Aug 27, 2026
8be960f
test(core): extend the activation scan through the return, not just t…
lidge-jun Aug 27, 2026
2a72cc0
Merge pull request #2751 from lidge-jun/codex/lock-activation-invariants
lidge-jun Aug 27, 2026
a195ba6
docs(devlog): close the dev hardening unit with a promotion-readiness…
lidge-jun Aug 27, 2026
c457c70
Merge pull request #2752 from lidge-jun/codex/dev-hardening-readiness
lidge-jun Aug 27, 2026
3bfea61
fix(kiro): enable the code-mode catalog nudge so ALL_TOOLS discovery …
Aug 27, 2026
8f702b2
fix(kiro): reserve catalog room for the code-mode execution path
Aug 27, 2026
a4d9fb8
docs(devlog): record wp2 check evidence and the live parallel-delegat…
Aug 27, 2026
d44c406
test(kiro): assert the byte budget holds when exec is reserved
Aug 27, 2026
9421938
docs(devlog): record the remote shard 4/4 triage
Aug 27, 2026
eeb7740
Merge pull request #2750 from lidge-jun/codex/kiro-subagent-delegatio…
lidge-jun Aug 27, 2026
bb31c26
docs(devlog): record that dev advanced past the sha the readiness sta…
lidge-jun Aug 27, 2026
7c333f3
Merge pull request #2754 from lidge-jun/codex/readiness-sha-addendum
lidge-jun Aug 27, 2026
f7f07fd
docs(devlog): plan the dev -> preview -> main release train
lidge-jun Aug 27, 2026
7ca954f
Merge pull request #2755 from lidge-jun/codex/release-train-roadmap
lidge-jun Aug 27, 2026
e25b653
merge dev into main for the v2.34.0 release
lidge-jun Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
226 changes: 226 additions & 0 deletions .github/scripts/closed-pr-branch-cleanup.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
"use strict";

/**
* Deletion planning for branches left behind by closed-without-merge pull
* requests.
*
* GitHub's repository-level `delete_branch_on_merge` only fires on merge, so a
* PR that is closed unmerged leaves its head branch in the repository forever.
* This module decides which of those branches may be deleted; the workflow
* performs the deletion.
*
* Kept as a pure module so the safety rules can be unit-tested without Actions
* and without a live repository.
*/

/** Branches that may never be deleted regardless of pull-request state. */
const PROTECTED_BRANCHES = Object.freeze(["main", "dev", "preview", "gh-pages"]);

/** Default grace period before a closed PR's head branch becomes eligible. */
const DEFAULT_GRACE_DAYS = 14;

function normalizeBranchName(value) {
return String(value || "").trim();
}

/**
* A commit id, lowercased for comparison.
*
* The REST and GraphQL APIs are not consistent about case, and a full 40-character
* sha compared case-sensitively against an abbreviated or upper-case one silently
* reads as "different" - which here would mean "keep", so the failure direction is
* safe, but it would make the guard useless rather than protective. Anything that
* is not a plausible hex object id becomes null, i.e. unknown.
*/
function normalizeOid(value) {
const text = String(value || "").trim().toLowerCase();
return /^[0-9a-f]{7,64}$/.test(text) ? text : null;
}

function isProtectedBranch(name) {
return PROTECTED_BRANCHES.includes(normalizeBranchName(name));
}

function toTimestamp(value) {
if (!value) return null;
const ms = Date.parse(String(value));
return Number.isFinite(ms) ? ms : null;
}

/**
* Reasons a candidate branch is kept. Exported so the workflow can log a
* stable, greppable verdict per branch instead of a free-form sentence.
*/
const KEEP_REASONS = Object.freeze({
PROTECTED: "protected-branch",
MERGED: "pull-request-merged",
OPEN: "open-pull-request",
BASE_OF_OPEN: "base-of-open-pull-request",
CROSS_REPOSITORY: "cross-repository-head",
MISSING_CLOSED_AT: "missing-closed-at",
WITHIN_GRACE: "within-grace-period",
MOVED_SINCE_CLOSE: "branch-moved-since-close",
UNKNOWN_HEAD_SHA: "unknown-head-sha",
});

/**
* Plan deletions for head branches of closed-unmerged pull requests.
*
* Every rule here is a safety rule, and each one exists because the opposite
* behavior destroys work that is still referenced:
*
* - A branch is a candidate only when *every* pull request that ever used it as
* a head is closed and unmerged. One open or merged PR on the same branch
* keeps it, because reopening a PR whose head branch is gone cannot restore
* the commits.
* - A branch that is the base of an open pull request is kept. Deleting it
* closes the stacked child PR that targets it.
* - Cross-repository (fork) heads are never touched: they live in the
* contributor's repository and this token has no business there.
* - A grace period after `closed_at` leaves room to reopen a PR that was
* closed by mistake.
* - The branch must still POINT AT a commit one of those closed pull requests
* had as its head. Matching by NAME alone deletes reused work: `codex/`-style
* names get picked up again all the time, and a branch recreated for new work
* inherits the closed history of every PR that ever used that name. The tip
* moved, so the branch is not the closed PR's branch any more - it only shares
* its label.
* - A branch whose current tip cannot be determined is kept. An unknown tip is
* not evidence of an abandoned branch, and this job's mistakes are not
* recoverable.
*
* @param {object} input
* @param {Array<object>} input.pullRequests Pull requests with
* `headRefName`, `headRefOid`, `baseRefName`, `state`, `merged`, `closedAt`,
* and `isCrossRepository`.
* @param {Array<string|{name: string, oid?: string}>} input.branches Branches
* that currently exist. A bare string carries no tip, which is treated as an
* unknown tip and kept.
* @param {number} [input.now] Current time in milliseconds.
* @param {number} [input.graceDays] Days to wait after `closedAt`.
* @returns {{ deletions: Array<{branch: string, pullRequests: number[]}>,
* keeps: Array<{branch: string, reason: string}> }}
*/
function planClosedPrBranchDeletions({
pullRequests = [],
branches = [],
now = Date.now(),
graceDays = DEFAULT_GRACE_DAYS,
}) {
// Accepts both shapes so an older caller passing bare names still works - it
// just gets the conservative answer, because a name without a tip cannot be
// proven safe to delete.
/** @type {Map<string, string|null>} */
const existing = new Map();
for (const entry of branches) {
const name = normalizeBranchName(typeof entry === "string" ? entry : entry && entry.name);
if (!name) continue;
const oid = typeof entry === "string" ? null : normalizeOid(entry && entry.oid);
existing.set(name, oid);
}
const graceMs = Math.max(0, Number(graceDays) || 0) * 24 * 60 * 60 * 1000;

/** @type {Map<string, object[]>} */
const byHead = new Map();
const openBases = new Set();

for (const pr of pullRequests) {
const head = normalizeBranchName(pr && pr.headRefName);
if (head) {
const list = byHead.get(head) || [];
list.push(pr);
byHead.set(head, list);
}
const isOpen = String(pr && pr.state).toUpperCase() === "OPEN";
if (isOpen) {
const base = normalizeBranchName(pr && pr.baseRefName);
if (base) openBases.add(base);
}
}

const deletions = [];
const keeps = [];

for (const branch of [...existing.keys()].sort()) {
if (isProtectedBranch(branch)) {
keeps.push({ branch, reason: KEEP_REASONS.PROTECTED });
continue;
}

const related = byHead.get(branch) || [];
if (related.length === 0) continue; // No PR ever used it; out of scope.

if (related.some((pr) => pr && pr.isCrossRepository === true)) {
keeps.push({ branch, reason: KEEP_REASONS.CROSS_REPOSITORY });
continue;
}
if (related.some((pr) => pr && pr.merged === true)) {
keeps.push({ branch, reason: KEEP_REASONS.MERGED });
continue;
}
if (related.some((pr) => String(pr && pr.state).toUpperCase() === "OPEN")) {
keeps.push({ branch, reason: KEEP_REASONS.OPEN });
continue;
}
if (openBases.has(branch)) {
keeps.push({ branch, reason: KEEP_REASONS.BASE_OF_OPEN });
continue;
}

const closedTimestamps = related.map((pr) => toTimestamp(pr && pr.closedAt));
if (closedTimestamps.some((ts) => ts === null)) {
keeps.push({ branch, reason: KEEP_REASONS.MISSING_CLOSED_AT });
continue;
}
const newestClosedAt = Math.max(...closedTimestamps);
if (now - newestClosedAt < graceMs) {
keeps.push({ branch, reason: KEEP_REASONS.WITHIN_GRACE });
continue;
}

// The tip check, last because it is the most expensive claim to satisfy and
// the cheaper rules above have already excluded most branches.
//
// A closed PR's head branch is only THIS branch if the branch still points at
// a commit that PR had as its head. Without this, a name reused for new work
// is deleted on the strength of an unrelated PR that happened to share the
// label months earlier - and a deleted branch whose commits were never pushed
// anywhere else is gone.
const currentOid = existing.get(branch) || null;
if (!currentOid) {
keeps.push({ branch, reason: KEEP_REASONS.UNKNOWN_HEAD_SHA });
continue;
}
const closedOids = new Set(
related.map((pr) => normalizeOid(pr && pr.headRefOid)).filter(Boolean),
);
// An empty set means the API gave us no head SHA for any of them, which is the
// unknown case again rather than a licence to delete.
if (closedOids.size === 0) {
keeps.push({ branch, reason: KEEP_REASONS.UNKNOWN_HEAD_SHA });
continue;
}
if (!closedOids.has(currentOid)) {
keeps.push({ branch, reason: KEEP_REASONS.MOVED_SINCE_CLOSE });
continue;
}

deletions.push({
branch,
pullRequests: related
.map((pr) => Number(pr && pr.number))
.filter((n) => Number.isFinite(n))
.sort((a, b) => a - b),
});
}

return { deletions, keeps };
}

module.exports = {
DEFAULT_GRACE_DAYS,
KEEP_REASONS,
PROTECTED_BRANCHES,
isProtectedBranch,
planClosedPrBranchDeletions,
};
165 changes: 165 additions & 0 deletions .github/scripts/closed-pr-branch-cleanup.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"use strict";

const { describe, it } = require("node:test");
const assert = require("node:assert/strict");
const {
DEFAULT_GRACE_DAYS,
KEEP_REASONS,
isProtectedBranch,
planClosedPrBranchDeletions,
} = require("./closed-pr-branch-cleanup.cjs");

const NOW = Date.parse("2026-08-26T00:00:00Z");
const DAY = 24 * 60 * 60 * 1000;
const longAgo = new Date(NOW - 60 * DAY).toISOString();

function closedPr(overrides) {
return {
number: 1,
state: "CLOSED",
merged: false,
isCrossRepository: false,
headRefName: "codex/example",
baseRefName: "dev",
closedAt: longAgo,
...overrides,
};
}

function keepReason(result, branch) {
const hit = result.keeps.find((entry) => entry.branch === branch);
return hit ? hit.reason : null;
}

function deletedBranches(result) {
return result.deletions.map((entry) => entry.branch);
}

describe("isProtectedBranch", () => {
it("protects the integration, release, and prerelease lines", () => {
for (const name of ["main", "dev", "preview", "gh-pages"]) {
assert.equal(isProtectedBranch(name), true, name);
}
assert.equal(isProtectedBranch("codex/dev"), false);
});
});

describe("planClosedPrBranchDeletions", () => {
it("deletes a branch whose only pull request closed unmerged past the grace period", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 42, headRefName: "codex/stale" })],
branches: ["codex/stale", "dev"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), ["codex/stale"]);
assert.deepEqual(result.deletions[0].pullRequests, [42]);
});

it("keeps a branch that any merged pull request used as a head", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [
closedPr({ number: 10, headRefName: "codex/reused" }),
closedPr({ number: 11, headRefName: "codex/reused", state: "MERGED", merged: true }),
],
branches: ["codex/reused"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "codex/reused"), KEEP_REASONS.MERGED);
});

it("keeps a branch that still has an open pull request", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [
closedPr({ number: 20, headRefName: "codex/active" }),
closedPr({ number: 21, headRefName: "codex/active", state: "OPEN", closedAt: null }),
],
branches: ["codex/active"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "codex/active"), KEEP_REASONS.OPEN);
});

it("keeps a closed stack parent while an open child still targets it", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [
closedPr({ number: 30, headRefName: "codex/stack-1" }),
closedPr({
number: 31,
state: "OPEN",
closedAt: null,
headRefName: "codex/stack-2",
baseRefName: "codex/stack-1",
}),
],
branches: ["codex/stack-1", "codex/stack-2"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "codex/stack-1"), KEEP_REASONS.BASE_OF_OPEN);
});

it("never touches a fork head branch", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [
closedPr({ number: 40, headRefName: "patch-1", isCrossRepository: true }),
],
branches: ["patch-1"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "patch-1"), KEEP_REASONS.CROSS_REPOSITORY);
});

it("waits out the grace period so a mistaken close can be reopened", () => {
const recent = new Date(NOW - 3 * DAY).toISOString();
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 50, headRefName: "codex/recent", closedAt: recent })],
branches: ["codex/recent"],
now: NOW,
graceDays: DEFAULT_GRACE_DAYS,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "codex/recent"), KEEP_REASONS.WITHIN_GRACE);
});

it("keeps a branch when a closed pull request has no closed_at timestamp", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 60, headRefName: "codex/unknown", closedAt: null })],
branches: ["codex/unknown"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "codex/unknown"), KEEP_REASONS.MISSING_CLOSED_AT);
});

it("refuses to delete a protected branch even if a closed pull request used it", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 70, headRefName: "dev" })],
branches: ["dev", "main", "preview"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
assert.equal(keepReason(result, "dev"), KEEP_REASONS.PROTECTED);
});

it("ignores branches that no pull request ever used", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 80, headRefName: "codex/known" })],
branches: ["codex/known", "codex/never-a-pr"],
now: NOW,
});
assert.deepEqual(deletedBranches(result), ["codex/known"]);
assert.equal(keepReason(result, "codex/never-a-pr"), null);
});

it("only plans deletions for branches that still exist", () => {
const result = planClosedPrBranchDeletions({
pullRequests: [closedPr({ number: 90, headRefName: "codex/already-gone" })],
branches: [],
now: NOW,
});
assert.deepEqual(deletedBranches(result), []);
});
});
Loading
Loading