code-foundry 0.37.0 → 0.37.2

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.
@@ -153,15 +153,15 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
153
153
 
154
154
  ## Workflow and check behavior
155
155
 
156
- | Event | Expected automation |
157
- | --- | --- |
158
- | Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |
159
- | Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
160
- | Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |
161
- | Scheduled or manual validation | Full audit tier |
162
- | Push to a working branch | Draft PR workflow |
163
- | Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |
164
- | Push to `main` | Release workflow; canonical validation already ran on the merged PR |
156
+ | Event | Expected automation |
157
+ | -------------------------------------------------- | ------------------------------------------------------------------------------------- |
158
+ | Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |
159
+ | Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
160
+ | Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |
161
+ | Scheduled or manual validation | Full audit tier |
162
+ | Push to a working branch | Draft PR workflow |
163
+ | Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |
164
+ | Push to `main` | Release workflow; canonical validation already ran on the merged PR |
165
165
 
166
166
  The single validation caller keys concurrency by event and pull-request head. A newer update to the same pull request cancels its superseded validation run; scheduled and manual audits remain independent. The mode-aware orchestrator fans out only the jobs required by that event and always concludes with the stable aggregate gate.
167
167
 
@@ -175,11 +175,11 @@ Security checks can be skipped when repository visibility or the GitHub plan doe
175
175
 
176
176
  ## Review and merge protocol
177
177
 
178
- | Change | Target | Merge method | Merge gate |
179
- | ----------------- | --------- | ------------------------------------------------------- | --------------------------------------------------------- |
180
- | Working branch | `staging` | Squash | All applicable required checks pass |
181
- | `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |
182
- | Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |
178
+ | Change | Target | Merge method | Merge gate |
179
+ | ---------------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------- |
180
+ | Working branch | `staging` | Squash | All applicable required checks pass |
181
+ | `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |
182
+ | Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |
183
183
 
184
184
  Reviewers focus on correctness, security, maintainability, test coverage, operational impact, and compatibility. Authors remain responsible for responding to feedback and verifying the final commit.
185
185
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.37.2](https://github.com/0xPlayerOne/code-foundry/compare/v0.37.1...v0.37.2) (2026-08-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **ci:** stabilize runners and release reconciliation ([#387](https://github.com/0xPlayerOne/code-foundry/issues/387)) ([ea2c503](https://github.com/0xPlayerOne/code-foundry/commit/ea2c503cb6ea9b944ffa5b70ff7fbfc3d56d3a10))
9
+
10
+ ## [0.37.1](https://github.com/0xPlayerOne/code-foundry/compare/v0.37.0...v0.37.1) (2026-08-08)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **sync:** prettier-canonical CONTRIBUTING.md tables for both topologies ([af9137b](https://github.com/0xPlayerOne/code-foundry/commit/af9137bc788853ed97c4c17aef9848b7f9d15fbf))
16
+
3
17
  ## [0.37.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.36.2...v0.37.0) (2026-08-07)
4
18
 
5
19
 
package/docs/RELEASES.md CHANGED
@@ -57,8 +57,9 @@ reject any non-`rebase` `merge_strategy` only when `staging-release` is
57
57
  configured, and always reject a non-`rebase` `release_merge_strategy`; the
58
58
  release workflow fails closed instead of falling back to `merge`. Both keep
59
59
  `main` fully linear, which is what makes the post-release reconciliation
60
- possible: release-only main commits cannot be discarded because they are
61
- allowed metadata-only, and all non-metadata drift is rejected before mutation.
60
+ possible. The final branch trees are inspected before mutation; validated
61
+ main-only changes are inherited by `staging`, while unpromoted staging work is
62
+ replayed on top of `main`.
62
63
 
63
64
  The `staging` → `main` reconciliation exists only in the `staging-release`
64
65
  topology. Patch-equivalent divergence between `main` and `staging` is treated
@@ -67,8 +68,8 @@ as aligned. When `staging` has pending commits that are not yet represented on
67
68
  detached worktree rooted at `main`, and then updates `staging` with an exact
68
69
  `--force-with-lease` to prevent
69
70
  unintended branch rewrites. There is no unconditional mirror force-push and no
70
- fallback synchronization commit path. `direct` repositories skip this step
71
- entirely.
71
+ fallback synchronization commit path. Indeterminate history, replay conflicts,
72
+ and stale leases fail closed. `direct` repositories skip this step entirely.
72
73
 
73
74
  `auto` selects a supported manifest. Use `simple` with `version.txt` for a
74
75
  repository without a package manifest and `none` for a repository that should
package/docs/WORKFLOWS.md CHANGED
@@ -97,9 +97,11 @@ it opens (or reuses) a generated `code-foundry/reconcile/main-to-staging`
97
97
  pull request whose head contains the exact target tip (the `main` tip for a
98
98
  fast-forward, the replay tip when staging-only commits are replayed) and whose
99
99
  body documents the reconciliation. Reruns reuse the open pull request instead
100
- of duplicating it; unexpected code divergence, replay conflicts, authentication
101
- errors, and ambiguous or stale pull request state still fail the job closed,
102
- and exact-lease protection stays in place for every direct push.
100
+ of duplicating it. Validated changes that landed directly on `main` are synced
101
+ back into `staging`; unpromoted staging commits are replayed on top. Indeterminate
102
+ history, replay conflicts, authentication errors, and ambiguous or stale pull
103
+ request state still fail the job closed, and exact-lease protection stays in
104
+ place for every direct push.
103
105
 
104
106
  For this reconciliation path, maintainer PATs and administrator roles are not
105
107
  authorized bypasses; the job deliberately authenticates with `github.token`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "0.37.0",
3
+ "version": "0.37.2",
4
4
  "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-or-later",
@@ -361,6 +361,12 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
361
361
  rendered = rendered.replace(/^(\s+unit-runner:)\s+.*$/m, `$1 ${config.unit_runner}`)
362
362
  }
363
363
  if (workflow === 'validation') {
364
+ // The mode classifier is a normal runner job in the caller rather than a
365
+ // reusable-workflow input. Keep it on the configured default runner so
366
+ // consumers that cannot use ubuntu-slim do not fail before validation.
367
+ if (config.runner) {
368
+ rendered = rendered.replace(/^ mode:\n name: Mode\n runs-on:\s+.*$/m, ` mode:\n name: Mode\n runs-on: ${config.runner}`)
369
+ }
364
370
  /** @type {Record<string, string|undefined>} */
365
371
  const runnerInputs = {
366
372
  'ci-runner': config.ci_runner ?? config.runner,
@@ -481,12 +487,12 @@ const DIRECT_DOC_REPLACEMENTS = {
481
487
  '7. Push to the fork and open a pull request targeting `main`.',
482
488
  ],
483
489
  [
484
- '| Event | Expected automation |\n| --- | --- |\n| Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |\n| Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |\n',
485
- '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |\n',
490
+ '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |\n| Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |\n',
491
+ '| Event | Expected automation |\n|------------------------------------------------------------------------------------------------------------------------------------------------|\n| Pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |',
486
492
  ],
487
493
  [
488
- '| Change | Target | Merge method | Merge gate |\n| ----------------- | --------- | ------------------------------------------------------- | --------------------------------------------------------- |\n| Working branch | `staging` | Squash | All applicable required checks pass |\n| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |\n',
489
- '| Change | Target | Merge method | Merge gate |\n| ------------------------- | ------ | ----------------------------------------------- | --------------------------------------- |\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |\n',
494
+ '| Change | Target | Merge method | Merge gate |\n| ---------------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------- |\n| Working branch | `staging` | Squash | All applicable required checks pass |\n| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |\n',
495
+ '| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |',
490
496
  ],
491
497
  [
492
498
  '1. Create a focused branch from `staging`.',
@@ -220,7 +220,7 @@ function compareVersions(a, b) {
220
220
  * Classify the relationship between main and staging using the final tree delta
221
221
  * when available. Historical commit paths can include equivalent workflow or
222
222
  * configuration changes that are no longer present in the branch delta, so the
223
- * final trees are the source of truth for release-only reconciliation. When
223
+ * final trees are the source of truth for reconciliation. When
224
224
  * directChangedPaths is supplied, unexpected paths in historical main-only
225
225
  * commits are ignored only when they are absent from the final tree delta
226
226
  * (their content is already identical in both branches); unexpected main-only
@@ -281,9 +281,9 @@ export function classifyReconciliation(input) {
281
281
  }
282
282
  if (!stagingOnlyCommits.length) {
283
283
  return {
284
- action: 'fail',
285
- reason: 'branch content differs outside release metadata.',
286
- unexpected,
284
+ action: 'fast-forward',
285
+ targetSha: mainSha,
286
+ reason: 'main contains validated changes that staging must inherit.',
287
287
  }
288
288
  }
289
289
  }
@@ -300,7 +300,11 @@ export function classifyReconciliation(input) {
300
300
  [...new Set(mainOnlyCommits.flatMap((commit) => commit.changedPaths || []))],
301
301
  allowed,
302
302
  ).filter((path) => directTreePaths === null || directTreePaths.has(path))
303
- if (unexpectedMain.length) {
303
+ // Without a final-tree comparison, retain the historical fail-closed
304
+ // behavior. When the final delta is known, main is the validated release
305
+ // source of truth: replay any staging-only work on top instead of deadlocking
306
+ // every later release because a hotfix landed directly on main.
307
+ if (unexpectedMain.length && directTreePaths === null) {
304
308
  return {
305
309
  action: 'fail',
306
310
  reason: 'main contains commits that are not release metadata.',
@@ -373,7 +377,7 @@ export function buildReconciliationPullRequestBody(input) {
373
377
  '',
374
378
  `Merging this pull request synchronizes \`${targetHead}\` with the exact target tip above; no other commits are introduced.`,
375
379
  '',
376
- 'Code Foundry reconciles only release metadata. Unexpected code divergence, replay conflicts, authentication failures, and ambiguous or stale state fail the release job closed and are never pushed around branch protection. Later releases retry the direct push first; when branch policy still rejects it, this pull request is updated instead of duplicated.',
380
+ `Code Foundry treats validated \`${sourceBase}\` as the shipped source of truth and preserves unpromoted \`${targetHead}\` work by replaying it on top. Indeterminate history, replay conflicts, authentication failures, and ambiguous or stale state fail the release job closed and are never pushed around branch protection. Later releases retry the direct push first; when branch policy still rejects it, this pull request is updated instead of duplicated.`,
377
381
  )
378
382
  return lines.join('\n')
379
383
  }