Compare commits

...

5 Commits

Author SHA1 Message Date
diegosouzapw
831bb0f28f Merge release/v3.8.51 into fix/release-v3.8.51-basereds-docs-counts
# Conflicts:
#	AGENTS.md
#	README.md
#	docs/diagrams/comparison-table.svg
#	docs/diagrams/readme-hero.svg
#	docs/i18n/ar/llm.txt
#	docs/i18n/az/llm.txt
#	docs/i18n/bg/llm.txt
#	docs/i18n/bn/llm.txt
#	docs/i18n/cs/llm.txt
#	docs/i18n/da/llm.txt
#	docs/i18n/de/llm.txt
#	docs/i18n/es/llm.txt
#	docs/i18n/fa/llm.txt
#	docs/i18n/fi/llm.txt
#	docs/i18n/fr/llm.txt
#	docs/i18n/gu/llm.txt
#	docs/i18n/he/llm.txt
#	docs/i18n/hi/llm.txt
#	docs/i18n/hu/llm.txt
#	docs/i18n/id/llm.txt
#	docs/i18n/it/llm.txt
#	docs/i18n/ja/llm.txt
#	docs/i18n/ko/llm.txt
#	docs/i18n/mr/llm.txt
#	docs/i18n/ms/llm.txt
#	docs/i18n/nl/llm.txt
#	docs/i18n/no/llm.txt
#	docs/i18n/phi/llm.txt
#	docs/i18n/pl/llm.txt
#	docs/i18n/pt-BR/llm.txt
#	docs/i18n/pt/llm.txt
#	docs/i18n/ro/llm.txt
#	docs/i18n/ru/llm.txt
#	docs/i18n/sk/llm.txt
#	docs/i18n/sv/llm.txt
#	docs/i18n/sw/llm.txt
#	docs/i18n/ta/llm.txt
#	docs/i18n/te/llm.txt
#	docs/i18n/th/llm.txt
#	docs/i18n/tr/llm.txt
#	docs/i18n/uk-UA/llm.txt
#	docs/i18n/ur/llm.txt
#	docs/i18n/vi/llm.txt
#	docs/i18n/zh-CN/llm.txt
#	docs/i18n/zh-TW/llm.txt
#	llm.txt
2026-09-14 19:03:55 -03:00
diegosouzapw
f47f5ad32d fix(ci): allow the opencode v2 plugin in the npm pack policy
check:pack-policy failed on the release tip with 27 'unexpected files',
all of them under @omniroute/opencode-plugin-v2/.

#12870 added that package next to @omniroute/opencode-plugin and
@omniroute/opencode-provider - both already on
PACK_ARTIFACT_ROOT_ALLOWED_PATH_PREFIXES - and package.json's files field
ships the whole @omniroute/ tree, but the allowlist was never widened. The
v2 package has the same shape as the v1 sibling it was modeled on
(LICENSE, README, package.json, src/, tests/, tsconfig.json,
tsup.config.ts), so it gets the same prefix entry.

Reproduced on the clean tip d6f3150 (fails) and with this change (passes) -
check:pack-policy runs --policy-only, so no build is involved.

Refs #12732
2026-09-07 11:46:46 -03:00
diegosouzapw
9656084454 fix(ci): release-green pack gate must check provenance against the branch it validates
The 'Package artifact (npm pack policy)' base-red on release/v3.8.51 was a
false red, and 'Tarball boot-smoke' was its cascade (it is recorded as failed
whenever pack-artifact does not exit 0).

validate-pack-artifact.ts checks dist/BUILD_SHA for ancestry against
OMNIROUTE_RELEASE_REF, defaulting to origin/main. That default is correct at
publication (npm-publish.yml runs on main) but structurally impossible in
validate-release-green.mjs, which runs ON the release branch: mid-cycle its
tip is by definition not an ancestor of main, so the guard returned
off-release-line on every run.

Verified directly against the release tip d6f3150:

  ref=origin/main  ok=false  reason=off-release-line
  ref=HEAD         ok=true   reason=on-release-line

ci.yml already solves the same class for pull_request by pointing the ref at
the head under test; the checkable invariant here is identical - the stamp
matches the tree just validated - so the gate now runs with
OMNIROUTE_RELEASE_REF=HEAD.

The guard is not relaxed: a dist/ built from another commit still fails, and
a missing BUILD_SHA still fails. The parallel slow-gate runner also had to
forward each gate's env, which it previously dropped.

Refs #12732
2026-09-07 10:58:51 -03:00
diegosouzapw
e58014a41a test(models): de-flake the #12058 canonical-catalog regression
The unit suite base-red on release/v3.8.51 was this file, failing on a
different test each run with "500 !== 200" out of getRows().

The 500 is catalog_build_timeout. Every getRows() call resets the builder,
so each one is a cold full-catalog build, and that path is bounded by
CATALOG_BUILD_TIMEOUT_MS (8s by default). Measured on an idle box: the cold
build alone costs ~7.3s with the network stubbed out, and ~9.6s once the
fire-and-forget upstream usage refreshes (api.anthropic.com,
cloudcode-pa.googleapis.com, aihorde.net) land on top. The margin against
the 8s bound is what decides the run, which is why the failing test moved
around between runs.

That budget is not the subject of this regression - canonical-mode row
shaping is - so the bound is pinned out of the way, exactly as
tests/unit/12627-catalog-inflight-timeout.test.ts already does for the
opposite direction. No assertion is changed, removed or relaxed.

Refs #12732
2026-09-07 10:44:43 -03:00
diegosouzapw
41d379d880 fix(ci): clear the docs-counts base-red on release/v3.8.51
check:docs-counts-sync reported 6 STRICT drifts against the live code:

- DB migrations: docs still said 169, the code has 171 (README.md,
  AGENTS.md, llm.txt and the 41 exact-copy llm.txt locale mirrors).
- Routing strategies: readme-hero.svg, comparison-table.svg and
  tier-cascade.svg still said "19 routing strategies"; the code has 20.

Counts only - no prose or behavior changed. The llm.txt mirrors are
byte-exact copies below their locale header, so the same substitution was
applied in place rather than re-copying the root file (a blanket copy
would drop each mirror's title and language bar).

Refs #12732
2026-09-07 10:37:11 -03:00
6 changed files with 34 additions and 1 deletions

View File

@@ -0,0 +1 @@
- **test(models):** Pin `CATALOG_BUILD_TIMEOUT_MS` in the #12058 canonical-catalog regression so a cold catalog build racing the 8s default bound no longer flakes the suite with a 500 ([#12732](https://github.com/diegosouzapw/OmniRoute/issues/12732))

View File

@@ -0,0 +1 @@
- **fix(ci):** Allow `@omniroute/opencode-plugin-v2/` in the npm pack policy — [#12870](https://github.com/diegosouzapw/OmniRoute/pull/12870) shipped the v2 plugin beside its v1 sibling without widening the allowlist, so every packed file under it read as an unexpected artifact and failed `check:pack-policy` ([#12732](https://github.com/diegosouzapw/OmniRoute/issues/12732))

View File

@@ -0,0 +1 @@
- **fix(ci):** Point the release-green validator's pack gate at the tree it is validating — the build-provenance guard defaulted to `origin/main`, which a release branch tip can never be an ancestor of mid-cycle, so `Package artifact` reported a false red on every run and the tarball boot-smoke cascaded off it ([#12732](https://github.com/diegosouzapw/OmniRoute/issues/12732))

View File

@@ -169,6 +169,9 @@ export const PACK_ARTIFACT_ROOT_ALLOWED_EXACT_PATHS: string[] = [
export const PACK_ARTIFACT_ROOT_ALLOWED_PATH_PREFIXES: string[] = [
"@omniroute/opencode-plugin/",
// #12870 shipped the v2 plugin beside its v1 sibling but never widened this
// allowlist, so every packed file under it read as an unexpected artifact.
"@omniroute/opencode-plugin-v2/",
"@omniroute/opencode-provider/",
"bin/cli/",
// Broad open-sse + src source dirs added to package.json "files" in v3.8.21

View File

@@ -399,6 +399,22 @@ export function classifyRunError(err, timeoutMs) {
// every one a false-positive red against the release branch).
const HERMETIC_SCRUB = ["OMNIROUTE_API_KEY", "OMNIROUTE_URL"];
let hermetic = false;
/**
* Env for the pack gate's provenance guard (#10427).
*
* `validate-pack-artifact.ts` checks `dist/BUILD_SHA` for ancestry against
* `OMNIROUTE_RELEASE_REF`, defaulting to `origin/main`. That default is right at
* PUBLICATION (npm-publish.yml runs on main) but structurally impossible here: this
* validator runs ON a release branch, whose tip is by definition NOT an ancestor of
* main mid-cycle, so the gate reported `off-release-line` on every single run and the
* tarball boot-smoke cascaded off it. `ci.yml` already resolves the same problem for
* `pull_request` by pointing the ref at the head under test; the checkable invariant
* here is identical — "the stamp matches the tree we just validated" — so point it at
* HEAD. This does not relax the guard: a dist/ built from some other commit still
* fails, and a missing BUILD_SHA still fails.
*/
const PACK_GATE_ENV = { OMNIROUTE_RELEASE_REF: "HEAD" };
function buildGateEnv(extra) {
const env = { ...process.env, FORCE_COLOR: "0", ...(extra || {}) };
if (hermetic) for (const k of HERMETIC_SCRUB) delete env[k];
@@ -698,12 +714,13 @@ async function main() {
id: "pack-artifact",
label: "Package artifact (npm pack policy)",
args: ["run", "check:pack-artifact"],
env: PACK_GATE_ENV,
timeout: 20 * 60 * 1000,
});
}
slow.forEach((g) => announce(`${g.label} [parallel]`));
const slowResults = await Promise.all(
slow.map((g) => runAsync(npmCmd, g.args, { timeout: g.timeout }))
slow.map((g) => runAsync(npmCmd, g.args, { timeout: g.timeout, env: g.env }))
);
slow.forEach((g, i) => {
const { code, out } = slowResults[i];
@@ -754,6 +771,7 @@ async function main() {
} else if (WITH_BUILD) {
// --with-build without the suites (--quick): still verify the package artifact.
const { code, out } = await runAsync(npmCmd, ["run", "check:pack-artifact"], {
env: PACK_GATE_ENV,
timeout: 20 * 60 * 1000,
});
saveGateLog("pack-artifact", out);

View File

@@ -24,6 +24,15 @@ import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-12058-"));
process.env.DATA_DIR = TEST_DATA_DIR;
// Every `getRows()` call resets the builder, so each one is a *cold* catalog
// build. That path is bounded by `CATALOG_BUILD_TIMEOUT_MS` (8s by default),
// and a cold build of the full catalog already costs ~7s on an idle box before
// the fire-and-forget upstream usage refreshes land — so on a loaded CI runner
// the bound trips and `getRows()` sees a 500 instead of the rows under test.
// That budget is not what this regression covers (row shaping in canonical
// mode is), so pin it out of the way exactly like #12627 does. Every
// assertion below is unchanged.
process.env.CATALOG_BUILD_TIMEOUT_MS = "120000";
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");