# Project export: TraceForge

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Modernize undocumented workflows without guessing.
- Devpost: https://devpost.com/software/traceforge-3r561i
- GitHub: https://github.com/a252937166/traceforge
- Demo: https://traceforge.axiqo.xyz/
- Video: https://www.youtube.com/embed/xQnKzDhUCl0?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Mr.ooo (4 commits)

## Devpost submission (written by the team)

### Inspiration

Critical workflows often survive because nobody is confident enough to replace them. Their real rules are scattered across UI behavior, API responses, database side effects, and operator memory. Generating a cleaner interface is easy; proving that refunds, approvals, inventory, and failure atomicity still behave correctly is the hard part. TraceForge is built around that missing proof. Instead of asking an AI to guess a specification from a few screenshots, it treats migration as an experiment: observe behavior, expose uncertainty, choose the next counterexample, rebuild inside a narrow evidence boundary, and let an independent verifier decide what matches.

### What it does

TraceForge runs one bounded legacy workflow through five server-owned stages: Observe records legacy decisions and SQLite before/after state. Infer asks a read-only GPT-5.6 Sol Trace Archaeologist for narrow, evidence-linked hypotheses, invariants, and explicit unknowns. Challenge asks Counterexample Hunter turns for discriminating inputs. The host—not the model—executes those inputs and exact boundary probes, then a Contract Critic resolves the behavior contract. Build gives Codex the contract, four failed proofs, and only disclosed scenarios. Codex can edit one workflow file in a detached worktree; it cannot change the verifier, commit, push, or deploy. Verify creates one verification-only input after the writing turn, resets both systems, and compares five deterministic fields across seven scenarios. The demo begins with a $45 standard damaged return and a $120 VIP damaged return. Crossed and boundary inputs reveal an undocumented priority rule: damaged returns at or above $500 enter manual review before tier-specific behavior. A zero-stock probe exposes another hidden requirement: a replacement must fail atomically with no return record or inventory side effects. Codex repairs rule priority, inventory disposition, and stockout atomicity. The host finishes at 7/7 scenarios, 35/35 assertions, and zero mismatches. The contract is intentionally narrow. It covers the observed DAMAGED branch. Non-damaged inputs are rejected with a typed OUTSIDE_EVIDENCE_BOUNDARY result before persistence or side effects, so the generated candidate cannot silently invent unsupported behavior.

### How we built it

gpt-5.6-sol performs four read-only, schema-constrained archaeology turns: Trace Archaeologist, two Counterexample Hunter turns, and Contract Critic. The host validates every cited evidence ID and executes every proposed scenario itself. OpenAI Codex SDK performs the single code-writing role in an isolated detached Git worktree. The repair input is immutable and contains the exact contract, four failed proofs, and disclosed scenario pack. A one-file allowlist prevents the writer from editing the verifier, tests, repository history, or deployment. TypeScript, Node.js, Express, node:sqlite, React, Vite, pnpm, native Server-Sent Events, Git worktrees, and JSON Schema form the product runtime. Deterministic assertions compare decision, return status, refund amount, sellable inventory, quarantine inventory, and failure atomicity. SHA-256 digests bind model inputs and outputs, repair inputs, candidate source and diff, commands, artifacts, evidence, scenario sets, and proof bodies. Why GPT-5.6 and Codex are essential GPT-5.6 is not a chat layer. In the authenticated source migration it completed four evidence-producing turns totaling 121,673 tokens. Each turn preserves its bounded application prompt, structured output, thread ID, timing, usage, digests, and cited evidence IDs. Its most important job is not summarization; it is choosing the next observation that separates plausible hidden rules. Codex receives the resolved contract and the real failed proofs. It changed one permitted TypeScript workflow module. The system then ended the writing turn and handed control to a host-owned verifier. The writer never sees the verification-only scenario while editing and cannot issue its own passing proof.

### Challenges we ran into

The hardest problem was separation of powers. A model that proposes a rule or writes code cannot also execute the legacy workflow or certify its own result. The host therefore owns scenario execution, evidence-ID validation, state resets, policy enforcement, tests, and proof issuance. We also learned that provenance has two different meanings. The original successful source proof must remain byte-for-byte reproducible, while the current application needs to prove which scenario set and recorded verifier artifact it is replaying today. TraceForge now preserves the historical object and wraps it in a separately verifiable v2 evidence envelope that binds the current scenario set and generated verifier artifact. The Local Runner exposed useful failures too: revoked authentication, usage limits, unsafe candidate patterns, and an older verifier fixture that did not reject out-of-contract inputs. We kept the policy fail-closed and added a host-owned SELLABLE boundary probe. A local proof can be issued only when the candidate rejects that input before any result or side effect. Accomplishments we are proud of Four real GPT-5.6 turns produce inspectable evidence and explicit uncertainty rather than a predetermined contract behind a chat UI. The unknown lifecycle is enforced: Build cannot begin while an in-scope blocking unknown remains. Codex receives the real contract and failed proofs but cannot edit or invoke the verifier. The source candidate passed 56/56 candidate-safe tests; four replay-integrity guards stay separate and visible. The final differential matrix passed 7/7 scenarios and 35/35 assertions with zero mismatches. Historical proof integrity and current replay binding can be checked independently. The public replay is honest: recorded GPT/Codex provenance plus a fresh host proof, not a disguised live model call. Judges can optionally run a fresh build with their own Codex through a pinned, loopback-only Local Runner. No credentials, generated source, session handles, or local files leave their machine.

### What we learned

The trustworthy output of AI-assisted modernization is not code alone. It is code plus evidence provenance, preserved failures, an explicit evidence boundary, a verifier outside the writer's control, and a precise statement of what was covered. The model's most valuable behavior was choosing the next experiment; the system's most valuable behavior was refusing to let the writer grade itself.

### What's next

Next we will add browser-extension capture for real web applications, redacted evidence envelopes, separate legacy and candidate services, signed append-only proof bundles, more database adapters, and maintainer-approved pull-request publication. Deterministic assertions and human-controlled promotion will remain the authority for proof and deployment. Scope and limitations This submission demonstrates one controlled Web returns workflow in a TypeScript process with REST and SQLite. It does not claim universal behavioral equivalence or arbitrary-application reconstruction. The proof claims conformance only for the seven executed scenarios and asserted fields. The public deployment does not expose an anonymous write-capable model trigger; the optional Local Runner is the explicit path for a fresh Codex build. Try it Live product: https://traceforge.axiqo.xyz Source code: https://github.com/a252937166/traceforge Source-run evidence: https://github.com/a252937166/traceforge/tree/main/docs/evidence/live-champion-run

## README (from the GitHub repository)

# TraceForge

[![verify](https://github.com/a252937166/traceforge/actions/workflows/ci.yml/badge.svg)](https://github.com/a252937166/traceforge/actions/workflows/ci.yml)

**Modernize undocumented workflows without guessing.**

TraceForge is an **evidence-bounded behavior migration system**. It turns observed workflow behavior into an evidence-linked contract, challenges that contract with counterexamples, lets Codex rebuild the workflow in an isolated worktree, and gives the final decision to a deterministic host verifier.

**Hosted showcase:** [traceforge.axiqo.xyz](https://traceforge.axiqo.xyz)

**2:44 judge demo:** [GPT-5.6 discovers the rules, Codex rebuilds, the host verifies](https://youtu.be/xQnKzDhUCl0)

The current executable laboratory is deliberately narrow: one Web returns workflow, REST, and SQLite. It is not a claim that arbitrary software can already be migrated. It demonstrates the hard part of that product honestly: preserving uncertainty, finding a hidden priority rule, rejecting an incomplete implementation, and issuing a proof limited to the scenarios actually executed.

**Migration Loom** is the name of TraceForge's judge-facing product experience: the evidence-custody path from recorded behavior to a bounded candidate and fresh host proof. TraceForge is built by **ouyangduning** as a solo project; the GitHub organization/account and video channel linked below are publication surfaces for the same entry.

## How Codex & GPT-5.6 were used

| System | Real role in the project | Verifiable output |
| --- | --- | --- |
| **GPT-5.6 Sol** | Four read-only, schema-constrained behavior-archaeology turns: propose competing hypotheses, choose discriminating counterexamples, and critique the final evidence-linked contract. The host—not the model—executes every proposed input. | `121,673` tokens of bounded inputs and structured outputs, with thread IDs, cited evidence IDs, and content digests in the [champion run evidence](docs/evidence/live-champion-run/README.md). |
| **OpenAI Codex SDK** | One isolated code-writing turn receives the resolved contract, four preserved failed proofs, and disclosed scenarios. It may repair only `apps/api/src/candidates/generated-return-workflow.ts`; it cannot edit the verifier, commit, push, deploy, or decide that it passed. | Codex thread `019f5244-7bef-71f2-8f25-8ed1446a539e`, its exact immutable inputs, accepted one-file diff, and host command log are checked in with the evidence. |
| **TraceForge host verifier** | Materializes a concrete verification-only input after the Codex turn, resets both systems, and compares deterministic decisions plus SQLite side effects. | `7/7` scenarios, `35/35` assertions, zero mismatches, and a downloadable digest-bound proof. |

GPT-5.6 is therefore the behavior investigator, Codex is the constrained implementer, and neither is allowed to certify its own result.

## The five-stage run

1. **Observe** — capture two SQLite-backed legacy traces: a $45 standard damaged return and a $120 VIP damaged return.
2. **Infer** — GPT-5.6 Sol proposes competing, schema-constrained hypotheses and cites trace evidence IDs.
3. **Challenge** — GPT-5.6 Sol proposes discriminating inputs; the host executes them, searches the exact $500 review boundary, and asks a contract critic to narrow the rules.
4. **Build** — the seeded candidate is rejected. Codex receives the evidence-bounded contract, all four failed proofs, and only the disclosed scenarios. It may edit the complete replacement module in a detached worktree, with a one-file allowlist and no network access.
5. **Verify** — after the Codex writing turn ends, the host generates one concrete verification-only input, resets state, and compares legacy and candidate behavior across six visible scenarios plus that verification-only scenario. The agent that writes code never sees that final input and never decides whether it passed.

The workbench is driven by server events from those stages. It does not advance through client-side timers or preload a successful result.

### Source-run and Local Runner isolation are different

The checked-in source run gave Codex a detached repository worktree and restricted legacy-oracle and verifier reads through the repair prompt. The host technically enforced the accepted **write** boundary—only `apps/api/src/candidates/generated-return-workflow.ts` could change—and rejected verifier-relevant tampering. That source run should not be described as filesystem-level read isolation.

The optional Local Runner has the stronger read boundary: it prepares a minimized writer workspace that omits the legacy implementation, verifier, hidden input, and private host files, then verifies the resulting candidate in a separate host-owned workspace. In both paths, Codex never decides whether its own output passed.

## Reproducible evidence

The checked-in [champion run evidence](docs/evidence/live-champion-run/README.md) records:

- source live migration `migration_efaa0383-628a-4fba-94df-96bfe344bcbe`;
- four real `gpt-5.6-sol` archaeology invocations totaling `121,673` tokens, with raw bounded inputs, structured outputs, thread IDs, and content digests;
- an explicit unknown lifecycle: `4` initial blocking unknowns, `4` evidence-linked resolutions, and `0` remaining unknowns before the host permits `READY_FOR_BUILD`;
- Codex thread `019f5244-7bef-71f2-8f25-8ed1446a539e` editing only `apps/api/src/candidates/generated-return-workflow.ts` from base commit `eb0e6169974b96bd3bff3b536b38ef5f665127c2`;
- the exact contract, four failed proofs, and disclosed scenarios supplied to Codex under repair-input digest `sha256:afe5ac02691e8929f1600f00bf57247b1915da88b759892087deb3b6e81755b8`;
- a post-turn host verification covering `2 observed + 2 counterexample + 2 boundary + 1 verification-only` scenarios;
- `56/56` candidate-safe tests, with four replay-only guards separated from the candidate worktree gate;
- `7/7` passing scenarios, `35/35` deterministic assertions, and zero mismatches;
- proof digest `sha256:4be44d476f222ca492d025a13f296997148142471e2387d532c61479bc3703bc`.

Six successful rows compare decision, return status, refund amount, sellable quantity, and quarantine quantity. The exhausted-stock counterexample instead compares five failure and atomicity facts: failure status, failure code plus message, no return record, unchanged inventory, and zero side effects.

The checked-in evidence directory is the successful **live-ai** source run. The public UI leads with **Replay a verified run** (`recorded-replay`): it streams the disclosed model events with their original provenance, then executes the differential suite again and issues fresh artifacts. No GPT or Codex call is implied to be running during replay. A new live run remains a secured, credentialled capability rather than an anonymous public trigger.

Verify the untouched historical proof and its derived v2 scenario-set envelope locally:

```bash
pnpm proof:verify-integrity docs/evidence/live-champion-run/proof.json
pnpm proof:verify-envelope docs/evidence/live-champion-run/source-run-envelope-v2.json
```

Both commands return `valid: true`. The first checks only the original object's canonical digest; the second binds its exact bytes and the checked-in recorded verifier artifact's exact bytes to the seven ordered per-scenario proof digests, then parses the artifact's unique final suite and recomputes coverage, scenario-set digest, and the split `56/56 + 4 replay guards` host gate. Fresh proofs issued by the hardened runtime use `pnpm proof:verify-current <proof.json>`.

Historical integrity result:

```json
{
  "valid": true,
  "claimedDigest": "sha256:4be44d476f222ca492d025a13f296997148142471e2387d532c61479bc3703bc",
  "computedDigest": "sha256:4be44d476f222ca492d025a13f296997148142471e2387d532c61479bc3703bc"
}
```

## Run the build with your own Codex

Reviewers can run the bounded **Build + Verify** stages with their own local Codex sign-in. The public site c

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 102 recognized source files, 1081 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 226)

```
.editorconfig
.gitattributes
.github/workflows/ci.yml
.gitignore
.nvmrc
apps/api/.gitignore
apps/api/package.json
apps/api/README.md
apps/api/scripts/verify-current-proof.ts
apps/api/scripts/verify-generated.ts
apps/api/scripts/verify-proof-integrity.ts
apps/api/scripts/verify-source-run-envelope.ts
apps/api/src/app.ts
apps/api/src/behavior-archaeology.ts
apps/api/src/candidates/generated-return-workflow.ts
apps/api/src/codex-adapter.ts
apps/api/src/digest.ts
apps/api/src/domain.ts
apps/api/src/legacy/return-workflow.ts
apps/api/src/migration-guard.ts
apps/api/src/migration-runner.ts
apps/api/src/migration-store.ts
apps/api/src/migration-types.ts
apps/api/src/proof-verifier.ts
apps/api/src/recorded-archaeology.generated.json
apps/api/src/recorded-archaeology.ts
apps/api/src/recorded-codex-build.generated.json
apps/api/src/recorded-codex-build.ts
apps/api/src/recorded-model-invocations.generated.json
apps/api/src/release.ts
apps/api/src/scenarios.ts
apps/api/src/server.ts
apps/api/src/service.ts
apps/api/src/store.ts
apps/api/src/types.ts
apps/api/tests/api.test.ts
apps/api/tests/champion-workflow.test.ts
apps/api/tests/codex-adapter.test.ts
apps/api/tests/contract-unknown-lifecycle.test.ts
apps/api/tests/evidence-boundary.test.ts
apps/api/tests/migration-api.test.ts
apps/api/tests/proof-verifier.test.ts
apps/api/tests/recorded-invocations.test.ts
apps/api/tests/release.test.ts
apps/api/tests/repair-api.test.ts
apps/api/tests/schema.test.ts
apps/api/tests/workflow.test.ts
apps/api/tsconfig.json
apps/local-runner/package.json
apps/local-runner/src/app-server-client.ts
apps/local-runner/src/artifact-page.ts
apps/local-runner/src/candidate-policy.ts
apps/local-runner/src/cli.ts
apps/local-runner/src/fixture-digest.ts
apps/local-runner/src/fixture.ts
apps/local-runner/src/local-page.ts
apps/local-runner/src/local-repair.ts
apps/local-runner/src/local-server.ts
apps/local-runner/src/manifest.ts
apps/local-runner/src/open-browser.ts
apps/local-runner/src/permissions.ts
apps/local-runner/src/runner-actions.ts
apps/local-runner/src/session.ts
apps/local-runner/tests/app-server-client.test.ts
apps/local-runner/tests/candidate-policy.test.ts
apps/local-runner/tests/fixture.test.ts
apps/local-runner/tests/local-page.test.ts
apps/local-runner/tests/local-repair.test.ts
apps/local-runner/tests/local-server.test.ts
apps/local-runner/tests/manifest.test.ts
apps/local-runner/tests/node-version.test.ts
apps/local-runner/tests/open-browser.test.ts
apps/local-runner/tests/permissions.test.ts
apps/local-runner/tests/real-app-server.test.ts
apps/local-runner/tests/release-checkout.ts
apps/local-runner/tests/runner-actions.test.ts
apps/local-runner/tests/session.test.ts
apps/local-runner/tsconfig.json
apps/web/index.html
apps/web/package.json
apps/web/README.md
apps/web/src/api.ts
apps/web/src/App.test.tsx
apps/web/src/App.tsx
apps/web/src/event-reducer.test.ts
apps/web/src/event-reducer.ts
apps/web/src/main.tsx
apps/web/src/migration-types.ts
apps/web/src/styles.css
apps/web/src/test-setup.ts
apps/web/tsconfig.app.json
apps/web/tsconfig.json
apps/web/tsconfig.node.json
apps/web/vite.config.ts
BUILD_LOG.md
BUILD_WEEK_CHANGES.md
deploy/install-release.sh
deploy/nginx-traceforge-http.conf
deploy/README.md
deploy/traceforge.env.example
deploy/traceforge.nginx.conf
deploy/traceforge.service
docs/acceptance-tests.md
docs/architecture.md
docs/behavior-contract.schema.json
docs/build-plan.md
docs/demo-script.md
docs/evidence/failed-champion-run-contract-boundary-20260711/artifacts.json
docs/evidence/failed-champion-run-contract-boundary-20260711/events.jsonl
docs/evidence/failed-champion-run-contract-boundary-20260711/job.json
docs/evidence/failed-champion-run-false-replay-gate-20260711/artifacts.json
docs/evidence/failed-champion-run-false-replay-gate-20260711/events.jsonl
docs/evidence/failed-champion-run-false-replay-gate-20260711/job.json
docs/evidence/failed-champion-run-sdk-timeout-20260711/artifacts.json
docs/evidence/failed-champion-run-sdk-timeout-20260711/events.jsonl
docs/evidence/failed-champion-run-sdk-timeout-20260711/job.json
docs/evidence/live-champion-run/artifacts.json
docs/evidence/live-champion-run/candidate.diff
docs/evidence/live-champion-run/codex/behavior-contract.json
docs/evidence/live-champion-run/codex/candidate-source.ts
[106 more files omitted for size]
```

### Dependencies

- apps/api/package.json: @openai/codex-sdk@0.144.1, @types/cors@^2.8.17, @types/express@^5.0.3, @types/node@^22.15.30, ajv@^8.17.1, ajv-formats@^3.0.1, cors@^2.8.5, express@^5.1.0, tsx@^4.19.4, typescript@^5.8.3
- apps/local-runner/package.json: @iarna/toml@2.2.5, @types/node@^22.15.30, tsx@^4.19.4, typescript@^5.8.3
- apps/web/package.json: @testing-library/jest-dom@^6.6.3, @testing-library/react@^16.3.0, @testing-library/user-event@^14.6.1, @types/node@^22.15.29, @types/react@^19.1.6, @types/react-dom@^19.1.5, @vitejs/plugin-react@^4.4.1, jsdom@^26.1.0, react@^19.1.0, react-dom@^19.1.0, typescript@~5.8.3, vite@^6.3.5, vitest@^3.1.4
- package.json: @playwright/test@1.61.1, concurrently@^9.2.1, tsx@^4.19.4

### Recent commits (newest first)

- Document final judge demo and Build Week delta
- Activate Local Runner v0.1.10 (#4)
- Publish Local Runner v0.1.10 evidence (#3)
- Harden TraceForge v0.1.10 release candidate
- Align runtime with unflagged Node SQLite
- Pin production release dependencies
- Harden proof integrity and judge experience
- fix: make hero split full bleed
- test: pin judge evidence and refresh captures
- feat: sharpen the judge-owned proof experience
- fix: accept safe coded workflow errors
- feat: harden Local Runner release capture
- docs: pin Local Runner v0.1.7 launch
- feat: publish seven-scenario champion evidence
- fix: parse modern TAP host gate totals
- feat: close contract and failure semantics
- docs: pin and publish the verified Local Runner
- fix: make the Local Runner browser flow executable
- feat: attest releases and clarify local gates
- fix: finish local runner cleanup before exit

## Key source files (fetched from GitHub, selected and truncated for size)

### SECURITY.md

```markdown
# Security policy

TraceForge currently operates only on the synthetic workflow included in this repository. Do not connect it to a production tenant or database.

## Reporting

Please report a vulnerability privately through GitHub Security Advisories once the public repository is available. Do not include credentials, raw customer data, database dumps, or captured session tokens in an issue.

## Trust boundaries

- Captured application content is untrusted input.
- Model-generated contracts and code are untrusted candidates.
- The deterministic verifier and immutable legacy baseline are the acceptance authority.
- Deployment, pull-request publication, and access to a non-synthetic system require human approval.


```

### BUILD_WEEK_CHANGES.md

```markdown
# Build Week change ledger

This ledger separates the pre-event project from the meaningful work completed
during OpenAI Build Week. TraceForge existed before the submission window; the
historical source archaeology and source proof are not presented as event-period
work.

The official Submission Period opened on **2026-07-13 at 09:00 Pacific Time**
(`2026-07-13T16:00:00Z`). Existing projects are evaluated only on meaningful
extensions made after that time, so every event-period claim below is bound to a
dated commit, CI run, or proof artifact.

## Event-start baseline

- Exact `main` commit immediately before the window:
  `131ca0fdc681d964ecbce0234ae249fa340101b2`.
- Baseline commit time: `2026-07-12T06:49:57Z`.
- Baseline subject: `Align runtime with unflagged Node SQLite`.
- Earlier hosted release recorded before the event:
  `652afb576815924607cecf9a632c0eb7f988e195`, built
  `2026-07-12T04:25:07.768Z`.
- Pre-existing work includes the core `Observe -> Infer -> Challenge -> Build ->
  Verify` architecture, the authenticated source GPT-5.6 archaeology, and the
  historical source proof.

Reproduce the baseline selection with:

```bash
git rev-list -1 --before="2026-07-13T16:00:00Z" main
```

## Meaningful extensions completed during Build Week

| UTC time | Commit / artifact | Event-period extension | Verification |
|---|---|---|---|
| `2026-07-14T03:30:02Z` | [PR #2](https://github.com/a252937166/traceforge/pull/2) / `d9b0d853acc7cab36eba859a778763c231e37325` | Hardened Local Runner v0.1.10: fail-closed `OUTSIDE_EVIDENCE_BOUNDARY`, host-owned refusal probe, current-proof verifier, historical v2 envelope verification, Node preflight, immutable tag/commit checks, and one-file writer custody. | API `85/85`; Web `17/17`; Local Runner `56` pass plus one intentional real-server skip; API/UI acceptance; repeatability `3/3`; [CI](https://github.com/a252937166/traceforge/actions/runs/29303663267). |
| `2026-07-14T03:54:26Z` | [PR #3](https://github.com/a252937166/traceforge/pull/3) / `343fbbb5ddad828c18b0f618893c50a6cb1d50a1` | Published the real v0.1.10 Local Runner run: preflight, changed-file diff, proof, cleanup report, summary, and full-resolution loopback screenshot. | Real `gpt-5.6-sol` Codex turn; `16/16` host gates; `7/7` scenarios; `35/35` assertions; stockout `5/5`; zero mismatches; proof `sha256:b67ba62f1e5cae421d96e8b28596a456f5234f8a303a070e67dcf5244832c272`; [CI](https://github.com/a252937166/traceforge/actions/runs/29304635286). |
| `2026-07-14T04:02:34Z` | [PR #4](https://github.com/a252937166/traceforge/pull/4) / `412973de86bdd9ad5253ec8a4cbcee365b704afd` | Activated v0.1.10 across every active reviewer surface and linked the immutable real-run evidence while preserving older versions as historical records. | `pnpm acceptance:all`; final [CI run](https://github.com/a252937166/traceforge/actions/runs/29304969532) completed successfully at `2026-07-14T04:04:52Z`. |
| `2026-07-14T04:03:19.672Z` | Production artifact build | Built the P
[truncated — 2304 more characters]
```

### package.json

```
{
  "name": "traceforge",
  "version": "0.1.10",
  "private": true,
  "description": "Evidence-bounded workflow modernization with differential proof.",
  "packageManager": "pnpm@10.33.2",
  "engines": {
    "node": ">=22.13.0"
  },
  "scripts": {
    "preinstall": "node scripts/check-node-version.cjs",
    "dev": "concurrently -n api,web -c blue,magenta \"pnpm --filter @traceforge/api dev\" \"pnpm --filter @traceforge/web dev\"",
    "local:run": "node scripts/check-node-version.cjs && node --import tsx apps/local-runner/src/cli.ts",
    "build": "pnpm -r build",
    "test": "pnpm -r --workspace-concurrency=1 test",
    "typecheck": "pnpm -r typecheck",
    "check": "pnpm typecheck && pnpm test && pnpm build",
    "acceptance:api": "pnpm --filter @traceforge/api build && node scripts/acceptance-api.mjs",
    "acceptance:ui": "pnpm --filter @traceforge/api build && node scripts/acceptance-ui.mjs",
    "acceptance:repeat": "pnpm --filter @traceforge/api build && node scripts/acceptance-repeat.mjs",
    "acceptance:local": "pnpm --filter @traceforge/local-runner test",
    "acceptance:all": "pnpm check && pnpm acceptance:local && pnpm acceptance:api && pnpm acceptance:ui && pnpm acceptance:repeat -- --runs 3",
    "release:package": "node scripts/package-release.mjs",
    "capture:showcase": "node scripts/capture-showcase.mjs",
    "capture:local-runner-release": "node --import tsx scripts/capture-local-runner-release.mjs",
    "evidence:extract-invocations": "node scripts/extract-recorded-invocations.mjs",
    "evidence:export-run": "node scripts/export-migration-run.mjs",
    "evidence:test-redaction": "node --test scripts/export-redaction.test.mjs",
    "evidence:update-recorded": "node scripts/update-recorded-champion.mjs",
    "proof:verify": "pnpm proof:verify-integrity",
    "proof:verify-integrity": "pnpm --filter @traceforge/api proof:verify-integrity",
    "proof:verify-current": "pnpm --filter @traceforge/api proof:verify-current",
    "proof:verify-envelope": "pnpm --filter @traceforge/api proof:verify-envelope"
  },
  "devDependencies": {
    "@playwright/test": "1.61.1",
    "concurrently": "^9.2.1",
    "tsx": "^4.19.4"
  }
}

```

### apps/local-runner/package.json

```
{
  "name": "@traceforge/local-runner",
  "version": "0.1.10",
  "private": true,
  "type": "module",
  "engines": {
    "node": ">=22.13.0"
  },
  "scripts": {
    "preinstall": "node ../../scripts/check-node-version.cjs",
    "start": "node ../../scripts/check-node-version.cjs && tsx src/cli.ts",
    "build": "tsc -p tsconfig.json --noEmit",
    "typecheck": "tsc -p tsconfig.json --noEmit",
    "test": "node --test --import tsx tests/*.test.ts"
  },
  "dependencies": {
    "@iarna/toml": "2.2.5"
  },
  "devDependencies": {
    "@types/node": "^22.15.30",
    "tsx": "^4.19.4",
    "typescript": "^5.8.3"
  }
}

```

### apps/web/package.json

```
{
  "name": "@traceforge/web",
  "private": true,
  "version": "0.1.10",
  "engines": {
    "node": ">=22.13.0"
  },
  "type": "module",
  "scripts": {
    "dev": "vite --host 0.0.0.0 --port 5174",
    "build": "tsc -b && vite build",
    "typecheck": "tsc -b --pretty false",
    "preview": "vite preview --host 0.0.0.0 --port 4173",
    "test": "vitest run"
  },
  "dependencies": {
    "@vitejs/plugin-react": "^4.4.1",
    "vite": "^6.3.5",
    "react": "^19.1.0",
    "react-dom": "^19.1.0"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^6.6.3",
    "@testing-library/react": "^16.3.0",
    "@testing-library/user-event": "^14.6.1",
    "@types/node": "^22.15.29",
    "@types/react": "^19.1.6",
    "@types/react-dom": "^19.1.5",
    "jsdom": "^26.1.0",
    "typescript": "~5.8.3",
    "vitest": "^3.1.4"
  }
}

```

### apps/api/package.json

```
{
  "name": "@traceforge/api",
  "version": "0.1.10",
  "private": true,
  "type": "module",
  "engines": {
    "node": ">=22.13.0"
  },
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "build": "tsc -p tsconfig.json",
    "typecheck": "tsc -p tsconfig.json --noEmit",
    "start": "node dist/server.js",
    "test": "node --test --import tsx tests/*.test.ts",
    "test:candidate": "TRACEFORGE_CANDIDATE_TESTS=1 node --test --import tsx tests/*.test.ts",
    "test:watch": "node --test --watch --import tsx tests/*.test.ts",
    "verify:generated": "tsx scripts/verify-generated.ts",
    "proof:verify": "tsx scripts/verify-proof-integrity.ts",
    "proof:verify-integrity": "tsx scripts/verify-proof-integrity.ts",
    "proof:verify-current": "tsx scripts/verify-current-proof.ts",
    "proof:verify-envelope": "tsx scripts/verify-source-run-envelope.ts"
  },
  "dependencies": {
    "@openai/codex-sdk": "0.144.1",
    "cors": "^2.8.5",
    "express": "^5.1.0"
  },
  "devDependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "^5.0.3",
    "@types/node": "^22.15.30",
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "tsx": "^4.19.4",
    "typescript": "^5.8.3"
  }
}

```

### apps/web/src/main.tsx

```typescript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import './styles.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

```

### apps/api/src/server.ts

```typescript
import { resolve } from "node:path";
import { createApp } from "./app.js";
import { ArtifactStore } from "./store.js";

const port = Number(process.env.PORT ?? 8787);
const host =
  process.env.HOST ?? (process.env.TRACEFORGE_ENABLE_CODEX === "1" ? "127.0.0.1" : "0.0.0.0");
const dbFile = process.env.TRACEFORGE_DB ?? resolve(process.cwd(), "data/traceforge.sqlite");
const store = new ArtifactStore(dbFile);
const { app } = createApp({ store });

const server = app.listen(port, host, () => {
  console.log(`TraceForge API listening on http://${host}:${port}`);
});

function shutdown() {
  server.close(() => {
    store.close();
    process.exit(0);
  });
}

process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);

```

### apps/local-runner/src/cli.ts

```typescript
#!/usr/bin/env node
import { createRequire } from "node:module";
import type { LocalRunnerServer } from "./local-server.js";

const require = createRequire(import.meta.url);
const { assertSupportedNodeVersion } = require("../../../scripts/check-node-version.cjs") as {
  assertSupportedNodeVersion(version?: string): void;
};

// Keep this check before dynamically importing the Runner graph. Older Node 22
// releases must receive a useful error instead of failing while linking
// `node:sqlite` or another runtime-only dependency.
assertSupportedNodeVersion(process.versions.node);

async function main(): Promise<void> {
  const [
    { prepareLocalFixture },
    { openLocalRunnerPage, shouldOpenLocalRunnerPage },
    { TraceForgeLocalActions },
    { startLocalRunnerServer },
    { LocalRunnerSession },
  ] = await Promise.all([
    import("./fixture.js"),
    import("./open-browser.js"),
    import("./runner-actions.js"),
    import("./local-server.js"),
    import("./session.js"),
  ]);
  const fixture = await prepareLocalFixture();
  const actions = new TraceForgeLocalActions(fixture);
  const session = new LocalRunnerSession(actions);
  let server: LocalRunnerServer | null = null;
  let shuttingDown = false;

  const shutdown = async (exitCode: number): Promise<void> => {
    if (shuttingDown) return;
    shuttingDown = true;
    await session.delete().catch(() => undefined);
    await server?.close().catch(() => undefined);
    process.exit(exitCode);
  };

  // Keep both handlers installed while async cleanup runs. Package-manager
  // wrappers and terminals may deliver more than one signal to the foreground
  // process group; a once-listener would let the second signal kill Node before
  // its verifier worktree is removed.
  process.on("SIGINT", () => void shutdown(130));
  process.on("SIGTERM", () => void shutdown(143));

  try {
    server = await startLocalRunnerServer(session);
    process.stdout.write(
      `\nTraceForge Local Runner\n${server.url}\n\nThe session is bound to 127.0.0.1. No Codex writing turn or verifier command runs before confirmation.\n`,
    );
    session.on("change", (snapshot) => {
      const detail = snapshot.errorCode ? ` · ${snapshot.errorCode}` : "";
      process.stdout.write(`[${snapshot.phase}] ${snapshot.title}${detail}\n`);
    });
    void session.initialize().catch(() => undefined);
    if (shouldOpenLocalRunnerPage()) {
      await openLocalRunnerPage(server.url).catch(() => {
        process.stdout.write("The browser did not open automatically. Open the localhost URL above.\n");
      });
    } else {
      process.stdout.write("Automatic browser opening is disabled for this run.\n");
    }
  } catch (error) {
    await shutdown(1);
    throw error;
  }
}

void main().catch((error: unknown) => {
  const message = error instanceof Error ? error.message : "LOCAL_RUNNER_START_FAILED";
  process.stderr.write(`TraceForge Local Runner could not start: ${message}\n`);
  process.exitCode = 1;
});

```

### apps/api/src/app.ts

```typescript
import cors, { type CorsOptions } from "cors";
import express, { type NextFunction, type Request, type Response } from "express";
import { CodexRepairAdapter, CodexRepairFailure } from "./codex-adapter.js";
import { sha256Digest } from "./digest.js";
import { MigrationRequestLimiter } from "./migration-guard.js";
import { MigrationCapacityError, MigrationRunner } from "./migration-runner.js";
import { MigrationStore } from "./migration-store.js";
import { readReleaseIdentity, type ReleaseIdentity } from "./release.js";
import { OutsideEvidenceBoundaryError } from "./scenarios.js";
import { ArtifactStore } from "./store.js";
import { TraceForgeService } from "./service.js";
import type { MigrationExecutionMode, MigrationProofBundle } from "./migration-types.js";
import type { CandidateVersion, ReturnWorkflowInput, SystemName } from "./types.js";

function isCandidateVersion(value: unknown): value is CandidateVersion {
  return value === "seeded" || value === "generated";
}

function isMigrationMode(value: unknown): value is MigrationExecutionMode {
  return value === "live-ai" || value === "recorded-replay" || value === "deterministic-only";
}

export interface AppDependencies {
  store?: ArtifactStore;
  service?: TraceForgeService;
  codexAdapter?: CodexRepairAdapter;
  migrationStore?: MigrationStore;
  migrationRunner?: MigrationRunner;
  release?: ReleaseIdentity;
  env?: NodeJS.ProcessEnv;
}

const DEFAULT_ALLOWED_ORIGINS = [
  "http://localhost",
  "http://localhost:5173",
  "http://localhost:5174",
  "http://localhost:4173",
  "http://127.0.0.1",
  "http://127.0.0.1:5173",
  "http://127.0.0.1:5174",
  "http://127.0.0.1:4173",
];

export class CorsOriginDeniedError extends Error {
  readonly code = "CORS_ORIGIN_DENIED";

  constructor(readonly origin: string) {
    super(`browser origin is not allowed: ${origin}`);
    this.name = "CorsOriginDeniedError";
  }
}

export function buildAllowedOrigins(env: NodeJS.ProcessEnv = process.env): Set<string> {
  const configured = (env.TRACEFORGE_ALLOWED_ORIGINS ?? "")
    .split(",")
    .map((origin) => origin.trim())
    .filter(Boolean);
  return new Set([...DEFAULT_ALLOWED_ORIGINS, ...configured]);
}

export function createApp(dependencies: AppDependencies = {}) {
  const env = dependencies.env ?? process.env;
  const store = dependencies.store ?? new ArtifactStore();
  const service = dependencies.service ?? new TraceForgeService(store);
  const codex = dependencies.codexAdapter ?? new CodexRepairAdapter({ env });
  const migrationStore = dependencies.migrationStore
    ?? new MigrationStore(env.TRACEFORGE_DB ?? (dependencies.store ? ":memory:" : undefined));
  const migrationRunner = dependencies.migrationRunner ?? new MigrationRunner(service, migrationStore, env, codex);
  const migrationLimiter = new MigrationRequestLimiter(env);
  const allowedOrigins = buildAllowedOrigins(env);
  const release = dependencies.release ?? readReleaseIdentity(env);
  const app = express();

  app.disable("x-powered-by");
  // Production binds the API to loopback. Only that trusted proxy may supply
  // X-Forwarded-For, preventing direct clients from choosing their rate key.
  app.set("trust proxy", "loopback");
  const corsOptions: CorsOptions = {
    origin(origin, callback) {
      if (!origin || allowedOrigins.has(origin)) {
        callback(null, true);
        return;
      }
      callback(new CorsOriginDeniedError(origin));
    },
  };
  app.use(cors(corsOptions));
  app.use(express.json({ limit: "1mb" }));

  app.get("/api/health", (_request, response) => {
    const codexStatus = codex.status();
    response.json({
      status: "ok",
      service: "traceforge-api",
      sqlite: "ready",
      ...(release ? { release } : {}),
      codexInstalled: codexStatus.installed,
      codexEnabled: codexStatus.enabled,
      codexConfigured: codexStatus.configured,
      codexStatus,
      gpt56Status: migrationRunner.archaeology.status(),
      migrationCapacity: migrationRunner.capacity(),
      timestamp: new Date().toISOString(),
    });
  });

  app.get("/api/scenarios", (_request, response) => {
    response.json({ data: service.listScenarios() });
  });

  app.get("/api/replacement/versions", (_request, response) => {
    response.json({
      data: [
        { id: "seeded", label: "Candidate 01 (observed-only)", purpose: "Contains two seeded rule and side-effect defects the verifier must reject" },
        { id: "generated", label: "Candidate 02 (complete module)", purpose: "The isolated Codex-editable replacement workflow" },
      ],
    });
  });

  app.post("/api/traces/capture", (request, response, next) => {
    try {
      const body = request.body as {
        system?: SystemName;
        candidateVersion?: CandidateVersion;
        scenarioId?: string;
        input?: ReturnWorkflowInput;
      };
      if (body.system !== "legacy" && body.system !== "replacement") {
        throw new Error("system must be legacy or replacement");
      }
      if (body.candidateVersion && !isCandidateVersion(body.candidateVersion)) {
        throw new Error("candidateVersion must be seeded or generated");
      }
      if (!body.input) throw new Error("input is required");
      const trace = service.capture(body.system, body.input, body.candidateVersion, body.scenarioId);
      const contract = body.system === "legacy" ? service.extractContract(trace) : undefined;
      response.status(201).json({ data: { trace, ...(contract ? { contract } : {}) } });
    } catch (error) {
      next(error);
    }
  });

  app.post("/api/verifications", (request, response, next) => {
    try {
      const body = (request.body ?? {}) as {
        scenarioId?: string;
        input?: ReturnWorkflowInput;
        candidateVersion?: CandidateVersion;
      };
      if (body.candidateVersion && !isCandidateVersion(body.candidateVersion)) {
        throw new Error("candidateVersion must be seeded or generated");
      }
      response.status(201).json({ data: service.run
[truncated — 11384 more characters]
```

[82 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]