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
@@ -2,25 +2,25 @@
2
2
 
3
3
  Opt-in validation of the combined commit produced by GitHub's merge queue.
4
4
 
5
- **Activation:** `merge_queue: true` in the consumer's `.github/code-foundry.yml`, followed by normal sync.
6
- **Required check:** Existing canonical `Validation / Gate`.
5
+ **Activation:** Set `merge_queue: true` in the consumer's
6
+ `.github/code-foundry.yml`, then run `sync`.
7
+ **Required check:** The canonical `Validation / Gate` aggregate check.
7
8
 
8
9
  The synchronizer adds `.github/workflows/validation-merge-queue.yml` only when
9
- explicitly enabled. The ordinary PR readiness workflow is unchanged: this feature
10
- does not turn draft pushes into CI, mark PRs ready, enqueue PRs, or change release
11
- behavior. Queue events receive the full audit even when staging PRs normally use
12
- fast validation. Release Please branch detection is deliberately not reused for
13
- a merge group containing several PRs; the group's combined tree is audited, not
14
- treated as a generated version-only diff.
10
+ explicitly enabled. Queue validation does not turn draft pushes into CI, mark
11
+ pull requests ready, enqueue pull requests, or change release behavior. Queue
12
+ events receive the full audit even when staging pull requests normally use fast
13
+ validation. Release Please branch detection is not reused for a merge group
14
+ containing several pull requests; the combined tree is audited as submitted.
15
15
 
16
16
  ```yaml
17
17
  merge_queue: true
18
18
  ```
19
19
 
20
- Normal `code-foundry sync` updates the generated queue caller alongside the other
21
- runtime pins. Explicit fleet runtime overrides are honored. The installed runtime
22
- must contain this feature, and queues require an exact commit or released version
23
- pin rather than a moving branch. Direct topology enables main; staging-release
20
+ Normal `npx code-foundry sync` updates the generated queue caller alongside the
21
+ other runtime pins. Explicit fleet runtime overrides are honored. The installed
22
+ runtime must contain this feature, and queues require an exact commit or released
23
+ version pin rather than a moving branch. Direct topology enables main; staging-release
24
24
  enables main and staging. Existing runner choices, Rust CodeQL sharding, and an
25
25
  explicit `codeql: false` policy select the same appropriate validation orchestrator
26
26
  as ordinary PRs. No CodeQL policy or runtime default is relaxed.
@@ -60,8 +60,7 @@ Setting `merge_queue: false` or removing the key removes only a caller bearing t
60
60
  exact Foundry management marker. A custom file at that path is preserved when
61
61
  disabled; enabling over it fails before synchronization writes, even with force.
62
62
  Symlinked workflow paths are rejected. Dry runs report changes without creating,
63
- updating, or deleting the caller. The original synchronizer is retained verbatim
64
- in `sync-core.mjs`; its public exports are preserved through the thin wrapper.
63
+ updating, or deleting the caller.
65
64
 
66
65
  Disable the repository's queue rule before removing its required queue workflow.
67
66
  Otherwise queued PRs will correctly wait for checks that no longer run.
@@ -74,16 +73,17 @@ configure required checks. Register the aggregate check, not PR-only mode or
74
73
  readiness checks that have no merge-group equivalent. An existing rule requiring
75
74
  individual checks needs those exact contexts reviewed as well. Do not enable the
76
75
  queue rule before the workflow is merged and a disposable queue exercise passes.
77
- No repository rule, branch protection, secret, merge setting, or queue is changed
78
- by this PR.
76
+ Enabling this workflow does not change repository rules, branch protection,
77
+ secrets, merge settings, or the queue itself.
79
78
 
80
79
  Focused tests cover event identity and rejection, generated audit wiring,
81
80
  configured CodeQL policy, pin evolution, idempotence, dry runs, and ownership
82
- preservation. They do not establish a live merge-group run or full sync integration.
83
- Before readiness, run the existing complete sync/fleet tests, locked formatter,
84
- linter, TypeScript and package budgets, and Actionlint against rendered callers
85
- and their pinned/local reusable workflow contracts. Exercise two queued PRs and
86
- one deliberately failing check in an eligible disposable repository.
81
+ preservation. They do not establish a live merge-group run or full sync
82
+ integration. Before enabling the queue rule, run the complete sync/fleet tests,
83
+ locked formatter, linter, type check, package budgets, and Actionlint against
84
+ rendered callers and their pinned/local reusable workflow contracts. Exercise two
85
+ queued pull requests and one deliberately failing check in an eligible
86
+ disposable repository.
87
87
 
88
88
  References: [GitHub merge-queue CI configuration](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue),
89
89
  [merge-group event](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#merge_group).
@@ -20,16 +20,15 @@ Commit a version-1 JSON manifest and use the installed, pinned Foundry runtime:
20
20
 
21
21
  Wire these scripts into the consumer's existing validation entrypoints. The
22
22
  Foundry runtime discovers only `performance:check`/`perf:check` and
23
- `test:e2e`/`e2e`; if those names do not already exist, they can run
24
- `bun run quality:build` and `bun run quality:browser`. If they do exist, preserve their current
25
- commands and compose the quality command after them rather than replacing the
26
- existing performance or E2E checks. The standalone entrypoint deliberately avoids
27
- changing the public CLI dispatch being introduced in the separate agent-validation
28
- PR. Install the reviewed Foundry version in the consumer's existing dependency
29
- manager and lockfile, not an unpinned network invocation. Add `.code-foundry/` to
30
- Git/package ignores and retain selected evidence through the consumer workflow's
31
- artifact uploader. Reports and browser traces may contain application data; review
32
- retention and never upload authenticated traces publicly without sanitization.
23
+ `test:e2e`/`e2e`. If those names do not already exist, they can run
24
+ `bun run quality:build` and `bun run quality:browser`. If they do exist, preserve
25
+ their current commands and compose the quality command after them rather than
26
+ replacing the existing performance or E2E checks. Install the reviewed Foundry
27
+ version in the consumer's existing dependency manager and lockfile, not through
28
+ an unpinned network invocation. Add `.code-foundry/` to Git/package ignores and
29
+ retain selected evidence through the consumer workflow's artifact uploader.
30
+ Reports and browser traces may contain application data; review retention and
31
+ never upload authenticated traces publicly without sanitization.
33
32
 
34
33
  ```json
35
34
  {
@@ -1,72 +1,77 @@
1
- # Qualified Publication
2
-
3
- Publish only the same immutable Code Foundry archive that passed consumer qualification.
4
-
5
- **Dependencies:** Consumer qualification (#544) and release integrity (#537).
6
- **Activation:** Opt-in replacement publisher; no existing publisher is silently changed.
7
-
8
- The reusable `qualified-foundry-publish.yml` downloads an explicitly named npm
9
- archive from an already-published immutable release, verifies the release and
10
- asset attestations against the caller's exact commit, qualifies that same archive
11
- on Node 20/22/24, and only then admits a protected npm publication job. The final
12
- job downloads only reports from its own workflow run **and run attempt**, rechecks
13
- all required fixtures and archive/source identities, repeats cryptographic asset
14
- verification, validates the package name/version, and publishes the tarball with
15
- lifecycle scripts disabled. It never publishes a directory or rebuilds the package.
16
-
17
- The publishing job uses a GitHub environment, serializes publication for a tag,
18
- and has no dependency installation/build step. Qualification has no npm credential.
19
- Normal npm trusted publishing is preferred; an explicit optional token supports
20
- existing consumers. Configure the trusted publisher for the **actual caller and
21
- reusable-workflow relationship** before enabling this route. Existing version
22
- publication is not overwritten: retrying an already-published version fails rather
23
- than treating a registry conflict or network error as proof of identity.
24
-
25
- ## Release producer contract
26
-
27
- Build and test a package once, attach its tarball to a **draft** release, then
28
- publish that release with immutability enabled. The archive must contain the
29
- Code Foundry CLI/templates; this is intentionally not a generic package harness.
30
- The candidate's `package.json` name must be `code-foundry` and its version must
31
- match the explicit tag. All qualification modules must exist in the caller commit.
32
- A recent GitHub CLI with `release verify` and `release verify-asset` is required;
33
- missing support or authentication errors fail closed.
34
-
35
- This workflow blocks npm publication, not a GitHub Release that was already
36
- published. It does **not** add assets after an immutable release is published.
37
- The `stage` command implements the draft-asset producer: it verifies qualification,
38
- checks immutability without changing settings, resolves the existing tag to the
39
- qualified commit, uploads the archive and digest-bound qualification receipt,
40
- rechecks uploaded digests, then publishes and verifies the release. It requires
41
- an existing draft and existing tag; it never creates/moves tags or overwrites
42
- conflicting assets. Settings permission failures block writes. Matching existing
43
- assets can resume staging; conflicting assets require manual reconciliation.
44
- The pre-release gate in #544 supplies the required matrix reports.
45
- The legacy Release Please workflow creates releases without
46
- this archive staging step. Wire the new `stage` command into a draft-producing
47
- caller instead of pointing the old direct-release caller at the new publisher:
48
-
49
- ```sh
50
- node src/commands/qualified-publication.mjs stage \
51
- "$GITHUB_REPOSITORY" "$TAG" "$SOURCE_SHA" "$ASSET" "$CANDIDATE_DIRECTORY" \
52
- "$REPORT_NODE_20" "$REPORT_NODE_22" "$REPORT_NODE_24"
53
- ```
54
-
55
- The stage command needs a credential with immutable-setting read, release
56
- write, and attestation-read access; a normal Actions token may lack the
57
- administration-read permission.
58
- No elevated credential is installed or requested automatically. The producer must
59
- also prevent concurrent tag mutation (for example with protected release-tag
60
- rules and a single tag-scoped producer); GitHub does not offer an atomic
61
- "publish this draft only if the tag still resolves to SHA" operation. The final
62
- verification blocks npm if that invariant is violated, but cannot undo an
63
- already-published immutable release.
64
-
65
- Disable the old npm path before
66
- activating the replacement to prevent racing publishers. None of those production
67
- settings or existing release workflows are changed in this PR.
68
-
69
- Example caller job after its release producer (illustrative job IDs):
1
+ # Qualified publication
2
+
3
+ Code Foundry publishes only the same immutable archive that passed consumer
4
+ qualification. This path is used by Code Foundry's own release caller; generated
5
+ consumer release callers keep the ordinary `release.yml` behavior.
6
+
7
+ ## Publication contract
8
+
9
+ The self-release pipeline is intentionally staged:
10
+
11
+ 1. `consumer-qualification.yml` packs the candidate once and qualifies it across
12
+ Node 20, 22, and 24.
13
+ 2. Release Please creates a draft release for the qualified source.
14
+ 3. The staging job attaches the exact archive and a digest-bound qualification
15
+ receipt, publishes the immutable GitHub Release, and verifies its identity.
16
+ 4. `qualified-foundry-publish.yml` downloads that archive and the reports from
17
+ its own workflow run and attempt, requalifies all three Node versions, and
18
+ publishes the tarball.
19
+
20
+ The reusable publisher downloads an explicitly named npm archive from the
21
+ already-published immutable release, verifies the release and asset attestations
22
+ against the caller's exact commit, and only then admits the npm publication job.
23
+ The final job downloads only reports from its own workflow run and attempt,
24
+ rechecks all required fixtures and archive/source identities, repeats cryptographic
25
+ asset verification, validates the package name/version, and publishes the tarball
26
+ with lifecycle scripts disabled. It never publishes a directory or rebuilds the
27
+ package.
28
+
29
+ The publishing job serializes publication for a tag and has no dependency
30
+ installation/build step. Qualification has no npm credential. This self-only
31
+ publisher has no environment approval gate; publication is automatic after its
32
+ completed gates. npm trusted publishing is preferred; an explicit optional token
33
+ supports environments that cannot use it. Configure the trusted publisher for the
34
+ **actual caller and reusable-workflow relationship** before enabling this route.
35
+ Existing version publication is not overwritten: retrying an already-published
36
+ version fails rather than treating a registry conflict or network error as proof
37
+ of identity.
38
+
39
+ The publisher never rebuilds the package, publishes a directory, or treats an
40
+ already-published version conflict as proof of success. The workflow uses npm
41
+ trusted publishing when no `NPM_TOKEN` is supplied; the optional token is a
42
+ fallback for environments that cannot use trusted publishing.
43
+
44
+ Qualification and publication are gated on `main` push or an explicitly
45
+ requested `workflow_dispatch`. The shared billing pause blocks normal runs. A
46
+ manual release-only dispatch can pass `billing-pause-bypass: true` through the
47
+ publisher, but it does not bypass environment approvals, branch protection, or
48
+ identity checks.
49
+
50
+ ## Release producer requirements
51
+
52
+ The producer must:
53
+
54
+ - pack the candidate with lifecycle scripts disabled;
55
+ - create or reuse a draft release for the exact package version;
56
+ - attach the package archive before the release is published;
57
+ - keep the tag at the qualified source commit;
58
+ - enable and verify GitHub release immutability before publication; and
59
+ - serialize release-tag mutation so two producers cannot race.
60
+
61
+ The candidate package must be named `code-foundry`, and its version must match
62
+ the explicit release tag. A recent GitHub CLI with `release verify` and
63
+ `release verify-asset` support is required. Missing support, ambiguous release
64
+ identity, unavailable permissions, changed assets, or conflicting assets fail
65
+ closed.
66
+
67
+ The generic reusable `release.yml` supports `defer-publication: true` for this
68
+ producer pattern. That mode suppresses its legacy npm, reconciliation, and
69
+ post-release jobs while exposing the release outputs needed by the self caller.
70
+ Consumer callers do not inherit the self-only qualification and staging jobs.
71
+
72
+ ## Reusable publisher interface
73
+
74
+ The caller supplies the tag and exact pre-attached archive name:
70
75
 
71
76
  ```yaml
72
77
  permissions:
@@ -74,6 +79,7 @@ permissions:
74
79
  attestations: read
75
80
  contents: read
76
81
  id-token: write
82
+
77
83
  jobs:
78
84
  publish:
79
85
  needs: release-producer
@@ -81,31 +87,98 @@ jobs:
81
87
  with:
82
88
  tag: ${{ needs.release-producer.outputs.tag }}
83
89
  asset: ${{ needs.release-producer.outputs.npm-asset }}
84
- environment: npm
85
90
  secrets:
86
91
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
87
92
  ```
88
93
 
89
- Only main-branch `push` and `workflow_dispatch` callers are admitted. Pull-request
90
- events (including fork PRs), release-event shortcuts, and billing-paused runs
91
- cannot publish through this workflow. The event guard does not itself verify
92
- branch protection or prohibit a fork's independent main-branch workflow; configure
93
- branch/environment protections and registry publisher identity separately.
94
- The tag must resolve to `github.sha`, not a caller-selected old commit. To retry
95
- an older release after main moves, use a separately reviewed recovery procedure;
96
- do not weaken the identity gate ad hoc.
97
-
98
- ## Local policy tests and trust
99
-
100
- `node --test test/qualified-publication.test.mjs` uses CLI/verifier fixtures to
101
- exercise missing matrix members, skipped checks, absent Actionlint, changed
102
- archives, invalid asset names, wrong package identity, and prevention of npm
103
- execution before verification. These tests do not establish live GitHub signing,
104
- OIDC permissions, registry publication, or runner tool availability.
105
-
106
- Qualification reports are not standalone signatures: they are trusted only after
107
- selection from this workflow's successful jobs in the same run attempt. Supplying
108
- arbitrary local JSON to the library is not a security boundary. The reusable
109
- workflow and its caller must be reviewed/trusted and protected; repository-owned
110
- code executes with the permissions of its job. No credentials or production
111
- resources were configured by adding this feature.
94
+ For the self repository, `release_self-ci.yml` supplies the release output and
95
+ uses the protected `npm` environment. Configure trusted publishing for the
96
+ actual caller/reusable-workflow relationship, not only for a similarly named
97
+ workflow. Protect both the `release` and `npm` environments with the intended
98
+ branch restrictions and approvals.
99
+
100
+ ## Identity and retry rules
101
+
102
+ Every qualification report is bound to the source SHA, archive digest, Node
103
+ version, and workflow attempt. The staging and publish jobs verify:
104
+
105
+ - the tag resolves to the current `github.sha`;
106
+ - the archive name and package identity are expected;
107
+ - all required Node reports belong to the same run attempt;
108
+ - the downloaded bytes match the qualified digest; and
109
+ - the release and assets have not been replaced.
110
+
111
+ On a failed or cancelled qualification, use **Re-run all jobs**. A failed-job-only
112
+ rerun cannot safely reuse an earlier pack or combine reports from different
113
+ attempts. Missing or expired artifacts require a fresh run.
114
+
115
+ If Release Please reports that no new release was created, the recovery path may
116
+ reuse an exact draft release only when its tag, version, source SHA, and draft
117
+ state still match the qualified candidate. An already-published release is never
118
+ restaged or overwritten. Inspect the retained staging and publication identity
119
+ receipts when recovery is needed.
120
+
121
+ ## Publication prerequisites
122
+
123
+ Enable immutable releases and verify the setting with the actual
124
+ `CODE_FOUNDRY_TOKEN` (or workflow credential), then set
125
+ `REQUIRE_IMMUTABLE_RELEASES=true`. Missing permissions, a disabled or unknown
126
+ setting, or a CLI without release verification support fail before Release Please
127
+ writes. Protect release tags against concurrent moves. The staging token needs
128
+ administration-read, contents-write, and verification access; it is never exposed
129
+ to qualification jobs. Preflight and staging reuse the producer's validated
130
+ credential selection, falling back to the workflow token only when the configured
131
+ token is rejected. Configure npm trusted-publisher identity for the actual
132
+ caller/reusable-workflow relationship, or explicitly retain the optional npm
133
+ token in the final publisher.
134
+
135
+ ## Trust boundaries
136
+
137
+ Qualification reports are evidence selected from successful jobs in the same
138
+ workflow attempt; they are not standalone signatures or authorization outside
139
+ the protected workflow. The workflow executes repository-owned code with the
140
+ permissions of its job. Keep credentials out of qualification jobs and review
141
+ release/environment protections separately. A YAML environment reference does
142
+ not prove that approval protections exist.
143
+
144
+ Run the full locked-toolchain suite, Actionlint contracts, and a disposable-repo
145
+ release/signing/registry rehearsal before production approval. The producer
146
+ serializes the full release workflow and never cancels an active publish. The
147
+ self caller auto-publishes after its gates without bypassing branch or review
148
+ requirements for source changes.
149
+
150
+ The staging command requires release-write, attestation-verification, and
151
+ immutable-setting read access. No elevated credential is installed automatically.
152
+ If the configured automation token is rejected, the producer's documented
153
+ fallback is used only where the workflow permits it; missing permissions fail
154
+ closed.
155
+
156
+ Use **Re-run all jobs** for qualification failures; attempts cannot reuse earlier
157
+ reports. If Release Please returns `release_created: false`, the recovery job
158
+ looks up only the package version's draft release through the authenticated,
159
+ paginated release list, resolves its tag, and resumes only when that tag still
160
+ points to the newly qualified source. Staging uses the same list because GitHub's
161
+ get-by-tag endpoint does not return draft releases. Missing or already published
162
+ releases are a safe no-op; malformed, inaccessible, or source-mismatched drafts
163
+ fail closed. Inspect the retained identity receipts. Once a release is
164
+ published, do not attempt to re-stage or overwrite it: rerun the verified
165
+ publisher from the same source-bound workflow after confirming npm has not already
166
+ accepted that version. Never weaken the SHA guard, move an immutable tag, or treat
167
+ npm's version-conflict response as success.
168
+
169
+ ## Validation
170
+
171
+ Run the focused local suites before changing this path:
172
+
173
+ ```sh
174
+ node --test test/consumer-qualification.test.mjs
175
+ node --test test/consumer-qualification-workflow.test.mjs
176
+ node --test test/qualification-handoff.test.mjs
177
+ node --test test/qualified-publication.test.mjs
178
+ node --test test/release-cutover.test.mjs
179
+ ```
180
+
181
+ These tests use fixtures and do not establish live GitHub signing, OIDC
182
+ permissions, registry publication, environment approvals, or runner tool
183
+ availability. Exercise those controls in a disposable repository before changing
184
+ production release settings.
@@ -1,9 +1,10 @@
1
1
  # Release integrity and build provenance
2
2
 
3
- Code Foundry now provides a read-only immutable-setting preflight, cryptographic
3
+ Code Foundry provides a read-only immutable-setting preflight, cryptographic
4
4
  release/asset verification, and an optional build-provenance action. These are
5
- separate guarantees: a checksum identifies bytes, an attestation identifies their
6
- origin, and GitHub's immutable-release setting prevents replacement after publish.
5
+ separate guarantees: a checksum identifies bytes, an attestation identifies
6
+ their origin, and GitHub's immutable-release setting prevents replacement after
7
+ publication.
7
8
 
8
9
  ## Enable immutable releases explicitly
9
10
 
@@ -16,9 +17,9 @@ can verify an explicitly selected tag without the variable. Billing pause is
16
17
  honored by both workflows. A skipped workflow is not verification evidence.
17
18
 
18
19
  Publish all assets to a draft release **before** publishing it. Do not attach or
19
- replace assets after an immutable release is published. The existing Release
20
- Please/npm workflow is not rewritten by this change; repositories adding release
21
- assets must review their attachment ordering before enabling immutability.
20
+ replace assets after an immutable release is published. If a repository adds
21
+ release assets, its release workflow must stage them before the release is
22
+ published; the verifier does not repair an already-published release.
22
23
 
23
24
  A release workflow can run this preflight before publication:
24
25
 
@@ -1,12 +1,13 @@
1
1
  # Required capabilities and task evidence
2
2
 
3
3
  Declared requirements fail closed when discovery cannot find an executable task.
4
- Existing optional task discovery remains available. Configure scalar values in
4
+ Optional task discovery remains available. Configure scalar values in
5
5
  `.github/code-foundry.yml`:
6
6
 
7
7
  ```yaml
8
- required_capabilities: type_check,unit,e2e,performance,coverage
8
+ required_capabilities: type_check,unit,e2e,eval,performance,coverage
9
9
  performance: true
10
+ eval: true
10
11
  coverage_enforcement: required
11
12
  coverage_minimum: 80
12
13
  coverage_metrics: lines,branches
@@ -14,16 +15,17 @@ coverage_report: coverage/coverage-summary.json
14
15
  ```
15
16
 
16
17
  Supported task capabilities are `format`, `lint`, `type_check`, `build`, `unit`,
17
- `integration`, `e2e`, `smoke`, and `performance`. `coverage` additionally requires
18
+ `integration`, `e2e`, `smoke`, `eval`, and `performance`. `coverage` additionally requires
18
19
  unit tests. Unknown names, contradictory requirements, and invalid thresholds
19
- are errors. `performance: true` now means required, not merely enabled when a
20
- script happens to exist. Use `performance: auto` to retain optional discovery.
20
+ are errors. `performance: true` and `eval: true` mean required, not merely
21
+ enabled when a script happens to exist. Use `performance: auto` or
22
+ `eval: auto` to retain optional discovery.
21
23
 
22
24
  The public `src/runtime.mjs` entrypoint delegates ecosystem execution to the
23
- unchanged private `src/runtime-core.mjs`. Keep both files and `src/lib` when
24
- vendoring the runtime. Published packages and the reusable workflows' existing
25
- cone-mode sparse checkout include both files. Do not call the private executor
26
- from consumer CI: it intentionally does not enforce the public policy contract.
25
+ private `src/runtime-core.mjs`. Keep both files and `src/lib` when vendoring the
26
+ runtime. Published packages and reusable workflows must include those paths. Do
27
+ not call the private executor from consumer CI: it does not enforce the public
28
+ policy contract.
27
29
 
28
30
  ## Coverage migration
29
31
 
@@ -84,10 +86,17 @@ script-derived reasons. Do not put credentials in command arguments. Artifact
84
86
  access follows repository/Actions visibility; receipt retention does not provide
85
87
  a sandbox or independently validate repository-authored evidence.
86
88
 
87
- `node src/runtime.mjs ci plan` prints a JSON discovery plan without executing
88
- checks. Discovery validates every required task before reusable workflows select
89
- jobs. A fast/unit-only tier is still a subset: discovery proves that E2E exists,
90
- not that E2E ran. Require the existing audit validation gate before merging.
89
+ Use the public CLI for a repository-facing discovery plan:
90
+
91
+ ```sh
92
+ npx code-foundry plan --tier audit --json
93
+ ```
94
+
95
+ The lower-level `node src/runtime.mjs ci plan` form remains useful to reusable
96
+ workflows and runtime tests. Both forms discover tasks without executing checks.
97
+ Discovery validates every required task before workflows select jobs. A
98
+ fast/unit-only tier is still a subset: discovery proves that E2E exists, not that
99
+ E2E ran. Require the audit validation gate before merging.
91
100
 
92
101
  Native task detection rejects known no-ops such as a JavaScript project with no
93
102
  build script or a Python project with no supported type-check command. Add a
@@ -98,5 +107,5 @@ an installed package manager or discovered project proves task execution.
98
107
 
99
108
  `node --test test/task-policy.test.mjs` exercises policy parsing, discovery,
100
109
  coverage parsing/thresholds/freshness/path safety, exit propagation, and reports
101
- with a deterministic executor fixture. The unchanged ecosystem executor remains
102
- covered by `test/runtime.test.mjs` in the full suite.
110
+ with a deterministic executor fixture. The ecosystem executor is covered by
111
+ `test/runtime.test.mjs` in the full suite.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.20.2",
3
+ "version": "1.25.3",
4
4
  "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
5
  "homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
6
6
  "bugs": {
@@ -300,8 +300,13 @@ export async function deliveryCommand(command, env = process.env) {
300
300
  else if (command === 'rollback') await rollback(env, state)
301
301
  else if (command === 'record-start') {
302
302
  const production = env.FOUNDRY_PHASE === 'production'
303
+ // pull_request workflows build the merge ref, while GitHub associates
304
+ // PR deployments with the head commit. The reusable workflow supplies
305
+ // that head SHA; direct pushes fall back to the checked-out source SHA.
306
+ const deploymentRef = env.GITHUB_DEPLOYMENT_REF || state.sourceSha
307
+ if (!/^[0-9a-f]{40}$/i.test(deploymentRef)) throw new Error('Invalid GitHub deployment ref')
303
308
  const deployment = await github(env, 'deployments', {
304
- ref: state.sourceSha,
309
+ ref: deploymentRef,
305
310
  environment: required(env, 'DEPLOYMENT_ENVIRONMENT'),
306
311
  auto_merge: false,
307
312
  required_contexts: [],