feat: keep run artifacts under hidden .pygienium/ and out of git

All per-check artifacts, all-summary, and export move from pygienium/ to
.pygienium/; ensureRunStateIgnored appends .pygienium/ to the target
repo's .gitignore on first run (opt out with --no-gitignore), so a run
never stages its own output. Export now reads a single canonical root.
This commit is contained in:
2026-08-09 16:45:29 -04:00
parent 288506e84d
commit d0e8ad5571
17 changed files with 183 additions and 82 deletions

View File

@@ -13,7 +13,7 @@
* - "why" comments that explain intent, rationale, or gotchas → KEEP
* - code self-explanatory with no comment → no comment needed (don't add one)
*
* Artifacts (under `<cwd>/pygienium/checks/comments/`):
* Artifacts (under `<cwd>/.pygienium/checks/comments/`):
* - `findings.md` — per-file line refs for each smell
* - `changes.md` — summary of edits + human-review items
*
@@ -28,14 +28,14 @@ export const COMMENTS_PHASE_ID = "C1";
/**
* Directory where this check writes its `findings.md` and `changes.md`
* artifacts: `<cwd>/pygienium/checks/comments/`. Based on `scope.cwd` (the
* artifacts: `<cwd>/.pygienium/checks/comments/`. Based on `scope.cwd` (the
* project root, always a directory) so the path is valid whether the scan
* target is a single file or a directory. Matches the spec's
* `pygienium/checks/comments/findings.md` relative-path notation.
* `.pygienium/checks/comments/findings.md` relative-path notation.
*/
export function commentsArtifactDir(scope: CheckScope): string {
const base = scope.cwd.replace(/\/+$/, "");
return `${base}/pygienium/checks/comments`;
return `${base}/.pygienium/checks/comments`;
}
/** Absolute path to the findings artifact for this check. */
@@ -71,7 +71,7 @@ Short + high value is the goal. Evaluate every comment in the target:
/**
* Build the analysis sub-agent task. Instructs the agent to read candidate
* source files, identify comment smells per the rubric, and write per-file line
* references to `pygienium/comments/findings.md`.
* references to `.pygienium/comments/findings.md`.
*/
export function buildCommentsScanTask(_cwd: string, scope: CheckScope): string {
const outDir = commentsArtifactDir(scope);
@@ -119,7 +119,7 @@ Write the report under \`${outDir}\` (create directories as needed).
/**
* Build the fix sub-agent task from the scan findings. Instructs the agent to
* apply safe removals/tightenings, leave "why" comments, and write a summary
* of edits plus anything needing human review to `pygienium/comments/changes.md`.
* of edits plus anything needing human review to `.pygienium/comments/changes.md`.
*/
export function buildCommentsFixTask(
_cwd: string,

View File

@@ -28,11 +28,11 @@ import { scopeRulesMarkdown } from "./scope.js";
export const COMPLEXITY_PHASE_ID = "C4";
/**
* Artifact directory: `<cwd>/pygienium/checks/complexity/`.
* Artifact directory: `<cwd>/.pygienium/checks/complexity/`.
*/
export function complexityArtifactDir(scope: CheckScope): string {
const base = scope.cwd.replace(/\/+$/, "");
return `${base}/pygienium/checks/complexity`;
return `${base}/.pygienium/checks/complexity`;
}
/** Absolute path to findings artifact. */
@@ -84,13 +84,12 @@ count decision points (if/else if/for/while/case/&&/||/catch) per function.
* Build the analysis sub-agent task. Instructs the agent to:
* 1. Compute cyclomatic complexity per function
* 2. Identify structural complexity smells
* 3. Write findings to pygienium/checks/complexity/findings.md
* 3. Write findings to .pygienium/checks/complexity/findings.md
*/
export function buildComplexityScanTask(
_cwd: string,
scope: CheckScope,
): string {
const outDir = complexityArtifactDir(scope);
const findingsFile = findingsPath(scope);
return `# Task: excessive complexity scan
@@ -173,7 +172,7 @@ Always create findings.md so the run has an artifact.
* 1. Split 50+ complexity functions
* 2. Refactor or justify 3549 functions
* 3. Apply safe refactors for structural smells
* 4. Write changes summary to pygienium/checks/complexity/changes.md
* 4. Write changes summary to .pygienium/checks/complexity/changes.md
*/
export function buildComplexityFixTask(
_cwd: string,

View File

@@ -950,14 +950,14 @@ export async function applyDeadCodeFixes(
// Artifact paths
// ---------------------------------------------------------------------------
const CHECK_DIRNAME = "pygienium/checks/dead-code";
const CHECK_DIRNAME = ".pygienium/checks/dead-code";
/** `<target>/pygienium/checks/dead-code/findings.md` */
/** `<target>/.pygienium/checks/dead-code/findings.md` */
export function findingsPath(target: string): string {
return join(target, CHECK_DIRNAME, "findings.md");
}
/** `<target>/pygienium/checks/dead-code/changes.md` */
/** `<target>/.pygienium/checks/dead-code/changes.md` */
export function changesPath(target: string): string {
return join(target, CHECK_DIRNAME, "changes.md");
}

View File

@@ -11,7 +11,7 @@
*
* Lifecycle:
* gate (need source files) → recon (shared) → scan sub-agent writes
* `<cwd>/pygienium/checks/deep-modules/findings.md` → [with --fix] fix
* `<cwd>/.pygienium/checks/deep-modules/findings.md` → [with --fix] fix
* sub-agent writes `changes.md`, inlines safe pass-throughs, and lists
* risky consolidations (external importers / public API) for human review.
*
@@ -32,7 +32,7 @@ import { isScopeSource, scopeRulesMarkdown } from "./scope.js";
/** Output directory for this check's persistent reports. */
export function deepModulesOutputDir(cwd: string): string {
return join(cwd, "pygienium", "checks", "deep-modules");
return join(cwd, ".pygienium", "checks", "deep-modules");
}
/** `findings.md` path for this check. */

View File

@@ -30,7 +30,7 @@
*
* Lifecycle:
* gate (need source files) → recon (shared) → scan sub-agent writes
* `<cwd>/pygienium/checks/defensive-guards/findings.md` separating redundant
* `<cwd>/.pygienium/checks/defensive-guards/findings.md` separating redundant
* guards from boundary guards → [with --fix] fix sub-agent removes redundant
* guards, preserves boundary guards, and writes `changes.md` distinguishing
* removed vs kept-with-reason.
@@ -52,7 +52,7 @@ import { isScopeSource, scopeRulesMarkdown } from "./scope.js";
/** Output directory for this check's persistent reports. */
export function defensiveGuardsOutputDir(cwd: string): string {
return join(cwd, "pygienium", "checks", "defensive-guards");
return join(cwd, ".pygienium", "checks", "defensive-guards");
}
/** `findings.md` path for this check. */