feat: System-Level Backlog & Out-of-Git Operation#19
Conversation
There was a problem hiding this comment.
Pull request overview
This PR makes the idea CLI usable outside of Git repositories by introducing a system-level backlog (XDG-aware) and a persistent --system flag, while preserving the existing in-repo default behavior (fab/backlog.md).
Changes:
- Add system-backlog path resolution (
SystemBacklogPath) and a centralized resolver (ResolveBacklogPath) with out-of-git fallback behavior. - Create missing parent directories on first mutating write to support fresh system backlogs.
- Add/adjust CLI flags, help text, docs, and both unit + integration tests for the new resolution behavior.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| src/internal/idea/idea.go | Adds system backlog path helper, resolution precedence helper, absolute path handling helper, and on-demand parent-dir creation for atomic writes. |
| src/internal/idea/idea_test.go | Adds unit tests for system backlog path + resolution precedence branches. |
| src/cmd/idea/main.go | Adds --system persistent flag and updates flag help text. |
| src/cmd/idea/resolve.go | Delegates path selection to internal/idea.ResolveBacklogPath. |
| src/cmd/idea/add.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/list.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/show.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/done.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/reopen.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/edit.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/rm.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/prune.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/fmt.go | Updates command long help to mention --system and out-of-git fallback. |
| src/cmd/idea/main_test.go | Adds integration tests covering out-of-git fallback, --system behavior, conflict error, and mkdir-on-write. |
| docs/specs/overview.md | Documents system backlog, out-of-git behavior, and resolution precedence. |
| docs/memory/cli/structure.md | Updates CLI structure “memory” doc to include system backlog + precedence. |
| docs/memory/cli/index.md | Updates generated index entry reflecting the updated structure memory doc description. |
| fab/changes/260613-2b3m-system-level-backlog/plan.md | Adds plan/requirements/tasks for the change. |
| fab/changes/260613-2b3m-system-level-backlog/intake.md | Adds intake rationale and decisions for the change. |
| fab/changes/260613-2b3m-system-level-backlog/.status.yaml | Tracks change status/progress metadata. |
| fab/changes/260613-2b3m-system-level-backlog/.history.jsonl | Tracks stage-transition history for the change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // ResolveFilePath determines the backlog file path. | ||
| // Priority: flagValue > IDEAS_FILE env > default (fab/backlog.md). | ||
| // The result is relative to repoRoot. | ||
| // The result is relative to repoRoot. An absolute flagValue / IDEAS_FILE value | ||
| // is honored verbatim (filepath.Join leaves an absolute second element intact | ||
| // only on its own; we guard it explicitly so an out-of-git config-dir root does | ||
| // not get prepended to an absolute override). |
There was a problem hiding this comment.
Fixed — clarified the ResolveFilePath doc comment — removed the misleading filepath.Join phrasing; absolute overrides are short-circuited by joinRoot. (9391b4e)
| // ResolveBacklogPath determines the backlog file path from the three persistent | ||
| // flag inputs, encoding the full resolution precedence (first match wins): | ||
| // | ||
| // 1. systemFlag set → the system backlog (git is skipped entirely). | ||
| // 2. fileFlag / IDEAS_FILE set → joined to the git root when inside a repo, | ||
| // else to the system config dir (an absolute value is honored verbatim). | ||
| // 3. mainFlag set → the main worktree root (git-only; errors | ||
| // outside a repo, unchanged). | ||
| // 4. inside a git repo → {worktree-root}/fab/backlog.md (the unchanged | ||
| // default). | ||
| // 5. outside a git repo → the system backlog (the graceful fallback). |
There was a problem hiding this comment.
Fixed — rewrote the ResolveBacklogPath doc comment to show that --main selects the root within which --file/IDEAS_FILE is applied (they compose, not first-match alternatives). (9391b4e)
| 1. **`--system`** — the system backlog, skipping git entirely (reachable from inside a repo too). | ||
| 2. **`--file <path>` / `IDEAS_FILE`** — joined to the git root when inside a repo, else to the system config dir (`~/.config/idea/`). An absolute value is used verbatim. | ||
| 3. **`--main`** — the main worktree root. Git-only: it still errors with `not in a git repository` outside a repo. | ||
| 4. **In a git repo, no override** — `{worktree-root}/fab/backlog.md` (the default). | ||
| 5. **Outside a git repo, no override** — the system backlog (the graceful fallback; commands no longer fail with `not in a git repository`). |
There was a problem hiding this comment.
Fixed — reworded the overview.md precedence list so --main selects the root and --file/IDEAS_FILE is rooted within it, instead of implying --main is ignored when --file is set. (9391b4e)
| @@ -1,5 +1,5 @@ | |||
| --- | |||
| description: "Source tree layout (cmd/idea + internal/idea), root command factory, command aliases vs. the bare-text shorthand, backlog line lifecycle (lenient read / canonical write incl. the escaped-text convention for multiline ideas and the explicit `idea fmt` canonicalizer with bare-checkbox adoption), help-dump contract, and version stamping" | |||
| description: "Source tree layout (cmd/idea + internal/idea), root command factory, backlog path resolution precedence (--system / --main / --file, the XDG ~/.config/idea/backlog.md system backlog, and the out-of-git graceful fallback), command aliases vs. the bare-text shorthand, backlog line lifecycle (lenient read / canonical write incl. the escaped-text convention for multiline ideas and the explicit `idea fmt` canonicalizer with bare-checkbox adoption), help-dump contract, and version stamping" | |||
There was a problem hiding this comment.
Fixed — updated the structure.md frontmatter to describe the system backlog as $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
| | [edit](edit.md) | `idea edit` two-form contract: inline replacement (two-arg form) vs. $EDITOR round-trip (`edit <query>`) — editor resolution chain, temp-file mechanics, edge/exit semantics, and the fake-editor test seam | 2026-06-12 | | ||
| | [prune](prune.md) | Bulk-remove subcommand (`idea prune`): dry-run-by-default/`--force` contract, stdout/stderr channel split, exit codes, the deliberate non-archival design, and the `removeIdeaAt` seam shared with `Rm` | 2026-06-12 | | ||
| | [structure](structure.md) | Source tree layout (cmd/idea + internal/idea), root command factory, command aliases vs. the bare-text shorthand, backlog line lifecycle (lenient read / canonical write incl. the escaped-text convention for multiline ideas and the explicit `idea fmt` canonicalizer with bare-checkbox adoption), help-dump contract, and version stamping | 2026-06-12 | | ||
| | [structure](structure.md) | Source tree layout (cmd/idea + internal/idea), root command factory, backlog path resolution precedence (--system / --main / --file, the XDG ~/.config/idea/backlog.md system backlog, and the out-of-git graceful fallback), command aliases vs. the bare-text shorthand, backlog line lifecycle (lenient read / canonical write incl. the escaped-text convention for multiline ideas and the explicit `idea fmt` canonicalizer with bare-checkbox adoption), help-dump contract, and version stamping | 2026-06-12 | |
There was a problem hiding this comment.
Fixed — regenerated docs/memory/cli/index.md via 'fab memory-index' so it reflects the updated structure.md frontmatter (no hand-edit). (9391b4e)
| --main targets the main worktree's backlog, --system targets the system-level | ||
| backlog (~/.config/idea/backlog.md), and --file / IDEAS_FILE point elsewhere | ||
| (see "idea --help"). Outside a git repo the system backlog is used | ||
| automatically. |
There was a problem hiding this comment.
Fixed — updated the reopen.go help text to mention $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
| --id and --date additionally change the matched idea's ID or date. --main | ||
| targets the main worktree's backlog and --file / IDEAS_FILE point elsewhere | ||
| (see "idea --help"). | ||
| targets the main worktree's backlog, --system targets the system-level backlog | ||
| (~/.config/idea/backlog.md), and --file / IDEAS_FILE point elsewhere (see | ||
| "idea --help"). Outside a git repo the system backlog is used automatically. |
There was a problem hiding this comment.
Fixed — updated the edit.go help text to mention $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
| remove anything. --main targets the main worktree's backlog, --system targets | ||
| the system-level backlog (~/.config/idea/backlog.md), and --file / IDEAS_FILE | ||
| point elsewhere (see "idea --help"). Outside a git repo the system backlog is | ||
| used automatically. |
There was a problem hiding this comment.
Fixed — updated the rm.go help text to mention $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
| history is the recovery path. --main targets the main worktree's backlog, | ||
| --system targets the system-level backlog (~/.config/idea/backlog.md), and | ||
| --file / IDEAS_FILE point elsewhere (see "idea --help"). Outside a git repo the | ||
| system backlog is used automatically. |
There was a problem hiding this comment.
Fixed — updated the prune.go help text to mention $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
| and exits 1 when the file would change, 0 when it is already canonical. --main | ||
| targets the main worktree's backlog and --file / IDEAS_FILE point elsewhere | ||
| (see "idea --help"). | ||
| targets the main worktree's backlog, --system targets the system-level backlog | ||
| (~/.config/idea/backlog.md), and --file / IDEAS_FILE point elsewhere (see | ||
| "idea --help"). Outside a git repo the system backlog is used automatically. |
There was a problem hiding this comment.
Fixed — updated the fmt.go help text to mention $XDG_CONFIG_HOME/idea/backlog.md, else ~/.config/idea/backlog.md. (9391b4e)
Add a --system persistent flag and graceful out-of-git fallback so idea works outside a git repository against ~/.config/idea/backlog.md (XDG-aware via os.UserConfigDir). Resolution precedence: --system -> --file/IDEAS_FILE -> --main -> in-repo default (fab/backlog.md) -> out-of-git system fallback. --system + --main is a conflict error; the config dir is created on demand on first write. File format and all CRUD semantics are unchanged; no new dependencies.
3c5b994 to
7bd32ff
Compare
Meta
Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Impact: +438/−33 code (excluding
fab/,docs/) · +849/−40 totalSummary
Every
ideacommand shells out togit rev-parseto locate a repo root, so outside a git repository every command fails — and there is nowhere to capture a cross-repo idea. This change adds a sanctioned non-git path: outside a repo, commands gracefully fall back to a system-level backlog at~/.config/idea/backlog.md(XDG-aware), and a new persistent--systemflag reaches that same target from anywhere. The in-git default (fab/backlog.md) is unchanged, keeping Constitution Principle II intact for the in-repo case.Changes
resolveFile()no longer hard-fails outside git. New precedence:--system→--file/IDEAS_FILE→--main(git-only) → in-repo default → out-of-git system fallback.--systempersistent flag — peer of--main, forces the system backlog from anywhere (including inside a repo);--system+--mainis a conflict error.SystemBacklogPath()resolves$XDG_CONFIG_HOME/idea/backlog.md(or~/.config/idea/backlog.md) viaos.UserConfigDir; the config dir is created on demand on first mutating write.fmt/list/showsemantics carry over verbatim; only the resolved path differs. No new dependencies.Longhelp anddocs/specs/overview.mdWorktree Behavior gain a system-backlog note documenting the new precedence.