code-foundry 1.20.2 → 1.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.github/CONTRIBUTING.md +5 -2
  2. package/.github/code-foundry.yml +1 -0
  3. package/.github/release-please-foundry.json +56 -0
  4. package/.github/workflows/cloudflare-delivery.yml +9 -0
  5. package/.github/workflows/cloudflare-deploy.yml +8 -1
  6. package/.github/workflows/eval.yml +116 -0
  7. package/.github/workflows/opencode-security_self-ci.yml +1 -1
  8. package/.github/workflows/qualified-foundry-publish.yml +6 -7
  9. package/.github/workflows/release.yml +58 -10
  10. package/.github/workflows/release_self-ci.yml +211 -8
  11. package/.github/workflows/validation-no-codeql.yml +34 -6
  12. package/.github/workflows/validation.yml +32 -5
  13. package/.github/workflows/validation_audit_self-ci.yml +1 -0
  14. package/.github/workflows/validation_self-ci.yml +1 -0
  15. package/.gitignore +1 -1
  16. package/AGENTS.md +5 -1
  17. package/CHANGELOG.md +95 -0
  18. package/README.md +23 -17
  19. package/docs/CONFIGURATION.md +189 -152
  20. package/docs/EVALS.md +139 -0
  21. package/docs/EXTENSIONS.md +28 -7
  22. package/docs/INITIALIZATION.md +13 -9
  23. package/docs/PERFORMANCE.md +67 -59
  24. package/docs/PUBLISHING.md +39 -14
  25. package/docs/README.md +37 -22
  26. package/docs/RELEASES.md +18 -9
  27. package/docs/WORKFLOWS.md +23 -4
  28. package/docs/agent-validation.md +6 -5
  29. package/docs/cloudflare-delivery.md +20 -8
  30. package/docs/consumer-qualification.md +11 -9
  31. package/docs/fleet-release-eligibility.md +14 -15
  32. package/docs/fleet-rollouts.md +3 -3
  33. package/docs/merge-queues.md +21 -21
  34. package/docs/product-quality.md +9 -10
  35. package/docs/qualified-publication.md +166 -93
  36. package/docs/release-integrity.md +7 -6
  37. package/docs/required-capabilities.md +24 -15
  38. package/package.json +1 -1
  39. package/src/commands/cloudflare-delivery.mjs +6 -1
  40. package/src/commands/qualified-publication.mjs +103 -12
  41. package/src/commands/release-integrity.mjs +46 -14
  42. package/src/commands/sync.mjs +30 -24
  43. package/src/lib/eval-envelope.mjs +234 -0
  44. package/src/lib/merge-queue.mjs +1 -0
  45. package/src/lib/product-quality.mjs +220 -16
  46. package/src/lib/task-policy.mjs +7 -0
  47. package/src/lib/validation-policy.mjs +10 -6
  48. package/src/runtime-core.mjs +166 -8
  49. package/src/runtime.mjs +3 -1
  50. package/src/templates/gitignore +3 -1
@@ -12,32 +12,235 @@ on:
12
12
  default: false
13
13
 
14
14
  permissions:
15
- actions: write
16
- contents: write
17
- issues: write
18
- pull-requests: write
19
- id-token: write
15
+ contents: read
16
+
17
+ # One owner for draft staging and npm publication. Never cancel an active release.
18
+ concurrency:
19
+ group: code-foundry-qualified-release-${{ github.repository }}-${{ github.ref }}
20
+ cancel-in-progress: false
20
21
 
21
22
  jobs:
22
23
  qualification:
23
24
  name: Qualify consumers
24
- if: vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true)
25
+ if: github.ref == 'refs/heads/main' && (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true))
25
26
  uses: ./.github/workflows/consumer-qualification.yml
26
27
  with:
27
28
  billing-pause-bypass: ${{ github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true }}
28
29
  permissions:
29
30
  actions: read
30
31
  contents: read
32
+
33
+ preflight:
34
+ name: Verify release prerequisites
35
+ if: github.ref == 'refs/heads/main' && (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true))
36
+ runs-on: ubuntu-24.04
37
+ timeout-minutes: 5
38
+ steps:
39
+ - name: Checkout trusted verifier
40
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
41
+ with:
42
+ persist-credentials: false
43
+ ref: ${{ github.sha }}
44
+ - name: Setup Node
45
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
46
+ with:
47
+ node-version: '24'
48
+ - name: Require activation and verify immutability without changing it
49
+ env:
50
+ REQUIRE_IMMUTABLE_RELEASES: ${{ vars.REQUIRE_IMMUTABLE_RELEASES }}
51
+ CODE_FOUNDRY_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
52
+ GH_TOKEN: ${{ github.token }}
53
+ run: |
54
+ set -euo pipefail
55
+ test "$REQUIRE_IMMUTABLE_RELEASES" = true || { echo 'Enable and review immutable release prerequisites before this cutover.' >&2; exit 1; }
56
+ gh release verify --help >/dev/null
57
+ gh release verify-asset --help >/dev/null
58
+ # Match the reusable producer's credential selection. A rejected
59
+ # configured token must not make the later staging job use it.
60
+ if [ -n "$CODE_FOUNDRY_TOKEN" ] && GH_TOKEN="$CODE_FOUNDRY_TOKEN" gh api "repos/${GITHUB_REPOSITORY}" --jq '.full_name' >/dev/null 2>&1; then
61
+ GH_TOKEN="$CODE_FOUNDRY_TOKEN" node src/commands/release-integrity.mjs settings --repo "$GITHUB_REPOSITORY"
62
+ else
63
+ node src/commands/release-integrity.mjs settings --repo "$GITHUB_REPOSITORY"
64
+ fi
65
+
31
66
  release:
32
67
  name: Release
33
- needs: qualification
34
- if: vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true)
68
+ needs: [qualification, preflight]
69
+ if: github.ref == 'refs/heads/main' && (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true))
35
70
  uses: ./.github/workflows/release.yml
36
71
  with:
37
72
  billing-pause-bypass: ${{ github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true }}
38
73
  runner: ubuntu-slim
39
74
  runtime-repository: 0xPlayerOne/code-foundry
40
75
  runtime-ref: ${{ github.sha }}
76
+ config-file: .github/release-please-foundry.json
77
+ defer-publication: true
78
+ permissions:
79
+ actions: write
80
+ contents: write
81
+ issues: write
82
+ pull-requests: write
83
+ # Required by the reusable legacy workflow's declared npm job, which is disabled here.
84
+ id-token: write
41
85
  secrets:
42
86
  CODE_FOUNDRY_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
87
+
88
+ recovery:
89
+ name: Recover qualified draft identity
90
+ needs: [qualification, release]
91
+ if: (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true)) && needs.qualification.result == 'success' && needs.release.result == 'success'
92
+ runs-on: ubuntu-24.04
93
+ timeout-minutes: 5
94
+ permissions:
95
+ contents: read
96
+ outputs:
97
+ found: ${{ steps.recover.outputs.found }}
98
+ tag: ${{ steps.recover.outputs.tag }}
99
+ sha: ${{ steps.recover.outputs.sha }}
100
+ env:
101
+ RELEASE_CREATED: ${{ needs.release.outputs.release_created }}
102
+ SOURCE_SHA: ${{ needs.qualification.outputs.source-sha }}
103
+ steps:
104
+ - name: Checkout trusted recovery runtime
105
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
106
+ with:
107
+ persist-credentials: false
108
+ ref: ${{ github.sha }}
109
+ - name: Setup Node
110
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
111
+ with:
112
+ node-version: '24'
113
+ - name: Locate an exact existing draft
114
+ id: recover
115
+ env:
116
+ GH_TOKEN: ${{ github.token }}
117
+ GITHUB_REPOSITORY: ${{ github.repository }}
118
+ run: |
119
+ set -euo pipefail
120
+ node --input-type=module <<'NODE'
121
+ import { appendFileSync, readFileSync } from "node:fs"
122
+ import { resolveTagCommit, runGh } from "./src/commands/release-integrity.mjs"
123
+ const output = process.env.GITHUB_OUTPUT
124
+ const write = (found, tag = "", sha = "") => appendFileSync(output, `found=${found}\ntag=${tag}\nsha=${sha}\n`)
125
+ if (process.env.RELEASE_CREATED === "true") {
126
+ write("false")
127
+ process.exit(0)
128
+ }
129
+ const version = JSON.parse(readFileSync("package.json", "utf8")).version
130
+ const tag = `v${version}`
131
+ // GitHub's get-by-tag endpoint does not return draft releases. Use
132
+ // the authenticated release list and inspect every page instead.
133
+ const endpoint = `repos/${process.env.GITHUB_REPOSITORY}/releases?per_page=100`
134
+ const response = runGh(["api", "--paginate", "--slurp", endpoint])
135
+ if (response.status !== 0) throw new Error("Could not inspect the expected draft release; recovery remains blocked")
136
+ let pages
137
+ try {
138
+ pages = JSON.parse(response.stdout)
139
+ } catch {
140
+ throw new Error("GitHub returned an invalid release response; recovery remains blocked")
141
+ }
142
+ if (!Array.isArray(pages) || pages.some((page) => !Array.isArray(page))) {
143
+ throw new Error("GitHub returned an invalid release list; recovery remains blocked")
144
+ }
145
+ const release = pages.flat().find((entry) => entry?.tag_name === tag)
146
+ if (!release || release.draft !== true) {
147
+ write("false")
148
+ process.exit(0)
149
+ }
150
+ if (release.tag_name !== tag) throw new Error("Existing draft tag does not match the expected package version")
151
+ const sourceSha = resolveTagCommit(process.env.GITHUB_REPOSITORY, tag, runGh)
152
+ if (sourceSha.toLowerCase() !== process.env.SOURCE_SHA.toLowerCase()) throw new Error("Existing draft tag does not match the qualified source SHA")
153
+ write("true", tag, sourceSha)
154
+ NODE
155
+
156
+ stage:
157
+ name: Stage qualified release
158
+ needs: [qualification, release, recovery]
159
+ if: (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true)) && github.ref == 'refs/heads/main' && (needs.release.outputs.release_created == 'true' || needs.recovery.outputs.found == 'true')
160
+ runs-on: ubuntu-24.04
161
+ timeout-minutes: 15
162
+ permissions:
163
+ actions: read
164
+ attestations: read
165
+ contents: write
166
+ env:
167
+ RELEASE_TAG: ${{ needs.release.outputs.tag_name || needs.recovery.outputs.tag }}
168
+ RELEASE_SHA: ${{ needs.release.outputs.sha || needs.recovery.outputs.sha }}
169
+ SOURCE_SHA: ${{ needs.qualification.outputs.source-sha }}
170
+ PACKAGE: ${{ needs.qualification.outputs.filename }}
171
+ CANDIDATE_SHA256: ${{ needs.qualification.outputs.sha256 }}
172
+ CANDIDATE_ARTIFACT: ${{ needs.qualification.outputs.candidate-artifact }}
173
+ steps:
174
+ - name: Checkout trusted staging runtime
175
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
176
+ with:
177
+ persist-credentials: false
178
+ ref: ${{ github.sha }}
179
+ - name: Setup Node
180
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
181
+ with:
182
+ node-version: '24'
183
+ - name: Require the release to identify this qualified candidate
184
+ run: |
185
+ node --input-type=module <<'NODE'
186
+ import assert from 'node:assert/strict'
187
+ import { readFileSync } from 'node:fs'
188
+ const env = process.env
189
+ const version = JSON.parse(readFileSync('package.json', 'utf8')).version
190
+ assert.match(env.SOURCE_SHA, /^[a-f0-9]{40}$/)
191
+ assert.equal(env.SOURCE_SHA, env.GITHUB_SHA)
192
+ assert.equal(env.RELEASE_SHA, env.SOURCE_SHA)
193
+ assert.equal(env.RELEASE_TAG, `v${version}`)
194
+ assert.equal(env.PACKAGE, `code-foundry-${version}.tgz`)
195
+ assert.match(env.CANDIDATE_SHA256, /^[a-f0-9]{64}$/)
196
+ assert.equal(env.CANDIDATE_ARTIFACT, `qualification-candidate-${env.GITHUB_RUN_ID}-${env.GITHUB_RUN_ATTEMPT}`)
197
+ NODE
198
+ - name: Retrieve only this attempt's qualified bytes and reports
199
+ env:
200
+ GH_TOKEN: ${{ github.token }}
201
+ run: |
202
+ set -euo pipefail
203
+ gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" \
204
+ --name "$CANDIDATE_ARTIFACT" --dir "$RUNNER_TEMP/candidate"
205
+ test "$(sha256sum "$RUNNER_TEMP/candidate/$PACKAGE" | cut -d' ' -f1)" = "$CANDIDATE_SHA256"
206
+ for node in 20 22 24; do
207
+ gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" \
208
+ --name "consumer-qualification-$GITHUB_RUN_ATTEMPT-node-$node" \
209
+ --dir "$RUNNER_TEMP/reports/$node"
210
+ done
211
+ - name: Stage identical assets then publish and verify the immutable release
212
+ env:
213
+ GH_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && secrets.CODE_FOUNDRY_TOKEN || github.token }}
214
+ run: |
215
+ set -euo pipefail
216
+ node src/commands/qualified-publication.mjs stage \
217
+ "$GITHUB_REPOSITORY" "$RELEASE_TAG" "$SOURCE_SHA" "$PACKAGE" \
218
+ "$RUNNER_TEMP/candidate" \
219
+ "$RUNNER_TEMP/reports/20/report.json" \
220
+ "$RUNNER_TEMP/reports/22/report.json" \
221
+ "$RUNNER_TEMP/reports/24/report.json" > "$RUNNER_TEMP/staging.json"
222
+ - name: Retain staging identity
223
+ if: always()
224
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
225
+ with:
226
+ name: release-staging-${{ github.run_id }}-${{ github.run_attempt }}
227
+ path: ${{ runner.temp }}/staging.json
228
+ if-no-files-found: warn
229
+ retention-days: 14
230
+
231
+ publish:
232
+ name: Publish verified package
233
+ needs: [qualification, release, recovery, stage]
234
+ if: (vars.CI_BILLING_PAUSED != 'true' || (github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true)) && github.ref == 'refs/heads/main' && needs.stage.result == 'success' && (needs.release.outputs.release_created == 'true' || needs.recovery.outputs.found == 'true')
235
+ uses: ./.github/workflows/qualified-foundry-publish.yml
236
+ permissions:
237
+ actions: read
238
+ attestations: read
239
+ contents: read
240
+ id-token: write
241
+ with:
242
+ tag: ${{ needs.release.outputs.tag_name || needs.recovery.outputs.tag }}
243
+ asset: ${{ needs.qualification.outputs.filename }}
244
+ billing-pause-bypass: ${{ github.event_name == 'workflow_dispatch' && inputs['release-while-paused'] == true }}
245
+ secrets:
43
246
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -42,6 +42,14 @@ on:
42
42
  required: false
43
43
  type: string
44
44
  default: ubuntu-slim
45
+ eval-runner:
46
+ description: >-
47
+ Runner used by the eval harness. Browser evals need a
48
+ Chrome-capable runner such as ubuntu-latest; ubuntu-slim does not
49
+ ship a browser.
50
+ required: false
51
+ type: string
52
+ default: ubuntu-latest
45
53
  codeql-runner:
46
54
  description: Runner used by CodeQL jobs.
47
55
  required: false
@@ -106,28 +114,47 @@ jobs:
106
114
  runner: ${{ inputs.test-runner }}
107
115
  unit-runner: ${{ inputs.unit-runner }}
108
116
  performance-runner: ${{ inputs.performance-runner }}
109
- unit-only: ${{ inputs.mode == 'fast' }}
117
+ # Release pull requests change version metadata only; their content was
118
+ # audited on the pull requests that merged into main. Integration, E2E,
119
+ # smoke, and performance lanes stay in the audit and scheduled lanes.
120
+ unit-only: ${{ inputs.mode == 'fast' || inputs.mode == 'release' }}
110
121
  artifact-prefix: ${{ inputs.artifact-prefix }}
111
122
  secrets:
112
123
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
113
124
 
114
125
  security:
115
126
  name: Security
116
- if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'audit' || inputs.mode == 'release')
127
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
117
128
  uses: ./.github/workflows/security.yml
118
129
  with:
119
130
  runtime-repository: ${{ inputs.runtime-repository }}
120
131
  runtime-ref: ${{ inputs.runtime-ref }}
121
132
  runner: ${{ inputs.security-runner }}
122
133
 
134
+ eval:
135
+ name: Eval
136
+ # Behavior evals cover content changes; the lean release lane skips them
137
+ # because its diff is version metadata only. The reusable workflow skips
138
+ # cleanly when the repository has no eval harness.
139
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
140
+ uses: ./.github/workflows/eval.yml
141
+ with:
142
+ runtime-repository: ${{ inputs.runtime-repository }}
143
+ runtime-ref: ${{ inputs.runtime-ref }}
144
+ runner: ${{ inputs.eval-runner }}
145
+ artifact-prefix: ${{ inputs.artifact-prefix }}
146
+
123
147
  # Aggregate check: "Validation / Gate" (caller job name + this job name).
124
148
  # Always evaluates; only jobs required for the mode must have succeeded.
125
- # The release tier runs the available CI/test/security suite. Its generated
126
- # release diff policy executes as a conditional step below, so no separate
127
- # release-policy job renders skipped checks on ordinary pull requests.
149
+ # The release tier requires the available fast suite; its diff is version
150
+ # metadata (validated against the release policy below), its content was
151
+ # audited on the pull requests that merged into main, and the scheduled
152
+ # audit lane re-covers drift. Its generated release diff policy executes
153
+ # as a conditional step below, so no separate release-policy job renders
154
+ # skipped checks on ordinary pull requests.
128
155
  gate:
129
156
  name: Gate
130
- needs: [ci, test, security]
157
+ needs: [ci, test, security, eval]
131
158
  if: vars.CI_BILLING_PAUSED != 'true' && always()
132
159
  runs-on: ubuntu-slim
133
160
  timeout-minutes: 10
@@ -136,6 +163,7 @@ jobs:
136
163
  FOUNDRY_CI: ${{ needs.ci.result }}
137
164
  FOUNDRY_TEST: ${{ needs.test.result }}
138
165
  FOUNDRY_SECURITY: ${{ needs.security.result }}
166
+ FOUNDRY_EVAL: ${{ needs.eval.result }}
139
167
  # This workflow is selected only for repositories whose canonical
140
168
  # configuration explicitly disables unavailable CodeQL. Treat that
141
169
  # policy decision as satisfied without registering a skipped PR check.
@@ -42,6 +42,14 @@ on:
42
42
  required: false
43
43
  type: string
44
44
  default: ubuntu-slim
45
+ eval-runner:
46
+ description: >-
47
+ Runner used by the eval harness. Browser evals need a
48
+ Chrome-capable runner such as ubuntu-latest; ubuntu-slim does not
49
+ ship a browser.
50
+ required: false
51
+ type: string
52
+ default: ubuntu-latest
45
53
  codeql-runner:
46
54
  description: Runner used by CodeQL jobs.
47
55
  required: false
@@ -106,14 +114,17 @@ jobs:
106
114
  runner: ${{ inputs.test-runner }}
107
115
  unit-runner: ${{ inputs.unit-runner }}
108
116
  performance-runner: ${{ inputs.performance-runner }}
109
- unit-only: ${{ inputs.mode == 'fast' }}
117
+ # Release pull requests change version metadata only; their content was
118
+ # audited on the pull requests that merged into main. Integration, E2E,
119
+ # smoke, and performance lanes stay in the audit and scheduled lanes.
120
+ unit-only: ${{ inputs.mode == 'fast' || inputs.mode == 'release' }}
110
121
  artifact-prefix: ${{ inputs.artifact-prefix }}
111
122
  secrets:
112
123
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
113
124
 
114
125
  security:
115
126
  name: Security
116
- if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'audit' || inputs.mode == 'release')
127
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
117
128
  uses: ./.github/workflows/security.yml
118
129
  with:
119
130
  runtime-repository: ${{ inputs.runtime-repository }}
@@ -134,15 +145,30 @@ jobs:
134
145
  rust-threads: ${{ inputs.rust-threads }}
135
146
  rust-max-parallel: ${{ inputs.rust-max-parallel }}
136
147
 
148
+ eval:
149
+ name: Eval
150
+ # Behavior evals cover content changes; the lean release lane skips them
151
+ # because its diff is version metadata only. The reusable workflow skips
152
+ # cleanly when the repository has no eval harness.
153
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
154
+ uses: ./.github/workflows/eval.yml
155
+ with:
156
+ runtime-repository: ${{ inputs.runtime-repository }}
157
+ runtime-ref: ${{ inputs.runtime-ref }}
158
+ runner: ${{ inputs.eval-runner }}
159
+ artifact-prefix: ${{ inputs.artifact-prefix }}
160
+
137
161
  # Aggregate check: "Validation / Gate" (caller job name + this job name).
138
162
  # Always evaluates; only jobs required for the mode must have succeeded.
139
- # The release tier runs the full audit suite so Release Please pull requests
140
- # expose no neutral suite checks. Its generated release diff policy executes
163
+ # The release tier requires the fast suite plus CodeQL: its diff is version
164
+ # metadata (validated against the release policy below), its content was
165
+ # audited on the pull requests that merged into main, and the scheduled
166
+ # audit lane re-covers drift. Its generated release diff policy executes
141
167
  # as a conditional step below, so ordinary pull requests still render no
142
168
  # skipped release-policy row.
143
169
  gate:
144
170
  name: Gate
145
- needs: [ci, test, security, codeql]
171
+ needs: [ci, test, security, codeql, eval]
146
172
  if: vars.CI_BILLING_PAUSED != 'true' && always()
147
173
  runs-on: ubuntu-slim
148
174
  timeout-minutes: 10
@@ -152,6 +178,7 @@ jobs:
152
178
  FOUNDRY_TEST: ${{ needs.test.result }}
153
179
  FOUNDRY_SECURITY: ${{ needs.security.result }}
154
180
  FOUNDRY_CODEQL: ${{ needs.codeql.result }}
181
+ FOUNDRY_EVAL: ${{ needs.eval.result }}
155
182
  steps:
156
183
  - name: Checkout runtime
157
184
  uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
@@ -34,6 +34,7 @@ jobs:
34
34
  unit-runner: ubuntu-slim
35
35
  performance-runner: ubuntu-latest
36
36
  security-runner: ubuntu-slim
37
+ eval-runner: ubuntu-latest
37
38
  codeql-runner: ubuntu-latest
38
39
  rust-shards: '["all"]'
39
40
  rust-threads: '1'
@@ -85,6 +85,7 @@ jobs:
85
85
  unit-runner: ubuntu-slim
86
86
  performance-runner: ubuntu-latest
87
87
  security-runner: ubuntu-slim
88
+ eval-runner: ubuntu-latest
88
89
  codeql-runner: ubuntu-latest
89
90
  rust-shards: '["all"]'
90
91
  rust-threads: '1'
package/.gitignore CHANGED
@@ -46,7 +46,7 @@ cache/
46
46
  !.github/actions/cache/action.yml
47
47
  typechain/
48
48
  coverage.json
49
- performance-results/
49
+ .code-foundry/
50
50
  tests/.bin/
51
51
  **/.app/
52
52
 
package/AGENTS.md CHANGED
@@ -106,7 +106,10 @@ This repository uses the `direct` workflow. Topic pull requests target `main`.
106
106
  - Keep ordinary pull requests in draft while preparing them. The generated
107
107
  Draft Guard converts ready ordinary pull requests to draft when they are
108
108
  opened or reopened, and runner-heavy validation starts only after an
109
- explicit `ready_for_review` transition.
109
+ explicit `ready_for_review` transition unless `draft_protection: false` is
110
+ configured for generated callers. That opt-out does not disable Draft Guard
111
+ or draft-PR automation. Cloudflare reusable callers use
112
+ `draft-protection: false`.
110
113
  - Run local validation and finish review preparation before marking an ordinary
111
114
  pull request ready. Ready pull requests stay ready when new commits arrive,
112
115
  and validation reruns for the current head; draft updates allocate no
@@ -146,6 +149,7 @@ node src/runtime.mjs ci unit
146
149
  node src/runtime.mjs ci integration
147
150
  node src/runtime.mjs ci e2e
148
151
  node src/runtime.mjs ci smoke
152
+ node src/runtime.mjs ci eval
149
153
  node src/runtime.mjs ci performance
150
154
  Security and dependency audits run through the GitHub Security workflow.
151
155
  ```
package/CHANGELOG.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.25.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.25.2...v1.25.3) (2026-09-10)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **release:** cover the attestation lag in publication retries ([#587](https://github.com/0xPlayerOne/code-foundry/issues/587)) ([7ae5e4b](https://github.com/0xPlayerOne/code-foundry/commit/7ae5e4bb95f68cbf4e2b48778776a0396c877271))
9
+
10
+ ## [1.25.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.25.1...v1.25.2) (2026-09-10)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **release:** retry integrity verification through the publication consistency window ([#585](https://github.com/0xPlayerOne/code-foundry/issues/585)) ([5b997dd](https://github.com/0xPlayerOne/code-foundry/commit/5b997dda7e272b59a386eeeda115e60ad284f6ce))
16
+
17
+ ## [1.25.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.25.0...v1.25.1) (2026-09-10)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **release:** wait for the release index before verifying a published release ([#583](https://github.com/0xPlayerOne/code-foundry/issues/583)) ([7823c14](https://github.com/0xPlayerOne/code-foundry/commit/7823c1473d8c5e7c17b039dc755ff5c8d1dba39c))
23
+
24
+ ## [1.25.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.24.0...v1.25.0) (2026-09-10)
25
+
26
+
27
+ ### Features
28
+
29
+ * **eval:** run the eval tier as a managed Validation / Eval lane ([#580](https://github.com/0xPlayerOne/code-foundry/issues/580)) ([9414889](https://github.com/0xPlayerOne/code-foundry/commit/94148894da9a627a6bd7c71c846848c198c1dfec))
30
+
31
+ ## [1.24.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.23.0...v1.24.0) (2026-09-10)
32
+
33
+
34
+ ### Features
35
+
36
+ * **validation:** run a lean release lane for Release Please pull requests ([#579](https://github.com/0xPlayerOne/code-foundry/issues/579)) ([a38ca75](https://github.com/0xPlayerOne/code-foundry/commit/a38ca75c7da577af8368467b8b026d0ec563fc41))
37
+
38
+ ## [1.23.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.22.1...v1.23.0) (2026-09-09)
39
+
40
+
41
+ ### Features
42
+
43
+ * add ci eval tier with shared report contract and budget gate ([#576](https://github.com/0xPlayerOne/code-foundry/issues/576)) ([7d881dd](https://github.com/0xPlayerOne/code-foundry/commit/7d881dd1bc6ace8e48dffff45b1a22a12bdae1c9))
44
+
45
+ ## [1.22.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.22.0...v1.22.1) (2026-09-09)
46
+
47
+
48
+ ### Bug Fixes
49
+
50
+ * **release:** use shell-safe recovery script ([#574](https://github.com/0xPlayerOne/code-foundry/issues/574)) ([264036f](https://github.com/0xPlayerOne/code-foundry/commit/264036f34afa4d7bc405285918395f2ce075bde3))
51
+
52
+ ## [1.22.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.21.3...v1.22.0) (2026-09-09)
53
+
54
+
55
+ ### Features
56
+
57
+ * **workflows:** protect draft pull requests by default ([#572](https://github.com/0xPlayerOne/code-foundry/issues/572)) ([6fa4ce1](https://github.com/0xPlayerOne/code-foundry/commit/6fa4ce1b2dde5eddff361b819722912fed7a9815))
58
+
59
+ ## [1.21.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.21.2...v1.21.3) (2026-09-09)
60
+
61
+
62
+ ### Bug Fixes
63
+
64
+ * **release:** unblock draft publication and PR deployment links ([#570](https://github.com/0xPlayerOne/code-foundry/issues/570)) ([35ab90f](https://github.com/0xPlayerOne/code-foundry/commit/35ab90f185483b0cd6a9c622b9793e46c90dd60c))
65
+
66
+ ## [1.21.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.21.1...v1.21.2) (2026-09-09)
67
+
68
+
69
+ ### Documentation
70
+
71
+ * refresh documentation for current workflows ([#568](https://github.com/0xPlayerOne/code-foundry/issues/568)) ([d0028e0](https://github.com/0xPlayerOne/code-foundry/commit/d0028e096371e1019c466f72f8744bdf832e067c))
72
+
73
+ ## [1.21.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.21.0...v1.21.1) (2026-09-09)
74
+
75
+
76
+ ### Bug Fixes
77
+
78
+ * release-hook-and-performance-safety ([#565](https://github.com/0xPlayerOne/code-foundry/issues/565)) ([0d410c6](https://github.com/0xPlayerOne/code-foundry/commit/0d410c68abfbc0d9fdd03b7aa81676489e459c19))
79
+ * **release:** automate self publication after CI ([91b2655](https://github.com/0xPlayerOne/code-foundry/commit/91b265585aa03e742e5bfc8a839b2794bf234491))
80
+
81
+
82
+ ### Performance
83
+
84
+ * **ci:** batch native Rust test targets by category ([#564](https://github.com/0xPlayerOne/code-foundry/issues/564)) ([6def882](https://github.com/0xPlayerOne/code-foundry/commit/6def8826e90b23d021a4f4587fa843dbb37df0e7))
85
+
86
+ ## [1.21.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.20.2...v1.21.0) (2026-09-09)
87
+
88
+
89
+ ### Features
90
+
91
+ * **release:** wire qualified draft staging and immutable publication ([#558](https://github.com/0xPlayerOne/code-foundry/issues/558)) ([19aea32](https://github.com/0xPlayerOne/code-foundry/commit/19aea32f50c747cdc5642d1752a9f02008c157f6))
92
+
93
+
94
+ ### Bug Fixes
95
+
96
+ * **quality:** harden HTML filtering ([#562](https://github.com/0xPlayerOne/code-foundry/issues/562)) ([ea45590](https://github.com/0xPlayerOne/code-foundry/commit/ea45590db24dc05ef12db57e80c7405fa217514f))
97
+
3
98
  ## [1.20.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.20.1...v1.20.2) (2026-09-09)
4
99
 
5
100
 
package/README.md CHANGED
@@ -39,6 +39,9 @@ contract. For normal updates, edit that file and run `npx code-foundry sync`.
39
39
  audits, Draft Guard, Draft PR, Release PR, and Release.
40
40
  - A deterministic performance lane with ordered command support, stable result
41
41
  artifacts, and an optional shared Node package budget profile.
42
+ - A deterministic eval tier (`ci eval`) that runs a repository's behavior-eval
43
+ harness against a shared report contract with optional budgets, keeping task
44
+ outcomes comparable across revisions and executors.
42
45
  - An opt-in product-quality runner for static sites, web apps, Workers, and
43
46
  published packages.
44
47
  - A small `.githooks/pre-commit` launcher with language-aware formatting and
@@ -58,7 +61,7 @@ preserved and can coexist with the standard baseline.
58
61
  The generated configuration is the one place to control the baseline. See
59
62
  [Configuration reference](docs/CONFIGURATION.md) for the visual configuration
60
63
  guide and [Initialization and synchronization](docs/INITIALIZATION.md) for
61
- the two-command workflow.
64
+ the init, sync, and doctor workflow.
62
65
 
63
66
  New repositories default to GPL-3.0-or-later. Existing projects preserve an
64
67
  authored license unless a replacement is explicitly selected. Our maintained
@@ -82,9 +85,11 @@ PRs: it converts them to drafts without checking out PR code. It verifies the
82
85
  event head and update timestamp before changing state, and excludes Release
83
86
  Please version PRs whose release workflow owns readiness. Pull-request
84
87
  validation runs on the ready-for-review transition and on new commits while a
85
- PR remains ready; draft updates allocate no validation runner. Converting a PR
86
- to draft runs only the lightweight cancellation control. Scheduled and manually
87
- dispatched audits are unaffected.
88
+ PR remains ready; draft updates allocate no validation runner by default. Set
89
+ `draft_protection: false` in generated consumer configuration, or pass
90
+ `draft-protection: false` to a Cloudflare reusable workflow, to run those gates
91
+ for drafts. Converting a PR to draft runs only the lightweight cancellation
92
+ control. Scheduled and manually dispatched audits are unaffected.
88
93
 
89
94
  Jobs are language-aware and skip irrelevant setup inside the applicable
90
95
  aggregate checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
@@ -125,9 +130,16 @@ workflow runs.
125
130
  In the default `direct` flow, changes reach `main` through feature pull
126
131
  requests and Release Please opens a versioned release PR against `main`. In
127
132
  the `staging-release` flow, a promotion PR promotes `staging` into `main`
128
- first. Either way, Release Please creates a GitHub release after the version
129
- PR is merged. npm publication is opt-in through `npm_publish: true` and
130
- supports npm trusted publishing or an `NPM_TOKEN` fallback.
133
+ first. Generated consumer callers create a GitHub release after the version PR
134
+ is merged; npm publication is opt-in through `npm_publish: true` and supports
135
+ npm trusted publishing or an `NPM_TOKEN` fallback.
136
+
137
+ Code Foundry's own release caller is stricter: it qualifies the package across
138
+ Node 20, 22, and 24, stages the exact qualified archive, publishes the
139
+ immutable GitHub Release, and publishes that archive through the verified
140
+ publisher. See
141
+ [Consumer qualification](docs/consumer-qualification.md) and [Qualified
142
+ publication](docs/qualified-publication.md).
131
143
 
132
144
  Read [Release management](docs/RELEASES.md),
133
145
  [Release integrity and build provenance](docs/release-integrity.md), and
@@ -137,16 +149,10 @@ copied into other repositories.
137
149
 
138
150
  ## Documentation and extensions
139
151
 
140
- The `docs/` directory contains generalized operational guides. Add
141
- repository-specific documentation there as well; synchronization does not
142
- replace files in `docs/`.
143
-
144
- - [Documentation index](docs/README.md)
145
- - [Initialization and synchronization](docs/INITIALIZATION.md)
146
- - [Workflow and CI conventions](docs/WORKFLOWS.md)
147
- - [Release management](docs/RELEASES.md)
148
- - [Publishing packages](docs/PUBLISHING.md)
149
- - [Caching and remote caching](docs/CACHING.md)
152
+ The `docs/` directory contains generalized operational guides. Start with the
153
+ [documentation index](docs/README.md), which groups every guide by task. Add
154
+ repository-specific documentation there as well; synchronization preserves
155
+ files in `docs/`.
150
156
 
151
157
  ## License
152
158