feat: modernize
This commit is contained in:
292
docs/reviews/2026-03-21-repo-lib-audit.md
Normal file
292
docs/reviews/2026-03-21-repo-lib-audit.md
Normal file
@@ -0,0 +1,292 @@
|
||||
# Repo-Lib Audit
|
||||
|
||||
Date: 2026-03-21
|
||||
|
||||
## Direct Answers
|
||||
|
||||
### 1. Does it work today?
|
||||
|
||||
Partially.
|
||||
|
||||
- `nix flake show --all-systems` succeeds from the repo root.
|
||||
- Before this audit, `nix flake check` failed because the old shell-based release test harness relied on a brittle regex over `nix derivation show` internals instead of asserting against stable JSON structure.
|
||||
- `mkRepo`, the template flake, the dev shell, and the formatter/check outputs all evaluate. The primary failure was test-harness fragility, not a clear functional break in the library itself.
|
||||
- The release path still carries real operational risk because [`packages/release/release.sh`](../../../packages/release/release.sh) combines mutation, formatting, commit, tag, and push in one command and uses destructive rollback.
|
||||
|
||||
### 2. Is the code organization maintainable?
|
||||
|
||||
Not in its current shape.
|
||||
|
||||
- [`packages/repo-lib/lib.nix`](../../../packages/repo-lib/lib.nix) is a single 879-line module that owns unrelated concerns:
|
||||
- tool schema normalization
|
||||
- hook/check config synthesis
|
||||
- shell banner generation
|
||||
- release step normalization
|
||||
- public API assembly
|
||||
- [`packages/repo-lib/shell-hook.sh`](../../../packages/repo-lib/shell-hook.sh) is not just presentation. It contains tool probing, parsing, error handling, and shell-failure behavior.
|
||||
- `mkDevShell` and `mkRepo` overlap conceptually and preserve legacy paths that make the main implementation harder to reason about.
|
||||
|
||||
### 3. Is the public API readable and usable for consumers?
|
||||
|
||||
Usable, but underspecified and harder to learn than the README suggests.
|
||||
|
||||
- [`README.md`](../../../README.md) presents `mkRepo` as a compact abstraction, but the real behavior is distributed across `lib.nix`, `shell-hook.sh`, generated Lefthook config, and the release script.
|
||||
- The boundaries between `config`, `perSystem`, `checks`, `lefthook`, `shell`, `tools`, and `release` are not obvious from the docs alone.
|
||||
- Raw `config.lefthook` / `perSystem.lefthook` passthrough is effectively required for advanced use, which means the higher-level `checks` abstraction is incomplete.
|
||||
|
||||
### 4. Which parts should be kept, split, or replaced?
|
||||
|
||||
Keep:
|
||||
|
||||
- the high-level `mkRepo` consumer entrypoint, if compatibility matters
|
||||
- the template
|
||||
- the structured release-step idea
|
||||
|
||||
Split:
|
||||
|
||||
- release tooling from repo shell/hook wiring
|
||||
- shell banner rendering from shell/package assembly
|
||||
- hook/check generation from the rest of `mkRepo`
|
||||
|
||||
Replace:
|
||||
|
||||
- custom flake output composition with `flake-parts`
|
||||
- custom hook glue with `lefthook.nix`
|
||||
- keep `treefmt-nix` as the formatting layer rather than wrapping it deeper
|
||||
|
||||
### 5. What is the lowest-complexity target architecture?
|
||||
|
||||
Option A: keep `repo-lib.lib.mkRepo` as a thin compatibility wrapper, but rebase its internals on established components:
|
||||
|
||||
- `flake-parts` for flake structure and `perSystem`
|
||||
- `treefmt-nix` for formatting
|
||||
- `lefthook.nix` for hooks
|
||||
- a separate `mkRelease` package for release automation, with explicit opt-ins for commit/tag/push
|
||||
|
||||
That preserves migration cost for consumers while removing most of the custom orchestration burden from this repo.
|
||||
|
||||
## Correctness Findings
|
||||
|
||||
### High: self-checks were failing because the test harness depended on unstable derivation internals
|
||||
|
||||
Files:
|
||||
|
||||
- the removed shell-based release test harness
|
||||
|
||||
Details:
|
||||
|
||||
- The repo did not pass `nix flake check` on the host system before this audit because the tests around `lefthook-check` assumed `nix derivation show` would expose `"/nix/store/...-lefthook.yml.drv"` as a quoted string.
|
||||
- Current Nix emits input derivations in a different JSON shape, so the regex broke even though the underlying derivation still existed.
|
||||
- This is a release blocker because the repo’s own baseline was red.
|
||||
|
||||
Assessment:
|
||||
|
||||
- Fixed in this audit by replacing the ad hoc scrape with a helper that locates the relevant input derivation from the JSON more defensibly.
|
||||
|
||||
### High: release rollback is destructive
|
||||
|
||||
Files:
|
||||
|
||||
- [`packages/release/release.sh`](../../../packages/release/release.sh)
|
||||
|
||||
Details:
|
||||
|
||||
- `revert_on_failure` runs `git reset --hard "$START_HEAD"` after any trapped error.
|
||||
- That will discard all working tree changes created during the release flow, including user-visible file changes that might be useful for debugging or manual recovery.
|
||||
|
||||
Assessment:
|
||||
|
||||
- This is too aggressive for a library-provided command.
|
||||
- Rollback should be opt-in, staged to a temp branch/worktree, or replaced with a safer failure mode that leaves artifacts visible.
|
||||
|
||||
### Medium: release performs too many side effects in one irreversible flow
|
||||
|
||||
Files:
|
||||
|
||||
- [`packages/release/release.sh`](../../../packages/release/release.sh)
|
||||
|
||||
Details:
|
||||
|
||||
- The default flow updates version state, runs release steps, formats, stages, commits, tags, and pushes.
|
||||
- There is no dry-run mode.
|
||||
- There is no `--no-push`, `--no-tag`, or `--no-commit` mode.
|
||||
- The command is framed as a package generated by the library, so consumers inherit a strong opinionated workflow whether they want it or not.
|
||||
|
||||
Assessment:
|
||||
|
||||
- Release should be separated from repo shell wiring and broken into explicit phases or flags.
|
||||
|
||||
## Organization And Readability Findings
|
||||
|
||||
### High: `lib.nix` is a monolith
|
||||
|
||||
Files:
|
||||
|
||||
- [`packages/repo-lib/lib.nix`](../../../packages/repo-lib/lib.nix)
|
||||
|
||||
Details:
|
||||
|
||||
- One file owns normalization helpers, shell assembly, banner formatting inputs, Lefthook synthesis, release templating, compatibility APIs, and top-level outputs.
|
||||
- The public API is therefore not separable from its implementation detail.
|
||||
|
||||
Assessment:
|
||||
|
||||
- This is the main maintainability problem in the repo.
|
||||
- Even if behavior is mostly correct, the cost of safely changing it is too high.
|
||||
|
||||
### Medium: shell UX logic is coupled to operational behavior
|
||||
|
||||
Files:
|
||||
|
||||
- [`packages/repo-lib/shell-hook.sh`](../../../packages/repo-lib/shell-hook.sh)
|
||||
- [`packages/repo-lib/lib.nix`](../../../packages/repo-lib/lib.nix)
|
||||
|
||||
Details:
|
||||
|
||||
- Tool banners do more than render text. They probe commands, parse versions, print failures, and may exit the shell startup for required tools.
|
||||
- That behavior is not obvious from the README example and is spread across generated shell script fragments.
|
||||
|
||||
Assessment:
|
||||
|
||||
- The banner feature is nice, but it is expensive in complexity and debugging surface relative to the value it adds.
|
||||
- If retained, it should be optional and isolated behind a smaller interface.
|
||||
|
||||
### Medium: legacy compatibility paths dominate the core implementation
|
||||
|
||||
Files:
|
||||
|
||||
- [`packages/repo-lib/lib.nix`](../../../packages/repo-lib/lib.nix)
|
||||
|
||||
Details:
|
||||
|
||||
- `mkDevShell` uses legacy tool normalization and its own feature toggles.
|
||||
- `mkRepo` carries a newer strict tool shape.
|
||||
- Both flows feed the same shell-artifact builder, which means the common implementation has to keep both mental models alive.
|
||||
|
||||
Assessment:
|
||||
|
||||
- Deprecate `mkDevShell` once a thin `mkRepo` wrapper exists over standard components.
|
||||
|
||||
## Public API And Usability Findings
|
||||
|
||||
### High: README underspecifies the real API
|
||||
|
||||
Files:
|
||||
|
||||
- [`README.md`](../../../README.md)
|
||||
|
||||
Details:
|
||||
|
||||
- The README explains the happy-path shape of `mkRepo`, but not the actual behavioral contract.
|
||||
- It does not provide a reference for:
|
||||
- tool spec fields
|
||||
- shell banner behavior
|
||||
- exact merge order between `config` and `perSystem`
|
||||
- what the `checks` abstraction cannot express
|
||||
- what `release` is allowed to mutate by default
|
||||
|
||||
Assessment:
|
||||
|
||||
- Consumers can start quickly, but they cannot predict behavior well without reading the implementation.
|
||||
|
||||
### Medium: abstraction boundaries are blurry
|
||||
|
||||
Files:
|
||||
|
||||
- [`README.md`](../../../README.md)
|
||||
- [`template/flake.nix`](../../../template/flake.nix)
|
||||
- [`packages/repo-lib/lib.nix`](../../../packages/repo-lib/lib.nix)
|
||||
|
||||
Details:
|
||||
|
||||
- `checks` looks like the high-level hook API, but advanced usage requires raw Lefthook passthrough.
|
||||
- `shell.bootstrap` is documented as the purity escape hatch, but the template uses it for tool bootstrapping and operational setup.
|
||||
- `release` is presented as optional packaging, but it is operational automation with repo mutation and remote side effects.
|
||||
|
||||
Assessment:
|
||||
|
||||
- These concepts should be separate modules with narrower contracts.
|
||||
|
||||
## Replacement Options
|
||||
|
||||
### Option A: thin compatibility layer
|
||||
|
||||
Keep `repo-lib.lib.mkRepo`, but make it a wrapper over standard components.
|
||||
|
||||
Use:
|
||||
|
||||
- `flake-parts` for top-level flake assembly and `perSystem`
|
||||
- `treefmt-nix` for formatting
|
||||
- `lefthook.nix` for Git hooks
|
||||
- a standalone `mkRelease` output for release automation
|
||||
|
||||
Pros:
|
||||
|
||||
- lower migration cost
|
||||
- preserves existing entrypoint
|
||||
- reduces bespoke glue
|
||||
|
||||
Cons:
|
||||
|
||||
- some compatibility debt remains
|
||||
- requires a staged migration plan
|
||||
|
||||
### Option B: full replacement
|
||||
|
||||
Stop positioning this as a general-purpose Nix library and keep only:
|
||||
|
||||
- the template
|
||||
- any repo-specific release helper
|
||||
- migration docs to standard tools
|
||||
|
||||
Pros:
|
||||
|
||||
- lowest long-term maintenance burden
|
||||
- clearest product boundary
|
||||
|
||||
Cons:
|
||||
|
||||
- highest consumer migration cost
|
||||
- discards the existing `mkRepo` API
|
||||
|
||||
## Final Recommendation
|
||||
|
||||
Choose **Option A**.
|
||||
|
||||
Rationale:
|
||||
|
||||
- `mkRepo` has enough consumer value to keep as a compatibility surface.
|
||||
- Most of the complexity is not unique value. It is custom orchestration around capabilities already provided by better-maintained ecosystem tools.
|
||||
- The release flow should be split out regardless of which option is chosen.
|
||||
|
||||
Concrete target:
|
||||
|
||||
1. Rebase flake structure on `flake-parts`.
|
||||
2. Replace custom hook synthesis with `lefthook.nix`.
|
||||
3. Keep `treefmt-nix` directly exposed instead of deeply wrapped.
|
||||
4. Make shell banners optional or move them behind a very small isolated module.
|
||||
5. Move release automation into a separate package with explicit side-effect flags.
|
||||
6. Mark `mkDevShell` deprecated once `mkRepo` is stable on the new internals.
|
||||
|
||||
## Migration Cost And Compatibility Notes
|
||||
|
||||
- A thin compatibility wrapper keeps consumer migration reasonable.
|
||||
- The biggest compatibility risk is release behavior, because some consumers may depend on the current commit/tag/push flow.
|
||||
- Introduce safer release behavior behind new flags first, then deprecate the old all-in-one default.
|
||||
- Keep template output working during the transition; it is currently the clearest example of intended usage.
|
||||
|
||||
## Required Validation For Follow-Up Work
|
||||
|
||||
- `nix flake show --all-systems`
|
||||
- `nix flake check`
|
||||
- minimal consumer repo using `mkRepo`
|
||||
- template repo evaluation
|
||||
- release smoke test in a temporary git repo
|
||||
- hook assertions that do not depend on private derivation naming/layout
|
||||
|
||||
## Sources
|
||||
|
||||
- `flake-parts`: https://flake.parts/
|
||||
- `treefmt-nix`: https://github.com/numtide/treefmt-nix
|
||||
- `lefthook.nix`: https://github.com/cachix/lefthook.nix
|
||||
- `devenv`: https://github.com/cachix/devenv
|
||||
@@ -1,99 +0,0 @@
|
||||
# TypeScript Monorepo Template Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Replace the minimal starter template with a Bun-only Moonrepo + TypeScript + Varlock monorepo template exposed through the existing flake template.
|
||||
|
||||
**Architecture:** Expand `template/` into a complete repository skeleton while keeping `repo-lib.lib.mkRepo` as the integration point. Adapt the strict TypeScript config layout and Varlock command pattern from `../moon`, and update release tests so they evaluate the full template contents.
|
||||
|
||||
**Tech Stack:** Nix flakes, repo-lib, Bun, Moonrepo, Varlock, TypeScript
|
||||
|
||||
---
|
||||
|
||||
## Chunk 1: Documentation Baseline
|
||||
|
||||
### Task 1: Update public template docs
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
|
||||
- [ ] **Step 1: Write the failing expectation mentally against current docs**
|
||||
|
||||
Current docs describe only a minimal starter template and do not mention Bun, Moonrepo, or Varlock.
|
||||
|
||||
- [ ] **Step 2: Update the README to describe the new template**
|
||||
|
||||
Document the generated workspace shape and first-run commands.
|
||||
|
||||
- [ ] **Step 3: Verify the README content is consistent with the template files**
|
||||
|
||||
Check all commands and filenames against the final template layout.
|
||||
|
||||
## Chunk 2: Template Skeleton
|
||||
|
||||
### Task 2: Replace the minimal template with a real monorepo skeleton
|
||||
|
||||
**Files:**
|
||||
- Modify: `template/flake.nix`
|
||||
- Create: `template/package.json`
|
||||
- Create: `template/bunfig.toml`
|
||||
- Create: `template/moon.yml`
|
||||
- Create: `template/tsconfig.json`
|
||||
- Create: `template/tsconfig.options.json`
|
||||
- Create: `template/tsconfig/browser.json`
|
||||
- Create: `template/tsconfig/bun.json`
|
||||
- Create: `template/tsconfig/package.json`
|
||||
- Create: `template/tsconfig/runtime.json`
|
||||
- Create: `template/.env.schema`
|
||||
- Modify: `template/.gitignore`
|
||||
- Create: `template/README.md`
|
||||
- Create: `template/apps/.gitkeep`
|
||||
- Create: `template/packages/.gitkeep`
|
||||
|
||||
- [ ] **Step 1: Add or update template files**
|
||||
|
||||
Use `../moon` as the source for Moonrepo, Varlock, and TypeScript patterns, removing product-specific details.
|
||||
|
||||
- [ ] **Step 2: Verify the template tree is coherent**
|
||||
|
||||
Check that all referenced files exist and that scripts reference only template-safe commands.
|
||||
|
||||
## Chunk 3: Test Coverage
|
||||
|
||||
### Task 3: Update release tests for the full template
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/release.sh`
|
||||
|
||||
- [ ] **Step 1: Add a failing test expectation**
|
||||
|
||||
The current template fixture copies only `template/flake.nix`, which is insufficient for the new template layout.
|
||||
|
||||
- [ ] **Step 2: Update fixture creation to copy the full template**
|
||||
|
||||
Rewrite template URL references in copied files as needed for local test evaluation.
|
||||
|
||||
- [ ] **Step 3: Verify the existing template evaluation case now uses the real skeleton**
|
||||
|
||||
Confirm `nix flake show` runs against the expanded template fixture.
|
||||
|
||||
## Chunk 4: Verification
|
||||
|
||||
### Task 4: Run template verification
|
||||
|
||||
**Files:**
|
||||
- Verify: `README.md`
|
||||
- Verify: `template/**/*`
|
||||
- Verify: `tests/release.sh`
|
||||
|
||||
- [ ] **Step 1: Run the release test suite**
|
||||
|
||||
Run: `nix develop -c bash tests/release.sh`
|
||||
|
||||
- [ ] **Step 2: Inspect the template file tree**
|
||||
|
||||
Run: `find template -maxdepth 3 -type f | sort`
|
||||
|
||||
- [ ] **Step 3: Verify the README examples still match the tagged template release pattern**
|
||||
|
||||
Check that versioned `repo-lib` URLs remain in the documented commands and release replacements.
|
||||
@@ -1,88 +0,0 @@
|
||||
# TypeScript Monorepo Template Design
|
||||
|
||||
## Goal
|
||||
|
||||
Add a new default template to this repository that generates a Bun-only TypeScript monorepo using Moonrepo, Varlock, and the shared TypeScript configuration pattern from `../moon`.
|
||||
|
||||
## Scope
|
||||
|
||||
The generated template should include:
|
||||
|
||||
- a Nix flake wired through `repo-lib.lib.mkRepo`
|
||||
- Bun-only JavaScript tooling
|
||||
- Moonrepo root configuration
|
||||
- strict shared TypeScript configs adapted from `../moon`
|
||||
- Varlock enabled from day one
|
||||
- a committed `.env.schema`
|
||||
- empty `apps/` and `packages/` directories
|
||||
- minimal documentation for first-run setup
|
||||
|
||||
The template should not include:
|
||||
|
||||
- demo apps or packages
|
||||
- product-specific environment variables or OpenBao paths from `../moon`
|
||||
- Node or pnpm support
|
||||
|
||||
## Architecture
|
||||
|
||||
The existing `template/` directory remains the exported flake template. Instead of containing only a starter `flake.nix`, it will become a complete repository skeleton.
|
||||
|
||||
The generated repository will keep the current `repo-lib` integration pattern:
|
||||
|
||||
- `template/flake.nix` calls `repo-lib.lib.mkRepo`
|
||||
- the shell provisions Bun, Moonrepo CLI, Varlock, and supporting tooling
|
||||
- repo checks remain driven through `mkRepo` and Lefthook
|
||||
|
||||
Moonrepo and Varlock will be configured at the workspace root. The template will expose root tasks and scripts that work even before any projects are added.
|
||||
|
||||
## Template Contents
|
||||
|
||||
The template should contain:
|
||||
|
||||
- `flake.nix`
|
||||
- `package.json`
|
||||
- `bunfig.toml`
|
||||
- `moon.yml`
|
||||
- `tsconfig.json`
|
||||
- `tsconfig.options.json`
|
||||
- `tsconfig/browser.json`
|
||||
- `tsconfig/bun.json`
|
||||
- `tsconfig/package.json`
|
||||
- `tsconfig/runtime.json`
|
||||
- `.env.schema`
|
||||
- `.gitignore`
|
||||
- `README.md`
|
||||
- `apps/.gitkeep`
|
||||
- `packages/.gitkeep`
|
||||
|
||||
It may also keep generic repo support files already useful in templates, such as `.envrc`, `.gitlint`, `.gitleaks.toml`, `.vscode/settings.json`, and `flake.lock`, as long as they remain template-safe.
|
||||
|
||||
## Data And Command Flow
|
||||
|
||||
On first use:
|
||||
|
||||
1. the user creates a repo from the flake template
|
||||
2. the shell provides Bun, Moonrepo, Varlock, and release support
|
||||
3. `bun install` installs `@moonrepo/cli`, `varlock`, and TypeScript-related dependencies
|
||||
4. entering the repo loads `varlock/auto-load`
|
||||
5. root commands like `bun run env:check`, `bun run env:scan`, and `moon run :typecheck` work without any sample projects
|
||||
|
||||
## Varlock Design
|
||||
|
||||
The template will include a minimal `.env.schema` with:
|
||||
|
||||
- one canonical environment selector
|
||||
- safe local defaults where practical
|
||||
- placeholders for OpenBao-backed secrets using generic template paths
|
||||
|
||||
Root scripts in `package.json` will follow the `../moon` pattern for `env:check` and `env:scan`, including `BAO_*` and `OPENBAO_*` compatibility exports. The template will not encode any product-specific namespace names.
|
||||
|
||||
## Testing
|
||||
|
||||
Existing release tests must continue to validate the exported template. The template fixture helper in `tests/release.sh` will need to copy the full template directory, not only `template/flake.nix`, so `nix flake show` exercises the real generated repository structure.
|
||||
|
||||
## Risks
|
||||
|
||||
- Moonrepo root task behavior must remain valid with no projects present.
|
||||
- Template-safe Varlock defaults must avoid broken first-run behavior while still demonstrating the intended pattern.
|
||||
- The release test harness must not accidentally preserve upstream URLs inside the copied template.
|
||||
Reference in New Issue
Block a user