code-foundry 0.34.12 → 0.34.13

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.
@@ -48,7 +48,7 @@ docs/* test/* refactor/* │ │
48
48
  | `staging` | Integration branch | Target normal pull requests here. Required checks must pass before merge. |
49
49
  | `feat/*`, `fix/*`, `chore/*`, `refactor/*`, `docs/*`, `test/*` | Focused work | Branch from `staging`; keep changes small and reviewable. |
50
50
 
51
- The Git workflow is `staging-release`: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **squashes** into `main` (`release_merge_strategy: squash`). Release automation never defaults to a merge method and never merges with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on any other merge strategy. Re-align `staging` with `main` after a release when needed.
51
+ The Git workflow is `staging-release`: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **rebases** into `main` (`release_merge_strategy: rebase`). Release automation never defaults to a merge method and never merges with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on any other merge strategy. Re-align `staging` with `main` after a release when needed.
52
52
 
53
53
  ## Before you start
54
54
 
@@ -179,7 +179,7 @@ Security checks can be skipped when repository visibility or the GitHub plan doe
179
179
  | ----------------- | --------- | ------------------------------------------------------- | --------------------------------------------------------- |
180
180
  | Working branch | `staging` | Squash | All applicable required checks pass |
181
181
  | `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |
182
- | Release Please version PR | `main` | Squash (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |
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
 
@@ -17,7 +17,7 @@ npm_publish: true
17
17
  license: agpl-3.0-or-later
18
18
  git_workflow: staging-release
19
19
  merge_strategy: rebase
20
- release_merge_strategy: squash
20
+ release_merge_strategy: rebase
21
21
  runner: ubuntu-latest
22
22
  unit_runner: ubuntu-slim
23
23
  cache_packages: auto
@@ -9,6 +9,7 @@ updates:
9
9
  open-pull-requests-limit: 99
10
10
  groups:
11
11
  github-actions:
12
+ applies-to: version-updates
12
13
  patterns: ['*']
13
14
  - package-ecosystem: npm
14
15
  directory: /
@@ -19,6 +20,7 @@ updates:
19
20
  open-pull-requests-limit: 99
20
21
  groups:
21
22
  npm-dependencies:
23
+ applies-to: version-updates
22
24
  patterns: ['*']
23
25
  - package-ecosystem: cargo
24
26
  directory: /
@@ -29,6 +31,7 @@ updates:
29
31
  open-pull-requests-limit: 99
30
32
  groups:
31
33
  cargo-dependencies:
34
+ applies-to: version-updates
32
35
  patterns: ['*']
33
36
  - package-ecosystem: pip
34
37
  directory: /
@@ -39,4 +42,5 @@ updates:
39
42
  open-pull-requests-limit: 99
40
43
  groups:
41
44
  python-dependencies:
45
+ applies-to: version-updates
42
46
  patterns: ['*']
@@ -84,17 +84,18 @@ jobs:
84
84
  : {}
85
85
  let releaseType = config.release_type || 'auto'
86
86
  let npmPublish = config.npm_publish || 'false'
87
- // The merge audit topology requires squash for Release Please version
88
- // pull requests into main. Release automation never defaults to a
89
- // merge method: an unset or non-squash release_merge_strategy fails
90
- // the release job before any pull request is created or merged.
87
+ // The merge audit topology requires rebase for Release Please version
88
+ // pull requests into main, matching the linear-history ruleset.
89
+ // Release automation never defaults to a merge method: an unset or
90
+ // non-rebase release_merge_strategy fails the release job before any
91
+ // pull request is created or merged.
91
92
  const releaseMergeStrategy = String(config.release_merge_strategy || '').trim().toLowerCase()
92
93
  if (releaseType === 'auto') {
93
94
  releaseType = fs.existsSync('package.json') ? 'node' : fs.existsSync('pyproject.toml') ? 'python' : fs.existsSync('Cargo.toml') ? 'rust' : fs.existsSync('version.txt') ? 'simple' : 'none'
94
95
  }
95
96
  if (!['node', 'python', 'rust', 'simple', 'none'].includes(releaseType)) throw new Error(`Unsupported release_type: ${releaseType}`)
96
- if (releaseMergeStrategy !== 'squash') {
97
- throw new Error(`release_merge_strategy must be "squash" for automated release merges; got ${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}`)
97
+ if (releaseMergeStrategy !== 'rebase') {
98
+ throw new Error(`release_merge_strategy must be "rebase" for automated release merges; got ${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}`)
98
99
  }
99
100
  if (releaseType === 'none' || !fs.existsSync('package.json')) npmPublish = 'false'
100
101
  let legacyReleaseType = ''
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.34.13](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.12...v0.34.13) (2026-08-03)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **reconcile:** classify patch-equivalent trees consistently ([#360](https://github.com/0xPlayerOne/code-foundry/issues/360)) ([c95f1bd](https://github.com/0xPlayerOne/code-foundry/commit/c95f1bdeaa69fc5fbcd42821bc633edbbd31de49))
9
+ * **release:** use rebase for release PRs ([#358](https://github.com/0xPlayerOne/code-foundry/issues/358)) ([3b2b2f5](https://github.com/0xPlayerOne/code-foundry/commit/3b2b2f5cee15e3f61a1688e5b3ef0847a6eb8c55))
10
+
3
11
  ## [0.34.12](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.11...v0.34.12) (2026-08-02)
4
12
 
5
13
 
package/README.md CHANGED
@@ -90,8 +90,8 @@ checks, runners, coverage, caching, and custom workflow extensions.
90
90
 
91
91
  The contribution policy uses the `staging-release` workflow: feature PRs squash
92
92
  into `staging`, the promotion PR rebases into `main` (`merge_strategy: rebase`),
93
- and Release Please version PRs squash into `main` (`release_merge_strategy:
94
- squash`). Release automation never defaults to a merge method and never merges
93
+ and Release Please version PRs rebase into `main` (`release_merge_strategy:
94
+ rebase`). Release automation never defaults to a merge method and never merges
95
95
  with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on
96
96
  any other strategy. GitHub Stacks is not part of this topology and does not
97
97
  reduce the required workflow runs.
@@ -49,7 +49,7 @@ repository manifests and source
49
49
  | `license` | `gpl-3.0-or-later`, `agpl-3.0-or-later`, `mit`, `preserve`, `none` | License policy; new repositories default to GPLv3 |
50
50
  | `git_workflow` | `staging-release` | Branch/release model; the standard model promotes `staging` into `main` |
51
51
  | `merge_strategy` | `rebase` | Promotion merge method for `staging` → `main`; the staging-release topology requires rebase |
52
- | `release_merge_strategy` | `squash` | Merge method for Release Please version PRs into `main`; release automation fails closed unless squash |
52
+ | `release_merge_strategy` | `rebase` | Merge method for Release Please version PRs into `main`; release automation fails closed unless rebase |
53
53
  | `runner` fields | GitHub runner names | Per-workflow runner policy |
54
54
 
55
55
  Supported features are `ci`, `codeql`, `security`, `test`, `draft-pr`,
package/docs/RELEASES.md CHANGED
@@ -15,10 +15,10 @@ versions and generate grouped changelog notes.
15
15
  The merge audit pins one merge method per transition in this topology. Feature
16
16
  and fix branches land on `staging` with **squash** merges, the `staging` → `main`
17
17
  promotion PR merges with **rebase** (`merge_strategy: rebase`), and Release
18
- Please version PRs merge with **squash** (`release_merge_strategy: squash`).
18
+ Please version PRs merge with **rebase** (`release_merge_strategy: rebase`).
19
19
  Release automation never defaults to a merge method and never merges with
20
20
  `--admin`: the release workflow fails closed unless `release_merge_strategy` is
21
- exactly `squash`. The current supported `git_workflow` is `staging-release`.
21
+ exactly `rebase`. The current supported `git_workflow` is `staging-release`.
22
22
 
23
23
  The release workflow opens or updates a versioned PR after changes reach
24
24
  `main`. Merging that PR updates the changelog, creates the Git tag and GitHub
@@ -35,13 +35,13 @@ Set these values in `.github/code-foundry.yml`:
35
35
  release_type: auto # auto, node, python, rust, simple, or none
36
36
  npm_publish: false # true only for an npm package
37
37
  merge_strategy: rebase # required: staging -> main promotion PRs rebase
38
- release_merge_strategy: squash # required: Release Please version PRs squash only
38
+ release_merge_strategy: rebase # required: Release Please version PRs rebase only
39
39
  ```
40
40
 
41
41
  `merge_strategy` applies to promotion PRs (`staging` into `main`) and
42
42
  `release_merge_strategy` to Release Please version PRs; feature PRs into
43
43
  `staging` use squash merges. The topology requires `merge_strategy: rebase`
44
- and `release_merge_strategy: squash`; `code-foundry doctor` and
44
+ and `release_merge_strategy: rebase`; `code-foundry doctor` and
45
45
  `code-foundry sync` reject any other value, and the release workflow fails
46
46
  closed instead of falling back to `merge`. Both keep `main` fully linear,
47
47
  which is what makes the post-release reconciliation possible: release-only
@@ -103,6 +103,6 @@ already passed).
103
103
 
104
104
  1. Merge tested changes from `staging` into `main`.
105
105
  2. Review the generated Release Please PR and changelog.
106
- 3. Merge the release PR with the repository's configured `release_merge_strategy` (**squash**; the release workflow fails closed on any other value).
106
+ 3. Merge the release PR with the repository's configured `release_merge_strategy` (**rebase**; the release workflow fails closed on any other value).
107
107
  4. Confirm the GitHub Release and any package publication.
108
108
  5. Synchronize `staging` with the new `main` release commit.
package/docs/WORKFLOWS.md CHANGED
@@ -42,13 +42,13 @@ enabled for the repository profile.
42
42
 
43
43
  The merge audit pins one merge method per transition. `code-foundry doctor`
44
44
  and `code-foundry sync` fail closed on any other strategy, and the release
45
- workflow refuses to run unless its strategy is exactly `squash`.
45
+ workflow refuses to run unless its strategy is exactly `rebase`.
46
46
 
47
47
  | Transition | Merge method | Enforcement |
48
48
  | --- | --- | --- |
49
49
  | Feature/fix PR into `staging` | Squash | Contribution policy; see `CONTRIBUTING.md` |
50
50
  | `staging` → `main` promotion PR | Rebase (`merge_strategy: rebase`) | `merge_strategy` must be `rebase`; merge commits are rejected |
51
- | Release Please version PR into `main` | Squash (`release_merge_strategy: squash`) | Release automation fails closed unless `squash`; never defaults to `merge`, never uses `--admin` |
51
+ | Release Please version PR into `main` | Rebase (`release_merge_strategy: rebase`) | Release automation fails closed unless `rebase`; never defaults to `merge`, never uses `--admin` |
52
52
 
53
53
  Release auto-merge waits for required checks and then polls `mergeStateStatus`
54
54
  until it is `CLEAN`, or `UNSTABLE` with `mergeable` `MERGEABLE`, before
@@ -59,7 +59,7 @@ additional required checks after earlier ones have passed (for example
59
59
  merge policy-blocked. The mergeability poll is bounded and fails closed on
60
60
  conflicts or timeout; releases without an automation token remain manual.
61
61
 
62
- Keeping `main` linear — rebase promotions and squash release PRs — is what
62
+ Keeping `main` linear — rebase promotions and rebase release PRs — is what
63
63
  lets the post-release reconciliation fast-forward or replay `staging` safely.
64
64
 
65
65
  Protect `staging` with the aggregate `Validation / Gate`, squash-only pull
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "0.34.12",
3
+ "version": "0.34.13",
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",
@@ -75,8 +75,8 @@ export function doctor(root, options = {}) {
75
75
  error(`merge_strategy must be "rebase" for the staging-release promotion topology; got "${mergeStrategy}".`)
76
76
  }
77
77
  const releaseMergeStrategy = config.release_merge_strategy ?? ''
78
- if (includesValue(features, 'release') && releaseMergeStrategy !== 'squash') {
79
- error(`release_merge_strategy must be "squash" for automated release merges; got "${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}".`)
78
+ if (includesValue(features, 'release') && releaseMergeStrategy !== 'rebase') {
79
+ error(`release_merge_strategy must be "rebase" for automated release merges; got "${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}".`)
80
80
  }
81
81
  for (const workflow of ['validation', 'draft-pr', 'release-pr', 'release']) {
82
82
  if (includesValue(features, workflow) && !existsSync(join(target, `.github/workflows/${workflow}.yml`))) error(`missing enabled workflow: ${workflow}.yml`)
@@ -84,8 +84,8 @@ export function syncRepository(options) {
84
84
  throw new Error(`Unsupported merge_strategy: ${mergeStrategy}; the staging-release topology requires rebase for staging to main promotions.`)
85
85
  }
86
86
  const releaseMergeStrategy = configured(config.release_merge_strategy, '')
87
- if (includesValue(features, 'release') && releaseMergeStrategy !== 'squash') {
88
- throw new Error(`Unsupported release_merge_strategy: ${releaseMergeStrategy || '(unset)'}; release automation requires squash for Release Please version pull requests and never defaults to merge.`)
87
+ if (includesValue(features, 'release') && releaseMergeStrategy !== 'rebase') {
88
+ throw new Error(`Unsupported release_merge_strategy: ${releaseMergeStrategy || '(unset)'}; release automation requires rebase for Release Please version pull requests and never defaults to merge.`)
89
89
  }
90
90
  const license = configured(config.license, existsSync(join(target, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later')
91
91
  const changed = []
@@ -460,7 +460,7 @@ function createDefaultConfig(root, source) {
460
460
  post_release: 'false', post_release_workflow: '', post_release_mode: 'auto',
461
461
  opencode_security: 'false',
462
462
  sync_mode: 'overlay', custom_workflows: 'preserve',
463
- license: existsSync(join(root, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later', git_workflow: 'staging-release', merge_strategy: 'rebase', release_merge_strategy: 'squash',
463
+ license: existsSync(join(root, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later', git_workflow: 'staging-release', merge_strategy: 'rebase', release_merge_strategy: 'rebase',
464
464
  }
465
465
  }
466
466
 
@@ -256,6 +256,12 @@ export function classifyReconciliation(input) {
256
256
  if (Array.isArray(directChangedPaths)) {
257
257
  const paths = [...new Set(directChangedPaths.map((path) => path.trim()).filter(Boolean))]
258
258
  const unexpected = unexpectedReleasePaths(paths, allowed)
259
+ // Git may hide patch-equivalent commits when divergentCommits uses
260
+ // --cherry-pick. If the final trees are identical and no non-equivalent
261
+ // commits remain, classify the branches consistently as aligned.
262
+ if (!paths.length && !mainOnlyCommits.length && !stagingOnlyCommits.length) {
263
+ return { action: 'aligned', targetSha: mainSha, reason: 'Branches have different history but identical content.' }
264
+ }
259
265
  const stagingOnlyReleaseOnly = stagingOnlyCommits.length > 0 && stagingOnlyCommits.every((commit) =>
260
266
  Array.isArray(commit.changedPaths) && commit.changedPaths.length > 0 && unexpectedReleasePaths(commit.changedPaths, allowed).length === 0,
261
267
  )