DimitriGilbert / DimitriGilbert/parseArger

Test & quality alignment plan

Open
#7 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
5
Forks
0
PR merge metrics
No merged PRs in 30d

Description

# parseArger — Test & Quality Alignment Plan

_Revised 2026-09-05: CI removed by owner decision — quality gates are local commands run by the owner/agents; no GitHub Actions._

- **Project:** parseArger (`/home/didi/workspace/parseArger`, GH: `DimitriGilbert/parseArger`)
- **Date:** 2026-09-05
- **Generated by the fleet test-alignment initiative** (28-repo audit + synthesis)
- **Audit report:** [`../.test-alignment-audit/reports/parseArger.md`](../.test-alignment-audit/reports/parseArger.md)
- **Fleet synthesis (decisions D1–D7, DoD):** [`../.test-alignment-audit/synthesis-decisions.md`](../.test-alignment-audit/synthesis-decisions.md)
*(links are workspace-relative; they resolve inside `/home/didi/workspace`, not on GitHub)*

**Stack reality:** core product is Bash (~25.8k LOC, self-hosting arg-parser framework), tested by a vendored bashunit suite (`lib/bashunit`, `lib/bashunit_ext`; 11 files, 111 tests, ~738 assertions) that executes generated scripts end-to-end. Two Bun sub-projects ride along: `packages/parsearger-js` (TS wrapper, `bun test` + `tsc --noEmit`) and `docs/` (Next.js 16, `eslint` + `check-types`). Root tooling is a lowercase `makefile` with 4 targets and no `test` target. No CI today (`.github/` holds only `ISSUE_TEMPLATE/`).

---

## 1. Adopted decisions (D1–D7 translated to bash)

| Decision | Adoption here | Notes / deviations |
|---|---|---|
| **D1 — ecosystem-native runner & layout** | **bashunit stays** (explicit, sanctioned deviation from the fleet's vitest norm — D1 names parseArger directly). Tests stay in `tests/*.test.sh`, directly executable, run from repo root. Fleet requirement "headless root-level one-command test entry" is satisfied by a new `make test` target. | No mass rename, no framework change. The vendored `lib/bashunit_ext` (`assert_files_equals`) stays. |
| **D2 — coverage: measure, gate almost nowhere** | **Bash repos: coverage not required.** Adopt the synthesis's explicit branch: **delete the orphaned `.simplecov`** (bashcov-era config with no Gemfile, no runner, no thresholds — an unowned config is worse than none). No thresholds ever. | Reverse option (adopt bashcov properly: Gemfile + runner + ratcheted threshold per D2 state 2) is recorded as an optional deferred phase (Phase 6), not v1. |
| **D3 — lint & format: one primary stack per language** | **`shellcheck` + shared `.shellcheckrc` and `shfmt -d` in the local gate** — exactly the bash clause of D3. Wired via makefile targets. | **Reality correction to the audit:** the audit says "only 2 inline disables"; the repo actually carries **67 scoped `# shellcheck disable=SC2145` directives** across generated code — the generator already emits shellcheck-acceptable output. This makes the gate cheaper; remediation focuses on what remains. |
| **D4 — quality metrics (CRAP/jscpd/knip)** | **N/A in v1.** All three tools are TS/npm-oriented; bash has no in-fleet precedent. Analogue recorded only: shellcheck severity summary as a report-only line printed by the local report command. Deferred to Phase 6 (optional). | No gate on any unmeasured metric (synthesis §5). |
| **D5 — no CI by design (owner decision 2026-09-05)** | **No GitHub Actions, no reusable-workflow caller, no local workflow.** The earlier "local `ci.yml` later swapped to a `DimitriGilbert/.github` `bash-ci.yml` caller" plan is dropped entirely. Enforcement = the root-level headless verification entrypoint (`make check`: test → shellcheck → shfmt, composed in Phases 1–3) run by the owner and by agents; the plan's phase validation gates are run by implementer/validator agents before any phase is declared done. Bun sub-projects (`packages/parsearger-js`, `docs/`) get their own local check lanes (Phase 4). |
| **D6 — shared config distribution** | Repo-local `.shellcheckrc` for now; it is the template other bash repos copy locally (org-repo hosting dropped per D5). `@dg/config` npm package: N/A (no TS core). | Partial adoption; sharing happens by copying, not cross-repo infrastructure. |
| **D7 — hooks: the local gate commands run by the owner/agents are the only authoritative gate** | Applies directly. No hooks in v1 (no lefthook/pre-commit). AGENTS.md states: "the headless local verification command (`make check`) is the quality gate, run by the owner/agents; local hooks are optional convenience." A repo with no hooks and a green `make check` is compliant. | — |

---

## 2. Execution model (subagent-orchestration skill)

Every phase below is executed by an **orchestrator** dispatching subagents — the orchestrator never writes code. Per phase:

1. **Implementer** dispatch with the COMPLETE phase requirements, file list, boundaries, the NO-SLOP policy, and instruction to run the phase's gatekeeping commands before reporting done.
2. **Validator** dispatch (different agent) that MUST read the changed files line-by-line, verify each requirement, re-run the gate commands, and enforce NO-SLOP. Validators never modify code.
3. On FAIL: **fixer** dispatch with ALL validator findings at once (fixer re-runs gatekeeping), then a fresh validator. Max 3 fix attempts per phase, then halt and report.
4. Phases are **sequential** unless marked parallel. Parallel phases use per-sub-phase implementer+validator pairs, then a mandatory **phase-wide validator** reading all sub-phase output together (integration, style coherence, no duplicated fixes).

**NO-SLOP policy for this repo (bash adaptation, pasted verbatim into every implementer/fixer dispatch):**

- NO placeholder code, NO `# TODO`, NO `# FIXME` — this includes resolving the existing TODO at `tests/000_generate.test.sh:28`, not adding new ones.
- NO unused variables or functions; no dead code left behind.
- NO unquoted variable expansions in new/modified lines (repo convention: always `"$var"`).
- Repo style is mandatory in all edits: **tabs** for indentation, `local` inside functions, `snake_case` naming, `die` for errors, `source` with paths resolved relative to the script (see `AGENTS.md`).
- Generated-code rule (AGENTS.md, CRITICAL): never hand-edit between `# @parseArger-parsing` … `-end` markers — change the emitting code in `bin/` (or the declarations) and regenerate via `bin/generate` / `make reparse`.
- Gatekeeping (this repo's equivalent of mandatory check-types): the phase's validation-gate commands must pass cleanly before any implementer/fixer reports done.

---

## 3. Phased plan

### Phase 0 — Suite truthfulness & runnability (effort: S)

**Goal:** the documented "run all tests" loop actually works, and every assertion asserts something.

**Tasks (implementer):**
1. Make all test files executable: `chmod +x` on `tests/000_generate.test.sh`, `tests/003_generate.flag.test.sh`, `tests/004_generate.arg.subcommand.test.sh`, `tests/005_parse.test.sh`, `tests/006_document.test.sh`, `tests/007_complete.test.sh`, `tests/008_html.test.sh`, `tests/009_project.test.sh` (8 of 11 are mode 644 today — the AGENTS.md loop `"$t"` aborts with *Permission denied* on the first one).
2. Fix the 2 vacuous assertions — `tests/000_generate.test.sh:172` (`test_generate_version_opt`) and `:204` (`test_generate_version_opt_short`): `assert_contains "$hlpmsg" "$hlpout"` references an undefined `$hlpmsg`, so the assertion always passes. Mirror `test_generate_version` (line 142): assert the generated script's `--$hlpopt` / `-$hlpopt` output contains `$ver` (`local ver="0.0.1"` is already in scope and unused for the assertion). If this uncovers a real bug in `--version-opt-name` / `--version-short-option` generation, fix the generator (`bin/generate` side), regenerate, and note it in the phase report.
3. Resolve the stale `# TODO: fix test with args should fail gracefully` at `tests/000_generate.test.sh:28` (above `test_generate_file`): either add the graceful-failure assertion the TODO describes (the adjacent `assert_exit_code "1" ... "arg1"` already hints at expected behavior — make it explicit and commented) or delete the TODO comment if the behavior is already fully asserted. No TODO may remain (NO-SLOP).
4. Delete `/home/didi/workspace/parseArger/.simplecov` (D2 bash branch: orphaned bashcov config, filters even reference test-generated `/tmp` paths). Leave `.gitignore`'s `coverage` entry — harmless — or remove it in the same commit; implementer's choice, validator accepts either.
5. Note for orchestrator: tests `source "./lib/bashunit_ext"` and invoke `./parseArger` via relative paths — **every test invocation is repo-root-cwd-dependent**. Preserve this; the makefile targets (Phase 1) anchor cwd at the repo root.

**Validation gate (validator must run all of these from `/home/didi/workspace/parseArger`):**
```bash
for t in tests/*.test.sh; do "$t" || exit 1; done # green, no Permission denied
test -x tests/000_generate.test.sh && ! ls .simplecov 2>/dev/null
grep -n 'assert_contains "$hlpmsg"' tests/000_generate.test.sh # must return nothing
grep -rn 'TODO\|FIXME' tests/ # must return nothing
```
Validator additionally reads `tests/000_generate.test.sh` in full and confirms both version-opt tests now assert `$ver` against real output.

**Roles:** 1 implementer → 1 validator (fix loop ≤3).

---

### Phase 1 — One-command runner + parallel-safe fixtures (effort: S)

**Goal:** `make test` is the headless root-level entry (D1 requirement); tests stop writing to hardcoded `/tmp/gentsttmp*` paths.

**Tasks (implementer):**
1. `makefile`: add a `test` target implementing the AGENTS.md loop:
```makefile
test:
@for t in tests/*.test.sh; do echo "Running $$t..."; "$$t" || exit 1; done
```
Add an aggregate `check: test` target as the future one-command gate (shellcheck/shfmt get appended in Phase 2). Keep the existing 4 targets untouched.
2. De-hardcode fixtures in all 11 `tests/*.test.sh`: replace `tftmp_file="/tmp/gentsttmp"` with a per-run temp dir, e.g. `tftmp_file="$(mktemp -d)"` plus a `trap 'rm -rf "$tftmp_file"' EXIT` at the top of each file; convert the remaining bare `/tmp` paths per file:
- `tests/000_generate.test.sh:129-139` — `/tmp/generate.source.test` → `"$tftmp_file/generate.source.test"` (and fix the literal in the `assert_contains` at line 135 to match the variable, e.g. `"source $tftmp_file/generate.source.test"`).
- `tests/005_parse.test.sh:226-248` — `/tmp/parse.source.test` → same pattern (including literals in assertions at 232/238/245).
- `tests/004_generate.arg.subcommand.test.sh:87-102` — `"/tmp/$scmdv"` → `"$tftmp_file/$scmdv"`.
- `tests/009_project.test.sh` — project names `gentsttmp_project*` are created via the scaffold; ensure they land under `"$tftmp_file"` (or cwd-anchored temp) and cleanup uses `rm -rf` on the temp dir, not per-assertion `rm`s that leak on failure.
- `tests/010_xdg.test.sh` already uses `"/tmp/xdg_test_config_$$"` — migrate to `mktemp -d` for consistency (it is the in-repo precedent that motivated this change).
3. Update `AGENTS.md` "Testing" section: document `make test` as the primary command, keep the per-file command, and add the D7 gate sentence ("CI on GitHub is the quality gate; hooks are optional local convenience").

**Validation gate (from repo root):**
```bash
make test # green
make test & make test; wait # two concurrent runs both green (parallel-safety smoke)
grep -rn '"/tmp/gentsttmp' tests/ # must return nothing
grep -rnE '=/tmp/|"/tmp/[a-z]' tests/ # implementer walks validator through any remaining /tmp hits
```
Validator reads all 11 diffed test files and confirms traps exist, assertions' embedded literals were updated together with paths, and no assertion was weakened during conversion.

**Roles:** 1 implementer → 1 validator (fix loop ≤3).

---

### Phase 2 — shellcheck + shfmt green (effort: M)

**Goal:** the core bash tree passes `shellcheck` and `shfmt -d` under an explicit, committed baseline — the D3 bash gate — without violating the generated-code contract.

**Tasks:**

*Sub-phase 2a (implementer A) — tooling config:*
1. Create `.shellcheckrc` at repo root: baseline global disables only for checks the repo deliberately rejects (start minimal; candidates: `SC2145` is already handled by scoped inline directives — do not duplicate globally). Add excludes for vendored code paths if needed.
2. Decide and document the shfmt profile: tab indentation (matches AGENTS.md), `shfmt -d -i 0` (or repo-equivalent flags) recorded verbatim in the makefile target so every run is identical.
3. Makefile: extend `check` with `shellcheck` and `shfmt -d` over the product tree: `parseArger`, `bin/` (recursive), `utils/`, `scripts/build-packages`, `tests/` — **excluding vendored `lib/bashunit` and `completely.bash`** (vendor stays unformatted; `lib/bashunit_ext` is 20 lines and may be included).

*Sub-phase 2b (implementers B/C/D — parallel) — remediation by area:*
- **B: hand-written surface** — `parseArger` (non-generated sections), `bin/bulk-parse`, `bin/create`, `bin/project`, `utils/*`, `scripts/build-packages`: fix findings at the source (quote expansions, local vars, proper test quoting). 67 scoped `SC2145` disables already exist in generated blocks — leave those alone; they are the intended pattern.
- **C: generated-code emitters** — where shellcheck findings live *between* `# @parseArger` markers, fix the emitting logic in `bin/generate`, `bin/arg*`, `bin/opt/*`, `bin/flag/*`, `bin/pos/*`, `bin/nested/*` templates, then regenerate with `bin/generate` / `make reparse`. Never hand-edit marker blocks. If a finding is a false positive inherent to emitted code, add a **scoped** inline `# shellcheck disable=` in the emitter (matching the existing SC2145 pattern), not a global rc entry.
- **D: tests** — `tests/*.test.sh` + `lib/bashunit_ext`: fix or scoped-disable; tests are also the consumer-facing examples of parseArger output style, so prefer real fixes.

*Phase-wide (after 2a–2d validators pass):* phase-wide validator runs the full gate, diffs `git status` to confirm no marker-block hand-edits slipped in (spot-check via `grep -c '@parseArger-parsing'` stability + `make reparse` idempotency), and checks style coherence across areas.

**Validation gate:**
```bash
shellcheck -x parseArger bin/**/*.sh utils/* scripts/build-packages tests/*.test.sh 2>/dev/null || \
shellcheck -x $(find bin utils tests -name '*.sh' -o -type f -path 'bin/*' | sort -u) # exact invocation lives in the makefile check target
make check # test + shellcheck + shfmt -d, all green
git diff --stat # reviewed by validator for unexpected mass churn
```
Gate policy: zero unaccepted findings at severity `warning` and above; any remaining `info`-level findings must be enumerated in the phase report (ratchet later, never lower).

**Roles:** 4 implementers (A–D, parallel for B/C/D after A lands) → 4 validators (one per sub-phase, dispatched right after each implementer) → 1 phase-wide validator. Fix loop ≤3 per sub-phase.

---

### Phase 3 — Gate composition: `make check` is the gate (effort: S)

**Goal:** the 111-test suite + shellcheck + shfmt run via one headless root command — the P1 gap closed locally (D5).

**Tasks (implementer):**
1. Finalize the `check` target composition: `make check` = `test` + `shellcheck` + `shfmt -d` (extended from Phase 2), run from repo root (tests are cwd-sensitive — the makefile anchors this).
2. Git identity for the run: `tests/009_project.test.sh` scaffolds projects that run `git init`/`git add`/`git commit`. The owner's/agents' machines normally have an identity configured; if the validating machine does not, use a throwaway identity via `git -c user.name=... -c user.email=...` env for the run — never a global config change. Repo-local config inside the scaffolded fixture is the cleaner follow-up (optional, Phase 6).
3. Update `AGENTS.md` Testing section: name `make check` as the quality gate (D7 wording).

**Validation gate:**
```bash
make check # test + shellcheck + shfmt -d, all green from repo root
git ls-files # no workflow file anywhere; nothing under .github/workflows/
```
The implementer/validator agents record the green `make check` output before the phase is declared done (D5).

**Known risks the implementer must handle:** (a) git identity for the Phase-1 tests (above); (b) `completely`-related tests must not require the `completely` gem/docker — the suite currently only asserts invocation, verify on the first full `make check` run; (c) no network access assumptions in tests.

**Roles:** 1 implementer → 1 validator.

---

### Phase 4 — Bun sub-project check lanes (effort: S)

**Goal:** `packages/parsearger-js` and `docs/` get ecosystem-native local check commands, kept out of the bash gate lane.

**Tasks (implementer):** document (and makefile-wire as separate targets, e.g. `check-js`, `check-docs`) two lanes:
- `parsearger-js` (scope: `packages/parsearger-js/**`): `bun install --frozen-lockfile` (root of that subproject; `bun.lock` exists) → `bun run test` → `bun run typecheck`.
- `docs` (scope: `docs/**`): same setup → `bun install --frozen-lockfile` → `bun run lint` → `bun run check-types`. (No `build` in v1 — the deploy path is manual via `docs` npm script; adding build to the lane is deferred to keep this phase S.)
The bash core lane stays independent of both (separate targets, no cross-dependency): a docs-only change cannot fail `make check` and vice versa.

**Validation gate:** all three lanes run green locally; verify independence by running the bash lane after touching nothing in `packages/`/`docs/` and confirming no Bun step executes.

**Roles:** 1 implementer → 1 validator.

---

### Phase 5 — Dependency hygiene, docs alignment, DoD sweep (effort: S)

**Goal:** finish the Definition of Done and leave the repo self-describing.

**Tasks (implementer):**
1. `renovate.json` at repo root: one-liner `{"$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["local>DimitriGilbert"]}`. **Deviation handling:** the org preset repo doesn't exist yet (verified 404), so also include a minimal inline config today (`schedule`, `packageRules` keeping `bun.lock` updated) and record in AGENTS.md that it must switch to the preset when the org repo lands. Verify no `"latest"` deps anywhere (`docs/package.json` pins exact versions — fine; `packages/parsearger-js` uses `^` — fine).
2. `AGENTS.md` final pass: Testing section matches reality exactly (runner = vendored bashunit, `make test`, per-file execution, cwd requirement, the `make check` gate, coverage = intentionally none per D2-bash, `.simplecov` deleted). No phantom commands (the fleet's cropcircle/lmaafy failure mode).
3. DoD sweep: walk the checklist in §4 below item by item; record final status in the phase report.

**Validation gate:** validator reads `AGENTS.md` against reality (every documented command exists and runs), `cat renovate.json` is valid JSON, and `make check` still green. `grep -rn '"latest"' docs/package.json packages/parsearger-js/package.json` returns nothing.

**Roles:** 1 implementer → 1 validator.

---

### Phase 6 — Optional / deferred (effort: M, not v1-blocking)

**Goal:** parked items with explicit triggers. No implementer dispatched until a trigger fires.

1. **bashcov adoption (reverse of the Phase 0 deletion):** if coverage is ever wanted for bash, do it properly — `Gemfile` (bashcov), `bundle exec bashcov ./tests/...` runner wired into a report-only local command, `.simplecov` with real thresholds per D2 state 2 (baseline − 5, ratchet +5). Trigger: a concrete need (e.g. a regression that coverage would have caught).
2. **Renovate preset convergence (D6):** swap inline config for `local>DimitriGilbert`. Trigger: preset published.
3. **Quality-metric analogue (D4):** report-only shellcheck-severity summary + `wc -l` test:code ratio printed by the report command. Trigger: a concrete need for the summary.
4. **Graceful-failure test debt:** the deleted TODO behavior from Phase 0 task 3 — if implemented as comment-removal rather than a new assertion, revisit adding a dedicated "generate with invalid args fails gracefully" test. Trigger: next touch of `bin/generate` error paths.

---

## 4. Definition of Done — per-item status (start of plan)

Fleet DoD (synthesis §3), TS-specific items marked N/A or translated:

| # | DoD item | Current status (2026-09-05) |
|---|---|---|
| 1 | Root-level headless test command exists, documented in AGENTS.md | **Missing** — AGENTS.md documents a copy-pasted loop; `makefile` has no `test` target → Phase 1 (`make test`, analogy item) |
| 2 | Headless verification entrypoint running typecheck + test + lint in one local command; agent records green before a phase is done | **Missing** — no one-command gate; 111 tests run only via the manual loop → Phases 1–4 (`make check`; Bun lanes for the sub-projects: typecheck → `bun run typecheck`; lint → shellcheck/shfmt) |
| 3 | Coverage measured and reported; baseline recorded; thresholds only per D2; never lowered | **N/A by decision** — D2 exempts bash repos; orphaned `.simplecov` deleted (Phase 0); status "intentionally none" recorded in AGENTS.md (Phase 5) |
| 4 | Language-appropriate lint installed, zero errors, wired into the headless entrypoint; dead lint task implemented or deleted | **Missing** — no shellcheck/shfmt anywhere (67 scoped inline disables exist in generated code); no dead lint task to delete (no turbo/make lint) → Phase 2 + Phase 3 |
| 5 | AGENTS.md "Testing" section matches reality — no phantom docs | **Mostly accurate, two defects** — documents a run-all loop that currently fails (8/11 test files non-executable, Phase 0); no mention of the gate/coverage decision (Phase 5) |
| 6 | Dead scaffold test deps removed or used | **N/A** — bash has no package deps; Bun sub-projects' deps are all real (`just-bash`, `esbuild`, `@types/bun`, Next/React). No unused RTL/jsdom analogue found |
| 7 | Renovate one-liner present; no `"latest"` deps | **Missing** — no renovate/dependabot config; no `"latest"` pins found (docs pins exact, parsearger-js uses `^`) → Phase 5 (with hub fallback) |
| 8 | Quality-report job (knip + jscpd + CRAP) as report-only artifact | **N/A in v1** — tools are TS-oriented; bash analogue deferred (Phase 6.4). Nothing metric-shaped is gated (synthesis §5) |
| 9 | Nothing satisfied by a fake pass | **2 violations found** — `assert_contains "$hlpmsg"` with undefined `$hlpmsg` at `tests/000_generate.test.sh:172,204` (always-true); plus the documented run-all loop is broken (permission denied) which is a false "tests don't run" state → Phase 0 |

---

## 5. Risks & repo-specific notes

1. **Bash version portability.** Local dev runs bash 5.3 (Fedora); the suite is expected compatible across bash 5.x — the first full `make check` run is the real proof. Non-goals: macOS bash 3.2 is not a supported target, but note `lib/bashunit_ext` uses GNU `md5sum` (macOS contributors need coreutils) — document in AGENTS.md rather than abstract now. Generated scripts hardcode `#!/bin/bash` — consistent with documenting bash 5.x as the supported runtime.
2. **Bun sub-projects stay out of the bash gate lane.** `packages/parsearger-js` and `docs/` get their own local check lanes with Bun tooling (`bun install --frozen-lockfile`, `bun test`, `bun tsc`). Never pnpm, never vitest (D1/D5). The bash lane must not require Bun and vice versa — a docs-only change cannot fail `make check`.
3. **Self-hosting regeneration hazard.** The product parses its own args; `parseArger` and `bin/*` contain generated marker blocks. All lint fixes inside markers must go through the emitters + `make reparse`, never hand edits (AGENTS.md CRITICAL rule). Phase 2's phase-wide validator explicitly checks regeneration idempotency and that `make test` stays green after every regeneration.
4. **shfmt churn on 25.8k LOC.** A full reformat is a huge diff that buries real changes and touches generated blocks. Mitigation: fix-only remediation first (shellcheck semantic fixes), and run shfmt with the documented profile so output matches existing style (tabs); if mass reformat is still triggered, it lands as its own dedicated commit separated from semantic fixes (validator enforces the separation when reviewing `git diff --stat`).
5. **Test cwd-dependence.** Tests `source "./lib/bashunit_ext"` and call `./parseArger` relative to repo root. All runner invocations must anchor cwd at the repo root (the makefile targets do this). Changing tests to be cwd-independent is out of scope (would touch every file for no gate value).
6. **Git identity on validating machines.** `tests/009_project.test.sh` scaffolds projects that run `git init`/`add`/`commit`; a machine without a configured identity needs a throwaway one for the run (env or `git -c` flags). The cleaner long-term fix is repo-local config inside the scaffolded fixture — optional follow-up, not required.
7. **Reality vs audit deltas (recorded, not silent):** (a) inline shellcheck disables: audit said 2, actual count is 67 (generated code emits them) — improves Phase 2 outlook; (b) audit missed that 8/11 test files lack exec bits, so the documented run-all loop fails immediately — added as Phase 0's first task; (c) `DimitriGilbert/.github` (the D5 hub) does not exist — moot under the 2026-09-05 no-CI decision; (d) `.simplecov` deletion follows the synthesis's own bash branch of D2, overriding the audit's "decide fleet-wide" framing (the fleet decision exists: bash coverage not required).
8. **Vacuous-assertion fix may surface product bugs.** If `--version-opt-name` output doesn't contain the version string, Phase 0 becomes fix-generator + regenerate + retest. That is the correct outcome (the test was silently not testing it); implementer must report it rather than weaken the assertion.

---

## 6. Effort summary

| Phase | Scope | Effort |
|---|---|---|
| 0 — Suite truthfulness & runnability | exec bits, 2 vacuous assertions, TODO, delete `.simplecov` | **S** |
| 1 — Runner + fixtures | `make test`/`check`, mktemp conversion (11 files), AGENTS.md | **S** |
| 2 — shellcheck + shfmt green | `.shellcheckrc`, makefile lint targets, remediation ×3 areas (parallel) | **M** |
| 3 — Gate composition (bash lane) | `make check` as the gate, git-identity note | **S** |
| 4 — Bun sub-project check lanes | parsearger-js + docs lanes, independent | **S** |
| 5 — Hygiene + docs + DoD sweep | renovate, AGENTS.md final, checklist walk | **S** |
| 6 — Optional/deferred | bashcov, preset convergence, metrics analogue | **M** (triggered, not v1) |

Total v1: Phases 0–5, roughly 3–4 focused sessions. First-phase goal when executed: **make the existing suite truthful and runnable** — every later phase (lint, gate, hygiene) stands on a suite that runs and asserts real things.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with Phase 0 in tests/000_generate.test.sh and the other tests/*.test.sh: run the repo-root test loop, inspect the two version-option assertions, and remove the orphaned .simplecov. Then read makefile and AGENTS.md before Phase 1; done means the specified make test/check gates pass, fixtures are parallel-safe, and the Bash, Bun, and docs validation lanes meet their listed commands.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, bun, next.js, typescript
Domain
build-system, documentation, testing, tooling
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.