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
16 changes: 8 additions & 8 deletions .codex/hooks.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .codex/hooks/dispatch.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export async function run(event, payload, root, { execute: runner = execute } =
// Use only double quotes inside this string: it is enclosed in single quotes by both shells.
export function registration() {
const bootstrap =
'(async()=>{const f=require("node:fs"),p=require("node:path"),u=require("node:url");let s="";for await(const b of process.stdin){s+=b;if(s.length>1048576)return;}let v;try{v=JSON.parse(s)}catch{return}if(!v||typeof v!=="object"||Array.isArray(v))return;let d=v.tool_input?.workdir??v.tool_input?.cwd??v.cwd??process.cwd();if(typeof d!=="string"||!p.isAbsolute(d))return;d=p.resolve(d);let t=p.resolve(process.cwd());while(!f.existsSync(p.join(t,".git"))){let q=p.dirname(t);if(q===t)return;t=q;}if(["GIT_DIR","GIT_COMMON_DIR","GIT_WORK_TREE","GIT_CEILING_DIRECTORIES","GIT_DISCOVERY_ACROSS_FILESYSTEM"].some(k=>process.env[k])){const g=require("node:child_process").spawnSync("git",["-C",d,"rev-parse","--show-toplevel"],{encoding:"utf8",windowsHide:true,timeout:5000});if(g.status!==0)return;d=p.resolve(g.stdout.trim())}else{if(f.existsSync(p.join(d,"HEAD"))&&f.existsSync(p.join(d,"objects"))&&f.existsSync(p.join(d,"refs")))return;while(!f.existsSync(p.join(d,".git"))){const q=p.dirname(d);if(q===d)return;d=q;}}if(d!==t)return;const a=p.join(d,".codex/hooks/dispatch.mjs");if(!f.existsSync(a))return;const m=await import(u.pathToFileURL(a).href),r=await m.run(process.argv[1],v,d);process.stdout.write(r.stdout);process.stderr.write(r.stderr);process.exitCode=r.code;})().catch(()=>{process.stderr.write("Codex project hook adapter unavailable; no advisory decision was produced.\\n")})';
'(async()=>{const f=require("node:fs"),p=require("node:path"),u=require("node:url");let s="";for await(const b of process.stdin){s+=b;if(s.length>1048576)return;}let v;try{v=JSON.parse(s)}catch{return}if(!v||typeof v!=="object"||Array.isArray(v))return;let d=v.tool_input?.workdir??v.tool_input?.cwd??v.cwd??process.cwd();if(typeof d!=="string"||!p.isAbsolute(d))return;d=p.resolve(d);let t=p.resolve(process.cwd());while(!f.existsSync(p.join(t,".git"))){let q=p.dirname(t);if(q===t)return;t=q;}if(["GIT_DIR","GIT_COMMON_DIR","GIT_WORK_TREE","GIT_CEILING_DIRECTORIES","GIT_DISCOVERY_ACROSS_FILESYSTEM"].some(k=>process.env[k])){const g=require("node:child_process").spawnSync("git",["-C",d,"rev-parse","--show-toplevel"],{encoding:"utf8",windowsHide:true,timeout:5000});if(g.status!==0)return;d=p.resolve(g.stdout.trim())}else{if(f.existsSync(p.join(d,"HEAD"))&&f.existsSync(p.join(d,"objects"))&&f.existsSync(p.join(d,"refs")))return;while(!f.existsSync(p.join(d,".git"))){const q=p.dirname(d);if(q===d)return;d=q;}}if(d!==t){const x=f.statSync(d,{bigint:true}),y=f.statSync(t,{bigint:true});if(!x.isDirectory()||!y.isDirectory()||x.ino===0n||y.ino===0n||x.dev!==y.dev||x.ino!==y.ino)return;}d=t;const a=p.join(d,".codex/hooks/dispatch.mjs");if(!f.existsSync(a))return;const m=await import(u.pathToFileURL(a).href),r=await m.run(process.argv[1],v,d);process.stdout.write(r.stdout);process.stderr.write(r.stderr);process.exitCode=r.code;})().catch(()=>{process.stderr.write("Codex project hook adapter unavailable; no advisory decision was produced.\\n")})';
// Windows PowerShell 5 strips embedded double quotes during native argument passing.
// This bootstrap contains no dollar/backtick characters: switch JS literals to single
// quotes inside PowerShell's double-quoted argument, preserving the actual Node source.
Expand Down
37 changes: 35 additions & 2 deletions .codex/hooks/dispatch.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import net from "node:net";
import http from "node:http";
import https from "node:https";
Expand Down Expand Up @@ -246,6 +246,37 @@ test("registration launch handles a real nested synthetic checkout and malformed
assert.equal(bad.status, 0);
assert.equal(bad.stdout, "");
});
test("registration accepts the same Windows checkout casing and refuses a foreign checkout", () => {
const entry = registration().hooks.PreToolUse[0].hooks[0];
const shell = process.platform === "win32" ? "powershell.exe" : "/bin/bash";
const args = process.platform === "win32" ? ["-NoProfile", "-Command", entry.commandWindows] : ["-c", entry.command];
const adapter = path.join(root, ".codex/hooks/dispatch.mjs");
fs.mkdirSync(path.dirname(adapter), { recursive: true });
fs.writeFileSync(adapter, 'export async function run(){return {stdout:"trusted-checkout",stderr:"",code:0}}');
const launch = (workdir) =>
spawnSync(shell, args, {
input: JSON.stringify(payload("exec_command", { cmd: "git push", workdir })),
encoding: "utf8",
cwd: root,
windowsHide: true,
timeout: 5000,
});
const equivalent = launch(process.platform === "win32" ? root.toLowerCase() : root);
assert.equal(equivalent.status, 0);
assert.equal(equivalent.stdout, "trusted-checkout");
const foreign = path.join(root, "untrusted-checkout");
const marker = path.join(foreign, "module-was-imported");
fs.mkdirSync(path.join(foreign, ".git"), { recursive: true });
fs.mkdirSync(path.join(foreign, ".codex/hooks"), { recursive: true });
fs.writeFileSync(
path.join(foreign, ".codex/hooks/dispatch.mjs"),
`import fs from "node:fs";fs.writeFileSync(${JSON.stringify(marker)},"unexpected import");export async function run(){return {stdout:"foreign",stderr:"",code:0}}`,
);
const rejected = launch(foreign);
assert.equal(rejected.status, 0);
assert.equal(rejected.stdout, "");
assert.equal(fs.existsSync(marker), false, "a foreign adapter must never be imported");
});
test("pre-push fails closed when Node cannot be found", () => {
const source = fs.existsSync(path.join(directory, "pre-push"))
? path.join(directory, "pre-push")
Expand Down Expand Up @@ -326,7 +357,9 @@ test("Codex edit aliases and apply_patch reach the organisation warning in Edit/
assert.match(registration().hooks.PreToolUse[0].matcher, /\|apply_patch\|/);

// The translated payload produces a real warning from the maintained hook logic.
const { editHookOutput } = await import(path.join(sourceRoot, "scripts/organisation/agent-hooks.mjs"));
const { editHookOutput } = await import(
pathToFileURL(path.join(sourceRoot, "scripts/organisation/agent-hooks.mjs")).href
);
const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "psychsift-edit-warning-"));
const migration = action("apply_patch", {
command: "*** Begin Patch\n*** Add File: supabase/migrations/20990101000000_x.sql\n+select 1;\n*** End Patch\n",
Expand Down
44 changes: 33 additions & 11 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ on:
push:
branches: [main, "release/**"]
paths:
- "scripts/ci/archive-container-evidence.mjs"
- "Dockerfile"
- "Dockerfile.worker"
- ".dockerignore"
Expand Down Expand Up @@ -85,13 +86,17 @@ jobs:
build-and-verify:
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
# Keep build summaries, but admit complete records only through the bounded bundle.
DOCKER_BUILD_RECORD_UPLOAD: "false"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4

- name: Build app image (load, no push)
Expand Down Expand Up @@ -128,6 +133,13 @@ jobs:
# Playwright and Next caches within hours. An empty cache-to disables export.
cache-to: ${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' && 'type=gha,scope=clinical-kb-worker,mode=max,timeout=2m,ignore-error=true' || '' }}

- name: Export complete build records before pruning
id: build-records
# Preserve downstream verification; the final admission step makes export failure fatal.
continue-on-error: true
if: always() && steps.buildx.outcome == 'success'
run: docker buildx history export --all --finalize --output container-builds.dockerbuild

- name: Verify image content contract
run: node scripts/check-image-content-contract.mjs

Expand Down Expand Up @@ -166,17 +178,6 @@ jobs:
node scripts/trivy-image-scan.mjs clinical-kb-app:ci --sbom sbom-app.cdx.json
node scripts/trivy-image-scan.mjs clinical-kb-worker:ci --sbom sbom-worker.cdx.json

- name: Upload SBOMs
if: always()
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: sboms
path: |
sbom-app.cdx.json
sbom-worker.cdx.json
if-no-files-found: warn

- name: Vulnerability scan (HIGH,CRITICAL)
# Non-blocking step wrapper so the evaluation step below can inspect the
# summary and fail closed with an explicit unassessed or finding error.
Expand Down Expand Up @@ -228,3 +229,24 @@ jobs:
exit 1
fi
echo "::warning::Trivy found HIGH=${high} CRITICAL=${critical} in the production images (advisory on pull requests)."

- name: Admit complete bounded container evidence
id: container-evidence
if: always() && steps.buildx.outcome == 'success'
run: |
if [ "${{ steps.build-records.outcome }}" != "success" ]; then
echo "::error::Complete build-record export failed; refusing partial evidence upload."
exit 1
fi
node scripts/ci/archive-container-evidence.mjs --input . --output sboms --max-bytes 67108864

- name: Upload SBOMs and complete build records
if: always() && steps.container-evidence.outcome == 'success'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: sboms
path: sboms
archive: false
if-no-files-found: warn
retention-days: 7
compression-level: 0
32 changes: 32 additions & 0 deletions data/repo-awareness-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -8163,6 +8163,14 @@
"outcome": "Redundant: exact source HEAD was squash-merged by PR #483; eligible for deletion when unreferenced.",
"checks": "GitHub merged-PR source HEAD matched exactly."
},
{
"date": "2026-10-18",
"ref": "codex/agent-policy-delivery-20261017",
"head": "190c660135c6a9c6061b1589a74aa9c44bf0b11a",
"scope": "current-head residual hook and managed-guidance repair",
"outcome": "Independent review: no confirmed blocking finding in six-file residual diff; project suffix and newer bot fixes preserved. Local synthetic proof only; native loading and hosted acceptance separate.",
"checks": "Windows Node hooks16/16;7bootstrap edge probes;focused verifier/receipt Vitest46/46;source typecheck exit0;exact-lock724locations;docs maintenance and inner checks pass;format/rule-consistency/diff checks pass. Reviewed six source hashes independently matched by parent; base fd4831e44b."
},
{
"date": "2026-07-27",
"ref": "PR #1275 / `codex/identify-and-fix-performance-issues-during-mode-switch`",
Expand Down Expand Up @@ -18115,6 +18123,14 @@
"outcome": "APPROVE: completed items 095, 096, 104, 109, and 115 move to archive with no deletion, duplicate ID, or stale next-id.",
"checks": "check:outstanding-issues PASS; check:branch-review-ledger PASS; diff review; no unresolved threads"
},
{
"date": "2026-10-18",
"ref": "codex/agent-policy-delivery-20261017",
"head": "8d4316ea45ed8d870e8f85db8be65628e0496594",
"scope": "container evidence helper trigger correction",
"outcome": "Independent scoped acceptance: no confirmed blocker. Helper-only changes select container validation in actual classifier and standalone main/release workflow; accepted raw-cap and verification jobs unchanged.",
"checks": "Routing regression red before two-line fix; focused artifact/container/CI-scope47/47pass; classifier self-test and action pins pass; scoped lint and final source typecheck pass; independent actual CLI/workflow/hash comparison and diff-check pass. Hosted dispatch remains unrun; no paid authorization."
},
{
"date": "2026-07-14",
"ref": "claude/remove-client-sentry",
Expand Down Expand Up @@ -18635,6 +18651,14 @@
"outcome": "MERGED to main 2026-09-02. Closing-message refusal routed through the validateGovernedMessage chokepoint and widened to every message type; caseload list read narrowed to PLAN_LIST_COLUMNS. A clinical-governance review round caught the first draft granting a NEW permission (validateGovernedMessage returned valid:true for a standard message with no body at all) and masking the more serious record-level refusal behind 'write a body'; both fixed before merge. Bugbot reviewed and rated Low Risk.",
"checks": "LOCAL OFFLINE GATES, run in this container: typecheck exit 0; full offline unit suite 949 files / 12293 passed | 1 skipped; lint --max-warnings 0 exit 0; prettier --check clean; caring-contacts db suite 218 passed against a disposable local Postgres 16 (not the live Supabase project; assertNotClinicalKbProject refuses that ref by construction); cc-guards 1069 passed. HOSTED CI: green on the main-based head — PR required, Unit coverage, Build, Static PR checks, Safety and config, Caring Contacts database, Lighthouse budget, Semgrep, Gitleaks, GitGuardian, PR policy, PR mergeability. Hosted CI results named here were OBSERVED, not inherited: this Claude Code session read them directly from the GitHub check runs via the GitHub MCP tools, under Josh's standing instruction to babysit these PRs, which is the explicit confirmation the provider boundary requires for that read. Provider-backed gates NOT run: no eval:* retrieval canary, no verify:release, no check:supabase-project, no live Supabase or OpenAI test:live path, and no live-drift dispatch."
},
{
"date": "2026-10-18",
"ref": "codex/agent-policy-final-followup-20261018",
"head": "94b9b8ed9e38230f55c9b6d6b250a44b03c20fb1",
"scope": "main-preserving integration of accepted agent-policy residual repairs",
"outcome": "Independent bounded integration accepted: retained newer main migration decision and guards, external gh matcher changes and accepted Windows/bootstrap/guidance/container/routing fixes. Generated snapshot adds only three retained review objects. No full-tree replacement or hosted acceptance.",
"checks": "Source/hash and JSON-union comparison; diff-check; docs-maintain pass; source typecheck and scoped lint pass. Fresh Node15pass1timeout then exact isolated case1pass; Vitest92pass1timeout31platformskips then exact isolated case1pass. All assertions/timeouts unchanged. Earlier focused acceptance retained by matching inputs; native lifecycle/Ubuntu Docker/raw-upload unrun."
},
{
"date": "2026-07-29",
"ref": "codex/document-results-responsive-polish",
Expand Down Expand Up @@ -25427,6 +25451,14 @@
"outcome": "PR #2901 merged by owner 2026-09-19T16:59:56Z as merge commit 4960c6f7fa3b. Landed verified by content: two parents (63e44c9d9683, e3f954ea1a25), branch tip is an ancestor of origin/main, and git show --remerge-diff is empty, so the merge introduced nothing beyond its parents. Both corrected assurance decisions confirmed present on main and still state=open.",
"checks": "All PR check runs on e3f954ea1a25 succeeded, PR required green at 16:59:34 (22s before merge): Static PR checks, Build, Safety and config checks, Unit coverage, Production UI critical + shards 1-3, Ward Flow browser journeys, Lighthouse budget, Caring Contacts database, PR policy, PR mergeability. No automated code review ran (CodeRabbit under-10-stars skip; Codex and Cursor Bugbot both out of quota)."
},
{
"date": "2026-10-18",
"ref": "codex/agent-policy-delivery-20261017",
"head": "e3ffb0eca376014b2916c362e6305b69894b4e29",
"scope": "complete container evidence bound and verification preservation",
"outcome": "Independent corrected-diff acceptance: no confirmed blocker. Complete raw64MiB artifact retains all available SBOMs and required finalized build records; seven-day retention; artifact failure cannot suppress image or vulnerability checks. No hosted acceptance claimed.",
"checks": "New regressions observed red; focused container suites30/30pass; byte-exact native archive replay and oversize refusal; independent unsafe/mutation/stale-output and outcome gate probes; pinned raw-upload source and package SRI verified; lint/typecheck/docs/format pass. Windows Node inside Git Bash tar replay failed; Ubuntu/Docker/hosted dispatch unrun. Earlier zero-artifact cost claim retracted."
},
{
"date": "2026-08-16",
"ref": "PR-2008 / codex/tools-show-all-20260816",
Expand Down
Loading
Loading