Skip to content

distill: Backlog Stubs Become GitHub Issues (#185) - #219

Merged
sameera merged 2 commits into
mainfrom
distill/2026-08-02-epic-185
Aug 3, 2026
Merged

distill: Backlog Stubs Become GitHub Issues (#185)#219
sameera merged 2 commits into
mainfrom
distill/2026-08-02-epic-185

Conversation

@sameera

@sameera sameera commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Distillation: Backlog Stubs Become GitHub Issues

Drained queue entries: .nexus/tmp/epic-185/ (ephemeral, same-sitting close) — provenance: #185

The why came from decision record #192, fetched and hash-verified against the digest stamped at close (55493c77…). The what came from the recorded range 3735d95…9d42385, resolved through merged PR #217.

backlog-stub — create

  • What changed: New page. A backlog stub is an epic identified but not yet planned — an epic issue carrying the declared epic classification plus exactly one label denoting that unplanned state. Covers both writers (the epic stage's oversized path, the close stage's deferred scope) filing through the one batch path with caller-supplied classification and a fail-closed label preflight; the never-a-sub-issue rule and the close-gate deadlock it prevents; promotion populating the same issue in place; the not-planned close for a stub too large for one epic; and the backlog collapsing to one query with one negated filter.
  • Why (Decision Log entry): "A stub is an epic born unplanned, and its number survives promotion" — a stub already is an epic, so modelling it as a third species would force every consumer to learn one and would answer the classification question twice, once per mode, where no suitable issue type exists.
  • Provenance: #185 (Backlog Stubs Become GitHub Issues #185)
  • Reciprocal edits: epic-approval-gate

epic-approval-gate — update

  • What changed: Sheds the stub detail it no longer owns (the slug, the per-feature file, promotion "on demand") to the new page, and states the current shape: oversized scope files stub issues, and the gate's consent covers an irreversible platform write rather than a local append. Invariant 4 rewritten accordingly. The alias stub decomposition moved to backlog-stub, where it now resolves.
  • Why (Decision Log entry): "Oversized scope files stub issues, and a promotion re-enters by issue number" — retiring the file retires the slug those blocks were addressed by, which is what forces the operation to be stated rather than inferred.
  • Provenance: #185 (Backlog Stubs Become GitHub Issues #185)
  • Reciprocal edits: backlog-stub

Reviewer notes

1. backlog-stub declares only one touches link, and that is a cap artefact rather than a judgement about the concept. Its real neighbours are publishing-config-resolution (the unplanned label is one more resolved key; the batch path's classification now comes from the caller), issue-sourced-planning (the resolver refuses an unplanned epic by name), and durable-close-record (deferred scope is filed post-checkpoint, before the record naming those numbers is committed). All three sit at 398–400 body words with 7/7 invariants. A reciprocal Integration Points bullet costs ~15 words, so declaring any of those touches would push the target over the 400-word cap, and an update may not compress still-true content to make room. epic-approval-gate was linkable only because this epic genuinely superseded its stub prose. Those relationships are carried in backlog-stub's own prose instead.

2. The store is saturated against the cap store-wide. Nine pages sit at exactly 400 words, twenty more at 394–399. New concepts can no longer link into the existing graph without a split somewhere, which degrades the touches-as-neighbour-list retrieval the store depends on. Flagging as an operational finding; no page was split in this drain, since none of the saturated pages is broad because of this epic.

3. One anchor outside the touched set was refreshed. .nexus/anchors/workspace-resolution.md carried two lines this epic falsified — the stub-promotion glob across backlogs, and close writing deferred scope under the feature path. The close record explicitly deferred that repoint to the drain rather than hand-editing a derived file on the feature branch (record #192 invariant 17, narrowed with rationale). Anchors are derived state that stale-rebuilds by design, so it is regenerated here.

4. One extra commit rides this branch. 9278722 adds docs/delivery/lessons/2026-08-02-backlog-stubs-as-issues.md — epic #185's process lesson. The close wrote it, PR #217 merged without it, and the close record points at that exact path, so the trunk carried a dangling reference. Committed with the lead's explicit consent at the preflight gate.

Anchors refreshed (derived, never hand-edited)

  • .nexus/anchors/backlog-stub.md @ 9d42385a3585858bf599987598a214d4daa37968
  • .nexus/anchors/epic-approval-gate.md @ 9d42385a3585858bf599987598a214d4daa37968
  • .nexus/anchors/workspace-resolution.md @ 9d42385a3585858bf599987598a214d4daa37968

Atlas regenerated (derived)

  • docs/concepts.md (48 concepts)

Consumed queue entries (removed by this PR)

This PR already removes the drained entry's committed home on the branch, so the merge deletes it from main atomically with the page writes — no manual post-merge step:

  • .nexus/queue/epic-185/ — the epic's per-user scratch dir (recoverable via git history). The drained entry itself was ephemeral, so this is what the committed removal targets.
  • The .nexus/tmp/epic-185/ copy is machine-local and is cleaned, uncommitted, by the next /nxs.distill run once this PR's provenance is on the trunk.

sameera and others added 2 commits August 2, 2026 08:52
The close wrote this lesson but the feature PR merged without it, leaving
the close record pointing at a path that was never committed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Creates the backlog-stub concept and updates epic-approval-gate, which
sheds the stub detail it no longer owns. Refreshes the anchors for both
plus the stale stub-promotion glob line on workspace-resolution, and
removes the consumed scratch dir.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sameera
sameera merged commit 4871acc into main Aug 3, 2026
@sameera
sameera deleted the distill/2026-08-02-epic-185 branch August 3, 2026 12:18
sameera added a commit that referenced this pull request Aug 4, 2026
The distiller's surfaces still read the cap as covering the whole body, so
a drain facing a full page had no legal way to record a real edge and the
honest move was to drop it and describe the interaction in prose. PR #219
did exactly that, three times.

The page-patching step now caps a page's own content and states that
Integration Points is bounded per entry instead, at 40 words a bullet, so
a page over 400 total body words through its neighbour list needs no split
and no compression. The split step and the eviction of last resort both
name own-content overflow as their only trigger; neighbour-list pressure
is explicitly not one. The reciprocity fan-out states the remedy the new
ceiling needs: write the bullet within 40 words, and if the interaction
genuinely will not fit, that is two interactions — declare two edges,
never drop or demote one.

The validator step's rule becomes "a non-zero exit blocks" rather than
"any finding blocks", with advisories named as the exception a drain
carries into the PR body and proceeds past. The store's usage README
matches the new denominator and the per-bullet bound.

Closes #224
sameera added a commit that referenced this pull request Aug 4, 2026
The distiller's surfaces still read the cap as covering the whole body, so
a drain facing a full page had no legal way to record a real edge and the
honest move was to drop it and describe the interaction in prose. PR #219
did exactly that, three times.

The page-patching step now caps a page's own content and states that
Integration Points is bounded per entry instead, at 40 words a bullet, so
a page over 400 total body words through its neighbour list needs no split
and no compression. The split step and the eviction of last resort both
name own-content overflow as their only trigger; neighbour-list pressure
is explicitly not one. The reciprocity fan-out states the remedy the new
ceiling needs: write the bullet within 40 words, and if the interaction
genuinely will not fit, that is two interactions — declare two edges,
never drop or demote one.

The validator step's rule becomes "a non-zero exit blocks" rather than
"any finding blocks", with advisories named as the exception a drain
carries into the PR body and proceeds past. The store's usage README
matches the new denominator and the per-bullet bound.

Closes #224
sameera added a commit that referenced this pull request Aug 6, 2026
PR #219 recorded three real interactions of backlog-stub as prose because
each neighbour sat within two words of the old 400-word body cap and a
reciprocal bullet did not fit. Epic #220 re-cut the cap to measure a page's
own content, so the fan-out can no longer fail — the edges are declared here:
publishing-config-resolution, issue-sourced-planning, durable-close-record,
each with its mirrored bullet and reciprocal Decision Log entry.

Hand curation (last_updated_by: manual): both epics had already drained, so
no queue entry was left to carry the edges. Atlas regenerated; anchors
untouched, since no code changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant