Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
0627a2c
chore(release): open dev at 2.100.0 before releasing 2.99.0 (#8313)
github-actions[bot] Nov 7, 2026
5279c91
fix(gui): configure Google Vertex ADC (#8311)
lidge-jun Nov 8, 2026
573c1dc
docs(readme): GOAT link, official-API commercial note, account pool u…
lidge-jun Nov 8, 2026
56d9ab4
docs: plan automatic update parity (#8275)
lidge-jun Nov 8, 2026
b3373c9
fix(gui): show WorkBuddy credit balance in quota bar (#8323)
lidge-jun Nov 8, 2026
b670ddb
fix(combo): stop the prompt-cache usage leak — replay native Messages…
vadymhimself Nov 8, 2026
569bacd
Release preview and stable from verified dev commits (#8328)
lidge-jun Nov 8, 2026
cf46eac
fix(tests): use native Windows paths for release shell (#8335)
lidge-jun Nov 8, 2026
a235ef5
fix(gui): show verified Claude account in provider overview (#8334)
lidge-jun Nov 8, 2026
f8dfc2f
Diagnose Windows native-main claim setup failures (#8341)
lidge-jun Nov 8, 2026
35d96de
Fix leading BOM handling in JSONC configuration (#8205)
oocheol Nov 8, 2026
e5c9e3f
Fix supplementary Han token estimates (#8207)
oocheol Nov 8, 2026
d16ba6c
Stop sidecar parsing at terminal events (#8209)
oocheol Nov 8, 2026
a545580
Preserve final sidecar citation titles (#8198)
oocheol Nov 8, 2026
fabc69e
fix: serialize Lab public-evidence mutation with an OS-held lock and …
lidge-jun Nov 8, 2026
7fe985a
fix(combos): keep Codex metadata frames from committing a combo child…
Ingwannu Nov 8, 2026
1c97e3c
ci: add targeted Windows native claim diagnostic lane (#8345)
lidge-jun Nov 8, 2026
10972dd
Add offline signed-update verification and checkpoint codec (#8294)
lidge-jun Nov 8, 2026
fac611e
docs(devlog): plan default-on (opt-out) telemetry and the opencodex.m…
lidge-jun Nov 8, 2026
2c01f56
docs(devlog): design Child-to-Home account move over Remote Link (OCX…
lidge-jun Nov 8, 2026
687dec8
Show observed Claude CLI quota for the current account (#7916)
wtfsayo Nov 8, 2026
f14a2c1
feat(link): add lightweight Rust ocx-child ephemeral Child relay and …
lidge-jun Nov 8, 2026
9d7473f
fix(gui): show Claude account email when privacy.maskEmails is false …
lidge-jun Nov 8, 2026
f1c895e
test: use independent expected paths in the Windows release PATH cont…
lidge-jun Nov 8, 2026
afd487b
fix(release): stream progress while watching a dispatched release (#8…
lidge-jun Nov 8, 2026
ae350dd
docs(release): describe history reconciliation and attested resume (#…
MannXo Nov 8, 2026
4bef566
Support image inputs for Claude CLI (#7978)
nickdavis Nov 8, 2026
e5e757a
feat(link): zero-preinstall SSH ocx-child planting, --purge detach, a…
lidge-jun Nov 8, 2026
578c8bd
Reconcile sidecar text snapshots (#8197)
oocheol Nov 8, 2026
28b38f9
ci: run heavy Linux jobs on the lidge self-hosted pool for trusted ru…
lidge-jun Nov 8, 2026
3999251
test(gui): cover verified Claude Overview account labels
afgonullu Nov 8, 2026
f6506e7
ci: pin release evidence policy to the current ci.yml (#8377)
lidge-jun Nov 8, 2026
df4b71b
fix(integrations): keep Aside aggregate current when unselected profi…
lidge-jun Nov 8, 2026
9e7b3ea
fix(link): serve ocx link status over a private local control socket …
lidge-jun Nov 8, 2026
77d97d2
fix(link): raise Child preflight output cap and name the limit (#8380)
lidge-jun Nov 8, 2026
8cf0582
chore: remove retired release branch references (#8381)
lidge-jun Nov 8, 2026
74fb6f0
test(gui): restore Overview account-label test globals exactly (#8375)
lidge-jun Nov 8, 2026
295159f
perf(usage): index filtered ledger queries and resume append ingestio…
lidge-jun Nov 8, 2026
c813ecc
fix(gui): explain a refused Remember instead of reporting the admin t…
lidge-jun Nov 8, 2026
a72c522
fix(codex): retry a read-only Windows catalog replacement (#8382)
lidge-jun Nov 8, 2026
534adad
test(responses): skip sockets when checking assertion persistence (#8…
lidge-jun Nov 9, 2026
e5a22fe
fix(cli): report an unavailable provider preset as a usage error (#8310)
shu-chen-dot-ca Nov 9, 2026
83c9c3e
feat(link): sync route intent and materialize clients per device (#82…
lidge-jun Nov 9, 2026
6ce65a5
fix(quota): read Kimi Coding Plan usage from the regional kimi.ai ori…
lidge-jun Nov 9, 2026
57cb4bb
fix(codex): probe the app-bundled CLI when no Codex CLI resolves (#8395)
lidge-jun Nov 9, 2026
4995e7c
docs: scope the Remember proxy refusal to standalone dashboards and l…
lidge-jun Nov 9, 2026
b684b46
feat(anthropic): add opt-in thinking display policy (#8392)
lidge-jun Nov 9, 2026
d503449
fix(link): show the Child's own reason when ocx link add fails (#8390)
lidge-jun Nov 9, 2026
1176557
fix(copilot): keep Auto negotiation off real DNS in tests and survive…
lidge-jun Nov 9, 2026
ff2f5de
fix(update): keep bun's postinstall enabled on npm 11 and diagnose a …
lidge-jun Nov 9, 2026
62bba48
fix(gui): recover Aside overwrite previews instead of failing silentl…
lidge-jun Nov 9, 2026
0a1d59e
fix(integrations): leave an uninstalled owned client alone on implici…
lidge-jun Nov 9, 2026
d38d2e3
docs(providers): add custom gateway verification guide (#8350)
lidge-jun Nov 9, 2026
9fb295b
fix(codex): reclaim stale shim restore lock with several dead owners …
Ingwannu Nov 9, 2026
9aeffab
fix(relay): report an untyped SSE error envelope as response.failed (…
Ingwannu Nov 9, 2026
e76511d
fix(google): clear replayed thought signatures on a real HTTP 400 (#8…
Ingwannu Nov 9, 2026
0c3fd3f
Fix startup recovery on specific bind addresses (#8046)
andrew05060414 Nov 9, 2026
9633acd
Add Claude CLI schema output fixtures (#8078)
adirwt852-cloud Nov 9, 2026
0fac612
Revert 14 PRs admin-merged on CI alone without required review (#8402)
lidge-jun Nov 9, 2026
b263b08
fix(quota): read Kimi Coding Plan usage from the regional kimi.ai ori…
lidge-jun Nov 9, 2026
f40c97b
fix(codex): probe the app-bundled CLI when no Codex CLI resolves (#83…
lidge-jun Nov 9, 2026
9573456
docs: scope the Remember proxy refusal to standalone dashboards and l…
lidge-jun Nov 9, 2026
fa4341a
feat(anthropic): add opt-in thinking display policy (#8392) (#8406)
lidge-jun Nov 9, 2026
364e8a9
fix(link): show the Child's own reason when ocx link add fails (#8390…
lidge-jun Nov 9, 2026
01e94ff
fix(copilot): keep Auto negotiation off real DNS in tests and survive…
lidge-jun Nov 9, 2026
9129c0e
fix(update): keep bun's postinstall enabled on npm 11 and diagnose a …
lidge-jun Nov 9, 2026
8c812be
fix(gui): recover Aside overwrite previews instead of failing silentl…
lidge-jun Nov 9, 2026
6dac511
fix(integrations): leave an uninstalled owned client alone on implici…
lidge-jun Nov 9, 2026
d079ecc
docs(providers): add custom gateway verification guide (#8350) (#8412)
lidge-jun Nov 9, 2026
f3657d3
fix(codex): reclaim stale shim restore lock with several dead owners …
lidge-jun Nov 9, 2026
1d16d79
fix(google): clear replayed thought signatures on a real HTTP 400 (#8…
lidge-jun Nov 9, 2026
b33fab7
feat(usage): extend opt-in cache continuation diagnostics (#7479)
yuanyuanlove Nov 9, 2026
e6df67e
feat(providers): add cheapaimodel API-key preset (#7899)
nicho810 Nov 9, 2026
be5c40e
fix(t3code): declare model efforts and tint the provider badge (#8085)
mushikingh Nov 9, 2026
97d26c7
fix(exports): honor native OpenAI display name overrides (#8234)
colthreepv Nov 9, 2026
f2f3c6a
fix(dictation): extend streaming protocol support and allow ten-minut…
colthreepv Nov 9, 2026
0428e0d
fix(responses): keep OpenGateway lifecycle output_text from reading a…
lidge-jun Nov 9, 2026
80d79b5
fix(oauth): stop killing blocked Claude Keychain reads (#8327)
gaurav0107 Nov 9, 2026
ee36269
Fix encrypted orphan reasoning replay for opted-in Ark Kimi endpoints…
hyperdai Nov 9, 2026
fb814f9
docs: follow-ups to the re-landed Remember, custom gateway and owned-…
lidge-jun Nov 9, 2026
15f39a3
fix(codex): borrow the app-bundled catalog only when no Codex CLI res…
lidge-jun Nov 9, 2026
036d0b2
fix: preserve Chat tool defaults on OpenAI Responses routes (#8144)
Simon-Opopeee Nov 9, 2026
d97bfe4
fix(claude): keep a Claude Code session's cache key and pooled accoun…
vadymhimself Nov 9, 2026
f1a132e
fix(service): wait out a manual launchd bootout before reporting fail…
lidge-jun Nov 9, 2026
2bf8ec6
fix(providers): classify Meta's Muse Code refusal as a plan restricti…
lidge-jun Nov 9, 2026
c0fedf2
feat(telemetry): default-on anonymous telemetry core with a human-onl…
lidge-jun Nov 9, 2026
25a1bfc
fix(config): wait for complete owner metadata during first registrati…
luvs01 Nov 9, 2026
9e863b1
feat(desktop): Windows installer page to disclose telemetry and opt o…
lidge-jun Nov 9, 2026
6ea0e35
feat(gui): telemetry consent popup on first run and after updates, wi…
lidge-jun Nov 9, 2026
ad5110c
docs(claude-code): note that the per-turn tk token is dropped from se…
lidge-jun Nov 9, 2026
2817da8
feat(telemetry-collector): Cloudflare Worker + D1 collector and publi…
lidge-jun Nov 9, 2026
5511f62
docs(telemetry): telemetry and privacy guide plus configuration refer…
lidge-jun Nov 9, 2026
289727d
feat(docs-site): public usage dashboard at opencodex.me/dashboard (#8…
lidge-jun Nov 9, 2026
f0f34d0
fix(link): run the install serving the Child before Desktop or PATH c…
lidge-jun Nov 9, 2026
8d29015
feat(telemetry): opt-in public profile and personal usage rank (#8393)
lidge-jun Nov 9, 2026
c81be32
feat(combo): add jevEffortMode to keep JEV from re-tiering a cache-se…
andrew05060414 Nov 9, 2026
3580fc9
fix(responses): preserve Codex client metadata on routed requests (#8…
ParsifalC Nov 9, 2026
5096156
test(usage): state the filter index availability contract Windows can…
lidge-jun Nov 9, 2026
a1d7d05
test(release): run the attach step from a script file so Windows keep…
lidge-jun Nov 9, 2026
2f40e96
test(update): review the signed-update verification modules in the up…
lidge-jun Nov 9, 2026
79ba4f2
fix(usage): wait for a concurrently created filter index instead of c…
lidge-jun Nov 9, 2026
1e8e7e7
test(clients): give each Desktop lifecycle case the budget its child …
lidge-jun Nov 9, 2026
4a22eda
docs(site): redesign landing, navigation, and theme (#8005)
Ingwannu Nov 9, 2026
3372695
fix(gui): preserve provider drafts and bind saves to their dashboard …
lidge-jun Nov 9, 2026
a144140
fix(usage): keep the filter index's WAL sidecars so filtered queries …
lidge-jun Nov 9, 2026
e963af3
test(usage): name the input that moved when the warm aggregate rebuil…
lidge-jun Nov 9, 2026
4b38e9a
test(rust): derive toolchain homes from the rustup proxy and report t…
lidge-jun Nov 9, 2026
3842ebc
ci: refresh the Windows shard durations from batch 42694893702 (#8463)
lidge-jun Nov 9, 2026
8cab704
test(usage): read the warm base after the stage's work and name a Win…
lidge-jun Nov 9, 2026
5cb7d65
ci: refresh the shared shard durations from Ubuntu and macOS logs (#8…
lidge-jun Nov 10, 2026
0d691be
feat(anthropic): add Claude Fable 5.2 pricing, fast mode and provider…
lidge-jun Nov 10, 2026
7877b64
fix(release): publish the verified npm tarball as a local path (#8467)
lidge-jun Nov 10, 2026
05cb4d5
fix(release): start the 2.100.0 changelog at the reviewed legacy base…
lidge-jun Nov 10, 2026
1bea094
fix(anthropic): rank Fable accounts by its share of the weekly limit …
lidge-jun Nov 10, 2026
b534ca1
feat(gui): show a spinner while telemetry consent and profile actions…
lidge-jun Nov 10, 2026
550d0d6
fix(responses): reject malformed retained compact input before routin…
luvs01 Nov 10, 2026
05d517e
fix(telemetry-collector): attach telemetry.opencodex.me as a Custom D…
lidge-jun Nov 10, 2026
bab23a9
fix(sidecars): preserve identities across partial snapshots (#8401)
oocheol Nov 10, 2026
8090333
fix(mistral): bound image pruning memory and normalize malformed refe…
luvs01 Nov 10, 2026
7e2641c
fix(kiro): list Identity Center profiles without an oversized page (c…
lidge-jun Nov 10, 2026
8c28f5f
fix(config): revalidate ownership before honoring a spent publication…
luvs01 Nov 10, 2026
5f8a193
fix(venice): upscale inline images below the 64px minimum edge (#8083)
tachyon6 Nov 10, 2026
00c0216
fix(anthropic): present Claude Code 2.1.321 so Fable 5.2 is accepted …
lidge-jun Nov 10, 2026
9e58505
Merge stable OpenCodex v2.100.1
bcdonadio Nov 10, 2026
edd4cd8
Include upstream child sources in release archive
bcdonadio Nov 10, 2026
fce8995
Keep release documentation within its line budget
bcdonadio Nov 10, 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
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,10 @@ gui/.vite/
!native/remote-workspace-helper/Cargo.lock
!native/remote-workspace-helper/src/
!native/remote-workspace-helper/src/**
!native/ocx-child/
!native/ocx-child/Cargo.toml
!native/ocx-child/Cargo.lock
!native/ocx-child/src/
!native/ocx-child/src/**

**/*.log
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ contact_links:
url: https://github.com/lidge-jun/opencodex/security/advisories/new
about: Report undisclosed vulnerabilities privately to the maintainers. Do not open a public issue.
- name: Security policy
url: https://github.com/lidge-jun/opencodex/blob/main/SECURITY.md
url: https://github.com/lidge-jun/opencodex/blob/dev/SECURITY.md
about: Read the supported-version and reporting guidance before sharing security-sensitive details.
- name: Contributing guide
url: https://opencodex.me/contributing/
Expand Down
4 changes: 3 additions & 1 deletion .github/scripts/bcdn-package.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@

required = ['package.json', 'gui/dist/index.html', 'bin/ocx.mjs', 'bin/package-main.mjs',
'src/generated/compatibility-version.json', 'README.md', 'LICENSE', 'AGENTS_INSTALL.md',
'native/remote-workspace-helper/Cargo.toml', 'native/remote-workspace-helper/Cargo.lock']
'native/remote-workspace-helper/Cargo.toml', 'native/remote-workspace-helper/Cargo.lock',
'native/ocx-child/Cargo.toml', 'native/ocx-child/Cargo.lock',
'native/ocx-child/src/lib.rs', 'native/ocx-child/src/main.rs']
if any(f'package/{name}' not in files for name in required):
raise ValueError('Missing required package files')
if metadata['name'] != '@bitkyc08/opencodex' or not re.fullmatch(r'\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?', metadata['version']):
Expand Down
23 changes: 11 additions & 12 deletions .github/scripts/enforce-pr-target.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,23 @@ describe("enforce-pr-target workflow", () => {
.split("- name: Checkout trusted PR-quality scripts")[1]
.split(/\n {6}- name:/)[0];
assert.match(checkoutStep, /actions\/checkout@[0-9a-f]{40}/);
// The trusted ref comes from a fixed set of integration branches, never
// from the PR's own base commit: a stacked child's base is another open
// PR's head, and `base.sha` would let that unpromoted commit choose the
// code that runs with this job's write-capable token.
// The trusted ref is an integration branch, never the PR's own
// base commit: a stacked child's base is another open PR's head, and
// `base.sha` would let that unpromoted commit choose the code that runs
// with this job's write-capable token.
//
// `status` has no pull_request payload and sources from the default branch
// that supplied the privileged workflow. A `main`-targeting PR sources
// from `main` so the workflow definition and the scripts match. The
// donadiosolutions fork's `custom` base uses `custom`; other bases use `dev`.
// that supplied the privileged workflow. The donadiosolutions fork's
// `custom` base uses `custom`; other bases use `dev`.
//
// Exact equality, not fragment matching: separate checks for `status`,
// `main`, and `dev` would all pass with the operator grouping wrong or a
// surviving `base.sha` fallback.
// Exact equality, not fragment matching: separate checks for `status` and
// `dev` would both pass with the operator grouping wrong or a surviving
// `base.sha` fallback.
const ref = checkoutStep.match(/^\s*ref:\s*(.+)$/m)?.[1];
assert.ok(ref, "trusted checkout must declare ref");
assert.equal(
ref.replace(/\s+/g, " ").trim(),
"${{ github.event_name == 'status' && github.event.repository.default_branch || (github.event.pull_request.base.ref == 'main' && 'main' || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev')) }}",
"${{ github.event_name == 'status' && github.event.repository.default_branch || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev') }}",
);
assert.doesNotMatch(ref, /base\.sha|head\.(?:sha|ref)/);
// Pinning the checkout ref only gates one step. A later `run:` or
Expand Down Expand Up @@ -215,7 +214,7 @@ describe("enforce-pr-target workflow", () => {
const checkouts = workflow.match(/uses:\s*actions\/checkout@[\s\S]*?(?=\n {6}- name:|$)/g) ?? [];
for (const step of checkouts) {
const stepRef = (step.match(/^\s*ref:\s*(.+)$/m)?.[1] ?? "").replace(/\s+/g, " ").trim();
assert.equal(stepRef, "${{ github.event_name == 'status' && github.event.repository.default_branch || (github.event.pull_request.base.ref == 'main' && 'main' || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev')) }}", "every checkout must use the trusted ref");
assert.equal(stepRef, "${{ github.event_name == 'status' && github.event.repository.default_branch || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev') }}", "every checkout must use the trusted ref");
assert.doesNotMatch(step, /repository:/, "a checkout must not retarget its repository");
}
// Checkout is not the only way to obtain PR-controlled code. A `run:` step
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/pr-hygiene.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ describe("pr-hygiene workflow trust boundary", () => {
assert.ok(ref, "trusted checkout must declare ref");
assert.equal(
ref.replace(/\s+/g, " ").trim(),
"${{ github.event.pull_request.base.ref == 'main' && 'main' || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev') }}",
"${{ github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev' }}",
);
// A stacked child PR's base is another open PR's head; neither a base nor
// a head ref may select the code that runs with the write-capable token.
Expand Down Expand Up @@ -355,7 +355,7 @@ describe("pr-hygiene workflow trust boundary", () => {
const checkouts = workflow.match(/uses:\s*actions\/checkout@[\s\S]*?(?=\n {6}- name:|$)/g) ?? [];
for (const step of checkouts) {
const stepRef = (step.match(/^\s*ref:\s*(.+)$/m)?.[1] ?? "").replace(/\s+/g, " ").trim();
assert.equal(stepRef, "${{ github.event.pull_request.base.ref == 'main' && 'main' || (github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev') }}", "every checkout must use the trusted ref");
assert.equal(stepRef, "${{ github.repository == 'donadiosolutions/opencodex' && github.event.pull_request.base.ref == 'custom' && 'custom' || 'dev' }}", "every checkout must use the trusted ref");
assert.doesNotMatch(step, /repository:/, "a checkout must not retarget its repository");
}
// Checkout is not the only way to obtain PR-controlled code. A `run:` step
Expand Down
15 changes: 1 addition & 14 deletions .github/scripts/pr-quality-messages.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,7 @@ function buildFailureSections(failures, { pr, allowedBases, defaultBase }) {
"",
`This pull request currently targets ${inlineCode(pr.base.ref)}, but pull requests must target one of ${allowedBases.map(inlineCode).join(" or ")}.`,
"",
`@${pr.user.login} Please retarget this PR to ${inlineCode(defaultBase)}. All contributions go to ${inlineCode(defaultBase)}; \`main\` receives only release promotions. See our [Contributing guide](https://lidge-jun.github.io/opencodex/contributing/) for details. Thanks! 🙏`
);
}

if (failures.some(failure => failure.code === "wrong_ancestry")) {
sections.push(
"⚠️ **Wrong branch ancestry**",
"",
`This pull request targets ${inlineCode(pr.base.ref)}, but its head appears to sit on the current ${inlineCode("main")} tip while being far behind ${inlineCode(pr.base.ref)}.`,
"",
`@${pr.user.login} Rebase onto the current ${inlineCode(pr.base.ref)} branch instead of opening from ${inlineCode("main")}. That keeps already-released commits out of the integration branch.`
`@${pr.user.login} Please retarget this PR to ${inlineCode(defaultBase)}. All contributions go to ${inlineCode(defaultBase)}. See our [Contributing guide](https://lidge-jun.github.io/opencodex/contributing/) for details. Thanks! 🙏`
);
}

Expand Down Expand Up @@ -322,9 +312,6 @@ function failureSummary(failures, { pr }) {
if (failure.code === "wrong_base") {
return `wrong base (${pr.base.ref})`;
}
if (failure.code === "wrong_ancestry") {
return "wrong ancestry";
}
if (failure.code === "bad_description") {
return `bad description (${failure.reason})`;
}
Expand Down
9 changes: 3 additions & 6 deletions .github/scripts/pr-quality-messages.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,17 @@ describe("buildFailureSections", () => {
assert.match(sections, /@contributor Please retarget this PR to `dev`/);
});

it("builds ancestry, description, and screenshot sections", () => {
it("builds description and screenshot sections", () => {
const sections = buildFailureSections(
[
{ code: "wrong_ancestry" },
{ code: "bad_description", reason: "empty" },
{ code: "missing_ui_screenshot" }
],
{ pr: PR, allowedBases: ALLOWED_BASES, defaultBase: DEFAULT_BASE },
).join("\n");
assert.match(sections, /Wrong branch ancestry/);
assert.match(sections, /Pull request description/);
assert.match(sections, /UI screenshot required/);
assert.match(sections, /Rebase onto the current `main`/);
assert.doesNotMatch(sections, /Wrong branch ancestry/);
});
});

Expand All @@ -165,14 +163,13 @@ describe("failureSummary", () => {
failureSummary(
[
{ code: "wrong_base" },
{ code: "wrong_ancestry" },
{ code: "bad_description", reason: "empty" },
{ code: "missing_ui_screenshot" },
{ code: "mystery" }
],
{ pr: PR },
),
"wrong base (main); wrong ancestry; bad description (empty); missing UI screenshot; mystery",
"wrong base (main); bad description (empty); missing UI screenshot; mystery",
);
});
});
Expand Down
41 changes: 0 additions & 41 deletions .github/scripts/pr-quality.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ const { READINESS_LATEST_DEV_BEHIND_MAX } = require(
path.join(__dirname, "pr-quality-state.cjs")
);

const ANCESTRY_BEHIND_THRESHOLD = 20;
/** Cap on ahead_by vs main so stale `dev` forks (many commits ahead of main) are not flagged. */
const ANCESTRY_AHEAD_MAIN_MAX = 5;
const MIN_SECTION_LEN = 40;
const MIN_RICH_SECTIONS = 2;
const UNSTRUCTURED_MIN_LEN = 120;
Expand Down Expand Up @@ -106,20 +103,6 @@ const MARKDOWN_REFERENCE_DEF_RE = /^\s*\[([^\]]+)\]:\s*\S+/gm;
/** Embedded HTML image with a renderable `src` (`<img ... src="...">`). */
const HTML_IMAGE_RE = /<img\b[^>]*\bsrc\s*=\s*(?:"[^"]+"|'[^']+'|[^\s>"']+)[^>]*>/i;

function isWrongAncestry({
behindMain,
behindBase,
aheadMain = 0,
threshold = ANCESTRY_BEHIND_THRESHOLD,
aheadMainMax = ANCESTRY_AHEAD_MAIN_MAX,
}) {
return (
behindMain === 0 &&
behindBase >= threshold &&
aheadMain <= aheadMainMax
);
}

function authorHasPushPermission(permission) {
return permission === "admin" || permission === "maintain" || permission === "write";
}
Expand Down Expand Up @@ -528,12 +511,6 @@ function collectPrQualityFailures({
allowedBases,
title = "",
body,
behindMain,
behindBase,
aheadMain = 0,
authorPermission,
permissionLookupFailed = false,
ancestryLookupFailed = false,
/** True when baseRef is another open PR's head (stacked child). */
stackedBase = false,
/** Issue comments; a maintainer comment waives the GUI-screenshot gate. */
Expand All @@ -550,21 +527,6 @@ function collectPrQualityFailures({
const wrongBase = !allowedBases.includes(baseRef) && !stackedBase;
if (wrongBase) {
failures.push({ code: "wrong_base" });
} else {
// Permission lookup fails closed (still evaluate ancestry). Compare API
// failures skip ancestry — zeros would falsely pass the #644 heuristic.
// Stacked children skip ancestry against the integration base; their parent
// PR is the temporary target.
const skipAncestry =
stackedBase ||
ancestryLookupFailed ||
(!permissionLookupFailed && authorHasPushPermission(authorPermission));
if (
!skipAncestry &&
isWrongAncestry({ behindMain, behindBase, aheadMain })
) {
failures.push({ code: "wrong_ancestry" });
}
}

const desc = assessPrDescription(body);
Expand All @@ -587,12 +549,9 @@ function collectPrQualityFailures({
}

module.exports = {
ANCESTRY_BEHIND_THRESHOLD,
ANCESTRY_AHEAD_MAIN_MAX,
REVIEW_READINESS_ITEMS,
REVIEW_READINESS_START,
REVIEW_READINESS_END,
isWrongAncestry,
authorHasPushPermission,
assessPrDescription,
guiPathsChanged,
Expand Down
Loading
Loading