resolve-debt · git:20260615.d2c9a5c · 2026-06-15 · sha256 eadddf2e81c27808
resolve-debt git:20260615.d2c9a5cA
Immutable. This exact content is served forever at /api/v1/blob/eadddf2e81c27808.
--- name: resolve-debt description: "This skill should be used when triaging or closing open entries in the technical-debt ledger. Lists open debt, walks the operator through closing one with a linked GitHub issue." --- # Resolve Tech-Debt Ledger Entries Operator-facing surface for the `knowledge-base/project/learnings/technical-debt/` ledger. The ledger is populated reactively by `/soleur:compound`; this skill is the read + close half of the loop. Complement: [/soleur:harvest-debt](../harvest-debt/SKILL.md) surfaces inline `SOLEUR-DEBT:` markers in source code (the deferrals that have not yet been promoted into this ledger). harvest surfaces; compound promotes; this skill closes. Four modes: - **`--list`** — print a deterministic markdown table of open entries (severity desc, then date asc). Stdout only, no prompts. Pair with `--json` for agent / `/loop` composition. - **`--close N --status S [--linked-issue N]`** — non-interactive close. Bypasses prompts. Reuses the same validation surface as interactive mode (status enum, linked-issue range, fixture-path refusal, `gh issue view`, atomic mutation, body MD5 check). Index `N` follows the `--list` ordering. - **interactive (default)** — list, prompt for entry selection, prompt for new status + `linked_issue`, mutate the entry's frontmatter atomically, print the diff. Does NOT auto-commit; the operator commits on whatever branch they are on. - **`--no-verify`** — modifier on interactive / `--close`: skip the `gh issue view <N>` round-trip. Use offline or when `gh` is unavailable. The skill never calls `git commit` or `git push`. Recovery from a wrong close is `git checkout -- <file>` (pre-commit) or `git revert` (post-commit). ## Commands ### `list` ```bash python3 plugins/soleur/skills/resolve-debt/scripts/resolve-debt.py --list ``` Walks `knowledge-base/project/learnings/technical-debt/` (skips `archive/`). For each `.md` file, parses frontmatter via the `parse_frontmatter` helper from the repo-root `scripts/` directory (file: `frontmatter_lib.py`). Files with parse failures emit a stderr warning naming the file and are skipped — `--list` does not crash on malformed frontmatter. Filters to `status == open`. Sorts by `severity` desc (`high > medium > low > unset`), then `date` asc (oldest first). Output columns: `idx | file | date | severity | component-or-category | title`. Empty state: `No open debt entries.` exit 0. ### `close` (interactive default) ```bash python3 plugins/soleur/skills/resolve-debt/scripts/resolve-debt.py ``` 1. Display the same table as `--list`. 2. Prompt: `Select entry (1..N) or q to quit:`. Out-of-range or non-numeric → re-prompt up to 3 attempts, then exit 2. 3. Prompt: `Status (resolved | wont-fix):`. Enum reject → re-prompt. 4. If `resolved`: prompt `linked_issue (integer, e.g., 2723):`. Validated by `int()` parse (rejects strings, floats, shell metachars by construction) + range-check `1 <= n <= 9_999_999`. The bounds reject shell-metachar injection; the digit-count cap is incidental, not load-bearing. 5. Unless `--no-verify`: `gh issue view <N> --json state,title` with 5-second timeout. Non-zero exit prints `gh issue view failed (<reason>). Re-invoke with --no-verify to skip validation.` to stderr and exits 1. There is no closed-state warning branch — if the operator typed the number, they meant it. 6. Mutate atomically: serialize the new frontmatter to a tempfile in the same directory, then `os.replace`. SIGINT before `os.replace` leaves the original file untouched. 7. Print `git diff -- <file>` to stdout. Print `Diff above. Review and commit when ready. To undo: git checkout -- <file>. No auto-commit by design.` to stderr. Exit 0. ### `help` ```bash python3 plugins/soleur/skills/resolve-debt/scripts/resolve-debt.py --help ``` Prints a usage block enumerating the three modes; exit 0. ## Frontmatter Contract - `status`: required, enum `open | resolved | wont-fix`. Default `open` for new entries (set by `/soleur:compound`'s `resolution-template.md`). - `linked_issue`: required when `status: resolved`; optional when `status: wont-fix`; forbidden when `status: open`. Stored as a YAML integer, no `#` prefix. Why `status` instead of "absence-of-`linked_issue`": `wont-fix` is the load-bearing discriminator of record. Without `status`, there is no way to express "we know about this debt and have decided not to fix it." Future schema simplification must preserve `status` for this reason. See [knowledge-base/project/learnings/technical-debt/README.md](../../../../knowledge-base/project/learnings/technical-debt/README.md) for the full contract. ## Sharp Edges - **Frontmatter parsing goes through the shared `parse_frontmatter` helper in the repo-root `scripts/` directory** (file: `frontmatter_lib.py`), imported via `sys.path.insert`. The `backfill-frontmatter.py` one-shot migration in the same directory imports the same module — single source of truth. Do not re-implement YAML mutation in shell — `sed` range patterns match all `---` blocks and ledger bodies may contain horizontal-rule `---`. - **No auto-commit by design.** The skill prints the diff and stops. Ledger commits land on whatever branch the operator is on; auto-commit would risk wrong-branch writes. - **Archive is frozen.** The walker skips `knowledge-base/project/learnings/technical-debt/archive/`. Closed-out historical entries live there and are not re-surfaced. - **`gh issue view` failure is a hard stop.** No silent fallback to skip validation. The error message names the failure mode and points at `--no-verify` for the operator to opt in explicitly. - **Two schema shapes coexist.** Legacy entries use `module / problem_type / component / tags / severity`; current entries use `title / category / tags / severity`. The skill preserves whichever shape it finds. Schema unification is a separate follow-up. ## Non-Goals - `--undo-close` flag — recovery is `git checkout -- <file>` (pre-commit) or `git revert` (post-commit). - Bulk-resolve. - Severity filter (`--severity high`). - Scheduled scanner / re-surfacing of stale open entries — deferred to issue #3650 (Spec B).