code-foundry 1.9.10 → 1.9.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.9.11](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.10...v1.9.11) (2026-09-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **doctor:** support nested Rust crates ([#525](https://github.com/0xPlayerOne/code-foundry/issues/525)) ([0ffc87d](https://github.com/0xPlayerOne/code-foundry/commit/0ffc87d71c5e8069a26814dea2250e93a3e87416))
9
+
3
10
  ## [1.9.10](https://github.com/0xPlayerOne/code-foundry/compare/v1.9.9...v1.9.10) (2026-09-08)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.9.10",
3
+ "version": "1.9.11",
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": {
@@ -1,6 +1,6 @@
1
1
  // @ts-check
2
2
 
3
- import { existsSync, readFileSync } from 'node:fs'
3
+ import { existsSync, readFileSync, readdirSync } from 'node:fs'
4
4
  import { join, resolve } from 'node:path'
5
5
  import { spawnSync } from 'node:child_process'
6
6
  import { includesValue, readConfig } from '../lib/config.mjs'
@@ -80,11 +80,16 @@ export function doctor(root, options = {}) {
80
80
  if (profile.languages.split(',').includes('rust') && !commandExists('cargo'))
81
81
  error('Cargo is required for this repository')
82
82
  if (profile.languages.split(',').includes('rust')) {
83
- const metadata = spawnSync('cargo', ['metadata', '--no-deps', '--format-version', '1'], {
84
- cwd: target,
85
- stdio: 'ignore',
86
- })
87
- if (metadata.status !== 0) error('cargo metadata failed')
83
+ const manifests = rustManifestPaths(target)
84
+ if (!manifests.length) error('no Cargo.toml was found for the configured Rust language')
85
+ for (const manifest of manifests) {
86
+ const metadata = spawnSync(
87
+ 'cargo',
88
+ ['metadata', '--manifest-path', manifest, '--no-deps', '--format-version', '1'],
89
+ { cwd: target, stdio: 'ignore' }
90
+ )
91
+ if (metadata.status !== 0) error(`cargo metadata failed for ${manifest}`)
92
+ }
88
93
  }
89
94
  if (
90
95
  profile.languages.split(',').includes('python') &&
@@ -229,6 +234,45 @@ export function doctor(root, options = {}) {
229
234
  console.log('Repository doctor passed.')
230
235
  }
231
236
 
237
+ const ignoredRustDirectories = new Set([
238
+ '.git',
239
+ '.code-foundry',
240
+ '.mise',
241
+ '.next',
242
+ '.nuxt',
243
+ '.venv',
244
+ 'node_modules',
245
+ 'target',
246
+ 'vendor',
247
+ ])
248
+
249
+ /**
250
+ * Return repository-relative Cargo manifests that represent owned Rust code.
251
+ * A root workspace is authoritative; otherwise validate each nested crate while
252
+ * excluding dependency/build trees that CodeQL shards should not treat as owned.
253
+ * @param {string} root
254
+ * @returns {string[]}
255
+ */
256
+ export function rustManifestPaths(root) {
257
+ if (existsSync(join(root, 'Cargo.toml'))) return ['Cargo.toml']
258
+ /** @type {string[]} */
259
+ const manifests = []
260
+ /** @param {string} directory @param {string} relative */
261
+ function visit(directory, relative) {
262
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
263
+ if (entry.isDirectory() && ignoredRustDirectories.has(entry.name)) continue
264
+ const childRelative = relative ? join(relative, entry.name) : entry.name
265
+ const child = join(directory, entry.name)
266
+ if (entry.isDirectory()) visit(child, childRelative)
267
+ else if (entry.name === 'Cargo.toml') manifests.push(childRelative)
268
+ }
269
+ }
270
+ visit(root, '')
271
+ // Sorting a fresh local collection is deterministic and cannot mutate caller-owned state.
272
+ // oxlint-disable-next-line unicorn/no-array-sort
273
+ return manifests.sort()
274
+ }
275
+
232
276
  /** @param {string} root @param {string[]} args */
233
277
  function git(root, args) {
234
278
  return spawnSync('git', args, { cwd: root, encoding: 'utf8' }).stdout?.trim() ?? ''