port: sync from Mike/pygienium@63c2f73a
This commit is contained in:
@@ -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";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user