LearnNewsExamplesServices
Frontmatter
id11116
titleEpic-shape discipline: separate code-change commits from data-migration commits in PRs
stateClosed
labels
enhancementaimodel-experience
assigneesneo-opus-4-7
createdAtMay 10, 2026, 4:11 PM
updatedAtMay 25, 2026, 12:15 AM
githubUrlhttps://github.com/neomjs/neo/issues/11116
authorneo-opus-4-7
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 25, 2026, 12:15 AM

Epic-shape discipline: separate code-change commits from data-migration commits in PRs

Closedenhancementaimodel-experience
neo-opus-4-7
neo-opus-4-7 commented on May 10, 2026, 4:11 PM

Context

Operator @tobiu's framing 2026-05-10 in response to PR #11114 (Issue Chunk Migration, #11113):

"the idea for an epic was e.g. keeping code changes and data migration output inside separate commits. makes reviews easier. might be a friction gold topic."

PR #11114 surfaced this empirically: it bundled (a) 5 wire-format consumer code updates (~15 LOC of recursive-readdir mirror logic) AND (b) ~4190 ticket-file moves from flat → chunked nested structure in the SAME PR. Cycle-1 review struggled to isolate the code-change correctness from the data-migration noise. Even after cycle-1 cleanup (which removed accidental chore-sync + stray drafts + discussion drift — separate friction class), cycle-2's clean diff still has 5 code files mixed with 95+ data-rename files.

Same shape applies retroactively to #11113 epic design: the substrate-correct sub-ticket structure would have split this into:

  • Code sub: recursive-readdir mirror across 5 wire-format consumers (small, reviewable in isolation)
  • Data sub: 4190-ticket flat→chunked migration (mechanical, separate review)

The Problem

Mixed-scope PRs (code-change + data-migration in one diff) create review friction:

  1. Signal-to-noise asymmetry: 15 LOC of code logic drowned in 4190 file renames. Reviewer scrolls through data movement to verify code correctness.
  2. Squash-merge git history pollution: github's squash collapses ALL commits → final dev commit body contains the full mixed-scope diff. Future git blame / archeology mixes "what changed in the code" with "what data moved."
  3. Revertability cost: if the code change has a regression, reverting the squash-commit also reverts the data migration (or requires manual surgery to separate). Asymmetric blast-radius for the rollback decision.
  4. Review attention dilution: even attentive reviewers fatigue scrolling through mechanical data renames. Code-change defects get less scrutiny per LOC.

PR #11114 made this concrete enough that operator surfaced it as a substrate-evolution candidate.

The Fix

Add a Stage 3.5 (or augment Stage 3 sub-structure-coherence check) in epic-review-workflow.md that fires for epics involving both code changes AND data-migration:

Concrete patch shape.agents/skills/epic-review/references/epic-review-workflow.md (Stage 3 region):

+### Stage 3.5: Code-vs-Data-Migration Sub-Split Audit
+
+Trigger: epic body or sub-ticket prescriptions describe BOTH (a) code changes
+(updates to `.mjs` / `.ts` / `.js` / build-script logic) AND (b) data migration
+(file renames / mass content relocation / large structured data moves).
+
+Audit: verify sub-ticket structure splits these into SEPARATE sub-tickets:
+- Code sub-ticket(s) — small, reviewable in isolation; enables the new shape
+- Data-migration sub-ticket(s) — mechanical, separate review pass; consumes
+  the new shape after code lands
+
+Sequencing rule: code sub MUST land before data-migration sub (so the data
+lands in a substrate that already supports it). For dependency-cycle epics
+where this isn't possible, document the rationale explicitly.
+
+If the epic prescribes BOTH concerns in the SAME sub-ticket: flag as
+Required Action; recommend split. Empirical anchor: epic #11113 / PR #11114
+— mixed-scope diff (15 LOC code + 4190 file renames) creates review-friction
+that operator surfaced as friction-gold-candidate.

Acceptance Criteria

  • epic-review-workflow.md patched with Stage 3.5 (or augmented Stage 3) per the diff above
  • Sibling audit: ticket-create-workflow.md Stage 3 (Prescription Layer) gets a parallel reminder for epic-shape tickets specifically
  • Cross-references: PR #11114 cited as empirical anchor; operator's framing quote preserved as [paraphrase] since it's session-A2A not publicly visible
  • Empirical validation: next epic review where code+data both apply — verify Stage 3.5 fires + author splits sub-tickets accordingly

Out of Scope

  • Pre-PR lint detecting mixed-scope diff at commit-time — too mechanical; hard to detect "data migration" semantically without false positives. Stage 3.5 at epic-review time is the right tier.
  • Post-merge revert primitive that lets reviewers undo just data-migration without touching code — scope-creep; doesn't fix the review-friction problem at source.
  • Other PR-shape disciplines (e.g., separate commits within same PR) — squash-merge collapses these anyway; the right fix is at sub-ticket / PR-scope tier, not commit tier.
  • Retroactive split of PR #11114 — too late + low value; the cleanup cycle-1 already addressed the contamination. Future epics benefit from Stage 3.5.

Avoided Traps / Gold Standards Rejected

Decision Matrix

  1. Stage 3.5 in epic-review-workflow.md (Selected): Fires at the right tier (epic design time, BEFORE sub-tickets get filed against mixed-scope shape). Lowest implementation cost. Aligns with the substrate-evolution family of recent skill-payload calibrations (#11102 Verdict-Authority, #11105 template-adherence, Discussion #11112 epic-level V-B-A).

  2. Author-side discipline only (no skill-payload codification): Rejected. Per #11114 empirical anchor: discipline alone fails. PR #11114 author clearly knew about the data-migration scope but bundled with code anyway. Skill-payload codification is the gate that makes the discipline persist across agent-context-windows.

  3. Pre-PR commit-time lint: Rejected. Detecting "data-migration vs code change" semantically is hard (false-positive risk on ANY large refactor that touches many files). Stage 3.5 at epic-design time is upstream of this and avoids the false-positive class.

  4. Post-PR commit-shape requirement (separate commits within same PR): Rejected. Squash-merge collapses commits into one dev commit. Per-commit separation provides cycle-N review value but not post-merge git-history value. The right tier is sub-ticket / PR scope, not commit scope.

  5. Per-PR title-prefix convention (e.g., feat(code): vs feat(data):): Rejected as cosmetic. Conventional Commits scope already exists; adding a code-vs-data sub-class doesn't fix the underlying review-friction at the diff level.

  • Trap: Treating "small code change is the entire fix" when the same epic has data-migration scope. Rejection: PR #11114 demonstrates the failure mode — small code change buried in data-rename noise. Stage 3.5 catches this at epic-review time.
  • Trap: Letting operator-pushback be the substrate gate. Rejection: Operator surfaced this on PR #11114; the substrate-correct fix is to codify it so future epics don't need operator-policing.

Related

  • PR #11114 (#11113) — canonical empirical anchor; mixed-scope diff (15 LOC code + 4190 file renames) made cycle-1 review high-friction
  • Operator's framing 2026-05-10 (current session, A2A-only — [paraphrase] for peer corroboration)
  • epic-review skill payload (the substrate this ticket evolves)
  • AGENTS.md §13.2 friction → gold core value (this ticket IS the friction → gold conversion artifact)
  • #11102 (sister substrate-evolution: epic-resolution Verdict-Authority calibration)
  • #11105 (sister substrate-evolution: author-side template-adherence)
  • Discussion #11112 (sister substrate-evolution: epic-level V-B-A enforcement; this ticket plus #11102 + #11105 form a coherent skill-payload-calibration cluster)
  • Distinct from: chore-sync contamination pattern (3rd time across PR #11106 / #11109 / #11114) — that's a separate friction class about local-branch hygiene; THIS ticket is about epic design shape

Origin Session ID: c2912891-b459-4a03-b2af-154d5e264df1 Retrieval Hint: "code-vs-data-migration sub-split", "epic-review Stage 3.5", "PR #11114 friction-gold anchor"