code-foundry 1.6.1 → 1.8.0
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.
- package/.github/code-foundry.yml +2 -2
- package/.github/workflows/release-pr.yml +1 -1
- package/.gitignore +2 -0
- package/CHANGELOG.md +14 -0
- package/docs/CONFIGURATION.md +2 -2
- package/docs/PERFORMANCE.md +58 -0
- package/docs/README.md +1 -0
- package/docs/RELEASES.md +4 -5
- package/package.json +2 -1
- package/release-please-config.json +2 -0
- package/src/cli.mjs +13 -12
- package/src/commands/sync.mjs +9 -8
- package/src/templates/gitignore +2 -0
package/.github/code-foundry.yml
CHANGED
|
@@ -16,8 +16,8 @@ release_type: node
|
|
|
16
16
|
npm_publish: true
|
|
17
17
|
license: agpl-3.0-or-later
|
|
18
18
|
git_workflow: direct
|
|
19
|
-
merge_strategy:
|
|
20
|
-
release_merge_strategy:
|
|
19
|
+
merge_strategy: squash
|
|
20
|
+
release_merge_strategy: squash
|
|
21
21
|
runner: ubuntu-latest
|
|
22
22
|
unit_runner: ubuntu-slim
|
|
23
23
|
performance_runner: ubuntu-latest
|
|
@@ -257,7 +257,7 @@ jobs:
|
|
|
257
257
|
--method POST
|
|
258
258
|
--field base=main
|
|
259
259
|
--field head="$PROMOTION_BRANCH"
|
|
260
|
-
--field title="
|
|
260
|
+
--field title="chore(main): promote staging to main ($DATE)"
|
|
261
261
|
--field body=@"$BODY_FILE"
|
|
262
262
|
)
|
|
263
263
|
if [ "$HAS_AUTOMATION_TOKEN" != true ]; then
|
package/.gitignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.7.0...v1.8.0) (2026-09-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **performance:** enforce source budgets ([#499](https://github.com/0xPlayerOne/code-foundry/issues/499)) ([2f65ba1](https://github.com/0xPlayerOne/code-foundry/commit/2f65ba127f8fe186eda5d6bcae77150f13458428))
|
|
9
|
+
|
|
10
|
+
## [1.7.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.6.1...v1.7.0) (2026-09-08)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **release:** standardize generated PR titles ([#497](https://github.com/0xPlayerOne/code-foundry/issues/497)) ([44de0c4](https://github.com/0xPlayerOne/code-foundry/commit/44de0c4f1261a017a0395ddae268c203cccc71b4))
|
|
16
|
+
|
|
3
17
|
## [1.6.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.6.0...v1.6.1) (2026-09-08)
|
|
4
18
|
|
|
5
19
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -98,8 +98,8 @@ present.
|
|
|
98
98
|
- `direct` (default): feature branches open pull requests directly into
|
|
99
99
|
`main`. Validation and security scans run on every PR. No `staging` branch
|
|
100
100
|
exists, no promotion caller is generated, and `merge_strategy` is not
|
|
101
|
-
enforced. Release Please version PRs
|
|
102
|
-
|
|
101
|
+
enforced. Release Please version PRs squash into `main`
|
|
102
|
+
(`release_merge_strategy: squash`). Dependabot updates target `main`. This is
|
|
103
103
|
the right choice when a repository has no preview or staging environment.
|
|
104
104
|
- `staging-release` (opt-in): feature branches squash into `staging`, a
|
|
105
105
|
promotion PR rebases validated changes into `main` (`merge_strategy:
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Performance budgets and baselines
|
|
2
|
+
|
|
3
|
+
Code Foundry measures its source runtime with `bun run performance:check`. The
|
|
4
|
+
check writes `performance-results.json` for CI artifact upload and fails when a
|
|
5
|
+
budget is exceeded. Generated reports are ignored by Git because measurements
|
|
6
|
+
belong to the run that produced them, not the source tree.
|
|
7
|
+
|
|
8
|
+
## Enforced budgets
|
|
9
|
+
|
|
10
|
+
| Metric | Budget | Why it is bounded |
|
|
11
|
+
| ----------------------------------- | -----: | ---------------------------------------------------- |
|
|
12
|
+
| CLI help startup p95 | 250 ms | Detect eager imports and startup regressions |
|
|
13
|
+
| Runtime mode startup p95 | 250 ms | Detect baseline runtime initialization regressions |
|
|
14
|
+
| Focused runtime tests | 10 s | Keep the representative runtime contract inexpensive |
|
|
15
|
+
| Format, lint, type-check, and build | 15 s | Bound the local CI feedback loop |
|
|
16
|
+
| Runtime dependencies | 0 | Keep the installed CLI dependency-free |
|
|
17
|
+
| Development dependencies | 4 | Prevent unreviewed toolchain growth |
|
|
18
|
+
| Packed artifact | 200 kB | Bound registry transfer and install cost |
|
|
19
|
+
| Unpacked artifact | 750 kB | Bound installed footprint |
|
|
20
|
+
| Packed files | 80 | Detect accidental release contents |
|
|
21
|
+
|
|
22
|
+
The performance workflow disables build-cache reads and writes for this task.
|
|
23
|
+
That makes timing comparisons independent of a warm protected-branch cache and
|
|
24
|
+
prevents benchmark code from populating shared cache entries.
|
|
25
|
+
|
|
26
|
+
## v1.6.1 baseline
|
|
27
|
+
|
|
28
|
+
Measurements were taken on 2026-09-08 with Node 24.18.0. Process startup used
|
|
29
|
+
30 measured samples after four warmups; before and after samples were
|
|
30
|
+
interleaved on the same host.
|
|
31
|
+
|
|
32
|
+
| Measurement | Before | After | Change |
|
|
33
|
+
| -------------------------- | -------: | ----------------------: | -------: |
|
|
34
|
+
| CLI help median | 36.11 ms | 29.57 ms | -18.1% |
|
|
35
|
+
| CLI help p95 | 38.11 ms | 31.56 ms | -17.2% |
|
|
36
|
+
| Runtime mode median | - | 35.94 ms | baseline |
|
|
37
|
+
| Focused runtime tests | - | 2.08 s | baseline |
|
|
38
|
+
| Local CI checks | - | 0.50 s | baseline |
|
|
39
|
+
| Packed / unpacked artifact | - | 160,114 / 616,887 bytes | baseline |
|
|
40
|
+
| Packed files | - | 74 | baseline |
|
|
41
|
+
|
|
42
|
+
The startup reduction comes from loading command implementations only after
|
|
43
|
+
argument parsing selects a command. `--help` no longer imports sync, release,
|
|
44
|
+
fleet, doctor, and CI command modules.
|
|
45
|
+
|
|
46
|
+
The first isolated full hosted audit completed in 3 minutes 2 seconds. Its
|
|
47
|
+
longest jobs were TypeScript CodeQL (66 s), dependency audit (62 s), and unit
|
|
48
|
+
tests (46 s); all other suite jobs completed in 20 seconds or less. Those
|
|
49
|
+
measurements identify the three lanes to optimize before adding more CI fanout.
|
|
50
|
+
|
|
51
|
+
## Release path
|
|
52
|
+
|
|
53
|
+
Treat budget changes like source changes: explain the measured reason in a
|
|
54
|
+
pull request, run the complete validation gate, and merge only when the new
|
|
55
|
+
result artifact is available. A Release Please PR then carries the change into
|
|
56
|
+
the next version. Never raise a budget solely to clear CI; include before/after
|
|
57
|
+
measurements and the expected effect on local feedback, hosted runner time,
|
|
58
|
+
package transfer, or installed footprint.
|
package/docs/README.md
CHANGED
|
@@ -12,6 +12,7 @@ its own names, environments, and deployment details.
|
|
|
12
12
|
- [Release management](RELEASES.md)
|
|
13
13
|
- [Publishing packages](PUBLISHING.md)
|
|
14
14
|
- [Caching and remote caching](CACHING.md)
|
|
15
|
+
- [Performance budgets and baselines](PERFORMANCE.md)
|
|
15
16
|
|
|
16
17
|
## Repository-specific documentation
|
|
17
18
|
|
package/docs/RELEASES.md
CHANGED
|
@@ -24,9 +24,8 @@ topology, feature and fix branches land on `staging` with **squash** merges,
|
|
|
24
24
|
the `staging` → `main` promotion PR merges with **rebase** (`merge_strategy:
|
|
25
25
|
rebase`), and Release Please version PRs merge with **rebase**
|
|
26
26
|
(`release_merge_strategy: rebase`). In the `direct` topology, feature and fix
|
|
27
|
-
branches squash straight into `main` and Release Please version PRs
|
|
28
|
-
|
|
29
|
-
opted in). `merge_strategy` is not enforced. Release automation never defaults
|
|
27
|
+
branches squash straight into `main` and Release Please version PRs squash into
|
|
28
|
+
`main` (`release_merge_strategy: squash`). `merge_strategy` is not enforced. Release automation never defaults
|
|
30
29
|
to a merge method and never merges with `--admin`: `staging-release` accepts
|
|
31
30
|
only rebase for release PRs, while `direct` accepts rebase or squash.
|
|
32
31
|
|
|
@@ -46,7 +45,7 @@ release_type: auto # auto, node, python, rust, simple, or none
|
|
|
46
45
|
npm_publish: false # true only for an npm package
|
|
47
46
|
git_workflow: direct # direct (default) or staging-release
|
|
48
47
|
merge_strategy: rebase # staging-release only: staging -> main promotion PRs rebase
|
|
49
|
-
release_merge_strategy:
|
|
48
|
+
release_merge_strategy: squash # direct default; staging-release requires rebase
|
|
50
49
|
```
|
|
51
50
|
|
|
52
51
|
`git_workflow: staging-release` is opt-in; without it, repositories use the
|
|
@@ -136,6 +135,6 @@ already passed).
|
|
|
136
135
|
|
|
137
136
|
1. Merge tested changes into `main` (direct: feature PRs; staging-release: promote `staging` into `main`).
|
|
138
137
|
2. Review the generated Release Please PR and changelog.
|
|
139
|
-
3. Merge the release PR with the
|
|
138
|
+
3. Merge the release PR with squash in the direct topology (`release_merge_strategy: squash`).
|
|
140
139
|
4. Confirm the GitHub Release and any package publication.
|
|
141
140
|
5. staging-release only: synchronize `staging` with the new `main` release commit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
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": {
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"format:check": "oxfmt --check .",
|
|
44
44
|
"fmt": "oxfmt .",
|
|
45
45
|
"lint": "oxlint",
|
|
46
|
+
"performance:check": "node scripts/performance-check.mjs",
|
|
46
47
|
"test": "node --test",
|
|
47
48
|
"test:unit": "node --test",
|
|
48
49
|
"type-check": "tsc --project jsconfig.json",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
3
3
|
"bump-minor-pre-major": true,
|
|
4
|
+
"pull-request-title-pattern": "chore(main): release ${version}",
|
|
5
|
+
"group-pull-request-title-pattern": "chore(main): release ${version}",
|
|
4
6
|
"changelog-sections": [
|
|
5
7
|
{ "type": "feat", "section": "Features" },
|
|
6
8
|
{ "type": "fix", "section": "Bug Fixes" },
|
package/src/cli.mjs
CHANGED
|
@@ -4,16 +4,6 @@
|
|
|
4
4
|
import { resolve } from 'node:path'
|
|
5
5
|
import { readFileSync } from 'node:fs'
|
|
6
6
|
import { fileURLToPath } from 'node:url'
|
|
7
|
-
import { doctor } from './commands/doctor.mjs'
|
|
8
|
-
import {
|
|
9
|
-
dispatchPostReleaseHook,
|
|
10
|
-
reconcileRelease,
|
|
11
|
-
releaseRecoveryPlan,
|
|
12
|
-
validateReleasePullRequestDiffs,
|
|
13
|
-
} from './commands/release.mjs'
|
|
14
|
-
import { discoverRepositories, upgradeFleet } from './commands/fleet.mjs'
|
|
15
|
-
import { syncRepository } from './commands/sync.mjs'
|
|
16
|
-
import { manageCiBilling } from './commands/ci.mjs'
|
|
17
7
|
|
|
18
8
|
const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)))
|
|
19
9
|
|
|
@@ -133,12 +123,13 @@ function parseArgs(argv) {
|
|
|
133
123
|
return { command, options }
|
|
134
124
|
}
|
|
135
125
|
|
|
136
|
-
function main() {
|
|
126
|
+
async function main() {
|
|
137
127
|
const { command, options } = parseArgs(process.argv.slice(2))
|
|
138
128
|
const target = resolve(options.target)
|
|
139
129
|
|
|
140
130
|
if (command === 'init') {
|
|
141
131
|
try {
|
|
132
|
+
const { syncRepository } = await import('./commands/sync.mjs')
|
|
142
133
|
syncRepository({
|
|
143
134
|
target,
|
|
144
135
|
source: packageRoot,
|
|
@@ -151,12 +142,14 @@ function main() {
|
|
|
151
142
|
}
|
|
152
143
|
} else if (command === 'sync') {
|
|
153
144
|
try {
|
|
145
|
+
const { syncRepository } = await import('./commands/sync.mjs')
|
|
154
146
|
syncRepository({ target, source: packageRoot, dryRun: options.dryRun, force: options.force })
|
|
155
147
|
} catch (error) {
|
|
156
148
|
fail(error instanceof Error ? error.message : String(error))
|
|
157
149
|
}
|
|
158
150
|
} else if (command === 'doctor') {
|
|
159
151
|
try {
|
|
152
|
+
const { doctor } = await import('./commands/doctor.mjs')
|
|
160
153
|
doctor(target, { github: options.github })
|
|
161
154
|
} catch (error) {
|
|
162
155
|
console.error(`code-foundry: ${error instanceof Error ? error.message : String(error)}`)
|
|
@@ -164,6 +157,12 @@ function main() {
|
|
|
164
157
|
}
|
|
165
158
|
} else if (command === 'release') {
|
|
166
159
|
try {
|
|
160
|
+
const {
|
|
161
|
+
dispatchPostReleaseHook,
|
|
162
|
+
reconcileRelease,
|
|
163
|
+
releaseRecoveryPlan,
|
|
164
|
+
validateReleasePullRequestDiffs,
|
|
165
|
+
} = await import('./commands/release.mjs')
|
|
167
166
|
if (options.releaseSubcommand === 'hook') dispatchPostReleaseHook(target, options)
|
|
168
167
|
else if (options.releaseSubcommand === 'validate-prs') validateReleasePullRequestDiffs(target)
|
|
169
168
|
else if (options.releaseSubcommand === 'recovery-plan') releaseRecoveryPlan(target)
|
|
@@ -173,6 +172,7 @@ function main() {
|
|
|
173
172
|
}
|
|
174
173
|
} else if (command === 'fleet') {
|
|
175
174
|
try {
|
|
175
|
+
const { discoverRepositories, upgradeFleet } = await import('./commands/fleet.mjs')
|
|
176
176
|
const root = resolve(options.root)
|
|
177
177
|
if (options.fleetSubcommand === 'status')
|
|
178
178
|
console.log(JSON.stringify(discoverRepositories(root), null, 2))
|
|
@@ -189,6 +189,7 @@ function main() {
|
|
|
189
189
|
}
|
|
190
190
|
} else if (command === 'ci') {
|
|
191
191
|
try {
|
|
192
|
+
const { manageCiBilling } = await import('./commands/ci.mjs')
|
|
192
193
|
manageCiBilling(target, /** @type {'pause'|'resume'|'status'} */ (options.ciSubcommand))
|
|
193
194
|
} catch (error) {
|
|
194
195
|
fail(error instanceof Error ? error.message : String(error))
|
|
@@ -196,7 +197,7 @@ function main() {
|
|
|
196
197
|
} else fail(`unknown command: ${command}`)
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
main()
|
|
200
|
+
await main()
|
|
200
201
|
|
|
201
202
|
/** @param {string} root @returns {string} */
|
|
202
203
|
function readPackageVersion(root) {
|
package/src/commands/sync.mjs
CHANGED
|
@@ -108,7 +108,7 @@ export function syncRepository(options) {
|
|
|
108
108
|
const existingConfig = readConfig(configPath)
|
|
109
109
|
if (!Object.keys(existingConfig).length && !options.init)
|
|
110
110
|
throw new Error('Missing .github/code-foundry.yml; run init first.')
|
|
111
|
-
const defaults = createDefaultConfig(target, source)
|
|
111
|
+
const defaults = createDefaultConfig(target, source, existingConfig.git_workflow)
|
|
112
112
|
let config = { ...defaults, ...existingConfig }
|
|
113
113
|
// Resolve and validate the license policy before any sync writes occur
|
|
114
114
|
// (including config/default additions) so an unsupported policy fails
|
|
@@ -658,7 +658,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
658
658
|
],
|
|
659
659
|
[
|
|
660
660
|
'This repository uses the `staging-release` workflow: 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`). Feature PRs land on `staging` with squash merges; promotion and release PRs land on `main` with rebase merges. Re-align `staging` with `main` after a release when needed.',
|
|
661
|
-
'This repository uses the `direct` workflow: topic branches **squash** directly into `main`, and the Release Please version PR
|
|
661
|
+
'This repository uses the `direct` workflow: topic branches **squash** directly into `main`, and the Release Please version PR **squashes** into `main` (`release_merge_strategy: squash`). Feature and release PRs land on `main` with squash merges. No integration branch exists; all pull requests target `main`.',
|
|
662
662
|
],
|
|
663
663
|
],
|
|
664
664
|
'.github/CONTRIBUTING.md': [
|
|
@@ -676,7 +676,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
676
676
|
],
|
|
677
677
|
[
|
|
678
678
|
'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.',
|
|
679
|
-
'The Git workflow is `direct`: topic branches **squash** directly into `main`, and the Release Please version PR
|
|
679
|
+
'The Git workflow is `direct`: topic branches **squash** directly into `main`, 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 release merge strategy. Feature branches never touch `staging`; repositories with a preview/staging environment opt into `git_workflow: staging-release` explicitly.',
|
|
680
680
|
],
|
|
681
681
|
[
|
|
682
682
|
'git switch staging\ngit pull --ff-only origin staging',
|
|
@@ -702,7 +702,7 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
702
702
|
],
|
|
703
703
|
[
|
|
704
704
|
'| 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',
|
|
705
|
-
'| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` |
|
|
705
|
+
'| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` | Squash (`release_merge_strategy`) | Validation gate and release policy pass |',
|
|
706
706
|
],
|
|
707
707
|
['1. Create a focused branch from `staging`.', '1. Create a focused branch from `main`.'],
|
|
708
708
|
],
|
|
@@ -1068,11 +1068,12 @@ function buffersEqual(a, b) {
|
|
|
1068
1068
|
return a.equals(b)
|
|
1069
1069
|
}
|
|
1070
1070
|
|
|
1071
|
-
/** @param {string} root @param {string} source @returns {Record<string,string>} */
|
|
1072
|
-
function createDefaultConfig(root, source) {
|
|
1071
|
+
/** @param {string} root @param {string} source @param {string|undefined} configuredWorkflow @returns {Record<string,string>} */
|
|
1072
|
+
function createDefaultConfig(root, source, configuredWorkflow) {
|
|
1073
1073
|
const languages = detectLanguages(root).join(',')
|
|
1074
1074
|
const packageManager = detectPackageManager(root)
|
|
1075
1075
|
const runners = recommendRunners(root)
|
|
1076
|
+
const stagingRelease = configuredWorkflow === 'staging-release'
|
|
1076
1077
|
return {
|
|
1077
1078
|
version: '1',
|
|
1078
1079
|
profile: detectProfile(root),
|
|
@@ -1107,8 +1108,8 @@ function createDefaultConfig(root, source) {
|
|
|
1107
1108
|
custom_workflows: 'preserve',
|
|
1108
1109
|
license: existsSync(join(root, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later',
|
|
1109
1110
|
git_workflow: 'direct',
|
|
1110
|
-
merge_strategy: 'rebase',
|
|
1111
|
-
release_merge_strategy: 'rebase',
|
|
1111
|
+
merge_strategy: stagingRelease ? 'rebase' : 'squash',
|
|
1112
|
+
release_merge_strategy: stagingRelease ? 'rebase' : 'squash',
|
|
1112
1113
|
}
|
|
1113
1114
|
}
|
|
1114
1115
|
|