code-foundry 1.9.1 → 1.9.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.
@@ -1,5 +1,7 @@
1
1
  # Contributing
2
2
 
3
+ <!-- code-foundry-managed: config-aware-policy -->
4
+
3
5
  This guide is the operating contract for humans and automation contributing to this repository.
4
6
 
5
7
  It applies to TypeScript, Rust, Python, and mixed-language projects using this template.
@@ -1,5 +1,7 @@
1
1
  # Security Policy
2
2
 
3
+ <!-- code-foundry-managed: config-aware-policy -->
4
+
3
5
  ## Supported Versions
4
6
 
5
7
  The latest commit on `staging` receives security patches. Patches are promoted to `main` through the next release cycle.
@@ -80,9 +80,8 @@ jobs:
80
80
  cat > "$BODY_FILE" <<EOF
81
81
  CI PR created automatically by this workflow.
82
82
 
83
- This PR is ready for review once required validation passes. If the
84
- configured automation token is rejected, it is intentionally opened
85
- as a draft for manual readiness.
83
+ This PR is intentionally opened as a draft. Mark it ready for review
84
+ when the proposed change is ready to start required validation.
86
85
 
87
86
  **CI Status:** Pending — this workflow triggered on push to $BRANCH.
88
87
  EOF
@@ -94,6 +93,7 @@ jobs:
94
93
  --field head="$BRANCH"
95
94
  --field title="$PR_TITLE"
96
95
  --field body="@$BODY_FILE"
96
+ --field draft=true
97
97
  )
98
98
 
99
99
  CREATED=false
@@ -102,9 +102,7 @@ jobs:
102
102
  fi
103
103
 
104
104
  if [ "$CREATED" != true ]; then
105
- DRAFT_ARGS=("${CREATE_ARGS[@]}" --field draft=true)
106
- if GH_TOKEN="$GITHUB_TOKEN" gh api "${DRAFT_ARGS[@]}" > /dev/null 2> "$ERROR_FILE"; then
107
- echo "::notice title=Manual PR readiness required::The configured automation token was absent or rejected; this PR was opened as a draft with the short-lived workflow token."
105
+ if GH_TOKEN="$GITHUB_TOKEN" gh api "${CREATE_ARGS[@]}" > /dev/null 2> "$ERROR_FILE"; then
108
106
  CREATED=true
109
107
  fi
110
108
  fi
@@ -113,3 +111,4 @@ jobs:
113
111
  echo "::error title=Draft PR creation failed::Both the configured automation token and the workflow token failed to create the pull request."
114
112
  exit 1
115
113
  fi
114
+ echo "::notice title=Manual PR readiness required::The automated pull request was opened as a draft. Mark it ready for review to start validation."
@@ -3,6 +3,12 @@ name: Code Foundry
3
3
  on:
4
4
  pull_request:
5
5
  branches: [main, staging]
6
+ types:
7
+ - opened
8
+ - synchronize
9
+ - reopened
10
+ - ready_for_review
11
+ - converted_to_draft
6
12
  workflow_dispatch:
7
13
 
8
14
  permissions:
@@ -14,7 +20,8 @@ jobs:
14
20
  if: >-
15
21
  vars.CI_BILLING_PAUSED != 'true' &&
16
22
  (github.event_name == 'workflow_dispatch' ||
17
- startsWith(github.event.pull_request.head.ref, 'release-please--branches--main'))
23
+ (github.event.pull_request.draft == false &&
24
+ startsWith(github.event.pull_request.head.ref, 'release-please--branches--main')))
18
25
  runs-on: ubuntu-slim
19
26
  outputs:
20
27
  enabled: ${{ steps.detect.outputs.enabled }}
@@ -249,9 +249,9 @@ jobs:
249
249
  # Creation uses authenticated REST (gh api POST) rather than
250
250
  # `gh pr create`, which issues a GraphQL mutation that
251
251
  # NiftyLeague's long-lived fine-grained token policy rejects. The
252
- # REST payload keeps the exact base/head/title/body fields, adds
253
- # draft=true only when no automation token is configured, and stays
254
- # fail-closed through the create-race fallback below.
252
+ # REST payload keeps the exact base/head/title/body fields, always
253
+ # opens the automated promotion as a draft, and stays fail-closed
254
+ # through the create-race fallback below.
255
255
  CREATE_ARGS=(
256
256
  "repos/${GITHUB_REPOSITORY}/pulls"
257
257
  --method POST
@@ -259,11 +259,9 @@ jobs:
259
259
  --field head="$PROMOTION_BRANCH"
260
260
  --field title="chore(main): promote staging to main ($DATE)"
261
261
  --field body=@"$BODY_FILE"
262
+ --field draft=true
262
263
  )
263
- if [ "$HAS_AUTOMATION_TOKEN" != true ]; then
264
- CREATE_ARGS+=(--field draft=true)
265
- echo "::notice title=Manual PR readiness required::Created draft promotion PR because no automation token is configured. Configure CODE_FOUNDRY_TOKEN, or mark this PR ready manually to trigger validation."
266
- fi
264
+ echo "::notice title=Manual PR readiness required::Created a draft promotion PR. Mark it ready for review to start validation."
267
265
 
268
266
  # Prefer the configured automation token for the write, but
269
267
  # NiftyLeague rejects long-lived fine-grained tokens with HTTP 403
@@ -123,6 +123,12 @@ jobs:
123
123
  }
124
124
  fs.appendFileSync(env.GITHUB_OUTPUT, "audit_matrix=" + JSON.stringify(entries) + "\n");
125
125
  '
126
+ - name: Dependency Review
127
+ if: ${{ github.event_name == 'pull_request' && steps.profile.outputs.dependency_review == 'true' }}
128
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5
129
+ with:
130
+ fail-on-severity: high
131
+ license-check: true
126
132
 
127
133
  # Audits run only for detected languages: the audit matrix is built from the
128
134
  # profile, so repositories never see skipped checks for ecosystems they do
@@ -370,16 +376,3 @@ jobs:
370
376
  - name: Audit Python dependencies
371
377
  if: matrix.entry.language == 'python'
372
378
  run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security audit python
373
-
374
- dependency-review:
375
- name: Dependency Review
376
- needs: profile
377
- if: ${{ vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request' && needs.profile.outputs.dependency_review == 'true' }}
378
- runs-on: ${{ inputs.runner }}
379
- timeout-minutes: 10
380
- steps:
381
- - name: Review
382
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5
383
- with:
384
- fail-on-severity: high
385
- license-check: true
@@ -0,0 +1,165 @@
1
+ name: Code Foundry Validation (CodeQL unavailable)
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ mode:
7
+ description: Validation tier (fast, audit, or release).
8
+ required: true
9
+ type: string
10
+ runtime-repository:
11
+ description: Repository containing the Code Foundry runtime.
12
+ required: false
13
+ type: string
14
+ default: 0xPlayerOne/code-foundry
15
+ runtime-ref:
16
+ description: Code Foundry runtime tag or ref.
17
+ required: false
18
+ type: string
19
+ default: v1.0.5
20
+ ci-runner:
21
+ description: Runner used by CI jobs.
22
+ required: false
23
+ type: string
24
+ default: ubuntu-latest
25
+ test-runner:
26
+ description: Runner used by non-unit test jobs.
27
+ required: false
28
+ type: string
29
+ default: ubuntu-latest
30
+ unit-runner:
31
+ description: Runner used by unit tests.
32
+ required: false
33
+ type: string
34
+ default: ubuntu-slim
35
+ performance-runner:
36
+ description: Runner used by deterministic performance regression checks.
37
+ required: false
38
+ type: string
39
+ default: ubuntu-latest
40
+ security-runner:
41
+ description: Runner used by Security jobs.
42
+ required: false
43
+ type: string
44
+ default: ubuntu-slim
45
+ codeql-runner:
46
+ description: Runner used by CodeQL jobs.
47
+ required: false
48
+ type: string
49
+ default: ubuntu-latest
50
+ rust-shards:
51
+ description: JSON array of Rust scope sharding values. Use ["all"] for single-pass behavior.
52
+ required: false
53
+ type: string
54
+ default: '["all"]'
55
+ rust-threads:
56
+ description: Threads used for Rust extraction and analysis. Values above 1 opt into local parallelism.
57
+ required: false
58
+ type: string
59
+ default: '1'
60
+ rust-max-parallel:
61
+ description: Maximum Rust shard jobs allowed to run concurrently.
62
+ required: false
63
+ type: number
64
+ default: 1
65
+ secrets:
66
+ TURBO_TOKEN:
67
+ required: false
68
+ NEXTAUTH_SECRET:
69
+ required: false
70
+
71
+ # The orchestrator keeps the union of permissions needed by the chain it calls
72
+ # (CodeQL uploads require security-events: write). Nested reusable workflows
73
+ # can only maintain or reduce permissions, never elevate them.
74
+ permissions:
75
+ actions: read
76
+ contents: read
77
+ packages: read
78
+ security-events: write
79
+
80
+ jobs:
81
+ ci:
82
+ name: CI
83
+ if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'fast' || inputs.mode == 'audit')
84
+ uses: ./.github/workflows/ci.yml
85
+ with:
86
+ runtime-repository: ${{ inputs.runtime-repository }}
87
+ runtime-ref: ${{ inputs.runtime-ref }}
88
+ runner: ${{ inputs.ci-runner }}
89
+ secrets:
90
+ TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
91
+ NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
92
+
93
+ test:
94
+ name: Test
95
+ if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'fast' || inputs.mode == 'audit')
96
+ uses: ./.github/workflows/test.yml
97
+ with:
98
+ runtime-repository: ${{ inputs.runtime-repository }}
99
+ runtime-ref: ${{ inputs.runtime-ref }}
100
+ runner: ${{ inputs.test-runner }}
101
+ unit-runner: ${{ inputs.unit-runner }}
102
+ performance-runner: ${{ inputs.performance-runner }}
103
+ unit-only: ${{ inputs.mode == 'fast' }}
104
+ secrets:
105
+ TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
106
+
107
+ security:
108
+ name: Security
109
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
110
+ uses: ./.github/workflows/security.yml
111
+ with:
112
+ runtime-repository: ${{ inputs.runtime-repository }}
113
+ runtime-ref: ${{ inputs.runtime-ref }}
114
+ runner: ${{ inputs.security-runner }}
115
+
116
+ # Aggregate check: "Validation / Gate" (caller job name + this job name).
117
+ # Always evaluates; only jobs required for the mode must have succeeded.
118
+ # The release tier runs no suite jobs: its policy (generated release diff
119
+ # validation) executes as a conditional step below, so no separate
120
+ # release-policy job renders skipped checks on ordinary pull requests.
121
+ gate:
122
+ name: Gate
123
+ needs: [ci, test, security]
124
+ if: vars.CI_BILLING_PAUSED != 'true' && always()
125
+ runs-on: ubuntu-slim
126
+ timeout-minutes: 10
127
+ env:
128
+ FOUNDRY_MODE: ${{ inputs.mode }}
129
+ FOUNDRY_CI: ${{ needs.ci.result }}
130
+ FOUNDRY_TEST: ${{ needs.test.result }}
131
+ FOUNDRY_SECURITY: ${{ needs.security.result }}
132
+ # This workflow is selected only for repositories whose canonical
133
+ # configuration explicitly disables unavailable CodeQL. Treat that
134
+ # policy decision as satisfied without registering a skipped PR check.
135
+ FOUNDRY_CODEQL: success
136
+ steps:
137
+ - name: Checkout runtime
138
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
139
+ with:
140
+ persist-credentials: false
141
+ repository: ${{ inputs.runtime-repository }}
142
+ ref: ${{ inputs.runtime-ref }}
143
+ path: .github/.code-foundry
144
+ sparse-checkout: |
145
+ src/lib
146
+ src/runtime.mjs
147
+ - name: Install runtime
148
+ run: mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
149
+ - name: Checkout consumer repository
150
+ if: ${{ inputs.mode == 'release' }}
151
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
152
+ with:
153
+ persist-credentials: false
154
+ fetch-depth: 0
155
+ filter: blob:none
156
+ - name: Validate generated release diff
157
+ if: ${{ inputs.mode == 'release' }}
158
+ env:
159
+ FOUNDRY_BASE_SHA: ${{ github.event.pull_request.base.sha }}
160
+ FOUNDRY_HEAD_REF: ${{ github.event.pull_request.head.ref }}
161
+ FOUNDRY_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
162
+ FOUNDRY_REPOSITORY: ${{ github.repository }}
163
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" validation release_diff
164
+ - name: Evaluate aggregate gate
165
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" validation gate
@@ -8,6 +8,7 @@ on:
8
8
  - synchronize
9
9
  - reopened
10
10
  - ready_for_review
11
+ - converted_to_draft
11
12
 
12
13
  # Default every caller job to no repository permissions. Individual jobs grant
13
14
  # only the scopes their own validation path consumes.
@@ -21,7 +22,10 @@ concurrency:
21
22
  jobs:
22
23
  mode:
23
24
  name: Mode
24
- if: vars.CI_BILLING_PAUSED != 'true'
25
+ # Draft updates still create a lightweight skipped workflow record so a
26
+ # converted-to-draft event can cancel in-flight validation, but no runner
27
+ # or reusable validation workflow starts until the PR is ready for review.
28
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event.pull_request.draft == false
25
29
  runs-on: ubuntu-slim
26
30
  timeout-minutes: 10
27
31
  permissions:
@@ -60,7 +64,7 @@ jobs:
60
64
  validation:
61
65
  name: Validation
62
66
  needs: mode
63
- if: vars.CI_BILLING_PAUSED != 'true'
67
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event.pull_request.draft == false
64
68
  # Reusable workflows can only maintain or reduce the caller job's scopes.
65
69
  # The audit tier needs security-events: write for CodeQL uploads.
66
70
  permissions:
package/AGENTS.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Agent Instructions
2
2
 
3
+ <!-- code-foundry-managed: config-aware-policy -->
4
+
3
5
  These instructions are the repository-level operating contract for coding agents, including Hermes, OpenCode, and other automation.
4
6
 
5
7
  They complement `CONTRIBUTING.md`. More specific instructions in nested `AGENTS.md` files and project documentation take precedence for their directory.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.9.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.2...v1.9.3) (2026-09-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **ci:** suppress unavailable and draft checks ([#507](https://github.com/0xPlayerOne/code-foundry/issues/507)) ([e0b313a](https://github.com/0xPlayerOne/code-foundry/commit/e0b313ad1e4601ccd14066fb97a4f547400a6eaa))
9
+
10
+ ## [1.9.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.1...v1.9.2) (2026-09-08)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **sync:** refresh config-aware policies ([#505](https://github.com/0xPlayerOne/code-foundry/issues/505)) ([466150d](https://github.com/0xPlayerOne/code-foundry/commit/466150dcf263187e9cb08be2a2c2fe7ff67ef060))
16
+
3
17
  ## [1.9.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.0...v1.9.1) (2026-09-08)
4
18
 
5
19
 
package/README.md CHANGED
@@ -74,8 +74,13 @@ The standard workflow triggers are:
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
 
77
- Jobs are language-aware and skip irrelevant setup while remaining visible as
78
- successful required checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
77
+ Automated feature/fix and staging-promotion pull requests open as drafts.
78
+ Pull-request validation waits until a PR is marked ready for review; later
79
+ commits retrigger it, and converting the PR back to draft cancels in-flight
80
+ validation. Scheduled and manually dispatched audits are unaffected.
81
+
82
+ Jobs are language-aware and skip irrelevant setup inside the applicable
83
+ aggregate checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
79
84
  test runner (repositories using another linter or formatter keep full control
80
85
  through their own `lint`/`format` scripts, which the runtime honors).
81
86
  Rust uses `rustfmt`, Clippy with warnings as errors, and native
@@ -85,7 +90,10 @@ tests. Solidity projects retain their native toolchain and test runner.
85
90
  CodeQL remains separate from CI and Security. With the default `codeql: auto`
86
91
  and `dependency_review: auto` policies, public repositories use the free GitHub
87
92
  security checks while private repositories skip them unless explicitly opted
88
- in and supported by GitHub Advanced Security. JavaScript, Python, and Rust
93
+ in and supported by GitHub Advanced Security. Set an unavailable private-repo
94
+ capability to `false` during sync to omit its CodeQL job from pull requests;
95
+ Dependency Review runs as a conditional Security step and does not register a
96
+ separate skipped check. JavaScript, Python, and Rust
89
97
  audits remain available without Advanced Security. Code Foundry does not enable
90
98
  GitHub Code Quality or other paid GitHub features.
91
99
 
package/docs/WORKFLOWS.md CHANGED
@@ -12,6 +12,11 @@ pull_request:
12
12
  # direct topology: branches: [main]
13
13
  ```
14
14
 
15
+ The generated caller suppresses runner and reusable-workflow jobs while the
16
+ pull request is a draft. It listens for `ready_for_review` to start validation,
17
+ for later `synchronize` events to rerun it, and for `converted_to_draft` to
18
+ cancel in-flight validation through the caller's concurrency group.
19
+
15
20
  The separate `validation-audit.yml` caller is pinned to the configured released
16
21
  runtime and handles scheduled and manual audits:
17
22
 
@@ -29,8 +34,9 @@ results satisfiable for the release commit). In the
29
34
  `direct` topology (the default) every pull request targets `main` and runs the
30
35
  full audit tier, because there is no integration branch for a fast pass.
31
36
  Scheduled and manual runs select the audit tier in both topologies. Draft PR
32
- automation separately listens to supported topic-branch pushes, promotion
33
- automation listens to `staging` pushes (staging-release only), and release
37
+ automation separately listens to supported topic-branch pushes and always
38
+ opens those PRs as drafts. Promotion automation listens to `staging` pushes
39
+ (staging-release only) and also always opens its PR as a draft. Release
34
40
  automation listens to `main` pushes.
35
41
  Custom deployment, indexing, search, Slither, or other workflows are
36
42
  repository-owned extensions and should keep their own triggers and permissions.
@@ -204,8 +210,7 @@ validation gate. Land changes through the standard `direct` or
204
210
  test/security workflows.
205
211
 
206
212
  Jobs detect applicability before installing tools. Per-language CodeQL and
207
- security-audit jobs are generated from detection, so empty language surfaces
208
- produce no checks at all instead of skipped rows; the aggregate
213
+ security-audit jobs are generated from detection; the aggregate
209
214
  `Validation / Gate` keeps branch protection unambiguous for mixed-language
210
215
  repositories by failing closed unless every generated check succeeds. An
211
216
  empty analysis matrix while analysis is enabled fails the build instead of
@@ -214,12 +219,16 @@ silently skipping every analyzer.
214
219
  ## Security behavior
215
220
 
216
221
  CodeQL is a separate workflow using GitHub's official actions. The default
217
- `codeql: auto` policy enables it for public repositories and skips it for
218
- private repositories unless explicitly enabled and Advanced Security is
219
- available. Dependency Review follows the same policy through
220
- `dependency_review: auto`; JavaScript, Python, and Rust audits remain
221
- available without Advanced Security. If GitHub default setup is enabled,
222
- disable its generated CodeQL workflow to avoid duplicate analysis.
222
+ `codeql: auto` policy enables it for public repositories and detects Advanced
223
+ Security availability for private repositories. When CodeQL is unavailable,
224
+ set `codeql: false` and sync: the generated caller selects an orchestrator that
225
+ omits CodeQL entirely, so pull requests do not show a skipped analyzer.
226
+ Dependency Review follows the same capability policy through
227
+ `dependency_review: auto`, but executes as a conditional step inside the
228
+ Security profile job and never registers a separate skipped pull-request
229
+ check. JavaScript, Python, and Rust audits remain available without Advanced
230
+ Security. If GitHub default setup is enabled, disable its generated CodeQL
231
+ workflow to avoid duplicate analysis.
223
232
 
224
233
  Code Foundry does not enable GitHub Code Quality or any paid GitHub feature.
225
234
  The repository's format and lint jobs are ordinary CI checks. Set `codeql:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.9.1",
3
+ "version": "1.9.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": {
@@ -65,6 +65,12 @@ const protectedFiles = new Set([
65
65
  'NOTICE',
66
66
  ])
67
67
 
68
+ const configAwarePolicyFiles = new Set([
69
+ 'AGENTS.md',
70
+ '.github/CONTRIBUTING.md',
71
+ '.github/SECURITY.md',
72
+ ])
73
+
68
74
  /** @type {Record<string, string>} */
69
75
  const licenseFiles = {
70
76
  'gpl-3.0-or-later': 'GPL-3.0-or-later.txt',
@@ -206,7 +212,7 @@ export function syncRepository(options) {
206
212
  const destination = join(target, file)
207
213
  if (!force && protectedFiles.has(file) && existsSync(destination)) {
208
214
  const existing = readFileSync(destination, 'utf8')
209
- if (!isLegacyManagedDoc(file, existing)) continue
215
+ if (!isLegacyManagedDoc(file, existing) && !isManagedConfigPolicy(file, existing)) continue
210
216
  }
211
217
  if (
212
218
  (file === 'LICENSE' || file === 'NOTICE') &&
@@ -458,7 +464,7 @@ function shouldInclude(file, languages, features, config) {
458
464
  if (workflow === 'release-pr' && !isStagingRelease(config.git_workflow)) return false
459
465
  // The tiered validation caller supersedes the legacy ci/test/security/codeql
460
466
  // event callers, so legacy feature names keep selecting it.
461
- if (workflow === 'validation') {
467
+ if (workflow === 'validation' || workflow === 'validation-audit') {
462
468
  return (
463
469
  includesValue(features, 'validation') ||
464
470
  LEGACY_GENERATED_CALLERS.some((legacy) => includesValue(features, legacy))
@@ -494,6 +500,15 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
494
500
  const localPrefix = 'uses: ./.github/workflows/'
495
501
  const remotePrefix = `uses: ${repository}/.github/workflows/`
496
502
  let rendered = content.replaceAll(localPrefix, remotePrefix)
503
+ // An explicitly unavailable CodeQL capability selects an orchestrator that
504
+ // omits the job entirely, so GitHub does not register a misleading skipped
505
+ // check on every pull request. `auto` retains runtime capability detection.
506
+ if (configured(config.codeql, 'auto') === 'false') {
507
+ rendered = rendered.replaceAll(
508
+ `${remotePrefix}validation.yml`,
509
+ `${remotePrefix}validation-no-codeql.yml`
510
+ )
511
+ }
497
512
  rendered = rendered.replace(
498
513
  new RegExp(`${escapeRegExp(remotePrefix)}([^\\s@]+)`, 'g'),
499
514
  `$&@${ref}`
@@ -786,7 +801,10 @@ export function isGeneratedEventCaller(content, stem, runtimeRepository) {
786
801
  const text = Buffer.isBuffer(content) ? content.toString('utf8') : String(content)
787
802
  if (!/^name:\s*Code Foundry\s*$/m.test(text)) return false
788
803
  if (/^\s*(runs-on|steps):/m.test(text)) return false
789
- if (!text.includes('runtime-repository:')) return false
804
+ // Older generated staging-promotion callers predate the explicit runtime
805
+ // repository input. They are still safe to identify structurally by their
806
+ // single reusable-workflow job so direct-topology syncs can remove them.
807
+ if (stem !== 'release-pr' && !text.includes('runtime-repository:')) return false
790
808
  if (!new RegExp(`^ ${stem}:`, 'm').test(text)) return false
791
809
  return new RegExp(
792
810
  `uses:\\s*${escapeRegExp(runtimeRepository)}/\\.github/workflows/${stem}\\.yml@`
@@ -1052,6 +1070,44 @@ function isLegacyManagedDoc(file, content) {
1052
1070
  return false
1053
1071
  }
1054
1072
 
1073
+ /**
1074
+ * Config-aware policy documents are generated contracts: a normal sync must
1075
+ * refresh them after branch-topology or validation-policy edits. The marker
1076
+ * owns future copies. Exact scaffold signatures migrate older generated
1077
+ * copies without treating arbitrary repository documentation as managed.
1078
+ * @param {string} file
1079
+ * @param {string} content
1080
+ */
1081
+ function isManagedConfigPolicy(file, content) {
1082
+ if (!configAwarePolicyFiles.has(file)) return false
1083
+ if (content.includes('<!-- code-foundry-managed: config-aware-policy -->')) return true
1084
+ if (file === 'AGENTS.md') {
1085
+ return (
1086
+ content.startsWith('# Agent Instructions\n') &&
1087
+ content.includes(
1088
+ 'These instructions are the repository-level operating contract for coding agents'
1089
+ ) &&
1090
+ content.includes('They complement `CONTRIBUTING.md`.')
1091
+ )
1092
+ }
1093
+ if (file === '.github/CONTRIBUTING.md') {
1094
+ return (
1095
+ content.startsWith('# Contributing\n') &&
1096
+ content.includes(
1097
+ 'This guide is the operating contract for humans and automation contributing to this repository.'
1098
+ ) &&
1099
+ content.includes('[Agent contract](#agent-operating-contract)')
1100
+ )
1101
+ }
1102
+ return (
1103
+ content.startsWith('# Security Policy\n') &&
1104
+ content.includes('## Reporting a Vulnerability') &&
1105
+ content.includes(
1106
+ 'This policy covers the code, configuration, dependencies, workflows, and generated artifacts maintained in this repository.'
1107
+ )
1108
+ )
1109
+ }
1110
+
1055
1111
  /** @param {string} target @param {string[]} args */
1056
1112
  function git(target, args) {
1057
1113
  spawnSync('git', args, { cwd: target, stdio: 'ignore' })