Initial commit: pygenium as git submodule
This commit is contained in:
50
tasks/01-scaffolding.md
Normal file
50
tasks/01-scaffolding.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 01. Extension scaffolding and project structure
|
||||
|
||||
meta:
|
||||
id: pygienium-01
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: []
|
||||
tags: [infrastructure, setup]
|
||||
|
||||
objective:
|
||||
|
||||
- Establish the pygienium extension directory, package.json, tsconfig, and a minimal index.ts that loads without error and surfaces a startup notification.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `pygienium/package.json` with pi package manifest (`pi.extensions`, keywords, peer deps echoing piolium)
|
||||
- `pygienium/tsconfig.json` (extends the repo tsconfig)
|
||||
- `pygienium/src/index.ts` default-export factory registering a `session_start` notify + a stub `/pygienium-help`
|
||||
- `pygienium/` subdirectories: `src/`, `src/modes/`, `src/checks/`, `agents/`, `skills/` (empty, with `.gitkeep`)
|
||||
- Verified load: `pi -e ./pygienium/src/index.ts -p "/pygienium-help"` runs without throwing
|
||||
|
||||
steps:
|
||||
|
||||
- Create the `pygienium/` tree and empty subdirectories
|
||||
- Author `package.json`: name `pygienium`, type module, `pi.extensions: ["./src/index.ts"]`, peerDeps mirroring piolium (`@earendil-works/pi-coding-agent`, `typebox`, etc.), engines bun >=1.1.0
|
||||
- Author `tsconfig.json` referencing the parent `tsconfig.json`
|
||||
- Author `src/index.ts`: import `ExtensionAPI`, default-export factory that registers a `session_start` notify ("Pygienium loaded. Run /pygienium-help.") and a `/pygienium-help` command printing a placeholder line
|
||||
- Confirm the extension auto-discovers from `~/.pi/agent/extensions/pygienium/src/index.ts` (per docs, subdir `index.ts`); if discovery prefers `pygienium/index.ts`, adjust entry path in package.json
|
||||
|
||||
tests:
|
||||
|
||||
- Manual: run `pi -e ./pygienium/src/index.ts -p "/pygienium-help"`; confirm the placeholder help renders
|
||||
- Manual: start pi in `~/.pi/agent/extensions` and confirm the startup notify appears without `session_start` errors
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- The directory tree and package.json exist with valid JSON
|
||||
- `pi` loads the extension via auto-discovery with no load errors
|
||||
- `/pygienium-help` responds with a non-empty line
|
||||
|
||||
validation:
|
||||
|
||||
- `node -e "JSON.parse(require('fs').readFileSync('pygienium/package.json','utf8'))"` exits 0
|
||||
- `pi -e ./pygienium/src/index.ts -p "/pygienium-help"` prints the placeholder
|
||||
|
||||
notes:
|
||||
|
||||
- Place the extension in `~/.pi/agent/extensions/pygienium/` so it auto-discovers and hot-reloads with `/reload`
|
||||
- Do NOT add backward-compat shims or migration paths (engineering rule)
|
||||
- Keep index.ts minimal here; full command wiring lands in task 06
|
||||
46
tasks/02-recon.md
Normal file
46
tasks/02-recon.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 02. Deterministic code reconnaissance module
|
||||
|
||||
meta:
|
||||
id: pygienium-02
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-01]
|
||||
tags: [infrastructure, no-model]
|
||||
|
||||
objective:
|
||||
|
||||
- Build `src/recon.ts`: a deterministic, no-model pass that walks the target repo and writes a compact markdown report (languages, manifests, file counts, dead-file candidates) so every check has stable ground truth.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/recon.ts` exporting `runRecon(cwd)`, `runReconAsync(cwd, opts)`, `reconReportPath(cwd)`, `ReconResult`
|
||||
- Writes `pygienium/recon/report.md` under cwd
|
||||
- Detects: languages by extension, build manifests, total files/bytes, git head/branch, and a "candidate files" list (source files not under skip dirs) written to `pygienium/recon/candidates.jsonl` + summary
|
||||
- Soft caps (MAX_FILES, MAX_BYTES) and SIGINT-safe async walk mirroring piolium's recon
|
||||
|
||||
steps:
|
||||
|
||||
- Port piolium's `recon.ts` structure: MANIFEST_FILES, LANGUAGE_BY_EXT, SKIP_DIRS, safe git exec, walkAndTally + async variant with yieldToEventLoop
|
||||
- Adapt skip dirs to include `pygienium` (own output dir)
|
||||
- Add a `candidates.jsonl` emitter listing source files (by language) for the check runners to consume; cap entries to keep it bounded
|
||||
- Export `buildReconReport` for unit testing
|
||||
|
||||
tests:
|
||||
|
||||
- Unit: `buildReconReport` on a fake ReconResult produces expected markdown sections (Arrange a result, Act build, Assert headers present)
|
||||
- Integration: run recon against this repo; assert report.md + candidates.jsonl exist and counts > 0
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `runRecon(cwd)` returns a ReconResult and writes report.md + candidates.jsonl
|
||||
- A repo without `.git` does not throw (graceful degradation)
|
||||
- Very large trees are capped without wedging
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/recon/report.md` and `pygienium/recon/candidates.jsonl` after a run
|
||||
|
||||
notes:
|
||||
|
||||
- Recon is Q0-equivalent: deterministic, runs in-process, no model calls
|
||||
- This is the foundation every check consumes for targeting
|
||||
47
tasks/03-agent-runner.md
Normal file
47
tasks/03-agent-runner.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 03. Sub-agent runner with createAgentSession
|
||||
|
||||
meta:
|
||||
id: pygienium-03
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-01]
|
||||
tags: [infrastructure, core]
|
||||
|
||||
objective:
|
||||
|
||||
- Build `src/agent-runner.ts`: spawn isolated child pi sessions via `createAgentSession`, capture transcripts/results, and return a typed result — the engine that powers every check's sub-agent phases.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/agent-runner.ts` exporting `runAgent(options)`, `AgentRuntimeModel`, `RunAgentResult`, `AgentRunError`, `buildRuntimeHeader`, `RuntimeContext`
|
||||
- Each run writes `pygienium/runs/<runId>/{prompt.md, transcript.jsonl, result.md, error.txt}`
|
||||
- Inherits parent model + modelRegistry + thinkingLevel (so child phases reason at the same depth)
|
||||
- AbortSignal support; `onEvent` forwarding hook for UI streaming
|
||||
- Child tools: the built-in edit/write/read/bash surface; noExtensions: true (avoid recursion)
|
||||
|
||||
steps:
|
||||
|
||||
- Port piolium's `agent-runner.ts` shape: composed system prompt = runtime header + agent systemPrompt; `DefaultResourceLoader` with noExtensions/noThemes/noContextFiles; in-memory SessionManager
|
||||
- Define `AgentDefinition` interface (name, description, systemPrompt, allowedTools, sourcePath) consumed here
|
||||
- Wire `session.subscribe` to capture final assistant text + stopReason + errorMessage
|
||||
- Handle abort: add/remove abort listener, call `session.agent.abort()`
|
||||
|
||||
tests:
|
||||
|
||||
- Unit: `buildRuntimeHeader` includes cwd, mode, phase, assigned output paths
|
||||
- Integration: run a smoke agent (no-tools, replies with a fixed string) via `runAgent`; assert result.text non-empty and transcript.jsonl exists
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `runAgent` returns RunAgentResult with text + transcriptPath + durationMs
|
||||
- Aborting the signal cancels the child session without leaving it running
|
||||
- A child that errors throws `AgentRunError` carrying the result
|
||||
|
||||
validation:
|
||||
|
||||
- Invoke a smoke run from a temporary command and inspect the runs dir
|
||||
|
||||
notes:
|
||||
|
||||
- This is the most direct piolium port; keep it faithful to reduce risk
|
||||
- Do NOT load extensions in the child (footgun) — `noExtensions: true`
|
||||
45
tasks/04-hygiene-state.md
Normal file
45
tasks/04-hygiene-state.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# 04. Resumable run-state persistence
|
||||
|
||||
meta:
|
||||
id: pygienium-04
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-01]
|
||||
tags: [infrastructure, state]
|
||||
|
||||
objective:
|
||||
|
||||
- Build `src/hygiene-state.ts`: a resumable state file (`pygienium/run-state.json`) tracking one run per invocation with per-check phase status, so interrupted runs can resume and `/pygienium-status` can report progress.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/hygiene-state.ts` exporting `initRun`, `latestRun`, `latestResumableRun`, `readRunState`, `applyPhaseStatus`, `markRunStatus`, `tallyPhases`
|
||||
- State schema: `{ runs: [{ run_id, mode, status, checks: { <check>: { status, attempt, last_error, artifacts, ... } } }] }`
|
||||
- Idempotent writes (read-modify-write with safe merge); file absent / unparseable handled gracefully
|
||||
|
||||
steps:
|
||||
|
||||
- Port piolium's `audit-state.ts` read/write helpers, renaming audit→run, phase→check
|
||||
- Implement `initRun(cwd, { mode })` returning a fresh run state record
|
||||
- `applyPhaseStatus(cwd, run, checkName, patch)` merges per-check status
|
||||
- `latestResumableRun` returns a run whose status is in_progress or failed (not complete)
|
||||
|
||||
tests:
|
||||
|
||||
- Unit: init -> apply phase complete -> markRunStatus complete reads back correctly
|
||||
- Unit: unparseable file returns `parseError` without throwing
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `readRunState(cwd)` returns `{ exists, parseError?, state? }`
|
||||
- applyPhaseStatus persists and is readable by a subsequent read
|
||||
- Resumable selection picks in_progress > failed, ignores complete
|
||||
|
||||
validation:
|
||||
|
||||
- Run a check, kill mid-flight, inspect `pygienium/run-state.json`
|
||||
|
||||
notes:
|
||||
|
||||
- Keep schema forward-compatible-by-addition only within this build; no legacy migrations
|
||||
- This file is the source of truth for `/pygienium-status` and `/pygienium-resume`
|
||||
46
tasks/05-infrastructure-utils.md
Normal file
46
tasks/05-infrastructure-utils.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 05. Scheduler, retry, and command-target parsing
|
||||
|
||||
meta:
|
||||
id: pygienium-05
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-01]
|
||||
tags: [infrastructure, utilities, no-model]
|
||||
|
||||
objective:
|
||||
|
||||
- Build three small infra modules the check runner needs: a concurrency-bounding scheduler, a retry-with-backoff helper, and a command argument parser.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/scheduler.ts`: `Scheduler` with `enqueue({id, run})`, burst cap from env `PYGIENIUM_MAX_AGENTS` (default 3), `dispose()`
|
||||
- `src/retry.ts`: `runWithRetry`, `readPositiveIntEnv`, `readNonNegativeIntEnv`, `errorMessage`, `yieldToEventLoop`
|
||||
- `src/command-target.ts`: `parseCommandArgs(args, cwd, opts)` → `{ cwd, tokens, args, error? }` supporting `[path]`, `--fresh`, `--fix`, `--check=<name>`, `--scope=<path>`
|
||||
|
||||
steps:
|
||||
|
||||
- Port piolium's `Scheduler` (Promise.allSettled under a semaphore-like cap) and `retry.ts` env helpers
|
||||
- Implement `runWithRetry(fn, { maxRetries, backoffBaseMs, backoffMaxMs, onRetry, signal })`
|
||||
- Implement `parseCommandArgs`: first non-flag token = optional target path (default cwd); collect `--flag` and `--opt=val` tokens into a tokens array + option lookup; return error string for malformed input
|
||||
|
||||
tests:
|
||||
|
||||
- Unit: scheduler caps concurrent runs at the configured value (spawn N no-op tasks, assert max in-flight)
|
||||
- Unit: retry exhausting throws the last error; onRetry invoked with backoff between attempts
|
||||
- Unit: parser handles `--fresh /repo --check=comments` → cwd=/repo, tokens=[--fresh, --check=comments], check=comments
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- Scheduler never exceeds the burst cap
|
||||
- retry respects maxRetries and aborts on signal
|
||||
- parser returns structured tokens with no ambiguity for the supported flags
|
||||
|
||||
validation:
|
||||
|
||||
- `grep -n "PYGIENIUM_MAX_AGENTS" src/scheduler.ts` present
|
||||
- Unit test suite for the three modules passes (if a test runner is configured)
|
||||
|
||||
notes:
|
||||
|
||||
- These are pure utilities; keep them dependency-free beyond node builtins
|
||||
- Grouped into one task because each is small and they're mutually independent
|
||||
48
tasks/06-check-registry.md
Normal file
48
tasks/06-check-registry.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# 06. Pluggable check registry and command wiring
|
||||
|
||||
meta:
|
||||
id: pygienium-06
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-02, pygienium-03, pygienium-04, pygienium-05]
|
||||
tags: [core, integration]
|
||||
|
||||
objective:
|
||||
|
||||
- Build the check registry + check runner that turns a `CheckDefinition` into a `/pygienium-<name>` command, wiring recon → sub-agent analysis → sub-agent fixes → verify → cleanup, and expose a phase-strip UI.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/registry.ts`: `CheckDefinition` interface (`name`, `label`, `description`, `agentName`, `phaseId`, `buildScanTask(cwd,scope)`, `buildFixTask(cwd,scope,findings)`, `gate(cwd)`) and a `registerCheck(def)` / `getAllChecks()` registry
|
||||
- `src/modes/check-runner.ts`: `runCheck(opts)` orchestrating Q0 recon (shared) → analysis sub-agent → fix sub-agent (optional on `--fix`) → verify gate → cleanup transient artifacts; writes run-state via task 04
|
||||
- `src/agents.ts`: `loadAgents({cwd})` reading markdown agent defs from `agents/*.md` (name, systemPrompt, allowedTools, sourcePath)
|
||||
- `src/index.ts` updated: register `/pygienium-help` and auto-register one `/pygienium-<check>` command per registered CheckDefinition; phase-strip status UI helper
|
||||
- `src/help.ts`: command + flag help builder (skeleton, populated in task 14)
|
||||
|
||||
steps:
|
||||
|
||||
- Define `CheckDefinition` and a module-level `Map` registry with `registerCheck`
|
||||
- Implement `runCheck`: init/resolve run state → run shared recon if missing → spawn analysis agent via agent-runner (task 03) with `buildScanTask` → if `--fix`, spawn fix agent with `buildFixTask` → applyPhaseStatus complete/failed → markRunStatus
|
||||
- Implement phase-strip UI helper (status key, initial phase, console stream forwarding) adapted from piolium's createPhaseStripCommandUi (simplified)
|
||||
- In index.ts: iterate registry, `pi.registerCommand("pygienium-"+def.name, { description, handler: runCheck wrapper })`
|
||||
- Ship `agents/scanner.md` and `agents/fixer.md` generic agent definitions used by all checks (analysis + fix roles)
|
||||
|
||||
tests:
|
||||
|
||||
- Unit: registry register/getAll returns inserted defs
|
||||
- Integration: register a no-op check whose agent writes a marker file; invoke its stub command; assert run-state marks it complete and the marker exists
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- A check registered via `registerCheck({name:"smoke", ...})` automatically exposes `/pygienium-smoke`
|
||||
- `runCheck` writes run-state and honors `--fix` vs scan-only
|
||||
- The phase strip UI shows the active phase and clears on completion
|
||||
|
||||
validation:
|
||||
|
||||
- Register a throwaway smoke check, run `/pygienium-smoke`, inspect `pygienium/run-state.json`
|
||||
|
||||
notes:
|
||||
|
||||
- This is the integration keystone; task 07 builds the first real check on top of it
|
||||
- Keep the registry open for extension: adding a check must NOT require editing index.ts command wiring
|
||||
46
tasks/07-check-comments.md
Normal file
46
tasks/07-check-comments.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 07. Comments hygiene check (first end-to-end check)
|
||||
|
||||
meta:
|
||||
id: pygienium-07
|
||||
feature: pygienium
|
||||
priority: P1
|
||||
depends_on: [pygienium-06]
|
||||
tags: [check, e2e-reference]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the comments hygiene check as the first full end-to-end check, serving as the reference pattern for the remaining checks: remove low-value comments, tighten verbose ones, keep "why" comments.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/comments.ts`: a `CheckDefinition` with `buildScanTask` and `buildFixTask`
|
||||
- `agents/comments-scanner.md` and `agents/comments-fixer.md` (or reuse generic scanner/fixer with a check-specific rubric embedded in the task text)
|
||||
- Rubric encoded in task text: comments that restate code = remove; verbose narration = tighten; `why` comments = keep; self-explanatory code = no comment needed; short + high value
|
||||
- `/pygienium-comments` runs E2E: recon → agent scans for comment smells → (on `--fix`) agent edits → report of changes
|
||||
|
||||
steps:
|
||||
|
||||
- Author the check definition: name `comments`, phaseId `C1`, allowedTools for analysis = read/bash/grep; for fix = read/edit/write/bash
|
||||
- Build scan task text instructing the agent to read candidates from recon, identify comment smells, write findings to `pygienium/checks/comments/findings.md` with per-file line refs
|
||||
- Build fix task text: apply safe removals/tightenings, leave `why` comments, write `changes.md` summarizing edits and anything needing human review
|
||||
- Register the check in index.ts via `registerCheck`
|
||||
- Implement `gate(cwd)`: findings.md exists
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: create a temp file with restating comments + a `why` comment; run `/pygienium-comments --fix`; assert restating comments removed, why comment kept, changes.md present
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `/pygienium-comments` produces findings.md without `--fix`
|
||||
- With `--fix`, low-value comments are removed and `why` comments survive
|
||||
- run-state marks the check complete and artifacts are recorded
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/checks/comments/{findings.md,changes.md}` after a run
|
||||
|
||||
notes:
|
||||
|
||||
- This task proves the whole framework works; prioritize getting it green before 08-11
|
||||
- The rubric is the user's spec: short + high value; what-comments bad, why-comments good
|
||||
42
tasks/08-check-deep-modules.md
Normal file
42
tasks/08-check-deep-modules.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 08. Deep-modules check
|
||||
|
||||
meta:
|
||||
id: pygienium-08
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-06]
|
||||
tags: [check]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the "deep modules, not shallow ones" check: detect modules with shallow abstractions (thin pass-throughs, single-call wrappers, unnecessary indirection) and recommend/apply consolidation.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/deep-modules.ts`: `CheckDefinition` with scan + fix tasks
|
||||
- Rubric: a module should provide a meaningful abstraction over its implementation; flag pass-through wrappers, one-line re-export modules, shallow classes with trivial getters, unnecessary adapter layers
|
||||
- `/pygienium-deep-modules` runs E2E
|
||||
|
||||
steps:
|
||||
|
||||
- Author `buildScanTask`: agent identifies shallow modules from recon candidates, writes findings to `pygienium/checks/deep-modules/findings.md`
|
||||
- Author `buildFixTask`: consolidate/inline where safe; flag risky consolidations for human review; write changes.md
|
||||
- Register the check
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: temp module that wraps a single lib call as a pass-through; run with `--fix`; assert it's flagged/removed and changes.md explains the consolidation
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `/pygienium-deep-modules` flags shallow modules in findings.md
|
||||
- With `--fix`, safe consolidations are applied; risky ones are listed for review, not auto-applied
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/checks/deep-modules/{findings.md,changes.md}`
|
||||
|
||||
notes:
|
||||
|
||||
- "Deep modules" = John Ousterhout's A Philosophy of Software Design; encode that definition in the rubric
|
||||
- Prefer conservative fixes: never auto-delete a module with external importers without confirmation
|
||||
42
tasks/09-check-dead-code.md
Normal file
42
tasks/09-check-dead-code.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 09. Dead code and obsolete paths check
|
||||
|
||||
meta:
|
||||
id: pygienium-09
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-06]
|
||||
tags: [check]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the dead-code / obsolete-paths check: find unreferenced exports, dead files, obsolete compatibility shims, migration paths, and unused config; remove them (engineering rule: no backward-compat layers).
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/dead-code.ts`: `CheckDefinition` with scan + fix tasks
|
||||
- Rubric: unreferenced functions/exports, files with zero importers (cross-checked against the review graph), deprecated/compat shims, migration helpers, unused dependencies
|
||||
- `/pygienium-dead-code` runs E2E
|
||||
|
||||
steps:
|
||||
|
||||
- Author `buildScanTask`: agent uses grep/import-graph + recon candidates to list dead code, writes `pygienium/checks/dead-code/findings.md` categorized by type
|
||||
- Author `buildFixTask`: remove clearly-dead items; list ambiguous ones (dynamic imports, runtime registration) for human review per pi-lens suspected-dead-weight semantics
|
||||
- Register the check
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: add an unused exported function + an obsolete compat wrapper; run `--fix`; assert both removed and changes.md lists them; assert a dynamically-imported shim is NOT auto-removed
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- findings.md categorizes dead code by type (export, file, shim, dep)
|
||||
- `--fix` removes clearly-dead items and preserves dynamic/runtime-registered ones with a review flag
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/checks/dead-code/{findings.md,changes.md}`
|
||||
|
||||
notes:
|
||||
|
||||
- Cross-reference the project_report "suspected dead weight" semantics — single-importer/zero-importer files
|
||||
- Engineering rule mandates removing obsolete paths rather than leaving compat shims
|
||||
53
tasks/10-check-complexity.md
Normal file
53
tasks/10-check-complexity.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 10. Excessive complexity check
|
||||
|
||||
meta:
|
||||
id: pygienium-10
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-06]
|
||||
tags: [check]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the excessive-complexity check: detect high cyclomatic complexity with concrete thresholds, plus unnecessarily fancy code, non-conventional patterns, and over-abstraction; refactor toward the simplest implementation that meets requirements.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/complexity.ts`: `CheckDefinition` with scan + fix tasks
|
||||
- Cyclomatic complexity thresholds (MUST enforce, not advisory):
|
||||
- **50+ → must refactor.** No exceptions. The function is too complex; break it up.
|
||||
- **35–49 → heavy skepticism.** Only keep if this is a massively critical point along the main path and the complexity genuinely must be here. Otherwise refactor. The agent must justify, in findings.md, why a 35–49 function is kept (critical path + why it can't be simplified).
|
||||
- **<35 → not flagged on cyclomatic grounds** (may still be flagged for other complexity smells like nesting/over-abstraction)
|
||||
- Rubric: speculative abstractions, premature config indirection, non-idiomatic patterns, over-engineered generics, unnecessary wrappers; refactor to common conventions and the simplest correct form
|
||||
- `/pygienium-complexity` runs E2E
|
||||
|
||||
steps:
|
||||
|
||||
- Author `buildScanTask`: agent identifies complexity hotspots:
|
||||
1. **Cyclomatic complexity** — compute via a deterministic tool when available (e.g. `lizard`/`radon`/`gocyclo`/language-native), fall back to counting decision points (if/else if/for/while/case/&&/||/catch) per function. Classify each function into the 50+ / 35–49 / below-35 bands above. Write per-function scores to `pygienium/checks/complexity/findings.md` with line refs.
|
||||
2. **Structural smells** — deep nesting (>3 levels), needless indirection, speculative abstractions — same findings.md, separate section.
|
||||
- findings.md includes a proposed simpler form for every flagged function.
|
||||
- Author `buildFixTask`: apply safe refactors (flatten nested conditionals, inline trivial wrappers, remove speculative config, split 50+ functions); for 35–49 functions, keep ONLY if the agent can justify critical-path necessity, else refactor. Flag risky refactors for review.
|
||||
- Register the check
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: temp file with a 55-decision-point function (must-refactor) + a 40-decision-point function (heavy-skepticism, must justify or refactor); run `--fix`; assert the 50+ is split, the 35–49 is either refactored or has a documented justification in changes.md
|
||||
- Integration: temp file with a needlessly abstracted config layer + deep nesting; run `--fix`; assert simplified
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- findings.md lists cyclomatic complexity scores per function banded as 50+/35-49/below-35
|
||||
- Every 50+ function is refactored by `--fix` (no 50+ remains post-fix)
|
||||
- Every kept 35–49 function has a documented justification (critical path + why-simpler-isn't-possible) in findings.md; unjustified ones are refactored
|
||||
- findings.md lists structural complexity hotspots with proposed simplifications
|
||||
- `--fix` applies safe refactors and preserves behavior (agent re-reads after edit)
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/checks/complexity/{findings.md,changes.md}`
|
||||
|
||||
notes:
|
||||
|
||||
- Encode the engineering rules directly in the rubric: simplest implementation, no speculative abstractions, grow in layers
|
||||
- The lens risk-hotspots (fan-in × complexity) and module_report complexity flags are signals to feed the agent
|
||||
42
tasks/11-check-defensive-guards.md
Normal file
42
tasks/11-check-defensive-guards.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 11. Redundant defensive guarding check
|
||||
|
||||
meta:
|
||||
id: pygienium-11
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-06]
|
||||
tags: [check]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the redundant-defensive-guarding check: remove excessive null checks, unnecessary try/catch, fallback paths that mask bugs, defensive code guarding invariants the type system already guarantees.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/checks/defensive-guards.ts`: `CheckDefinition` with scan + fix tasks
|
||||
- Rubric: redundant null/undefined checks where types are non-nullable, try/catch that only rethrows or swallows, fallback values that hide errors, defensive guards on already-validated input, compatibility fallbacks (engineering rule: remove, don't layer)
|
||||
- `/pygienium-defensive-guards` runs E2E
|
||||
|
||||
steps:
|
||||
|
||||
- Author `buildScanTask`: agent identifies defensive smells, writes `pygienium/checks/defensive-guards/findings.md`
|
||||
- Author `buildFixTask`: remove redundant guards; preserve guards that protect real external boundaries (user input, IO, parsing); write changes.md distinguishing removed vs kept-with-reason
|
||||
- Register the check
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: temp file with a null check on a typed-non-null param + a try/catch that swallows; run `--fix`; assert removed; assert a JSON.parse guard is preserved
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- findings.md separates redundant guards from legitimate boundary guards
|
||||
- `--fix` removes redundant guards and keeps boundary guards (IO, parsing, untrusted input)
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/checks/defensive-guards/{findings.md,changes.md}`
|
||||
|
||||
notes:
|
||||
|
||||
- Key judgment: guarding external boundaries (IO, untrusted input, parsing) is correct; guarding internal invariants the type system guarantees is noise
|
||||
- Engineering rule: no compatibility layers or fallbacks meant to be replaced later
|
||||
44
tasks/12-orchestrator-all.md
Normal file
44
tasks/12-orchestrator-all.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# 12. /pygienium-all master orchestrator
|
||||
|
||||
meta:
|
||||
id: pygienium-12
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-07, pygienium-08, pygienium-09, pygienium-10, pygienium-11]
|
||||
tags: [orchestration]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement `/pygienium-all`: run every registered check in sequence as ordered phases under a unified status strip, with resumable state and a final summary report.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `src/modes/all.ts`: `runAllChecks(opts)` iterating the registry, calling `runCheck` per check with shared recon, accumulating per-check status into run-state, writing `pygienium/all-summary.md`
|
||||
- `/pygienium-all` command wired in index.ts with phase strip listing all check names
|
||||
- Respects `--fresh`, `--fix`, and `--only=comments,complexity` to select a subset
|
||||
|
||||
steps:
|
||||
|
||||
- Implement `runAllChecks`: init a single run (mode "all"), run shared recon once, then for each registered check call `runCheck` with the existing run-state record (not a fresh one per check)
|
||||
- Build the phase strip from registry names; set initial phase to the first check
|
||||
- Aggregate final summary: per-check status, artifact paths, total findings/changes counts
|
||||
- Support `--only` filtering via the command-target parser
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: run `/pygienium-all` on a small repo; assert every check ran, run-state shows all complete, all-summary.md present
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `/pygienium-all` runs every registered check exactly once in registry order
|
||||
- Interrupted runs are resumable (in_progress/failed checks re-run; complete ones skipped unless `--fresh`)
|
||||
- all-summary.md lists per-check outcomes
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/run-state.json` and `pygienium/all-summary.md`
|
||||
|
||||
notes:
|
||||
|
||||
- This is the piolium "balanced"/"deep" mode analogue, but simpler: one run, sequential phases, shared recon
|
||||
- Ensure scheduler is not needed (sequential) unless we later parallelize independent checks
|
||||
43
tasks/13-resume-status-export.md
Normal file
43
tasks/13-resume-status-export.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 13. Resume, status, and export commands
|
||||
|
||||
meta:
|
||||
id: pygienium-13
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-04, pygienium-06]
|
||||
tags: [commands]
|
||||
|
||||
objective:
|
||||
|
||||
- Implement the operational commands: `/pygienium-resume` (continue the most recent non-complete run), `/pygienium-status` (show run progress), and `/pygienium-export` (export findings/changes with filters).
|
||||
|
||||
deliverables:
|
||||
|
||||
- `/pygienium-resume`: read run-state, pick latestResumableRun, re-dispatch that run's checks (complete ones skipped unless `--fresh`)
|
||||
- `/pygienium-status`: format run-state into a readable line list (per-check status, artifacts, errors)
|
||||
- `/pygienium-export`: gather all `pygienium/checks/*/findings.md` and `changes.md` with filters (`--check=`, `--status=`, `--out=`) into a single markdown or JSON bundle
|
||||
- All three wired in index.ts
|
||||
|
||||
steps:
|
||||
|
||||
- Port piolium's status/resume/export command shapes, adapting to run-state and check artifacts
|
||||
- `formatRunStatus(state)` builds the status line list
|
||||
- Export walks `pygienium/checks/*/` and applies filters before writing `pygienium/export.{md|json}`
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: start `/pygienium-all`, interrupt, run `/pygienium-status` (shows in_progress), `/pygienium-resume` (completes), `/pygienium-export`
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- `/pygienium-status` reports accurate per-check progress
|
||||
- `/pygienium-resume` continues a non-complete run without re-running complete checks
|
||||
- `/pygienium-export` produces a filtered bundle
|
||||
|
||||
validation:
|
||||
|
||||
- Inspect `pygienium/export.md` and the status output
|
||||
|
||||
notes:
|
||||
|
||||
- These mirror piolium's status/resume/export almost directly; keep behavior faithful
|
||||
50
tasks/14-readme-help-integration.md
Normal file
50
tasks/14-readme-help-integration.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 14. README, help text, and end-to-end integration
|
||||
|
||||
meta:
|
||||
id: pygienium-14
|
||||
feature: pygienium
|
||||
priority: P2
|
||||
depends_on: [pygienium-12, pygienium-13]
|
||||
tags: [docs, integration]
|
||||
|
||||
objective:
|
||||
|
||||
- Author the README and full help text, then run an end-to-end integration pass over the whole extension to verify all commands, the registry extensibility claim, and the exit criteria.
|
||||
|
||||
deliverables:
|
||||
|
||||
- `pygienium/README.md`: what it is, install, commands, flags, how to add a check (one file + registerCheck)
|
||||
- `src/help.ts` fully populated: per-command usage/does/example + CLI flag help, mirroring piolium's help.ts
|
||||
- `/pygienium-help` renders the full help block
|
||||
- Extensibility verification: add a new check in `checks/` + one registry line with NO index.ts command changes; confirm a new `/pygienium-<new>` command appears
|
||||
|
||||
steps:
|
||||
|
||||
- Write README sections: overview, the five checks, commands, flags, adding a check, architecture (sub-agent loops)
|
||||
- Populate help.ts COMMANDS + CLI_FLAGS arrays from the actual commands/flags implemented in 06-13
|
||||
- Extensibility test: create `checks/noop.ts` registering `registerCheck({name:"noop",...})`, reload, confirm `/pygienium-noop` exists and `/pygienium-help` lists it
|
||||
- Run `/pygienium-all` end-to-end on this repo and confirm the exit criteria
|
||||
|
||||
tests:
|
||||
|
||||
- Integration: `/pygienium-help` lists all 8+ commands and all flags
|
||||
- Integration: a newly registered check auto-creates its command without index.ts edits
|
||||
- Integration: `/pygienium-all` completes with all checks marked complete
|
||||
|
||||
acceptance_criteria:
|
||||
|
||||
- README documents install, commands, flags, and the one-file extensibility workflow
|
||||
- `/pygienium-help` output matches the implemented commands/flags exactly
|
||||
- A new check file + registerCheck entry yields a working `/pygienium-<name>` command with zero index.ts changes
|
||||
- All exit criteria from the feature README pass
|
||||
|
||||
validation:
|
||||
|
||||
- `pi -p "/pygienium-help"` prints the full help
|
||||
- Add the noop check, `/reload`, run `/pygienium-noop`, confirm success
|
||||
- Run `/pygienium-all` and inspect the final summary
|
||||
|
||||
notes:
|
||||
|
||||
- This is the acceptance gate for the whole feature
|
||||
- If the extensibility claim fails here, refactor the registry in task 06 before declaring done
|
||||
42
tasks/README.md
Normal file
42
tasks/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Pygienium — Code Hygiene Extension
|
||||
|
||||
Objective: A pi extension (piolium-style sub-agent loops) that runs highly-structured code-hygiene passes over a repo to clean up common LLM-code quality issues.
|
||||
|
||||
Status legend: [ ] todo, [~] in-progress, [x] done
|
||||
|
||||
Tasks
|
||||
|
||||
- [x] 01 — scaffolding → `01-scaffolding.md`
|
||||
- [x] 02 — recon → `02-recon.md`
|
||||
- [x] 03 — agent-runner → `03-agent-runner.md`
|
||||
- [x] 04 — hygiene-state → `04-hygiene-state.md`
|
||||
- [x] 05 — infrastructure-utils → `05-infrastructure-utils.md`
|
||||
- [x] 06 — check-registry → `06-check-registry.md`
|
||||
- [x] 07 — check-comments → `07-check-comments.md`
|
||||
- [x] 08 — check-deep-modules → `08-check-deep-modules.md`
|
||||
- [x] 09 — check-dead-code → `09-check-dead-code.md`
|
||||
- [x] 10 - check-complexity → `10-check-complexity.md` (incl. cyclomatic complexity: 50+ must-refactor, 35–49 heavy-skepticism)
|
||||
- [x] 11 — check-defensive-guards → `11-check-defensive-guards.md`
|
||||
- [x] 12 — orchestrator-all → `12-orchestrator-all.md`
|
||||
- [x] 13 — resume-status-export → `13-resume-status-export.md`
|
||||
- [x] 14 — readme-help-integration → `14-readme-help-integration.md`
|
||||
|
||||
Dependencies
|
||||
|
||||
- 02, 03, 04, 05 depend on 01
|
||||
- 06 depends on 02, 03, 04, 05
|
||||
- 07, 08, 09, 10, 11 depend on 06 (07 serves as the reference E2E check)
|
||||
- 12 depends on 07, 08, 09, 10, 11
|
||||
- 13 depends on 04, 06
|
||||
- 14 depends on 12, 13
|
||||
|
||||
Exit criteria
|
||||
|
||||
- The feature is complete when `/pygienium-help` lists all commands/flags, each `/pygienium-<check>` command runs an isolated sub-agent that scans a target, applies fixes, and emits a findings+changes report; `/pygienium-all` runs every registered check in sequence with a unified status strip and resumable state; `/pygienium-resume`, `/pygienium-status`, and `/pygienium-export` work; and adding a new check requires only a new file in `checks/` plus one registry entry (no index.ts command-wiring changes).
|
||||
|
||||
Architecture reference
|
||||
|
||||
- Style: piolium (`@vigolium/piolium`) sub-agent loops via `createAgentSession`
|
||||
- Distribution: local extension under `~/.pi/agent/extensions/pygienium/`, structured to be npm-publishable later
|
||||
- Each check = a "mode": deterministic recon → sub-agent analysis → sub-agent fixes → verify → cleanup
|
||||
- Check registry makes the system extensible: new check = new file + registry entry
|
||||
Reference in New Issue
Block a user