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:
@@ -60,12 +60,24 @@ function resolveCwd(args: string, ctxCwd: string): string {
|
||||
return resolve(ctxCwd, tok);
|
||||
}
|
||||
|
||||
/** Strip a leading flag token (`--fix`) from args, returning the remainder. */
|
||||
function splitFlags(args: string): { fix: boolean; rest: string } {
|
||||
/**
|
||||
* Strip leading flag tokens (`--fix`, `--fresh`, `--no-gitignore`) from args,
|
||||
* returning the remainder (the positional `[path]`).
|
||||
*/
|
||||
function splitFlags(args: string): {
|
||||
fix: boolean;
|
||||
fresh: boolean;
|
||||
rest: string;
|
||||
noGitignore: boolean;
|
||||
} {
|
||||
const tokens = args.trim().length > 0 ? args.trim().split(/\s+/) : [];
|
||||
const fix = tokens.includes("--fix");
|
||||
const rest = tokens.filter((t) => t !== "--fix").join(" ");
|
||||
return { fix, rest };
|
||||
const fresh = tokens.includes("--fresh");
|
||||
const noGitignore = tokens.includes("--no-gitignore");
|
||||
const rest = tokens
|
||||
.filter((t) => t !== "--fix" && t !== "--fresh" && t !== "--no-gitignore")
|
||||
.join(" ");
|
||||
return { fix, fresh, rest, noGitignore };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,12 +88,13 @@ function splitFlags(args: string): { fix: boolean; rest: string } {
|
||||
function parseResumeArgs(
|
||||
args: string,
|
||||
ctxCwd: string,
|
||||
): { cwd: string; fresh: boolean } {
|
||||
): { cwd: string; fresh: boolean; gitignore: boolean } {
|
||||
const tokens = args.trim().length > 0 ? args.trim().split(/\s+/) : [];
|
||||
const fresh = tokens.includes("--fresh");
|
||||
const gitignore = !tokens.includes("--no-gitignore");
|
||||
const positional = tokens.find((t) => !t.startsWith("--"));
|
||||
const cwd = positional ? resolve(ctxCwd, positional) : ctxCwd;
|
||||
return { cwd, fresh };
|
||||
return { cwd, fresh, gitignore };
|
||||
}
|
||||
|
||||
/** `/pygienium-help` */
|
||||
@@ -116,9 +129,12 @@ export async function handleCheckCommand(
|
||||
hasUI: ctx.hasUI,
|
||||
});
|
||||
|
||||
const giNote = outcome.gitignoreAppended
|
||||
? " · .pygienium/ added to .gitignore"
|
||||
: "";
|
||||
print(
|
||||
ctx,
|
||||
`pygienium ${check.label}: ${outcome.status}${outcome.error ? ` — ${outcome.error}` : ""}`,
|
||||
`pygienium ${check.label}: ${outcome.status}${outcome.error ? ` — ${outcome.error}` : ""}${giNote}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -142,13 +158,17 @@ export async function handleAllCommand(
|
||||
target: parsed.target,
|
||||
fix: parsed.fix,
|
||||
fresh: parsed.fresh,
|
||||
gitignore: parsed.gitignore,
|
||||
only: parsed.only,
|
||||
ui: ctx.ui,
|
||||
hasUI: ctx.hasUI,
|
||||
});
|
||||
const giNote = outcome.gitignoreAppended
|
||||
? " · .pygienium/ added to .gitignore"
|
||||
: "";
|
||||
print(
|
||||
ctx,
|
||||
`pygienium: all-run ${outcome.status} — ${outcome.ran.length} ran, ${outcome.skipped.length} skipped; summary → ${allSummaryPath(ctx.cwd)} (${runStatePath(ctx.cwd)})`,
|
||||
`pygienium: all-run ${outcome.status} — ${outcome.ran.length} ran, ${outcome.skipped.length} skipped; summary → ${allSummaryPath(ctx.cwd)} (${runStatePath(ctx.cwd)})${giNote}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -178,7 +198,7 @@ export async function handleResumeCommand(
|
||||
args: string,
|
||||
ctx: PygieniumCtx,
|
||||
): Promise<void> {
|
||||
const { cwd, fresh } = parseResumeArgs(args, ctx.cwd);
|
||||
const { cwd, fresh, gitignore } = parseResumeArgs(args, ctx.cwd);
|
||||
let state = await loadRunState(cwd);
|
||||
if (!state) {
|
||||
print(ctx, "pygienium: no run state to resume.");
|
||||
@@ -202,6 +222,7 @@ export async function handleResumeCommand(
|
||||
// unless --fresh.
|
||||
let ran = 0;
|
||||
let skipped = 0;
|
||||
let giAppended = false;
|
||||
for (const entry of Object.values(state.checks)) {
|
||||
const def = getCheck(entry.name);
|
||||
if (!def) {
|
||||
@@ -258,7 +279,7 @@ export async function handleExportCommand(
|
||||
if (result.entries.length === 0) {
|
||||
print(
|
||||
ctx,
|
||||
`pygienium: nothing to export (no findings.md/changes.md under ${cwd}/pygienium/checks/).`,
|
||||
`pygienium: nothing to export (no findings.md/changes.md under ${cwd}/.pygienium/checks/).`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user