You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Epic: Tmp-First Analyze & Close Artifacts, with GitHub Fallback for Distill
⚠️Utilization risk: assessed L (1–2 weeks). Fills the sprint with no slack for overruns —
watch for scope creep, particularly in the distill fallback story.
Description
Under issue-sourced planning (#114), a local (non---pr) run of /nxs.analyze already resolves
an epic it doesn't find committed by materializing it under the gitignored .nexus/tmp/, and writes analyze-receipt.md beside it there — nothing to commit, nothing durable, by design. /nxs.close,
however, still talks about writing close-record.md "into the committed queue entry" even when the
entry it inherited is that same .nexus/tmp/ materialization. There is no born-at-close mechanism
for the local path (that only exists for --pr mode, in Phase 0.5), and in single-repo or hub mode a
local close never runs git commit itself — so today, a local close against an issue-sourced epic
produces a close-record.md that the spec calls "committed" but that no step ever actually commits.
(Member mode is the exception: its Phase 7.5 migration does commit the entry, into the hub queue —
Story 5 carries that path.) /nxs.distill then has nothing reliable to drain: it scans only the
committed queue for a close-record.md.
This epic makes the local, same-sitting flow the primary case it should already be: the same
person runs /nxs.analyze then /nxs.close then /nxs.distill back to back, so analyze-receipt.md
and close-record.md are legitimately transient — they exist to hand off from one command to the
very next, not to survive to a different session or machine. Both land in .nexus/tmp/ and /nxs.distill looks there first, consuming the entry directly without requiring anyone to commit a
throwaway file. --pr mode is materially unaffected — it already commits close-record.md onto the
distill branch (Phase 7.6) because those artifacts have no feature PR to ride, and /nxs.analyze --pr
already publishes its result as a PR review rather than a file. Those two mechanisms stay as they are.
The gap this closes is recovery when .nexus/tmp is gone — a different machine, a cleared tmp
directory, a distill run days after the close. For a --pr-closed epic, /nxs.distill can already
fall back to durable GitHub state: the analyze verdict lives in the PR's published review, and the
close record's Key Decisions + Deviation Rationale prose is already posted verbatim on the epic
issue's close comment (/nxs.close Phase 8.2). This epic wires that fallback into distill's entry
discovery. For a local, non---pr close, there is no PR to fall back to — if .nexus/tmp is gone,
distill has no durable copy of the close record's rationale to recover. This epic requires distill to
report that condition precisely (name the entry, name why it can't be drained) rather than silently
mistaking it for "not yet closed" or fabricating an empty rationale; the exact resolution (a hard
block vs. a degraded close-record-only drain) is a judgment call for /nxs.decision-record to settle
against this epic's invariants, not something decided here.
Success Metrics
A local close of an issue-sourced epic (/nxs.analyze → /nxs.close, no --pr) in single-repo or
hub mode produces zero new files in the committed queue — analyze-receipt.md and close-record.md
both live under .nexus/tmp/ — and nothing requires a manual git add/git commit to hand off to /nxs.distill. (Member mode still migrates its entry into the hub queue, as today.)
A tmp-resolved entry is drained exactly once: after its distillation-PR merges, a later /nxs.distill run does not rediscover it.
/nxs.distill run immediately after such a local close drains the entry with no extra flags and no
prior commit, in the same sitting.
/nxs.distill --recover <epic-issue> run against a --pr-closed epic whose .nexus/tmp is empty
(fresh checkout, cleared tmp) recovers the analyze verdict and the close record's rationale from
GitHub, with no content loss versus draining it fresh off the worktree. (Amended at implementation
per record Decision Record: Tmp-First Analyze & Close Artifacts, with GitHub Fallback for Distill #176: recovery is an explicit per-entry path, never a discovery source — an ordinary
no-argument run does not scan closed epic issues.)
/nxs.distill never silently drains an epic with fabricated or missing rationale, and never
silently treats a genuinely-closed-but-unrecoverable local entry as "not yet closed."
Personas
Per docs/product/context.md. The Secondary — Solo developer persona is the direct motivator for
the local same-sitting flow (Description); the Primary — Engineer on a small team persona is the
one who hits the tmp-cleared / different-machine recovery case this epic's distill fallback covers.
Assumptions
--pr mode's existing artifact placement (PR review for analyze, committed-then-git rm'd close-record.md on the distill branch for close) is materially correct and stays as-is; this epic
only adds tmp-first lookup and GitHub-fallback discovery on top of it for /nxs.distill, it does
not change what --pr mode writes or where.
"Same sitting" in local mode means the same machine, uncleared .nexus/tmp, no requirement that it
be the same terminal session — .nexus/tmp persisting across a wrapper restart is treated as normal,
not as the "different machine" recovery case.
Old-contract entries (a committed epic.md predating Issue-Sourced Planning: Nothing Commits Until Close #114) are out of scope for behavior change —
every story above preserves their existing committed-artifact path unchanged.
Member mode keeps its durable end-state. A member-repo close is always non---pr, and its
Phase 7.5 migration commits the entry into the hub queue. Moving the local artifacts under a
gitignored path must not break that migration or leave a second, separately drainable tmp copy
behind (Story 5). "Ephemeral" describes where a member close writes, never where it ends.
Out of Scope
Changing what --pr mode writes or where (Phase 0.5 / Phase 7.6 of /nxs.close, or the PR-review
publish step of /nxs.analyze) — only local-mode placement and distill's discovery/fallback change.
Any change to the decision-record's own storage or its hash-verification contract.
Deciding, at the epic level, whether the unrecoverable-local-entry case (Story 4's last AC) is a hard
block or a degraded drain — that judgment belongs to /nxs.decision-record.
Epic: Tmp-First Analyze & Close Artifacts, with GitHub Fallback for Distill
Description
Under issue-sourced planning (#114), a local (non-
--pr) run of/nxs.analyzealready resolvesan epic it doesn't find committed by materializing it under the gitignored
.nexus/tmp/, and writesanalyze-receipt.mdbeside it there — nothing to commit, nothing durable, by design./nxs.close,however, still talks about writing
close-record.md"into the committed queue entry" even when theentry it inherited is that same
.nexus/tmp/materialization. There is no born-at-close mechanismfor the local path (that only exists for
--prmode, in Phase 0.5), and in single-repo or hub mode alocal close never runs
git commititself — so today, a local close against an issue-sourced epicproduces a
close-record.mdthat the spec calls "committed" but that no step ever actually commits.(Member mode is the exception: its Phase 7.5 migration does commit the entry, into the hub queue —
Story 5 carries that path.)
/nxs.distillthen has nothing reliable to drain: it scans only thecommitted queue for a
close-record.md.This epic makes the local, same-sitting flow the primary case it should already be: the same
person runs
/nxs.analyzethen/nxs.closethen/nxs.distillback to back, soanalyze-receipt.mdand
close-record.mdare legitimately transient — they exist to hand off from one command to thevery next, not to survive to a different session or machine. Both land in
.nexus/tmp/and/nxs.distilllooks there first, consuming the entry directly without requiring anyone to commit athrowaway file.
--prmode is materially unaffected — it already commitsclose-record.mdonto thedistill branch (Phase 7.6) because those artifacts have no feature PR to ride, and
/nxs.analyze --pralready publishes its result as a PR review rather than a file. Those two mechanisms stay as they are.
The gap this closes is recovery when
.nexus/tmpis gone — a different machine, a cleared tmpdirectory, a distill run days after the close. For a
--pr-closed epic,/nxs.distillcan alreadyfall back to durable GitHub state: the analyze verdict lives in the PR's published review, and the
close record's Key Decisions + Deviation Rationale prose is already posted verbatim on the epic
issue's close comment (
/nxs.closePhase 8.2). This epic wires that fallback into distill's entrydiscovery. For a local, non-
--prclose, there is no PR to fall back to — if.nexus/tmpis gone,distill has no durable copy of the close record's rationale to recover. This epic requires distill to
report that condition precisely (name the entry, name why it can't be drained) rather than silently
mistaking it for "not yet closed" or fabricating an empty rationale; the exact resolution (a hard
block vs. a degraded close-record-only drain) is a judgment call for
/nxs.decision-recordto settleagainst this epic's invariants, not something decided here.
Success Metrics
/nxs.analyze→/nxs.close, no--pr) in single-repo orhub mode produces zero new files in the committed queue —
analyze-receipt.mdandclose-record.mdboth live under
.nexus/tmp/— and nothing requires a manualgit add/git committo hand off to/nxs.distill. (Member mode still migrates its entry into the hub queue, as today.)/nxs.distillrun does not rediscover it./nxs.distillrun immediately after such a local close drains the entry with no extra flags and noprior commit, in the same sitting.
/nxs.distill --recover <epic-issue>run against a--pr-closed epic whose.nexus/tmpis empty(fresh checkout, cleared tmp) recovers the analyze verdict and the close record's rationale from
GitHub, with no content loss versus draining it fresh off the worktree. (Amended at implementation
per record Decision Record: Tmp-First Analyze & Close Artifacts, with GitHub Fallback for Distill #176: recovery is an explicit per-entry path, never a discovery source — an ordinary
no-argument run does not scan closed epic issues.)
/nxs.distillnever silently drains an epic with fabricated or missing rationale, and neversilently treats a genuinely-closed-but-unrecoverable local entry as "not yet closed."
Personas
Per
docs/product/context.md. The Secondary — Solo developer persona is the direct motivator forthe local same-sitting flow (Description); the Primary — Engineer on a small team persona is the
one who hits the tmp-cleared / different-machine recovery case this epic's distill fallback covers.
Assumptions
--prmode's existing artifact placement (PR review for analyze, committed-then-git rm'dclose-record.mdon the distill branch for close) is materially correct and stays as-is; this epiconly adds tmp-first lookup and GitHub-fallback discovery on top of it for
/nxs.distill, it doesnot change what
--prmode writes or where..nexus/tmp, no requirement that itbe the same terminal session —
.nexus/tmppersisting across a wrapper restart is treated as normal,not as the "different machine" recovery case.
epic.mdpredating Issue-Sourced Planning: Nothing Commits Until Close #114) are out of scope for behavior change —every story above preserves their existing committed-artifact path unchanged.
--pr, and itsPhase 7.5 migration commits the entry into the hub queue. Moving the local artifacts under a
gitignored path must not break that migration or leave a second, separately drainable tmp copy
behind (Story 5). "Ephemeral" describes where a member close writes, never where it ends.
Out of Scope
--prmode writes or where (Phase 0.5 / Phase 7.6 of/nxs.close, or the PR-reviewpublish step of
/nxs.analyze) — only local-mode placement and distill's discovery/fallback change.block or a degraded drain — that judgment belongs to
/nxs.decision-record.Open Questions
None.