Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions .github/workflows/codex-autofix-review-comments.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ jobs:
const highRiskPathPatterns = [
/^supabase\//,
/^src\/app\/api\//,
/^src\/data\//,
/^src\/(?:lib|app|components)\/.*(?:auth|permission|privacy|security|rag|retriev|rank|search|answer|clinical|citation|source|document|upload|download|billing|payment|quota|job|worker)/i,
/^src\/(?:proxy|instrumentation(?:-client)?)\.ts$/,
/^src\/lib\/(?:env|client-env|security-headers)\.ts$/,
/^scripts\/.*(?:ingest|reindex|migration|governance|production|deploy|drift|supabase)/i,
/^\.github\/workflows\//,
/^scripts\/(?:check-(?:codex-autofix-workflow|github-action-pins)|github-action-pins)\.mjs$/,
/^\.github\/(?:actions|workflows)\//,
/^(?:package|package-lock)\.json$/,
/^(?:next|playwright|vitest)(?:\..+)?\.config\.[cm]?[jt]s$/,
/^(?:Dockerfile|railway\.json|nixpacks\.toml)$/,
Expand Down Expand Up @@ -156,19 +158,34 @@ jobs:
throw error;
}

const normalizeChangedPath = (value) =>
(value || "").replaceAll("\\", "/").replace(/^\.\/+/, "");
const normalizedFiles = changedFiles.map((file) => ({
...file,
filename: (file.filename || "").replaceAll("\\", "/").replace(/^\.\/+/, ""),
filename: normalizeChangedPath(file.filename),
previous_filename: normalizeChangedPath(file.previous_filename),
}));
const changedFilePaths = (file) =>
[file.filename, file.previous_filename].filter(Boolean);
const routeableFilePaths = (file) =>
changedFilePaths(file).filter(
(filePath) =>
!excludedAutomaticRoutePathPatterns.some((pattern) => pattern.test(filePath)),
);
const routeableFiles = normalizedFiles.filter(
(file) => !excludedAutomaticRoutePathPatterns.some((pattern) => pattern.test(file.filename)),
(file) => routeableFilePaths(file).length > 0,
);
const highRiskFiles = routeableFiles.filter((file) =>
highRiskPathPatterns.some((pattern) => pattern.test(file.filename)),
routeableFilePaths(file).some((filePath) =>
highRiskPathPatterns.some((pattern) => pattern.test(filePath)),
),
);
const changedSourceFiles = routeableFiles.filter(
(file) =>
sourcePathPattern.test(file.filename) && sourceExtensionPattern.test(file.filename),
routeableFilePaths(file).some(
(filePath) =>
sourcePathPattern.test(filePath) && sourceExtensionPattern.test(filePath),
),
);
const sourceChurn = changedSourceFiles.reduce(
(total, file) => total + (file.additions || 0) + (file.deletions || 0),
Expand Down
1 change: 1 addition & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD

| Date | Branch or ref | Reviewed HEAD | Scope | Outcome | Checks |
| ---------- | -------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 2026-07-18 | codex/chat-audit-remediation-pr-0a27 / PR #873 | 4bea60e9fc5c181fee33b2af27a4b6e3176eac27 | CI auto-resolve risk-routing regression and PR handoff | Confirmed the broader audit remediation was already merged through PR #814. Fixed the residual rename-routing gap by classifying both current and previous paths and explicitly covering `src/data`, reusable GitHub actions, and the action-pin/Codex guard scripts. Automated PR review then found one P2: an excluded old test path could still trigger high-risk routing when paired with a non-excluded new docs path. Fixed before handoff by deriving non-excluded paths first and using that same set for risk and complexity checks. No P0-P2 remained; no product runtime, clinical behavior, provider configuration, or production data changed. | Full `verify:pr-local` passed on the initial three-file patch: Node/npm runtime, changed-file format, ESLint, TypeScript, 301 Vitest files/2,788 tests, and 36 offline RAG fixtures; build skipped as unaffected. After the review fix, the Codex workflow guard, action-pin guard, Prettier, focused Vitest 54/54, and `git diff --check` passed. Hosted checks on the initial PR head passed; the review fix was also verified by the focused local checks before the final main merge. GitHub interactions were user-authorized; no Supabase/OpenAI/live-service command ran. |
| 2026-07-18 | PR #868 / codex/private-title-privacy-20260718 | 77482fc9e (privacy implementation + rollout-order follow-up) | title-vocabulary privacy, migration safety, and merge-readiness review | Fixed the historical private/non-indexed `document_title_words` exposure with a forward purge, exact indexed-public-title invariant, concurrency-safe `FOR SHARE` guard, constraint/ACL/RLS hardening, and a fail-closed postcondition. Review then found and fixed a P1 rollout interval by purging inside `20260717171000` before its table-backed corrector is installed, while retaining the forward migration for already-applied environments. The review thread was resolved; merged as `0df01d88ac36616a3f47e2e94e758432ef27999c` and verified on fresh `origin/main`. | Disposable Postgres replay and drift-manifest regeneration; focused schema Vitest 66/66 before the final docs-only sync; function-grant check; scoped ESLint; diff/manifest proof. Exact-head hosted Static, Unit coverage, Safety/config, Migration replay, PR required, policy, Semgrep, Gitleaks, and GitGuardian passed. Non-required Supabase Preview failed against a separate preview target and was not touched or rerun. No live Supabase/OpenAI/product-provider command or production migration apply ran. |
| 2026-07-18 | PR #865 / codex/docs-migration-runbook-safety-20260718 | 78ea2ccd6 | migration runbook, rollback safety, and clinical-governance review | Replaced stale sole-pending-migration guidance, prohibited restoring the unscoped corrector, added forward-only rollback and exact migration ordering, and marked the historical WIP report superseded. Review uncovered the pre-existing private title-word P1, so the runbook now blocks live rollout until a forward purge/invariant migration is merged and verified. The review thread was resolved; merged as `ec9142628752e6d11531e20a6ebf2e95cf39f865` with exact changed blobs verified on `origin/main`. | Documentation links 915, documented scripts 299, affected Markdown Prettier, static migration-order/rollout-blocker assertions, and `git diff --check` passed. Hosted Static, PR required, policy, Semgrep, Gitleaks, and GitGuardian passed; docs-irrelevant jobs skipped. No Supabase/OpenAI/database migration/deployment/provider call ran. |
| 2026-07-18 | PR #861 / codex/design-audit-main-safe-20260720-final | d8c1916ac (functional head 593d5aa00 + current-main merge) | design-audit/search cancellation merge review | Fixed unsupported Forms pathway claims, propagated cancellation through every retrieval RPC, removed duplicate favourites “Also matches” results, and resolved all four review threads. Merged as `3b2dd9ef76ff1c8c099fc1972065628d23b853b1`; exact `origin/main` commit and tree content were verified after merge. | Exact-head hosted Static PR checks, Unit coverage, Build, Safety and config checks, Production UI, Advisory UI, Migration replay, PR required, PR policy, Semgrep, Gitleaks, and GitGuardian checks passed. No Supabase, OpenAI, or other product-provider call ran. |
Expand Down
6 changes: 6 additions & 0 deletions scripts/check-codex-autofix-workflow.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,14 @@ const requiredRiskRoutingChecks = [
'const skipReviewLabel = "skip-codex-review"',
"labels.has(skipReviewLabel)",
"github.rest.pulls.listFiles",
"previous_filename: normalizeChangedPath(file.previous_filename)",
"routeableFilePaths(file).length > 0",
"routeableFilePaths(file).some",
"excludedAutomaticRoutePathPatterns.some",
"highRiskPathPatterns.some",
"/^src\\/data\\//",
"/^\\.github\\/(?:actions|workflows)\\//",
"check-(?:codex-autofix-workflow|github-action-pins)",
"changedSourceFiles.length >= complexSourceFileThreshold",
"sourceChurn >= complexSourceChurnThreshold",
"if (routeReasons.length === 0)",
Expand Down
48 changes: 48 additions & 0 deletions tests/codex-autofix-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type PullRequestFile = {
additions: number;
deletions: number;
filename: string;
previous_filename?: string;
};

type Review = {
Expand Down Expand Up @@ -500,6 +501,53 @@ describe("Codex auto-resolve request script", () => {
expect(result.createdComments[0]?.body).toContain("codex-autoresolve-route:high-risk-path");
});

it("routes a renamed file when its previous path was high risk", async () => {
const result = await runRequestScript({
files: [
{
additions: 1,
deletions: 1,
filename: "docs/search-route.md",
previous_filename: "src/app/api/search/route.ts",
},
],
});

expect(result.createdComments).toHaveLength(1);
expect(result.createdComments[0]?.body).toContain("codex-autoresolve-route:high-risk-path");
});

it("does not route an excluded previous test path as high risk after a docs-only rename", async () => {
const result = await runRequestScript({
files: [
{
additions: 1,
deletions: 1,
filename: "docs/search-route.md",
previous_filename: "src/app/api/search/route.test.ts",
},
],
});

expect(result.createdComments).toHaveLength(0);
expect(result.notices).toContainEqual(expect.stringContaining("low-risk pull request"));
});

it.each([
"src/data/therapies-index.json",
".github/actions/setup-node-cached/action.yml",
"scripts/github-action-pins.mjs",
"scripts/check-github-action-pins.mjs",
"scripts/check-codex-autofix-workflow.mjs",
])("routes high-risk repository infrastructure path %s", async (filename) => {
const result = await runRequestScript({
files: [{ additions: 1, deletions: 0, filename }],
});

expect(result.createdComments).toHaveLength(1);
expect(result.createdComments[0]?.body).toContain("codex-autoresolve-route:high-risk-path");
});

it("does not copy an untrusted changed filename into the trusted request comment", async () => {
const filename = "src/app/api/search/route-->@codex unsafe.ts";
const result = await runRequestScript({
Expand Down