better recon info in certain (nested) situations
All checks were successful
port-to-omp / port (push) Successful in 6s

This commit is contained in:
2026-08-12 21:59:49 -04:00
parent 3fd386a637
commit 63c2f73a5e
7 changed files with 84 additions and 41 deletions

View File

@@ -21,14 +21,13 @@
* @module pygienium/checks/deep-modules
*/
import { readdirSync } from "node:fs";
import { join } from "node:path";
import {
registerCheck,
type CheckDefinition,
type CheckScope,
} from "./registry.js";
import { isScopeSource, scopeRulesMarkdown } from "./scope.js";
import { hasScopeSources, scopeRulesMarkdown } from "./scope.js";
/** Output directory for this check's persistent reports. */
export function deepModulesOutputDir(cwd: string): string {
@@ -50,23 +49,13 @@ export function changesPath(cwd: string): string {
* with zero source files gives the scanner nothing to classify.
*/
function deepModulesGate(cwd: string): string | undefined {
let found = false;
try {
const entries = readdirSync(cwd);
for (const entry of entries) {
if (isScopeSource(entry)) {
found = true;
break;
}
}
if (hasScopeSources(cwd)) return undefined;
} catch {
// unreadable cwd → let the agent decide; don't block.
return undefined;
}
if (!found) {
return "no source files found to inspect";
}
return undefined;
return "no source files found to inspect";
}
/**

View File

@@ -41,14 +41,13 @@
* @module pygienium/checks/defensive-guards
*/
import { readdirSync } from "node:fs";
import { join } from "node:path";
import {
registerCheck,
type CheckDefinition,
type CheckScope,
} from "./registry.js";
import { isScopeSource, scopeRulesMarkdown } from "./scope.js";
import { hasScopeSources, scopeRulesMarkdown } from "./scope.js";
/** Output directory for this check's persistent reports. */
export function defensiveGuardsOutputDir(cwd: string): string {
@@ -70,23 +69,13 @@ export function changesPath(cwd: string): string {
* with zero source files gives the scanner nothing to analyse.
*/
function defensiveGuardsGate(cwd: string): string | undefined {
let found = false;
try {
const entries = readdirSync(cwd);
for (const entry of entries) {
if (isScopeSource(entry)) {
found = true;
break;
}
}
if (hasScopeSources(cwd)) return undefined;
} catch {
// unreadable cwd → let the agent decide; don't block.
return undefined;
}
if (!found) {
return "no source files found to inspect";
}
return undefined;
return "no source files found to inspect";
}
/**

View File

@@ -9,6 +9,10 @@
* @module pygienium/checks/scope
*/
import { readdirSync, statSync } from "node:fs";
import type { Dirent } from "node:fs";
import { join } from "node:path";
/**
* Implementation-code file extensions pygienium inspects.
*
@@ -106,6 +110,38 @@ export function isScopeSource(path: string): boolean {
return SCOPE_EXTENSIONS.has(lower.slice(dot));
}
/**
* True when the tree rooted at `root` contains at least one in-scope source
* file. Walks recursively (honoring {@link SCOPE_EXCLUDE_DIRS}) — a top-level
* entry scan alone would skip any repo whose source lives in subdirectories,
* e.g. `game/` or `src/`, even though recon's git inventory finds hundreds of
* files. A file root is judged by {@link isScopeSource} directly.
*/
export function hasScopeSources(root: string): boolean {
const st = statSync(root, { throwIfNoEntry: false });
if (!st) return false;
if (st.isFile()) return isScopeSource(root);
const stack = [root];
while (stack.length > 0) {
const dir = stack.pop() as string;
let entries: Dirent[];
try {
entries = readdirSync(dir, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
if (entry.isDirectory()) {
if (SCOPE_EXCLUDE_DIRS.has(entry.name)) continue;
stack.push(join(dir, entry.name));
} else if (entry.isFile() && isScopeSource(entry.name)) {
return true;
}
}
}
return false;
}
/**
* Markdown section injected into every scan task string so the sub-agent knows
* exactly what to inspect and what to skip — stated once here, not copy-pasted

View File

@@ -36,7 +36,6 @@
* @module pygienium/checks/todos
*/
import { readdirSync } from "node:fs";
import { readFile, readdir, stat } from "node:fs/promises";
import { join, relative } from "node:path";
import { loadRunState } from "../run-state.js";
@@ -46,6 +45,7 @@ import {
type CheckScope,
} from "./registry.js";
import {
hasScopeSources,
isScopeSource,
SCOPE_EXCLUDE_DIRS,
scopeRulesMarkdown,
@@ -405,23 +405,13 @@ function renderFindings(
* with zero source files gives the scanner nothing to analyse.
*/
function todosGate(cwd: string): string | undefined {
let found = false;
try {
const entries = readdirSync(cwd);
for (const entry of entries) {
if (isScopeSource(entry)) {
found = true;
break;
}
}
if (hasScopeSources(cwd)) return undefined;
} catch {
// unreadable cwd → let the agent decide; don't block.
return undefined;
}
if (!found) {
return "no source files found to inspect";
}
return undefined;
return "no source files found to inspect";
}
/**