diff --git a/.agents/skills/lustra/SKILL.md b/.agents/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.agents/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.agents/skills/lustra/reference/audit.md b/.agents/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.agents/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.agents/skills/lustra/reference/baseline.md b/.agents/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.agents/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.agents/skills/lustra/reference/ci.md b/.agents/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.agents/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.agents/skills/lustra/reference/deadcode.md b/.agents/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.agents/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.agents/skills/lustra/reference/docs.md b/.agents/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.agents/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.agents/skills/lustra/reference/libs.md b/.agents/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.agents/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.agents/skills/lustra/reference/license.md b/.agents/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.agents/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.agents/skills/lustra/reference/lint.md b/.agents/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.agents/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.agents/skills/lustra/reference/perf.md b/.agents/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.agents/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.agents/skills/lustra/reference/prettier.md b/.agents/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.agents/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.agents/skills/lustra/reference/review.md b/.agents/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.agents/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.agents/skills/lustra/reference/security.md b/.agents/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.agents/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.agents/skills/lustra/reference/structure.md b/.agents/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.agents/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.agents/skills/lustra/reference/tests.md b/.agents/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.agents/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.agents/skills/lustra/reference/types.md b/.agents/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.agents/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.claude/skills/lustra/SKILL.md b/.claude/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.claude/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.claude/skills/lustra/reference/audit.md b/.claude/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.claude/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.claude/skills/lustra/reference/baseline.md b/.claude/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.claude/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.claude/skills/lustra/reference/ci.md b/.claude/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.claude/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.claude/skills/lustra/reference/deadcode.md b/.claude/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.claude/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.claude/skills/lustra/reference/docs.md b/.claude/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.claude/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.claude/skills/lustra/reference/libs.md b/.claude/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.claude/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.claude/skills/lustra/reference/license.md b/.claude/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.claude/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.claude/skills/lustra/reference/lint.md b/.claude/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.claude/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.claude/skills/lustra/reference/perf.md b/.claude/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.claude/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.claude/skills/lustra/reference/prettier.md b/.claude/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.claude/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.claude/skills/lustra/reference/review.md b/.claude/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.claude/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.claude/skills/lustra/reference/security.md b/.claude/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.claude/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.claude/skills/lustra/reference/structure.md b/.claude/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.claude/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.claude/skills/lustra/reference/tests.md b/.claude/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.claude/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.claude/skills/lustra/reference/types.md b/.claude/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.claude/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.codex/skills/lustra/SKILL.md b/.codex/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.codex/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.codex/skills/lustra/reference/audit.md b/.codex/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.codex/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.codex/skills/lustra/reference/baseline.md b/.codex/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.codex/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.codex/skills/lustra/reference/ci.md b/.codex/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.codex/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.codex/skills/lustra/reference/deadcode.md b/.codex/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.codex/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.codex/skills/lustra/reference/docs.md b/.codex/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.codex/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.codex/skills/lustra/reference/libs.md b/.codex/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.codex/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.codex/skills/lustra/reference/license.md b/.codex/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.codex/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.codex/skills/lustra/reference/lint.md b/.codex/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.codex/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.codex/skills/lustra/reference/perf.md b/.codex/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.codex/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.codex/skills/lustra/reference/prettier.md b/.codex/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.codex/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.codex/skills/lustra/reference/review.md b/.codex/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.codex/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.codex/skills/lustra/reference/security.md b/.codex/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.codex/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.codex/skills/lustra/reference/structure.md b/.codex/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.codex/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.codex/skills/lustra/reference/tests.md b/.codex/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.codex/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.codex/skills/lustra/reference/types.md b/.codex/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.codex/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.cursor/skills/lustra/SKILL.md b/.cursor/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.cursor/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.cursor/skills/lustra/reference/audit.md b/.cursor/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.cursor/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.cursor/skills/lustra/reference/baseline.md b/.cursor/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.cursor/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.cursor/skills/lustra/reference/ci.md b/.cursor/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.cursor/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.cursor/skills/lustra/reference/deadcode.md b/.cursor/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.cursor/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.cursor/skills/lustra/reference/docs.md b/.cursor/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.cursor/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.cursor/skills/lustra/reference/libs.md b/.cursor/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.cursor/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.cursor/skills/lustra/reference/license.md b/.cursor/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.cursor/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.cursor/skills/lustra/reference/lint.md b/.cursor/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.cursor/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.cursor/skills/lustra/reference/perf.md b/.cursor/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.cursor/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.cursor/skills/lustra/reference/prettier.md b/.cursor/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.cursor/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.cursor/skills/lustra/reference/review.md b/.cursor/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.cursor/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.cursor/skills/lustra/reference/security.md b/.cursor/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.cursor/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.cursor/skills/lustra/reference/structure.md b/.cursor/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.cursor/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.cursor/skills/lustra/reference/tests.md b/.cursor/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.cursor/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.cursor/skills/lustra/reference/types.md b/.cursor/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.cursor/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.gemini/skills/lustra/SKILL.md b/.gemini/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.gemini/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.gemini/skills/lustra/reference/audit.md b/.gemini/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.gemini/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.gemini/skills/lustra/reference/baseline.md b/.gemini/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.gemini/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.gemini/skills/lustra/reference/ci.md b/.gemini/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.gemini/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.gemini/skills/lustra/reference/deadcode.md b/.gemini/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.gemini/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.gemini/skills/lustra/reference/docs.md b/.gemini/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.gemini/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.gemini/skills/lustra/reference/libs.md b/.gemini/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.gemini/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.gemini/skills/lustra/reference/license.md b/.gemini/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.gemini/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.gemini/skills/lustra/reference/lint.md b/.gemini/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.gemini/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.gemini/skills/lustra/reference/perf.md b/.gemini/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.gemini/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.gemini/skills/lustra/reference/prettier.md b/.gemini/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.gemini/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.gemini/skills/lustra/reference/review.md b/.gemini/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.gemini/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.gemini/skills/lustra/reference/security.md b/.gemini/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.gemini/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.gemini/skills/lustra/reference/structure.md b/.gemini/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.gemini/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.gemini/skills/lustra/reference/tests.md b/.gemini/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.gemini/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.gemini/skills/lustra/reference/types.md b/.gemini/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.gemini/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.github/skills/lustra/SKILL.md b/.github/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.github/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.github/skills/lustra/reference/audit.md b/.github/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.github/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.github/skills/lustra/reference/baseline.md b/.github/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.github/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.github/skills/lustra/reference/ci.md b/.github/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.github/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.github/skills/lustra/reference/deadcode.md b/.github/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.github/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.github/skills/lustra/reference/docs.md b/.github/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.github/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.github/skills/lustra/reference/libs.md b/.github/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.github/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.github/skills/lustra/reference/license.md b/.github/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.github/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.github/skills/lustra/reference/lint.md b/.github/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.github/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.github/skills/lustra/reference/perf.md b/.github/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.github/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.github/skills/lustra/reference/prettier.md b/.github/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.github/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.github/skills/lustra/reference/review.md b/.github/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.github/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.github/skills/lustra/reference/security.md b/.github/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.github/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.github/skills/lustra/reference/structure.md b/.github/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.github/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.github/skills/lustra/reference/tests.md b/.github/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.github/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.github/skills/lustra/reference/types.md b/.github/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.github/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.gitignore b/.gitignore index 2d98f97..60868e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,13 @@ node_modules/ *.tgz + +# Generated skill targets — source of truth is skill/; regenerated by npm run build +.agents/skills/lustra/ +.claude/skills/lustra/ +.cursor/skills/lustra/ +.gemini/skills/lustra/ +.codex/skills/lustra/ +.github/skills/lustra/ +.kiro/skills/lustra/ +.opencode/skills/lustra/ +.qoder/skills/lustra/ diff --git a/.kiro/skills/lustra/SKILL.md b/.kiro/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.kiro/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.kiro/skills/lustra/reference/audit.md b/.kiro/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.kiro/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.kiro/skills/lustra/reference/baseline.md b/.kiro/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.kiro/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.kiro/skills/lustra/reference/ci.md b/.kiro/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.kiro/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.kiro/skills/lustra/reference/deadcode.md b/.kiro/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.kiro/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.kiro/skills/lustra/reference/docs.md b/.kiro/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.kiro/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.kiro/skills/lustra/reference/libs.md b/.kiro/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.kiro/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.kiro/skills/lustra/reference/license.md b/.kiro/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.kiro/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.kiro/skills/lustra/reference/lint.md b/.kiro/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.kiro/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.kiro/skills/lustra/reference/perf.md b/.kiro/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.kiro/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.kiro/skills/lustra/reference/prettier.md b/.kiro/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.kiro/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.kiro/skills/lustra/reference/review.md b/.kiro/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.kiro/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.kiro/skills/lustra/reference/security.md b/.kiro/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.kiro/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.kiro/skills/lustra/reference/structure.md b/.kiro/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.kiro/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.kiro/skills/lustra/reference/tests.md b/.kiro/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.kiro/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.kiro/skills/lustra/reference/types.md b/.kiro/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.kiro/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.opencode/skills/lustra/SKILL.md b/.opencode/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.opencode/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.opencode/skills/lustra/reference/audit.md b/.opencode/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.opencode/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.opencode/skills/lustra/reference/baseline.md b/.opencode/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.opencode/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.opencode/skills/lustra/reference/ci.md b/.opencode/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.opencode/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.opencode/skills/lustra/reference/deadcode.md b/.opencode/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.opencode/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.opencode/skills/lustra/reference/docs.md b/.opencode/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.opencode/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.opencode/skills/lustra/reference/libs.md b/.opencode/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.opencode/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.opencode/skills/lustra/reference/license.md b/.opencode/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.opencode/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.opencode/skills/lustra/reference/lint.md b/.opencode/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.opencode/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.opencode/skills/lustra/reference/perf.md b/.opencode/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.opencode/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.opencode/skills/lustra/reference/prettier.md b/.opencode/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.opencode/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.opencode/skills/lustra/reference/review.md b/.opencode/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.opencode/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.opencode/skills/lustra/reference/security.md b/.opencode/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.opencode/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.opencode/skills/lustra/reference/structure.md b/.opencode/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.opencode/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.opencode/skills/lustra/reference/tests.md b/.opencode/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.opencode/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.opencode/skills/lustra/reference/types.md b/.opencode/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.opencode/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/.qoder/skills/lustra/SKILL.md b/.qoder/skills/lustra/SKILL.md deleted file mode 100644 index d8ebf97..0000000 --- a/.qoder/skills/lustra/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: lustra -description: "Use when the user wants to clean up AI slop, harden a codebase, or run technical due diligence: review code for security flaws and vulnerable or wrongly-licensed dependencies, find and remove dead code, audit dependency health, run and triage linters, type checkers, test suites and Prettier, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, fix project structure, or produce one aggregated health report across all of these. Triggers on phrases like clean this up, find security issues, remove dead code, check dependencies, lint, typecheck, run the tests, format, review my code, check licenses, is this slow, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps real tools (npm audit, knip, eslint, tsc, the test runner, prettier, npm outdated, license-checker) and triages their output. Not for UI/visual design work." -user-invocable: true -argument-hint: "[audit|security|license|libs|types|tests|deadcode|lint|review|perf|structure|docs|ci|prettier|baseline] [target]" -allowed-tools: Bash Read Edit Grep Glob ---- - -# Lustra - -Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not -guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. - -## Dispatch - -`$1` is the command. `$2` and beyond are the target (a path or glob). When no target is -given, default to the whole repository. - -- If `$1` is empty or `help`, print the command list below and stop. -- Otherwise read `${CLAUDE_SKILL_DIR}/reference/$1.md` and follow it exactly, scoped to the - target. If `reference/$1.md` does not exist, say so and print the command list. - -## Commands - -Grouped by lifecycle phase. `audit` runs the diagnostic ones together. - -**Assess / start** -- `audit` — meta-command: one graded health report across every dimension (due diligence). -- `baseline` — scaffold the guardrail configs a project should have, for the detected stack. - -**Iterate** -- `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. -- `tests` — run the suite, coverage on the diff, catch fake/empty tests. -- `lint` — ESLint plus AI-slop smells that no rule catches. -- `prettier` — formatting drift. - -**Polish** -- `security` — vulnerabilities: secrets, injection, broken authorization, vulnerable deps. -- `license` — dependency license compatibility and IP risk. -- `deadcode` — unused files, exports, and dependencies (knip). -- `libs` — dependency health: outdated, deprecated, duplicated, unused. -- `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. -- `docs` — documentation drift and undocumented public surface. - -**Maintain** -- `ci` — pipeline soundness: real gates, CI security, reproducibility. -- `structure` — detect the stack, then report or reorganize project structure. - -## Rules that override every reference file - -These come from the project's own engineering guidelines and are not negotiable: - -1. **Surgical.** Every changed line must trace to the requested command. Never "improve" - adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. -3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is - low-confidence, say so plainly. Do not present a partial pass as a clean one. -4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. diff --git a/.qoder/skills/lustra/reference/audit.md b/.qoder/skills/lustra/reference/audit.md deleted file mode 100644 index 1d933d3..0000000 --- a/.qoder/skills/lustra/reference/audit.md +++ /dev/null @@ -1,58 +0,0 @@ -# audit - -**Purpose:** the meta-command. One aggregated health report across every Lustra -dimension — the answer to "I inherited this code, what's here?" and to "is everything in -order?" (technical due diligence). - -## Run - -Execute the other commands in **diagnostic mode only — detect and triage, do not fix -anything**, in this order, and collect their findings: - -1. **Legal / risk:** `security`, `license` -2. **Supply chain:** `libs` -3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` - -Each runs over the whole target. Skip a dimension only if its tooling/stack is absent, -and record the skip explicitly — a gap is a due-diligence finding, not a blank. - -`baseline` is **not** part of audit (it is generative, not diagnostic). If `baseline` -would have lots to do, note "no project guardrails" under maintainability instead. - -## Triage - -Per dimension, assign a grade — **pass / concerns / fail** — with the one or two findings -that drove it. Surface every **blocking** item (exploitable security, copyleft -contamination, a green-but-fake test suite, a pipeline that gates nothing) at the top, -above the per-dimension detail. Do not average a fail away into a "B". - -## Fix policy - -Audit **never edits**. It ends by offering to drill into any single dimension with that -command (which then applies its own fix policy). One report, zero changes. - -## Report - -``` -Lustra audit — - -Blocking - - : - -Scorecard - Legal/risk pass|concerns|fail - Supply chain ... - Reliability ... - Maintainability ... - Bus factor/ops ... - -Detail - - -Skipped - -``` - -End with the recommended next command(s), highest-risk first. diff --git a/.qoder/skills/lustra/reference/baseline.md b/.qoder/skills/lustra/reference/baseline.md deleted file mode 100644 index 9a5c18c..0000000 --- a/.qoder/skills/lustra/reference/baseline.md +++ /dev/null @@ -1,35 +0,0 @@ -# baseline - -**Purpose:** the *start* command — establish the guardrail configs a project should have -had on day one, for the detected stack. The only generative command; treat it accordingly. - -## Detect - -1. Detect the stack as in `structure.md` (language, framework, build tool, test runner, - package manager). -2. Inventory what already exists: linter, formatter, type-checker, test, CI, editorconfig, - gitignore, license, lockfile. **Existing config is authoritative — never overwrite it.** -3. Identify only the *missing* guardrails for this stack. - -## Triage - -Propose the minimum standard set for the detected stack, nothing speculative -(CLAUDE.md §2): formatter + linter + type-checker config, a test setup if none, a CI -workflow that gates them, `.gitignore`, `.editorconfig`, `LICENSE` if absent. Do not -add tools the stack doesn't need or the team hasn't signaled wanting. - -## Fix policy - -This command writes new files, so it is the most destructive — rule 5 applies hardest: - -- Present the full list of files to create with their proposed contents **first**. -- Create only what the user approves, one coherent group at a time (e.g. lint+format - together), each independently reviewable. -- Never modify or "upgrade" an existing config as part of baseline — that is a separate, - explicit decision. If an existing config is weak, *report* it, don't rewrite it. -- Match conventions the project already shows (indentation, module style). - -## Report - -Detected stack, what exists, what is missing, then the proposed file set for confirmation. -After applying, list exactly what was created. diff --git a/.qoder/skills/lustra/reference/ci.md b/.qoder/skills/lustra/reference/ci.md deleted file mode 100644 index 501f24b..0000000 --- a/.qoder/skills/lustra/reference/ci.md +++ /dev/null @@ -1,32 +0,0 @@ -# ci - -**Purpose:** the pipeline that guards the project is itself sound. - -## Detect - -1. Locate CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`, - `.circleci/`, etc. If a real project has none, that is the top finding. -2. Check the pipeline actually gates: are lint, types, tests, build, and audit run, and - do they **fail** the job (not `|| true`, not `continue-on-error` masking failures)? -3. Security/hygiene: secrets echoed into logs, untrusted PR code running with secrets, - unpinned third-party actions (`@main`), missing least-privilege `permissions`, - no dependency/lockfile install integrity (`npm ci` vs `npm install`). -4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic - install from the lockfile. - -## Triage - -Rank: a gate that doesn't gate (green pipeline, broken check) > security exposure in CI > -non-reproducible build > missing-but-non-critical step. The most dangerous finding is a -pipeline that *looks* green while enforcing nothing — call it out first. - -## Fix policy - -- Auto: nothing — CI changes affect every future build. -- Propose (diff + ask): the specific workflow edit (add the failing gate, pin the action, - scope `permissions`, switch to `npm ci`), one concern per change, with the risk it closes. - -## Report - -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. diff --git a/.qoder/skills/lustra/reference/deadcode.md b/.qoder/skills/lustra/reference/deadcode.md deleted file mode 100644 index 2824092..0000000 --- a/.qoder/skills/lustra/reference/deadcode.md +++ /dev/null @@ -1,32 +0,0 @@ -# deadcode - -**Purpose:** remove code that nothing reaches, with proof, not guesses. - -## Detect - -1. `npx -y knip --reporter json`, scoped to the target if knip supports the workspace. - If a `knip.json` exists, use it; do not overwrite it. -2. If knip cannot run (no Node project / unsupported stack), fall back to: build the - import graph for the target with Grep/Glob and flag exported symbols and files with - zero inbound references. State clearly this fallback is lower confidence. - -## Triage - -knip over-reports across these categories — review each before acting: - -- **Unused files / exports:** confirm there is no dynamic import, string-keyed require, - framework convention (route/page files), or barrel re-export reaching them. -- **Unused dependencies:** confirm they are not used only in scripts, config, or types. -- Entry points, public API surfaces, and intentionally-exported library code are *not* - dead code even with zero internal callers — exclude them. - -## Fix policy - -Deleting code is a scope decision (rule 2). Never bulk-delete. Present the confirmed-dead -set as a checklist with the evidence for each item, then delete only what the user -approves, in one reviewable change. Remove imports your deletions orphan; nothing else. - -## Report - -Three groups: confirmed dead (with evidence), likely dead (needs human call), excluded -(why it looked dead but isn't). diff --git a/.qoder/skills/lustra/reference/docs.md b/.qoder/skills/lustra/reference/docs.md deleted file mode 100644 index c54afe0..0000000 --- a/.qoder/skills/lustra/reference/docs.md +++ /dev/null @@ -1,33 +0,0 @@ -# docs - -**Purpose:** documentation that matches the code — the bus-factor leg of due diligence. - -## Detect - -1. README/setup drift: run the documented install/build/run steps mentally against the - actual manifest and scripts. Flag commands, env vars, and versions that no longer - match reality. -2. Public-surface coverage: enumerate exported API (public functions, CLI commands, HTTP - routes, config keys) and flag the ones with no doc or doc comment. -3. Stale/lying docs: comments and docs describing behavior the code no longer has, - examples that would not run, dead links, TODO/`coming soon` that never came. -4. Missing essentials for the project type: no README, no LICENSE reference, no - contributing/setup notes where the project clearly needs them. - -## Triage - -Rank: wrong docs (actively misleading) > missing docs for public surface > thin docs > -cosmetic. A confidently wrong README is worse than no README — say so. Do not demand -docs for private internals. - -## Fix policy - -- Auto: nothing — prose is judgment. -- Propose (diff + ask): corrected steps/examples grounded in the actual code, and - doc stubs for undocumented public surface. Never invent behavior to fill a gap; if the - code's intent is unclear, flag it as a question, not a fabricated description. - -## Report - -Drift (doc vs. reality, with the mismatch), undocumented public surface, stale items — -each `file:line`/section with the concrete correction proposed. diff --git a/.qoder/skills/lustra/reference/libs.md b/.qoder/skills/lustra/reference/libs.md deleted file mode 100644 index 66f7cf1..0000000 --- a/.qoder/skills/lustra/reference/libs.md +++ /dev/null @@ -1,32 +0,0 @@ -# libs - -**Purpose:** a clear, risk-ranked picture of dependency health and what to upgrade. - -## Detect - -1. `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile present). -2. `npm audit --json` for advisories on those deps. -3. `npx -y knip --dependencies` for unused and unlisted dependencies. -4. Inspect the manifest for: deprecated packages (npm marks these on install), two - packages solving the same job, and pinned-but-ancient versions. - -## Triage - -Group every dependency into one of: - -- **Safe** — patch/minor with no breaking notes; batch these. -- **Review** — minor with behavior changes, or a transitive security bump. -- **Major** — semver-major; one at a time, needs changelog reading and a test run. -- **Remove** — unused (confirm like `deadcode` does before trusting knip). -- **Replace** — deprecated or duplicated; name the recommended successor. - -## Fix policy - -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. -- Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical - change per step, never a blanket bump. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/.qoder/skills/lustra/reference/license.md b/.qoder/skills/lustra/reference/license.md deleted file mode 100644 index b63b4f8..0000000 --- a/.qoder/skills/lustra/reference/license.md +++ /dev/null @@ -1,35 +0,0 @@ -# license - -**Purpose:** the legal/IP leg of due diligence — does the dependency tree put the -project's own license at risk. - -## Detect - -1. Read the project's declared license from the manifest. If absent, that is itself a - top finding. -2. Enumerate dependency licenses: `npx -y license-checker --json` (or the pnpm/yarn - equivalent), including transitive. For non-JS stacks use the stack's tool - (`pip-licenses`, `go-licenses`, `cargo about`) if present; otherwise read manifests - and state the result is partial. -3. Flag: copyleft (GPL/AGPL/LGPL) reaching a proprietary or permissively-licensed - project, packages with **no** license or `UNLICENSED`, custom/unrecognized licenses, - and missing attribution for licenses that require it (BSD/MIT/Apache NOTICE). - -## Triage - -Rank by legal exposure: AGPL/GPL contamination of a distributed proprietary product is -**blocking**; LGPL via dynamic linking is conditional; missing attribution is fixable; -permissive-on-permissive is clear. Distinguish runtime deps (contaminating) from -dev-only deps (generally not). Never give a legal conclusion — surface the risk and -recommend counsel for blocking cases. - -## Fix policy - -- Auto: nothing. License changes are decisions, not edits. -- Propose (diff + ask): replacing a problematic package with a compatibly-licensed - equivalent, or adding the required attribution/NOTICE file. - -## Report - -Project license, the dependency-license matrix grouped by risk tier, blocking items -called out first, and explicit "needs legal review" flags. State coverage gaps. diff --git a/.qoder/skills/lustra/reference/lint.md b/.qoder/skills/lustra/reference/lint.md deleted file mode 100644 index 3b18d99..0000000 --- a/.qoder/skills/lustra/reference/lint.md +++ /dev/null @@ -1,33 +0,0 @@ -# lint - -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. - -## Detect - -1. If an ESLint config exists, `npx -y eslint . --format json` scoped to the target. -2. If none exists, do **not** silently add one. Run with a minimal recommended config and - say the result is advisory; offer to add a real config as a separate, confirmed step. -3. Read the target for AI-slop smells no rule catches: - - Abstractions with exactly one caller; indirection that only forwards. - - `try/catch` that logs and rethrows, swallows, or re-wraps with no added meaning. - - Comments that restate the code, section-header comments, `added for X` notes, - leftover TODOs. - - Defensive checks for conditions the type system or call sites make impossible. - - Dead config keys and options wired to nothing. - -## Triage - -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely -— name the caller count, the impossible condition, the comment that adds nothing. Skip -stylistic preferences the repo's own config does not enforce. - -## Fix policy - -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. -- Propose (diff + ask): every slop-smell change — these are semantic. Match existing - style; do not reformat untouched lines. - -## Report - -Two sections: ESLint (counts + remaining manual items) and slop smells (`file:line`, -the smell, the concrete justification, the proposed change). diff --git a/.qoder/skills/lustra/reference/perf.md b/.qoder/skills/lustra/reference/perf.md deleted file mode 100644 index 6579f24..0000000 --- a/.qoder/skills/lustra/reference/perf.md +++ /dev/null @@ -1,33 +0,0 @@ -# perf - -**Purpose:** find code that is correct but wasteful — the slop that works and is slow. - -## Detect - -Static reading of the target (no synthetic benchmarking unless the user asks): - -- N+1 queries / calls in a loop, awaits serialized inside a loop that could batch. -- Synchronous or blocking IO on a hot/request path. -- Unbounded growth: loading a whole collection to use one item, missing pagination, - caches with no eviction, recursion without a bound. -- Repeated work: recomputation that could be hoisted/memoized, redundant re-renders - (framework-specific), O(n²) where O(n) is trivial. -- Bundle weight (front-end target): a heavy dependency used for one helper, a missing - dynamic import on a large rarely-used path. Use `npx -y source-map-explorer` / - bundler stats only if a build output exists. - -## Triage - -Rank by `frequency of the path × cost of the waste`. A slow startup script is not a slow -request handler. Skip micro-optimizations with no measurable impact — say so rather than -listing them. Flag only what you can name concretely (the loop, the query, the import). - -## Fix policy - -- Auto: nothing — perf changes alter behavior risk. -- Propose (diff + ask): the specific transform (batch, hoist, paginate, lazy-load), with - the reason it is faster and any correctness caveat. One change per finding. - -## Report - -Findings ranked by impact: `file:line` — the waste — the hot path it sits on — proposed fix. diff --git a/.qoder/skills/lustra/reference/prettier.md b/.qoder/skills/lustra/reference/prettier.md deleted file mode 100644 index dab8fee..0000000 --- a/.qoder/skills/lustra/reference/prettier.md +++ /dev/null @@ -1,27 +0,0 @@ -# prettier - -**Purpose:** formatting drift, fixed mechanically, with nothing else touched. - -## Detect - -1. `npx -y prettier --check` over the target. Honor any existing `.prettierrc` and - `.prettierignore`; do not create or modify them. -2. If the project has no Prettier config, run with defaults and say the result reflects - Prettier defaults, not a project standard; offer to add a config as a separate - confirmed step. - -## Triage - -There is nothing to triage — Prettier output is deterministic. Just separate files it can -reformat from files it cannot parse (report parse failures as real errors to fix at the -source, not format). - -## Fix policy - -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. -- Never hand-edit formatting or "tidy" code Prettier did not flag. - -## Report - -Count of files reformatted, list of unparseable files with their errors. diff --git a/.qoder/skills/lustra/reference/review.md b/.qoder/skills/lustra/reference/review.md deleted file mode 100644 index 632e967..0000000 --- a/.qoder/skills/lustra/reference/review.md +++ /dev/null @@ -1,36 +0,0 @@ -# review - -**Purpose:** a focused human-grade review of a change, not a tool dump. - -## Scope - -If the target is a path, review that path. Otherwise review the working diff -(`git diff` against the merge base, or staged/unstaged if not a branch). If there is no -diff and no path, ask what to review. - -## Detect - -Use the other commands' tools as inputs where they help: run `eslint`, `npm audit`, and -`knip` over the changed files and fold real findings in. Then read the change for what -tools miss: - -- Correctness: off-by-one, error paths, async/await misuse, missed `null`/empty cases. -- Edge cases the change introduces or fails to handle. -- Design: wrong abstraction level, leaky boundaries, state that should not be shared. -- Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). - -## Triage - -Three buckets: **blocking** (correctness/security), **should-fix** (design/maintainability), -**optional** (preference — mark as such, keep few). Cite `file:line` and explain *why* it -is wrong, not just that it differs from taste. - -## Fix policy - -Review proposes; it does not auto-edit. Offer to apply blocking fixes as a separate, -confirmed step after the user has read the review. - -## Report - -The three buckets, ordered, each item: `file:line` — issue — why — suggested fix. diff --git a/.qoder/skills/lustra/reference/security.md b/.qoder/skills/lustra/reference/security.md deleted file mode 100644 index 5fa5107..0000000 --- a/.qoder/skills/lustra/reference/security.md +++ /dev/null @@ -1,37 +0,0 @@ -# security - -**Purpose:** find real, exploitable security defects, not theoretical lint noise. - -## Detect - -Run, scoped to the target: - -1. `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` based on the - lockfile present). Skip with a note if there is no manifest. -2. Secret sweep with Grep over the target: private keys (`BEGIN .* PRIVATE KEY`), - AWS keys (`AKIA[0-9A-Z]{16}`), generic high-entropy assignments to names containing - `secret|token|password|apikey`, and `.env` files committed alongside code. -3. If `semgrep` is on PATH, `semgrep --config auto --json`. Do not install it. -4. Read the source in the target for: unparameterized SQL/shell built by string - concatenation, `eval`/`new Function`/`child_process` on untrusted input, missing - authorization checks on mutation handlers, unsafe deserialization, and disabled TLS - verification. - -## Triage - -Rank each finding by `severity × confidence × blast radius`. Drop tool findings that are -test fixtures, examples, or unreachable. Separate "confirmed" from "needs human judgment". -A transitive advisory with no exploit path is noted, not raised to critical. - -## Fix policy - -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. -- Propose (diff + ask): code changes for injection/authz/deserialization, any major - version bump, removing a committed secret (also state it must be rotated, not just - deleted). - -## Report - -Grouped by severity. Each: `file:line` — finding — exploit path — recommended action. -End with what was skipped and why. diff --git a/.qoder/skills/lustra/reference/structure.md b/.qoder/skills/lustra/reference/structure.md deleted file mode 100644 index acfbd50..0000000 --- a/.qoder/skills/lustra/reference/structure.md +++ /dev/null @@ -1,40 +0,0 @@ -# structure - -**Purpose:** detect the stack, judge its structure against that stack's conventions, then -either advise or reorganize — the user's choice. - -## Detect the stack - -Read manifests at the target root to identify language and framework: `package.json` -(and which framework — Next.js, etc.), `pyproject.toml`/`setup.py`, `go.mod`, -`Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. Note the build tool, -test runner, and module system. State the detected stack explicitly before judging -anything — if detection is ambiguous, ask rather than assume. - -## Assess - -Against the conventions of the *detected* stack (not a generic ideal), report: - -- Layout that fights the framework's expected structure. -- Mixed concerns: business logic in routes/controllers, god modules, circular packages. -- Inconsistent naming/casing across the same layer. -- Missing or misplaced test, config, and entry-point locations for this stack. -- Folders that exist for no reason; files in the wrong layer. - -Be concrete: name the file, the convention it violates, the expected location. - -## Then offer two paths - -Present both and let the user pick: - -- **(a) Recommendations only** — the assessment above, ranked by payoff vs. churn, no - changes made. -- **(b) Reorganize** — produce a staged plan: each step is one coherent move (relocate a - layer, split a god module, rename for consistency) with the file moves and the import - updates it forces. Execute **one step at a time, confirming each**, keeping every step - independently reviewable. Never bulk-move the tree in one shot (rule 5). After each - step, update imports your move broke and nothing else. - -## Report - -Detected stack, ranked assessment, then the chosen path's output. diff --git a/.qoder/skills/lustra/reference/tests.md b/.qoder/skills/lustra/reference/tests.md deleted file mode 100644 index 93bce7b..0000000 --- a/.qoder/skills/lustra/reference/tests.md +++ /dev/null @@ -1,31 +0,0 @@ -# tests - -**Purpose:** prove the code is actually tested — not that test files merely exist. - -## Detect - -1. Identify the runner from the manifest (jest/vitest/mocha/pytest/go test/cargo test). - Run it. If it cannot run, report that as the top finding — untestable is worse than failing. -2. Coverage **on the change**, not globally: diff against the merge base and check which - added/changed lines have no covering test. Global % hides slop. -3. Read the test files in the target for fake assurance — the AI-slop signature: - - Assertions that cannot fail (`expect(true).toBe(true)`, snapshot of a mock). - - Tests that exercise the mock, not the unit. - - `skip`/`only`/`xit` left in, empty test bodies, `assert(result)` with no expectation. - - One happy path, zero error/edge cases. - -## Triage - -Rank: failing tests > changed code with no coverage > fake/empty tests > thin coverage of -critical paths. A green suite full of fake assertions is a **red** finding, stated plainly. - -## Fix policy - -- Auto: nothing. Tests are semantic. -- Propose (diff + ask): the missing test cases (real assertions on real behavior, error - and edge paths), and removal of fake/skipped tests with the reason for each. - -## Report - -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. diff --git a/.qoder/skills/lustra/reference/types.md b/.qoder/skills/lustra/reference/types.md deleted file mode 100644 index eddcfc6..0000000 --- a/.qoder/skills/lustra/reference/types.md +++ /dev/null @@ -1,31 +0,0 @@ -# types - -**Purpose:** make the type checker pass honestly — not by silencing it. - -## Detect - -1. Run the project's type checker: `npx -y tsc --noEmit` (honor the existing `tsconfig`), - or `mypy`/`pyright`, `go vet`, `cargo check` for the detected stack. -2. Sweep the target for type-system evasion — the AI-slop signature: - - `any`, `as any`, `as unknown as`, `@ts-ignore`/`@ts-expect-error` with no reason, - `# type: ignore`, non-null `!` used to mute an error rather than express an invariant. - - `strict`/`noImplicitAny` disabled to make errors disappear. - -## Triage - -Real type errors first, ranked by how much they hide (a wrong return type beats an unused -`@ts-ignore`). Distinguish a legitimate escape hatch (documented external boundary) from -slop (a silenced error). Do not raise pre-existing config-level looseness as if the change -introduced it — note it separately. - -## Fix policy - -- Auto: nothing — narrowing a type is a semantic change. -- Propose (diff + ask): the correct type/narrowing that removes the error at the source. - Never "fix" by adding `any`, casting, or widening a signature. Never tighten global - config as a side effect of a targeted command (rule 1). - -## Report - -Type-checker errors (`file:line`, message, proposed real fix) and evasion sites -(`file:line`, what is being hidden). diff --git a/README.md b/README.md index 55a296d..1735c93 100644 --- a/README.md +++ b/README.md @@ -125,14 +125,18 @@ where available. ## Contributing -`skill/` is the **single source of truth** — `skill/SKILL.md` (the router) and -`skill/reference/*.md` (one file per command). `npm run build` compiles it into the -committed per-harness directories (`.claude/`, `.agents/`, `.cursor/`, `.gemini/`, -`.github/`) via `scripts/providers.js`. Edit `skill/`, never the generated dirs, then -rebuild and commit. `npm test` runs the smoke suite. - -Publishing: push to the public `breim/lustra` repo, `npm run build`, commit the generated -dirs, `npm publish --access public`. skills.sh discovery is automatic via the skills CLI. +`skill/` is the **single source of truth** and the only skill content tracked in git — +`skill/SKILL.md` (the router) and `skill/reference/*.md` (one file per command). Edit +`skill/`, nothing else. `npm run build` compiles it into the per-harness directories +(`.claude/`, `.agents/`, `.cursor/`, `.gemini/`, `.github/`, …) via +`scripts/providers.js`; those dirs are gitignored — local artifacts for dogfooding this +repo and for the smoke suite (`npm test` runs `build` itself). + +Publishing: push to the public `breim/lustra` repo, bump the version, and +`npm publish --access public` (`prepublishOnly` runs `build`). The npm `files` whitelist +ships only `skill/` — the generated per-harness dirs are never published. At install time +`scripts/install-skill.js` copies `skill/` into the user's selected clients; skills.sh +discovery is automatic via the skills CLI. ## License diff --git a/skill/SKILL.md b/skill/SKILL.md index d8ebf97..4df840e 100644 --- a/skill/SKILL.md +++ b/skill/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: Bash Read Edit Grep Glob Lustra wraps real code-hygiene tooling and applies judgment on top of it. It does not guess where a tool would. It runs the tool, filters false positives, ranks what matters, -and fixes only what is safe to fix automatically. +and applies only the changes the user approves. ## Dispatch @@ -54,11 +54,26 @@ These come from the project's own engineering guidelines and are not negotiable: 1. **Surgical.** Every changed line must trace to the requested command. Never "improve" adjacent code, comments, or formatting that the command did not target. -2. **No silent scope changes.** Deleting code, moving files, or removing a dependency is a - scope decision. Auto-apply only mechanically-safe fixes (formatting, an unambiguously - unused import). For anything semantic, show the diff and ask first. +2. **No silent changes — ever.** Nothing is auto-applied, not even mechanically-safe + formatting or an unambiguously unused import. Every change is presented as an itemized + checklist with its evidence/diff, and only the items the user approves are applied. 3. **Report honestly.** If a tool is missing, a step was skipped, or a finding is low-confidence, say so plainly. Do not present a partial pass as a clean one. 4. **English only**, in all output and any code or config you write. -5. **Confirm before destructive or hard-to-reverse actions.** A staged plan with explicit - confirmation, never a bulk rewrite. +5. **Confirm before any file or dependency change.** Not just destructive or + hard-to-reverse ones — every edit goes through the Confirmation flow below as a staged, + explicitly-confirmed checklist, never a bulk rewrite. + +## Confirmation flow + +The single flow every command follows (the `deadcode` pattern). Reference files do not +redefine it: + +1. Run the read-only detect/triage steps automatically — these never need confirmation. +2. Present every proposed change as an itemized checklist: the `file`/target, the exact + action (command or diff), and the evidence/reason per item. +3. Apply only the items the user approves, in one reviewable change. +4. Re-run the relevant check to confirm clean, then report what was applied, what was + skipped, and why. + +Read-only detection is exempt. Changing files or dependencies is not. diff --git a/skill/reference/libs.md b/skill/reference/libs.md index 66f7cf1..5661d2d 100644 --- a/skill/reference/libs.md +++ b/skill/reference/libs.md @@ -22,7 +22,8 @@ Group every dependency into one of: ## Fix policy -- Auto: the **Safe** batch, only with a lockfile, showing every version delta. +- Present the **Safe** group as a checklist (each package + version delta); apply only + the approved items, only with a lockfile. - Propose (diff + ask): **Review**, **Major**, **Remove**, **Replace** — one logical change per step, never a blanket bump. diff --git a/skill/reference/lint.md b/skill/reference/lint.md index 3b18d99..4bd66ab 100644 --- a/skill/reference/lint.md +++ b/skill/reference/lint.md @@ -23,7 +23,8 @@ stylistic preferences the repo's own config does not enforce. ## Fix policy -- Auto: `eslint --fix` for the autofixable set, then re-run to confirm zero regressions. +- Present the autofixable set as a checklist (rule + `file:line` per item). On approval, + run `eslint --fix` scoped to the approved files, then re-run to confirm zero regressions. - Propose (diff + ask): every slop-smell change — these are semantic. Match existing style; do not reformat untouched lines. diff --git a/skill/reference/prettier.md b/skill/reference/prettier.md index dab8fee..274c7a7 100644 --- a/skill/reference/prettier.md +++ b/skill/reference/prettier.md @@ -18,8 +18,8 @@ source, not format). ## Fix policy -- Auto: `prettier --write` on the drifted files. This is the canonical mechanically-safe - fix (rule 2). Re-run `--check` to confirm clean. +- Present the drifted files as an itemized checklist (rule 2). On approval, run + `prettier --write` on the approved subset only, then re-run `--check` to confirm clean. - Never hand-edit formatting or "tidy" code Prettier did not flag. ## Report diff --git a/skill/reference/security.md b/skill/reference/security.md index 5fa5107..3c24a59 100644 --- a/skill/reference/security.md +++ b/skill/reference/security.md @@ -25,8 +25,8 @@ A transitive advisory with no exploit path is noted, not raised to critical. ## Fix policy -- Auto: bump a vulnerable dependency only when the audit reports a non-breaking fixed - range and a lockfile exists; show the version delta. +- Present each vulnerable-dependency bump as a checklist item (package, version delta, + advisory, breaking? y/n). Apply only the approved bumps. - Propose (diff + ask): code changes for injection/authz/deserialization, any major version bump, removing a committed secret (also state it must be rotated, not just deleted).