From 72864705b9596448864316d51ae579088c3bc192 Mon Sep 17 00:00:00 2001 From: Henrique Breim Date: Sun, 17 May 2026 05:34:05 +0200 Subject: [PATCH 1/4] chore: ignore .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 60868e0..a1bdbf1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ *.tgz +.DS_Store # Generated skill targets — source of truth is skill/; regenerated by npm run build .agents/skills/lustra/ From ed17663917f13c3357635adf6dae676398d1d43d Mon Sep 17 00:00:00 2001 From: Henrique Breim Date: Sun, 17 May 2026 05:34:06 +0200 Subject: [PATCH 2/4] feat(skill): make commands stack-agnostic, rename lint/prettier/libs, add design/observability/migrate Replace hardcoded JS tooling with a shared Stack detection contract in SKILL.md plus per-ecosystem tool tables in every tool-running command. Rename lint->analyze, prettier->format, libs->deps (deps scope sharpened: deletion is deadcode, vuln remediation is security, major upgrades are migrate). Add design (paradigm-aware SOLID/cohesion), observability (logging quality), and migrate (guided major upgrade). Normalize every reference file to Purpose/Detect/Triage/Fix policy/Report; update README. --- README.md | 47 ++++++++++++++----------- bin/lustra.js | 33 +++++++++-------- skill/SKILL.md | 33 +++++++++++++---- skill/reference/{lint.md => analyze.md} | 27 +++++++++----- skill/reference/audit.md | 17 +++++---- skill/reference/ci.md | 22 +++++++++--- skill/reference/deadcode.md | 20 +++++++---- skill/reference/deps.md | 47 +++++++++++++++++++++++++ skill/reference/design.md | 38 ++++++++++++++++++++ skill/reference/format.md | 38 ++++++++++++++++++++ skill/reference/libs.md | 33 ----------------- skill/reference/license.md | 36 ++++++++++++++----- skill/reference/migrate.md | 36 +++++++++++++++++++ skill/reference/observability.md | 44 +++++++++++++++++++++++ skill/reference/perf.md | 18 +++++++--- skill/reference/prettier.md | 27 -------------- skill/reference/review.md | 23 ++++++------ skill/reference/security.md | 12 +++++-- skill/reference/structure.md | 13 +++---- skill/reference/tests.md | 21 ++++++++--- 20 files changed, 418 insertions(+), 167 deletions(-) rename skill/reference/{lint.md => analyze.md} (50%) create mode 100644 skill/reference/deps.md create mode 100644 skill/reference/design.md create mode 100644 skill/reference/format.md delete mode 100644 skill/reference/libs.md create mode 100644 skill/reference/migrate.md create mode 100644 skill/reference/observability.md delete mode 100644 skill/reference/prettier.md diff --git a/README.md b/README.md index 1735c93..de3259e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Lustra The code-hygiene skill that makes your AI harness clean up its own slop. 1 skill, -15 commands wrapping real tooling, from first commit to technical due diligence. +18 commands wrapping real tooling, from first commit to technical due diligence. > Install with `npx skills add breim/lustra`, or `npm i -g lustra-cli` for a global skill. @@ -11,14 +11,15 @@ AI writes code that runs and looks fine and is quietly wrong: dead abstractions, error handling, tests that assert nothing, dependencies nobody uses, a green pipeline that gates nothing. Linters catch a slice of it. The rest needs judgment on top of real tools. -Lustra runs the actual tooling — `npm audit`, `knip`, `eslint`, `tsc`, your test runner, -`prettier`, `license-checker` — then triages the output: filters false positives, ranks by -real risk, fixes only what is mechanically safe, and proposes the rest as a diff. It does -not guess where a tool would. It runs the tool and applies judgment. +Lustra detects your stack and runs its actual tooling — the dependency auditor, linter, +type checker, test runner, formatter, dead-code and license scanners — then triages the +output: filters false positives, ranks by real risk, fixes only what is mechanically +safe, and proposes the rest as a diff. It does not guess where a tool would. It runs the +tool and applies judgment. ## What's Included -15 commands under one skill, mapped to a project lifecycle. `audit` runs the diagnostic +18 commands under one skill, mapped to a project lifecycle. `audit` runs the diagnostic ones together for a one-shot health report. | Phase | Command | What it does | @@ -26,16 +27,19 @@ ones together for a one-shot health report. | start | `audit` | One graded health report across every dimension (due diligence) | | start | `baseline` | Scaffold the guardrail configs for the detected stack | | iterate | `review` | Structured correctness / design / slop review of a diff or path | -| iterate | `types` | Type-checker triage; catch `any`/`@ts-ignore` evasion | +| iterate | `types` | Type-checker triage; catch `any`/`@ts-ignore`-style evasion | | iterate | `tests` | Run the suite, coverage on the diff, catch fake/empty tests | -| iterate | `lint` | ESLint plus AI-slop smells no rule catches | -| iterate | `prettier`| Formatting drift, fixed mechanically | +| iterate | `analyze` | The linter's findings plus AI-slop smells no rule catches | +| iterate | `format` | Formatting drift, fixed mechanically | | polish | `security` | Exploitable defects: secrets, injection, authz, vulnerable deps | | polish | `license` | Dependency license compatibility and IP risk | | polish | `deadcode` | Unused files, exports, dependencies — confirmed before deletion | -| polish | `libs` | Dependency health: outdated, deprecated, duplicated, unused | +| polish | `deps` | Dependency health and upgrades: outdated, deprecated, duplicated | +| polish | `design` | Module/package design: SOLID, or cohesion/coupling for non-OO stacks | +| polish | `observability` | Logging and instrumentation quality so failures are diagnosable | | polish | `perf` | Performance smells: N+1, blocking IO, unbounded growth, bundle weight | | polish | `docs` | Documentation drift and undocumented public surface | +| maintain | `migrate` | Guided one-major-at-a-time dependency migration with codemods | | maintain | `ci` | Pipeline soundness: real gates, CI security, reproducibility | | maintain | `structure` | Detect the stack, then advise or reorganize project structure | @@ -50,11 +54,11 @@ maintain.** - **Start** — `audit` an inherited codebase to see what you really have; `baseline` a fresh one so it has guardrails from day one. -- **Iterate** — while building, `review` the diff, then `types`, `tests`, `lint`, - `prettier` to keep the loop honest. -- **Polish** — before shipping, harden it: `security`, `license`, `deadcode`, `libs`, - `perf`, `docs`. -- **Maintain** — over time, `ci` and `structure` keep the project from rotting. +- **Iterate** — while building, `review` the diff, then `types`, `tests`, `analyze`, + `format` to keep the loop honest. +- **Polish** — before shipping, harden it: `security`, `license`, `deadcode`, `deps`, + `design`, `observability`, `perf`, `docs`. +- **Maintain** — over time, `migrate`, `ci` and `structure` keep the project from rotting. For technical due diligence, `audit` is the answer: it runs security, license, supply chain, reliability, maintainability and bus-factor checks and grades each — without @@ -117,11 +121,14 @@ lustra build # regenerate the per-harness skill directorie ## Supported Tools -Lustra orchestrates tools you already use and stays out of the way when one is absent -(it says so rather than guessing): `npm audit`, `knip`, `eslint`, `tsc`, the project's -test runner (jest/vitest/mocha/pytest/…), `prettier`, `npm outdated`, `license-checker`, -and `semgrep` when present. Non-JS stacks are detected and handled with their own tooling -where available. +Lustra detects the stack first, then orchestrates the tools you already use for it and +stays out of the way when one is absent (it says so rather than guessing): the +dependency-vulnerability scanner (`npm audit`/`pip-audit`/`govulncheck`/`cargo audit`), +linter (ESLint/Ruff/`go vet`/Clippy), type checker (`tsc`/mypy/`go vet`/`cargo check`), +test runner (jest/vitest/pytest/`go test`/`cargo test`), formatter +(Prettier/Black/`gofmt`/`rustfmt`), dead-code and license scanners, and `semgrep` when +present. Each command's reference file carries its own per-ecosystem tool table; an +unknown stack falls back to static reading, flagged as lower-confidence. ## Contributing diff --git a/bin/lustra.js b/bin/lustra.js index 1385eb6..3802ddb 100644 --- a/bin/lustra.js +++ b/bin/lustra.js @@ -113,21 +113,24 @@ Usage: Clients: ${providers.map(p => p.provider).join(', ')} Skill commands (inside your agent): - /lustra audit One graded health report (due diligence) - /lustra baseline Scaffold guardrail configs for the stack - /lustra review Structured review of a diff or path - /lustra types Type-checker triage, catch evasion - /lustra tests Run suite, diff coverage, catch fake tests - /lustra lint ESLint + AI-slop smells - /lustra prettier Fix formatting drift - /lustra security Find exploitable security defects - /lustra license Dependency license / IP risk - /lustra deadcode Remove unused files, exports, dependencies - /lustra libs Audit dependency health - /lustra perf Performance smells - /lustra docs Documentation drift and gaps - /lustra ci Pipeline soundness - /lustra structure Detect the stack, advise or reorganize`) + /lustra audit One graded health report (due diligence) + /lustra baseline Scaffold guardrail configs for the stack + /lustra review Structured review of a diff or path + /lustra types Type-checker triage, catch evasion + /lustra tests Run suite, diff coverage, catch fake tests + /lustra analyze Linter findings + AI-slop smells + /lustra format Fix formatting drift + /lustra security Find exploitable security defects + /lustra license Dependency license / IP risk + /lustra deadcode Remove unused files, exports, dependencies + /lustra deps Dependency health and upgrades + /lustra design Design quality: SOLID / cohesion / coupling + /lustra observability Logging and instrumentation quality + /lustra perf Performance smells + /lustra docs Documentation drift and gaps + /lustra migrate Guided one-major dependency migration + /lustra ci Pipeline soundness + /lustra structure Detect the stack, advise or reorganize`) } } diff --git a/skill/SKILL.md b/skill/SKILL.md index 4df840e..fdf357b 100644 --- a/skill/SKILL.md +++ b/skill/SKILL.md @@ -1,8 +1,8 @@ --- 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." +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 formatters, evaluate design principles (SOLID and the cohesion/coupling equivalents for non-OO stacks), audit logging and observability, find performance smells, check documentation and CI health, scaffold baseline configs for the detected stack, do a structured code review, guide a one-major-at-a-time dependency migration, 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 the design, check logging, is this slow, migrate a dependency, fix the project structure, set up the project, audit everything, due diligence, or this looks like AI slop. Wraps the detected stack's real tooling — dependency auditor, linter, type checker, test runner, formatter, dead-code and license scanners — and triages its 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]" +argument-hint: "[audit|baseline|review|types|tests|analyze|format|security|license|deadcode|deps|design|observability|perf|docs|migrate|ci|structure] [target]" allowed-tools: Bash Read Edit Grep Glob --- @@ -31,20 +31,25 @@ Grouped by lifecycle phase. `audit` runs the diagnostic ones together. **Iterate** - `review` — structured correctness / design / slop review of a diff or path. -- `types` — type-checker triage; catch `any`/`@ts-ignore` evasion. +- `types` — type-checker triage; catch `any`/`@ts-ignore`-style 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. +- `analyze` — the linter's findings plus AI-slop smells that no rule catches. +- `format` — formatting drift, fixed mechanically. **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. +- `deadcode` — unused files, exports, and dependencies; deletes only what is confirmed. +- `deps` — dependency health and upgrades: outdated, deprecated, duplicated. Reports + unused deps and advisories but defers deletion to `deadcode` and vuln fixes to `security`. +- `design` — module/package design quality: SOLID, or cohesion/coupling/composition for + non-OO stacks. Module-scoped, unlike diff-scoped `review` or layout-scoped `structure`. +- `observability` — logging and instrumentation quality so failures are diagnosable. - `perf` — performance smells: N+1, blocking IO, unbounded growth, bundle weight. - `docs` — documentation drift and undocumented public surface. **Maintain** +- `migrate` — guided one-major-at-a-time dependency migration: changelog, codemods, suite. - `ci` — pipeline soundness: real gates, CI security, reproducibility. - `structure` — detect the stack, then report or reorganize project structure. @@ -77,3 +82,17 @@ redefine it: skipped, and why. Read-only detection is exempt. Changing files or dependencies is not. + +## Stack detection + +Every command that runs a tool first identifies the stack. Reference files point here and +do not redefine this: + +1. Read the manifests at the target root to identify language and framework: + `package.json` (and the framework), `pyproject.toml`/`setup.py`, `go.mod`, + `Cargo.toml`, `pom.xml`/`build.gradle`, `Gemfile`, `composer.json`. +2. State the detected stack explicitly before running anything. If detection is ambiguous + or the repo is polyglot, ask rather than assume. +3. Pick the tool from the reference file's per-ecosystem table. If no tool exists for the + detected stack, say so and fall back to static reading — mark that result + lower-confidence. Never run a stack's tool against a project that is not that stack. diff --git a/skill/reference/lint.md b/skill/reference/analyze.md similarity index 50% rename from skill/reference/lint.md rename to skill/reference/analyze.md index 4bd66ab..8f89dc2 100644 --- a/skill/reference/lint.md +++ b/skill/reference/analyze.md @@ -1,12 +1,22 @@ -# lint +# analyze -**Purpose:** the linter's findings, plus the slop a linter structurally cannot see. +**Purpose:** the linter / static analyzer'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. +Detect the stack (SKILL.md § Stack detection), then run its linter scoped to the target: + +| Stack | Linter | +| --- | --- | +| JS/TS | `npx -y eslint . --format json` | +| Python | `ruff check --output-format json` (or `flake8`/`pylint`) | +| Go | `go vet ./...` and `staticcheck ./...` if present | +| Rust | `cargo clippy --message-format json` | + +1. If a linter config exists for the stack, use it. +2. If none exists, do **not** silently add one. Run with the tool's recommended config, + say the result is advisory, and 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. @@ -17,18 +27,19 @@ ## Triage -ESLint errors before warnings. For slop smells, only raise ones you can justify concretely +Linter 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 - 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. + run the linter's autofix scoped to the approved files, then re-run to confirm zero + regressions. Confirmation flow per SKILL.md. - 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`, +Two sections: linter (counts + remaining manual items) and slop smells (`file:line`, the smell, the concrete justification, the proposed change). diff --git a/skill/reference/audit.md b/skill/reference/audit.md index 1d933d3..e204ebb 100644 --- a/skill/reference/audit.md +++ b/skill/reference/audit.md @@ -4,22 +4,25 @@ dimension — the answer to "I inherited this code, what's here?" and to "is everything in order?" (technical due diligence). -## Run +## Detect 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` +2. **Supply chain:** `deps` 3. **Reliability:** `types`, `tests` -4. **Maintainability:** `deadcode`, `lint`, `review`, `perf` -5. **Bus factor / ops:** `structure`, `docs`, `ci` +4. **Maintainability:** `deadcode`, `analyze`, `review`, `design`, `perf` +5. **Bus factor / ops:** `structure`, `docs`, `observability`, `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. +and record the skip explicitly — a gap is a due-diligence finding, not a blank. If a +dimension errors or times out, record it as Skipped with the reason and continue; a +partial audit is reported as partial, never as a pass. -`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. +`baseline` and `migrate` are **not** part of audit (they are generative, not +diagnostic). If `baseline` would have lots to do, note "no project guardrails" under +maintainability instead. ## Triage diff --git a/skill/reference/ci.md b/skill/reference/ci.md index 501f24b..b6d9673 100644 --- a/skill/reference/ci.md +++ b/skill/reference/ci.md @@ -10,7 +10,8 @@ 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`). + no deterministic lockfile install (the stack's frozen-install mode, e.g. `npm ci`, + `pip install --require-hashes`, `go mod download` + verify, `cargo build --locked`). 4. Reproducibility: pinned toolchain versions, cache keyed correctly, deterministic install from the lockfile. @@ -23,10 +24,21 @@ 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. +- Present the fixes as an itemized checklist, one concern per item: the specific workflow + edit (add the failing gate, pin the action, scope `permissions`, switch to a frozen + install) with the risk it closes. Apply only approved items; Confirmation flow per + SKILL.md. ## Report -Pipeline inventory, gate analysis (what is enforced vs. claimed), security/reproducibility -findings — each with the proposed config change. +``` +CI — + +Pipeline inventory: + +Gate analysis + enforced|claimed-only|absent + +Security/reproducibility + - — proposed config change +``` diff --git a/skill/reference/deadcode.md b/skill/reference/deadcode.md index 2824092..e0dcd5c 100644 --- a/skill/reference/deadcode.md +++ b/skill/reference/deadcode.md @@ -4,15 +4,23 @@ ## 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. +Detect the stack (SKILL.md § Stack detection), then run its dead-code tool scoped to the +target: + +| Stack | Tool | +| --- | --- | +| JS/TS | `npx -y knip --reporter json` (honor an existing `knip.json`; do not overwrite) | +| Python | `vulture` (or `ruff check --select F401,F811`) | +| Go | `staticcheck ./...` (unused) and `go vet ./...` | +| Rust | `cargo +nightly udeps` if present; otherwise compiler `dead_code` warnings | + +If no tool exists for the stack, fall back to building the import graph for the target +with Grep/Glob and flagging 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: +these tools over-report 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. diff --git a/skill/reference/deps.md b/skill/reference/deps.md new file mode 100644 index 0000000..a2b9116 --- /dev/null +++ b/skill/reference/deps.md @@ -0,0 +1,47 @@ +# deps + +**Purpose:** a clear, risk-ranked picture of dependency **health and upgrades** — +outdated, deprecated, duplicated. This command reports; it does not own the fixes that +belong elsewhere: unused-dependency *deletion* is `deadcode`, vulnerability *remediation* +is `security`, and executing a major upgrade is `migrate`. `deps` flags those and hands +off; it only applies safe patch/minor bumps itself. + +## Detect + +Detect the stack (SKILL.md § Stack detection), then run its dependency tools: + +| Stack | Outdated | Advisories | +| --- | --- | --- | +| Node | `npm outdated --json` (or the pnpm/yarn equivalent for the lockfile) | `npm audit --json` | +| Python | `pip list --outdated --format json` (or `uv pip list --outdated`) | `pip-audit` | +| Go | `go list -u -m -json all` | `govulncheck ./...` | +| Rust | `cargo outdated` | `cargo audit` | + +If no tool exists for the stack, read the manifest/lockfile directly and say the result +is partial. Then inspect the manifest for deprecated packages (the package manager marks +these), 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; report it and recommend `migrate` (one at a time). +- **Unused** — report only; `deadcode` owns the deletion decision. +- **Replace** — deprecated or duplicated; name the recommended successor. + +Advisories are surfaced with their severity but are `security`'s call to remediate — note +them, do not bump them here unless the bump is also a Safe one. + +## Fix policy + +- Present the **Safe** group as a checklist (each package + version delta); apply only + the approved items, only with a lockfile. Confirmation flow per SKILL.md. +- Everything else is report-and-hand-off, not edited here: Review/Replace as a proposal, + Major → `migrate`, Unused → `deadcode`, advisories → `security`. + +## Report + +The five groups above. For majors, link/quote the relevant changelog breaking changes and +point to `migrate`. End with skipped items and the command that owns each handoff. diff --git a/skill/reference/design.md b/skill/reference/design.md new file mode 100644 index 0000000..ae4dc5e --- /dev/null +++ b/skill/reference/design.md @@ -0,0 +1,38 @@ +# design + +**Purpose:** the logical design quality of a module or package — not a diff (`review`), +not file/folder layout (`structure`). Paradigm-aware: SOLID framing for OO codebases; +cohesion/coupling/composition framing for Go, Rust, and functional ones. + +## Detect + +Detect the stack (SKILL.md § Stack detection) and pick the lens: + +- **OO (Java/C#/TS classes/Python classes):** single responsibility, open/closed, Liskov + substitutability, interface segregation, dependency inversion. +- **Non-OO (Go/Rust/functional/procedural):** module cohesion, afferent/efferent + coupling, composition over inheritance, dependency *direction* (do stable modules depend + on volatile ones?), package boundaries and what leaks across them. + +Read the target's public surface, its dependency graph, and the size/shape of its units. +Flag, with the symbol named: god objects/functions, leaky or one-caller abstractions, +import cycles, inverted dependency direction, an interface no caller needs in full, +shared mutable state across boundaries. + +## Triage + +Rank by `blast radius × how entrenched it is`. Three buckets: **blocking** (architectural +rot that will compound), **should-fix** (real but contained), **optional** (defensible +taste — keep few). Name the principle, not a vibe; if the design is sound, say so plainly +rather than inventing findings. + +## Fix policy + +- Auto: nothing — design changes are structural and semantic. +- Propose (diff + ask): the specific refactor and the principle it restores, one change + per finding, never a sweeping rewrite. Confirmation flow per SKILL.md. + +## Report + +Findings ranked by bucket, each: `target` — principle violated — why it bites — proposed +refactor. State the lens used (SOLID vs. cohesion/coupling) and why. diff --git a/skill/reference/format.md b/skill/reference/format.md new file mode 100644 index 0000000..d2668ed --- /dev/null +++ b/skill/reference/format.md @@ -0,0 +1,38 @@ +# format + +**Purpose:** formatting drift, fixed mechanically, with nothing else touched. + +## Detect + +Detect the stack (SKILL.md § Stack detection), then run its formatter in check mode: + +| Stack | Formatter (check) | Write | +| --- | --- | --- | +| JS/TS | `npx -y prettier --check` | `prettier --write` | +| Python | `ruff format --check` (or `black --check`) | `ruff format` / `black` | +| Go | `gofmt -l` | `gofmt -w` | +| Rust | `cargo fmt --check` | `cargo fmt` | + +1. Honor any existing formatter config (`.prettierrc`/`.prettierignore`, `pyproject.toml`, + etc.); do not create or modify it. +2. If the project has no formatter config, run with the tool's defaults and say the result + reflects tool defaults, not a project standard; offer to add a config as a separate + confirmed step. + +## Triage + +Output is deterministic, so there is nothing to rank. Split the result into two sets: +files the formatter can rewrite, and files it cannot parse. A parse failure is a real +error to fix at the source — never "format away" by hand. + +## Fix policy + +- Present the drifted files as an itemized checklist. On approval, run the formatter's + write mode on the approved subset only, then re-run check mode to confirm clean. + Confirmation flow per SKILL.md. +- Never hand-edit formatting or "tidy" code the formatter did not flag. + +## Report + +Count of files reformatted (and which), then the unparseable files each with `file:line` +and the parser error — listed as fix-at-source items, not formatting. diff --git a/skill/reference/libs.md b/skill/reference/libs.md deleted file mode 100644 index 5661d2d..0000000 --- a/skill/reference/libs.md +++ /dev/null @@ -1,33 +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 - -- 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. - -## Report - -The five groups above. For majors, link/quote the relevant changelog breaking changes. -End with skipped items and why. diff --git a/skill/reference/license.md b/skill/reference/license.md index b63b4f8..d6ff830 100644 --- a/skill/reference/license.md +++ b/skill/reference/license.md @@ -7,10 +7,15 @@ project's own license at risk. 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. +2. Enumerate dependency licenses (including transitive) with the stack's tool (SKILL.md + § Stack detection). If none is present, read manifests and state the result is partial: + + | Stack | Tool | + | --- | --- | + | JS/TS | `npx -y license-checker --json` (or the pnpm/yarn equivalent) | + | Python | `pip-licenses --format=json` | + | Go | `go-licenses report ./...` | + | Rust | `cargo about generate` (or `cargo-license`) | 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). @@ -26,10 +31,25 @@ 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. +- Present remediable items as an itemized checklist — per item: the package, its license, + the risk, and the proposed action (replace with a named compatibly-licensed equivalent, + or add the required attribution/NOTICE entry). Apply only approved items; Confirmation + flow per SKILL.md. Blocking legal-exposure items are flagged for counsel, not "fixed". ## 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. +``` +License — + +Project license: + +Blocking + - — needs legal review + +Matrix (grouped by risk tier) + Copyleft/risk runtime|dev + Attribution ... + Clear permissive-on-permissive + +Coverage gaps: +``` diff --git a/skill/reference/migrate.md b/skill/reference/migrate.md new file mode 100644 index 0000000..64a910c --- /dev/null +++ b/skill/reference/migrate.md @@ -0,0 +1,36 @@ +# migrate + +**Purpose:** execute one major dependency upgrade, isolated and verified. `deps` only +reports health and batches safe bumps; `migrate` does the risky part — read the breaking +notes, apply codemods, run the suite, keep the change isolated. + +## Detect + +One major per invocation, never chained. Take the target dependency from the argument or +from `deps`'s **Major** group. Detect the stack (SKILL.md § Stack detection), then: + +1. Read the changelog / release notes / migration guide for the exact version delta — + quote the breaking items, do not summarize from memory. +2. Find whether an official codemod exists for this upgrade. +3. Inventory affected call sites with Grep over the changed API surface. + +## Triage + +Classify each breaking change: **mechanical** (a codemod handles it), **manual** (needs a +human decision per call site), **behavioral-risky** (compiles but changes runtime +behavior — the dangerous class). Order the work so the test suite can attribute any +failure to this upgrade alone. + +## Fix policy + +rule 5 applies hardest — this changes a dependency and many call sites. Present the plan +first: the single dependency, the version delta, the breaking items, the call-site list, +and the codemod command(s). On approval apply as **one isolated change** — no unrelated +bumps, no opportunistic edits — then run the test suite and report. Confirmation flow per +SKILL.md. + +## Report + +Dependency + version delta, breaking changes addressed (and how), call sites changed, +codemods applied, suite result, and the manual follow-up that still remains. If the suite +fails, say so with the output — do not present a half-done migration as complete. diff --git a/skill/reference/observability.md b/skill/reference/observability.md new file mode 100644 index 0000000..30e55ab --- /dev/null +++ b/skill/reference/observability.md @@ -0,0 +1,44 @@ +# observability + +**Purpose:** logging and instrumentation good enough that a production failure is +diagnosable from the outside, not a guess. + +## Detect + +Detect the stack (SKILL.md § Stack detection), then locate its logging surface: + +| Stack | Typical loggers | +| --- | --- | +| JS/TS | `console`, pino, winston, bunyan | +| Python | `logging`, structlog, loguru | +| Go | `log`, `slog`, zap, zerolog | +| Rust | `log`, `tracing`, env_logger | + +Read the target for: + +- Ad-hoc logging (`console.log`/`print`) where a structured logger is the convention. +- Missing or inconsistent log levels; everything at one level. +- Errors logged without context (no cause, no stack, no correlating id). +- Secrets or PII in log lines (tokens, passwords, emails, full request bodies). +- Swallowed errors: empty catch, catch-and-continue with no log, errors converted to a + bare boolean. +- Critical paths with no instrumentation: request handlers, background jobs, external + calls, and retries with no metric, span, or log. + +## Triage + +Rank: swallowed errors / secrets in logs > errors with no context > inconsistent +levels/structure > absent metrics or tracing on hot paths > cosmetic. Separate confirmed +from needs-human-judgment. A log line that leaks a secret is **blocking** — say so. + +## Fix policy + +- Auto: nothing — logging changes are semantic. +- Propose (diff + ask): add the missing context, redact the secret, log-and-rethrow the + swallowed error, add the level or span — one change per finding. Confirmation flow per + SKILL.md. + +## Report + +Findings ranked, each: `file:line` — the issue — the operational impact (what an on-call +engineer cannot see because of it) — proposed fix. End with what was skipped and why. diff --git a/skill/reference/perf.md b/skill/reference/perf.md index 6579f24..a413eb3 100644 --- a/skill/reference/perf.md +++ b/skill/reference/perf.md @@ -12,9 +12,16 @@ Static reading of the target (no synthetic benchmarking unless the user asks): 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. +- Bundle weight (front-end stacks only, and only if a build output exists): a heavy + dependency used for one helper, a missing dynamic import on a large rarely-used path. + +| Stack | Bundle inspector | +| --- | --- | +| Webpack | `webpack-bundle-analyzer` on existing stats | +| Vite/Rollup | `rollup-plugin-visualizer` output | +| Any with source maps | `npx -y source-map-explorer` | + +Skip this step entirely for non-front-end stacks and say so. ## Triage @@ -25,8 +32,9 @@ listing them. Flag only what you can name concretely (the loop, the query, the i ## 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. +- Present the transforms as an itemized checklist, one per finding: the specific change + (batch, hoist, paginate, lazy-load), why it is faster, and any correctness caveat. + Apply only approved items; Confirmation flow per SKILL.md. ## Report diff --git a/skill/reference/prettier.md b/skill/reference/prettier.md deleted file mode 100644 index 274c7a7..0000000 --- a/skill/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 - -- 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 - -Count of files reformatted, list of unparseable files with their errors. diff --git a/skill/reference/review.md b/skill/reference/review.md index 632e967..1230098 100644 --- a/skill/reference/review.md +++ b/skill/reference/review.md @@ -2,23 +2,23 @@ **Purpose:** a focused human-grade review of a change, not a tool dump. -## Scope +## Detect -If the target is a path, review that path. Otherwise review the working diff +Scope first: 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: +Use the other commands' tools as inputs where they help: run the detected stack's linter, +dependency auditor, and dead-code detector (as `analyze`, `security`, and `deadcode` +would for that stack — see SKILL.md § Stack detection) 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. +- Design: wrong abstraction level, leaky boundaries, state that should not be shared + (deep module design is `design`'s job — flag, don't audit it here). - Slop: invented APIs, plausible-but-wrong library usage, over-engineering, fake - robustness (see `lint.md` smells). + robustness (see `analyze.md` smells). ## Triage @@ -28,8 +28,9 @@ 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. +Review proposes; it does not auto-edit. After the user has read the review, offer the +blocking fixes as an itemized checklist (one per finding, with its diff) and apply only +the approved items — Confirmation flow per SKILL.md. should-fix/optional stay as proposals. ## Report diff --git a/skill/reference/security.md b/skill/reference/security.md index 3c24a59..a55f92c 100644 --- a/skill/reference/security.md +++ b/skill/reference/security.md @@ -4,10 +4,16 @@ ## Detect -Run, scoped to the target: +Detect the stack (SKILL.md § Stack detection). 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. +1. The stack's dependency-vulnerability scanner. Skip with a note if there is no manifest: + + | Stack | Scanner | + | --- | --- | + | Node | `npm audit --json` (or `pnpm audit --json` / `yarn npm audit --json` per lockfile) | + | Python | `pip-audit --format json` | + | Go | `govulncheck ./...` | + | Rust | `cargo audit --json` | 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. diff --git a/skill/reference/structure.md b/skill/reference/structure.md index acfbd50..5b07304 100644 --- a/skill/reference/structure.md +++ b/skill/reference/structure.md @@ -3,15 +3,12 @@ **Purpose:** detect the stack, judge its structure against that stack's conventions, then either advise or reorganize — the user's choice. -## Detect the stack +## Detect -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. +Detect the stack (SKILL.md § Stack detection). Additionally note the build tool, test +runner, and module system, since structure is judged against *that* stack's conventions. -## Assess +## Triage Against the conventions of the *detected* stack (not a generic ideal), report: @@ -23,7 +20,7 @@ Against the conventions of the *detected* stack (not a generic ideal), report: Be concrete: name the file, the convention it violates, the expected location. -## Then offer two paths +## Fix policy Present both and let the user pick: diff --git a/skill/reference/tests.md b/skill/reference/tests.md index 93bce7b..dd42cbb 100644 --- a/skill/reference/tests.md +++ b/skill/reference/tests.md @@ -22,10 +22,23 @@ critical paths. A green suite full of fake assertions is a **red** finding, stat ## 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. +- Present an itemized checklist: each proposed new test case (target file, the behavior + it asserts, error/edge path covered) and each fake/skipped test to remove with its + reason. Apply only approved items; Confirmation flow per SKILL.md. ## Report -Suite status, uncovered changed lines (`file:line`), fake/skipped tests with evidence, -then the proposed test additions ranked by risk. +``` +Tests — + +Suite: pass|fail|cannot-run + +Uncovered changed lines + + +Fake/skipped + + +Proposed additions (ranked by risk) + +``` From 29818d219aa5e5d3a6f33f553fb4fe077a7780a8 Mon Sep 17 00:00:00 2001 From: Henrique Breim Date: Sun, 17 May 2026 05:34:08 +0200 Subject: [PATCH 3/4] test(build): isolate generated provider dirs from the working tree Add LUSTRA_BUILD_ROOT override so builds under test target a tmpdir instead of polluting the repo. Add a contract test that fails if tool-running commands regress to JS-only. --- scripts/build.js | 3 ++- test/smoke.test.js | 51 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index eb051f4..adbbb79 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -4,6 +4,7 @@ const providers = require('./providers') const root = path.join(__dirname, '..') const source = path.join(root, 'skill') +const outRoot = process.env.LUSTRA_BUILD_ROOT || root if (!fs.existsSync(path.join(source, 'SKILL.md'))) { console.error('skill/SKILL.md not found — nothing to build') @@ -11,7 +12,7 @@ if (!fs.existsSync(path.join(source, 'SKILL.md'))) { } for (const { configDir, displayName } of providers) { - const dest = path.join(root, configDir, 'skills', 'lustra') + const dest = path.join(outRoot, configDir, 'skills', 'lustra') fs.rmSync(dest, { recursive: true, force: true }) fs.mkdirSync(dest, { recursive: true }) fs.cpSync(source, dest, { recursive: true }) diff --git a/test/smoke.test.js b/test/smoke.test.js index a39f7b1..fd5cfd6 100644 --- a/test/smoke.test.js +++ b/test/smoke.test.js @@ -26,9 +26,13 @@ function runNode(file, args, env) { } test('build produces SKILL.md + every reference file for each provider', () => { - execFileSync('node', [path.join(root, 'scripts', 'build.js')], { cwd: root }) + const out = tmpHome('lustra-build-') + execFileSync('node', [path.join(root, 'scripts', 'build.js')], { + cwd: root, + env: { ...process.env, LUSTRA_BUILD_ROOT: out } + }) for (const { configDir } of providers) { - const dir = path.join(root, configDir, 'skills', 'lustra') + const dir = path.join(out, configDir, 'skills', 'lustra') assert.ok( fs.existsSync(path.join(dir, 'SKILL.md')), `${configDir} SKILL.md` @@ -114,10 +118,11 @@ test('lustra install --all installs every provider; unknown client fails', () => }) test('lustra build via CLI regenerates every provider dir', () => { - runNode(bin, ['build'], {}) + const out = tmpHome('lustra-cli-build-') + runNode(bin, ['build'], { LUSTRA_BUILD_ROOT: out }) for (const { configDir } of providers) { assert.ok( - fs.existsSync(path.join(root, configDir, 'skills', 'lustra', 'SKILL.md')), + fs.existsSync(path.join(out, configDir, 'skills', 'lustra', 'SKILL.md')), configDir ) } @@ -153,3 +158,41 @@ test('lustra help lists every command and client', () => { .map(f => f.replace(/\.md$/, '')) for (const cmd of commands) assert.match(out, new RegExp(`/lustra ${cmd}\\b`)) }) + +test('tool-running commands stay stack-agnostic (no regression to JS-only)', () => { + const skill = path.join(root, 'skill') + const skillMd = fs.readFileSync(path.join(skill, 'SKILL.md'), 'utf8') + assert.match( + skillMd, + /## Stack detection/, + 'SKILL.md must define the shared Stack detection contract' + ) + + const toolCommands = [ + 'analyze', + 'format', + 'deps', + 'deadcode', + 'security', + 'license' + ] + for (const cmd of toolCommands) { + const md = fs.readFileSync( + path.join(skill, 'reference', `${cmd}.md`), + 'utf8' + ) + assert.match( + md, + /Stack detection/, + `${cmd}.md must reference Stack detection` + ) + assert.match(md, /\|\s*-+\s*\|/, `${cmd}.md must carry a tool table`) + for (const stack of ['Python', 'Go', 'Rust']) { + assert.match( + md, + new RegExp(`\\b${stack}\\b`), + `${cmd}.md must cover ${stack}, not just JS` + ) + } + } +}) From 3c26f2da7267ceb9a544b632d37625b75c4769ca Mon Sep 17 00:00:00 2001 From: Henrique Breim Date: Sun, 17 May 2026 05:34:09 +0200 Subject: [PATCH 4/4] chore(release): 0.1.2 --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ package-lock.json | 8 ++++---- package.json | 4 ++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36cbd3d..31834ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,38 @@ All notable changes to this project are documented in this file. The format is b [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.2] - 2026-05-17 + +### Added + +- `design` command: paradigm-aware module/package design review — SOLID for OO stacks, + cohesion/coupling/composition for Go, Rust, and functional ones. Module-scoped, distinct + from diff-scoped `review` and layout-scoped `structure`. +- `observability` command: logging and instrumentation quality — swallowed errors, + secrets/PII in logs, missing error context, absent metrics on critical paths. +- `migrate` command: guided one-major-at-a-time dependency migration with changelog + reading, codemods, and isolated verification. +- `SKILL.md` gains a shared Stack detection section; reference files point to it instead + of assuming a Node project. +- `LUSTRA_BUILD_ROOT` override in `scripts/build.js` to direct generated provider + directories elsewhere. + +### Changed + +- Renamed `lint` → `analyze`, `prettier` → `format`, `libs` → `deps` (the last with a + sharpened scope: health and upgrades only — deletion is `deadcode`, vulnerability + remediation is `security`, major upgrades are `migrate`). +- Decoupled the skill from the JS/npm ecosystem: every tool-running command now carries a + per-ecosystem tool table (Node/Python/Go/Rust) with an explicit fallback, instead of + hardcoding `eslint`/`prettier`/`npm`/`knip`. Now 18 commands. +- Normalized every reference file to the same structure (Purpose / Detect / Triage / + Fix policy / Report) and updated `README.md`, `SKILL.md`, and the package description. + +### Fixed + +- Smoke tests no longer write provider directories into the repository working tree; + builds under test target a temporary directory. + ## [0.1.1] - 2026-05-17 ### Changed diff --git a/package-lock.json b/package-lock.json index f11caa5..f337a4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "lustra", - "version": "0.1.1", + "name": "lustra-cli", + "version": "0.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "lustra", - "version": "0.1.1", + "name": "lustra-cli", + "version": "0.1.2", "hasInstallScript": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index 7302f97..572a4ab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "lustra-cli", - "version": "0.1.1", - "description": "Code-hygiene skill for AI coding agents: clean AI slop, find security flaws, dead code, dependency rot, lint, format, review, and project structure.", + "version": "0.1.2", + "description": "Stack-agnostic code-hygiene skill for AI coding agents: clean AI slop, find security flaws, dead code, dependency rot, design and logging issues; lint, format, type-check, test, review, migrate dependencies, and fix project structure.", "license": "MIT", "author": "Henrique Breim ", "repository": {