Skip to content

A lightweight lane for small fixes to reach the concept store #263

Description

@sameera

Epic: A lightweight lane for small fixes to reach the concept store

⚠️ Utilization risk: assessed L (1–2 weeks). Fills the sprint with no slack for overruns. Watch for scope creep.

Description

The knowledge machinery is gated on epics. The distiller is the only writer of the concept store, it drains only entries, and an entry is drainable only when it holds both an epic.md and a close-record.md. Each of those two files has exactly one producer today, and both producers require an epic issue and at least one story sub-issue. So recording the reason behind a two-line fix costs four durable artifacts and two review cycles: an epic issue, a story issue, an implementation pull request, and a distillation pull request.

The practical result is that the reasons behind small fixes are not recorded at all. A developer facing that price either skips the rationale or dresses the fix as an epic. The first loses knowledge the store exists to hold. The second inflates the store with ceremony and buries the decisions that matter.

This epic adds a fifth entry point. A new /nxs.fix command creates the two files directly for a change that has already landed, taking one GitHub reference as its input and asking the developer why the change mattered. A structural rule, called the razor, keeps the lane honest. A fix entry may only append decision log entries, exactly one per changed page, and only to pages that already exist. It may not create a page, retire one, or change what a page asserts. The rule is enforced mechanically in the validator, on the computed page diff, before the distillation pull request opens. A change that needs to alter a page's stated behavior is a design change, and it keeps taking the epic lane.

Success Metrics

  • A developer records the reason for a small fix with one GitHub number as the only durable artifact required, against the four the epic lane forces today.
  • Every fix entry that reaches a distillation pull request appends exactly one decision log entry per changed page and leaves the rest of that page byte-identical, apart from the last_updated_by: frontmatter line and trailing whitespace.
  • A fix whose page changes would alter what a page asserts is refused with a named reason before the distillation pull request opens, rather than merged.
  • Draining an epic entry behaves exactly as it did before this change.
  • Running /nxs.fix creates nothing on GitHub and commits nothing to the repository.

Personas

Per docs/product/context.md. The actor throughout this epic is the primary persona, the engineer on a small team adopting Nexus, in two moments of their work: landing a small fix and later running the drain. This epic adds no new persona.

Assumptions

  • /nxs.fix is a command definition under .claude/commands/, driven the way the other nxs.* commands are. The only new code is the validator mode in Story 2 and the helper subcommand in Story 1.
  • The range --pr <N> subcommand is added to the existing pull-request worktree helper script rather than published as a new skill.
  • The entry files keep the names epic.md and close-record.md for a fix entry, as the specification decides, so the drain changes one line of discovery instead of gaining a parallel code path. The entry_kind: fix field carries the truth about what the entry is.
  • New TypeScript reaches the repository's 95% coverage bar through spec files beside each changed module.
  • The trunk branch is resolved the way the drain already resolves it, and no new configuration key is added.
  • Refusing a member repository is a hard block with no migration path, matching how /nxs.close --pr already behaves.

Out of Scope

  • A migration path that lets a member repository drain its own fix entries. The hub path covers the case, by running /nxs.fix from the hub with a qualified reference.
  • A --pr worktree flow for /nxs.fix. The lane commits nothing, so there is nothing to commit on a branch.
  • Batching. /nxs.fix creates one entry per run, and /nxs.distill batches as it already does.
  • Back-filling fixes that landed before this lane existed. The lane starts empty.
  • Any change to /nxs.close, /nxs.epic, or /nxs.decision-record.
  • Fixing the --require-epic guard in the epic resolver. The specification names it as the lane's first customer, to be done through the lane once the lane exists.
  • Letting a fix strike through an existing invariant in place. The specification defers this loosening until there is evidence the razor binds too tightly.
  • A drift advisory that watches for the lane becoming the default entry point.

Open Questions

None.

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicEpic (created by nxs-gh-create-epic)needs-designEpic warrants a decision record (nxs.decision-record files it as a sub-issue)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions