code-foundry 1.10.0 → 1.10.1

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.
@@ -181,11 +181,11 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
181
181
  | Exact Release Please pull request targeting `main` | Full validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
182
182
  | Scheduled or manual validation | Full audit tier |
183
183
  | Push to a working branch | Draft PR workflow |
184
- | Push to `main` | Release workflow; canonical validation already ran on the merged PR |
184
+ | Push to `main` | Release workflow plus default-branch CodeQL scan; validation ran on the merged PR |
185
185
 
186
186
  Draft pull requests do not start validation. The lightweight Draft Guard also converts ordinary pull requests opened, reopened, or updated while ready back to draft; it never checks out pull-request code and it excludes Release Please version heads, whose release workflow owns their state. Marking a pull request ready for review starts the applicable validation tier. Convert it back to draft after an update, then mark it ready again after every update so the required checks attach to the current head. Converting it to draft runs only the lightweight cancellation control.
187
187
 
188
- Pull-request validation keys concurrency by event and pull-request head, so a newer update cancels its superseded run. Scheduled and manual audits use a separate caller pinned to the protected default branch; this prevents caller-selected runtime code from executing with default-branch cache access. Both callers use the mode-aware orchestrator, which fans out only the required jobs and concludes with the stable aggregate gate.
188
+ Pull-request validation keys concurrency by event and pull-request head, so a newer update cancels its superseded run. Scheduled and manual audits use a separate caller pinned to the protected default branch; this prevents caller-selected runtime code from executing with default-branch cache access. Pull-request and scheduled/manual callers use the mode-aware orchestrator, which fans out only the required jobs and concludes with the stable aggregate gate. Main pushes run the default-branch CodeQL lane separately.
189
189
 
190
190
  Required checks are enforced by branch protection rulesets/branch protection. Do not duplicate their checklists in the pull request description; document validation commands and results instead.
191
191
 
@@ -1,6 +1,8 @@
1
1
  name: Code Foundry
2
2
 
3
3
  on:
4
+ push:
5
+ branches: [main]
4
6
  pull_request:
5
7
  branches: [main, staging]
6
8
  types:
@@ -18,9 +20,9 @@ concurrency:
18
20
  jobs:
19
21
  mode:
20
22
  name: Mode
21
- # The workflow is emitted only for ready_for_review, so draft pull requests
22
- # register no skipped validation checks and allocate no validation runner.
23
- if: vars.CI_BILLING_PAUSED != 'true'
23
+ # The mode classifier is only needed for pull requests. Main pushes use
24
+ # the dedicated default-branch CodeQL lane below.
25
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request'
24
26
  runs-on: ubuntu-slim
25
27
  timeout-minutes: 10
26
28
  permissions:
@@ -59,7 +61,7 @@ jobs:
59
61
  validation:
60
62
  name: Validation
61
63
  needs: mode
62
- if: vars.CI_BILLING_PAUSED != 'true'
64
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request'
63
65
  # Reusable workflows can only maintain or reduce the caller job's scopes.
64
66
  # The audit tier needs security-events: write for CodeQL uploads.
65
67
  permissions:
@@ -87,3 +89,23 @@ jobs:
87
89
  secrets:
88
90
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
89
91
  NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
92
+
93
+ # CodeQL requires a push analysis to populate default-branch code-scanning
94
+ # alerts. Keep the full validation gate pull-request-only so main pushes do
95
+ # not duplicate CI, test, or security work.
96
+ default-branch-codeql:
97
+ name: CodeQL (default branch)
98
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'push'
99
+ permissions:
100
+ actions: read
101
+ contents: read
102
+ packages: read
103
+ security-events: write
104
+ uses: ./.github/workflows/codeql.yml
105
+ with:
106
+ runtime-repository: 0xPlayerOne/code-foundry
107
+ runtime-ref: ${{ github.sha }}
108
+ runner: ubuntu-latest
109
+ rust-shards: '["all"]'
110
+ rust-threads: '1'
111
+ rust-max-parallel: 1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.10.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.10.0...v1.10.1) (2026-09-09)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **doctor:** honor shared config and correctly identify npm/Yarn lockfiles ([#533](https://github.com/0xPlayerOne/code-foundry/issues/533)) ([6464409](https://github.com/0xPlayerOne/code-foundry/commit/646440907ad3fc47f63e27b9621c8e0025459964))
9
+ * **validation:** scan default branch with CodeQL on push ([#540](https://github.com/0xPlayerOne/code-foundry/issues/540)) ([98d8241](https://github.com/0xPlayerOne/code-foundry/commit/98d8241522c78e1b6d3f4f29a44053d33888edba))
10
+
3
11
  ## [1.10.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.13...v1.10.0) (2026-09-08)
4
12
 
5
13
 
package/README.md CHANGED
@@ -70,7 +70,7 @@ when present and otherwise uses native language tooling; choose `native` or
70
70
 
71
71
  The standard workflow triggers are:
72
72
 
73
- - Pushes to `main` (and `staging` when `git_workflow: staging-release` is configured).
73
+ - Pushes to `main` (and `staging` when `git_workflow: staging-release` is configured); main pushes also run the default-branch CodeQL scan.
74
74
  - Pull requests targeting `main` (and `staging` in the staging-release topology).
75
75
  - Draft PR automation for supported feature/fix branches.
76
76
 
package/docs/WORKFLOWS.md CHANGED
@@ -4,16 +4,21 @@
4
4
 
5
5
  Validation uses two callers so pull-request code and default-branch-capable
6
6
  audit events never share a caller-selected runtime ref. The canonical
7
- `validation.yml` caller handles pull requests only:
7
+ `validation.yml` caller handles pull requests and a lightweight default-branch
8
+ CodeQL lane:
8
9
 
9
10
  ```yaml
11
+ push:
12
+ branches: [main] # CodeQL only
10
13
  pull_request:
11
14
  branches: [main, staging] # staging-release topology
12
15
  # direct topology: branches: [main]
13
16
  ```
14
17
 
15
- The generated validation caller listens only for `ready_for_review`, so draft
16
- pull requests register no validation checks and allocate no validation runner.
18
+ The generated validation caller listens for `ready_for_review` and `push` to
19
+ `main`. Draft pull requests register no validation checks and allocate no
20
+ validation runner; main pushes run only the default-branch CodeQL lane, while
21
+ full validation remains pull-request-only.
17
22
  A separate lightweight Draft Guard runs from the trusted base branch on
18
23
  `opened`, `reopened`, and `synchronize`; it converts ordinary ready pull
19
24
  requests back to draft without checking out pull-request code. It rechecks the
@@ -44,7 +49,7 @@ Scheduled and manual runs select the audit tier in both topologies. Draft PR
44
49
  automation separately listens to supported topic-branch pushes and always
45
50
  opens those PRs as drafts. Promotion automation listens to `staging` pushes
46
51
  (staging-release only) and also always opens its PR as a draft. Release
47
- automation listens to `main` pushes.
52
+ automation and default-branch CodeQL listen to `main` pushes.
48
53
  Custom deployment, indexing, search, Slither, or other workflows are
49
54
  repository-owned extensions and should use the same ready-transition policy.
50
55
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
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": {
@@ -5,6 +5,7 @@ import { join, resolve } from 'node:path'
5
5
  import { spawnSync } from 'node:child_process'
6
6
  import { includesValue, readConfig } from '../lib/config.mjs'
7
7
  import { recommendRunners, resolveProfile } from '../lib/profile.mjs'
8
+ import { packageManagerForLockfile } from '../lib/lockfiles.mjs'
8
9
  import { doctorGithub } from '../lib/github-doctor.mjs'
9
10
  import { isGeneratedEventCaller } from './sync.mjs'
10
11
 
@@ -69,9 +70,7 @@ export function doctor(root, options = {}) {
69
70
  if (lockfiles.length > 1) error('multiple JavaScript lockfiles found; keep one package manager')
70
71
  if (packageJson.packageManager && lockfiles.length) {
71
72
  const declared = String(packageJson.packageManager).split('@')[0]
72
- const actual = lockfiles[0]?.startsWith('bun')
73
- ? 'bun'
74
- : lockfiles[0]?.split('-')[0].replace('.yaml', '')
73
+ const actual = packageManagerForLockfile(lockfiles[0])
75
74
  if (actual && declared !== actual)
76
75
  error(`packageManager (${declared}) does not match ${actual} lockfile`)
77
76
  }
@@ -537,12 +537,15 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
537
537
  let rendered = content.replaceAll(localPrefix, remotePrefix)
538
538
  // An explicitly unavailable CodeQL capability selects an orchestrator that
539
539
  // omits the job entirely, so GitHub does not register a misleading skipped
540
- // check on every pull request. `auto` retains runtime capability detection.
540
+ // check on every pull request or an unused main-push run. `auto` retains
541
+ // runtime capability detection.
541
542
  if (configured(config.codeql, 'auto') === 'false') {
542
543
  rendered = rendered.replaceAll(
543
544
  `${remotePrefix}validation.yml`,
544
545
  `${remotePrefix}validation-no-codeql.yml`
545
546
  )
547
+ rendered = removeWorkflowBlock(rendered, 'default-branch-codeql')
548
+ rendered = removeWorkflowBlock(rendered, 'push')
546
549
  }
547
550
  rendered = rendered.replace(
548
551
  new RegExp(`${escapeRegExp(remotePrefix)}([^\\s@]+)`, 'g'),
@@ -640,6 +643,25 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
640
643
  return rendered
641
644
  }
642
645
 
646
+ /**
647
+ * Remove a root-level YAML block by id while preserving the surrounding file.
648
+ * This is used for workflow jobs and triggers whose feature is disabled by
649
+ * configuration.
650
+ * @param {string} content
651
+ * @param {string} blockId
652
+ * @returns {string}
653
+ */
654
+ function removeWorkflowBlock(content, blockId) {
655
+ const lines = content.split('\n')
656
+ const start = lines.findIndex((line) => line === ` ${blockId}:`)
657
+ if (start === -1) return content
658
+ let end = start + 1
659
+ while (end < lines.length && !/^ [A-Za-z0-9_-]+:\s*$/.test(lines[end])) end += 1
660
+ lines.splice(start, end - start)
661
+ if (content.endsWith('\n') && lines.at(-1) !== '') lines.push('')
662
+ return lines.join('\n')
663
+ }
664
+
643
665
  /**
644
666
  * Dependabot updates land on the repository's integration branch. Direct
645
667
  * repositories have no staging branch, so every update targets main. Cargo,
@@ -779,8 +801,8 @@ const DIRECT_DOC_REPLACEMENTS = {
779
801
  '7. Push to the fork and open a pull request targeting `main`.',
780
802
  ],
781
803
  [
782
- '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Draft pull request targeting `staging` | No runner-heavy validation; run local checks before requesting review |\n| Ready pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |\n| Draft ordinary pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |\n| Ready 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` | Full validation: CI, full tests, Security, and CodeQL, 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',
783
- '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Draft pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |\n| Ready pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Full validation: CI, full tests, Security, and CodeQL, 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',
804
+ '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Draft pull request targeting `staging` | No runner-heavy validation; run local checks before requesting review |\n| Ready pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |\n| Draft ordinary pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |\n| Ready 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` | Full validation: CI, full tests, Security, and CodeQL, 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 plus default-branch CodeQL scan; validation ran on the merged PR |\n',
805
+ '| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Draft pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |\n| Ready pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Full validation: CI, full tests, Security, and CodeQL, 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 plus default-branch CodeQL scan; validation ran on the merged PR |\n',
784
806
  ],
785
807
  [
786
808
  '| 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',
@@ -3,6 +3,7 @@
3
3
  import { readFileSync, readdirSync } from 'node:fs'
4
4
  import { join } from 'node:path'
5
5
  import { spawnSync } from 'node:child_process'
6
+ import { readConfig } from './config.mjs'
6
7
 
7
8
  /** @param {string} root @returns {{ errors: string[], warnings: string[], details: Record<string, unknown> }} */
8
9
  export function doctorGithub(root) {
@@ -306,22 +307,3 @@ function ghJson(args) {
306
307
  function commandExists(command) {
307
308
  return spawnSync(command, ['--version'], { stdio: 'ignore' }).status === 0
308
309
  }
309
-
310
- /** @param {string} root @returns {Record<string, string>} */
311
- function readConfig(root) {
312
- const file = join(root, '.github/code-foundry.yml')
313
- try {
314
- return Object.fromEntries(
315
- readFileSync(file, 'utf8')
316
- .split(/\r?\n/)
317
- .flatMap((line) => {
318
- const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*?)\s*$/)
319
- return match
320
- ? [[match[1], match[2].replace(/\s+#.*$/, '').replace(/^['"]|['"]$/g, '')]]
321
- : []
322
- })
323
- )
324
- } catch {
325
- return {}
326
- }
327
- }
@@ -0,0 +1,15 @@
1
+ // @ts-check
2
+
3
+ /** @type {Readonly<Record<string, string>>} */
4
+ const managers = Object.freeze({
5
+ 'bun.lock': 'bun',
6
+ 'bun.lockb': 'bun',
7
+ 'pnpm-lock.yaml': 'pnpm',
8
+ 'yarn.lock': 'yarn',
9
+ 'package-lock.json': 'npm',
10
+ })
11
+
12
+ /** @param {string | undefined} file @returns {string | undefined} */
13
+ export function packageManagerForLockfile(file) {
14
+ return file && Object.hasOwn(managers, file) ? managers[file] : undefined
15
+ }