@huseynsnmz/pi-board 0.15.3 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +24 -4
  2. package/CONTRIBUTING.md +7 -0
  3. package/README.md +55 -419
  4. package/SECURITY.md +19 -0
  5. package/docs/how-it-works.md +31 -0
  6. package/docs/reference.md +277 -0
  7. package/package.json +5 -11
  8. package/src/commands/agent-board.ts +26 -2
  9. package/src/commands/attach-flow.ts +4 -0
  10. package/src/core/double-press.mjs +6 -2
  11. package/src/core/slash-commands.mjs +52 -0
  12. package/src/index.ts +1 -1
  13. package/src/runtime/service.mjs +12 -0
  14. package/src/ui/dashboard.ts +59 -25
  15. package/src/ui/pty-attach.ts +8 -3
  16. package/IMPLEMENTATION_PLAN.md +0 -920
  17. package/PRD.md +0 -484
  18. package/PROGRESS.md +0 -142
  19. package/VERIFY.md +0 -115
  20. package/docs/BATCH_SELECTION_READ_FLOW.md +0 -277
  21. package/docs/EXPLORATION.md +0 -187
  22. package/docs/PTY_ATTACH_IMPLEMENTATION_PLAN.md +0 -581
  23. package/docs/RELEASE.md +0 -148
  24. package/docs/superpowers/plans/2026-08-15-screenlog-gc.md +0 -704
  25. package/docs/superpowers/plans/2026-08-16-attach-double-cursor-jiggle-retry.md +0 -499
  26. package/docs/superpowers/plans/2026-08-21-attach-coldstart-jiggle-rearm.md +0 -797
  27. package/docs/superpowers/plans/2026-08-21-dashboard-keypress-lag.md +0 -366
  28. package/docs/superpowers/plans/2026-08-21-issue-14-needs-input-no-auto-done.md +0 -576
  29. package/docs/superpowers/plans/2026-08-22-jiggle-shrink-and-hold.md +0 -337
  30. package/docs/superpowers/plans/2026-08-22-launch-cwd-favorites.md +0 -916
  31. package/docs/superpowers/plans/2026-08-22-question-tool-grouping.md +0 -211
  32. package/docs/superpowers/plans/2026-08-22-rename-state-labels.md +0 -182
  33. package/docs/superpowers/plans/2026-08-22-stable-list-order.md +0 -51
  34. package/docs/superpowers/plans/2026-08-27-locks-acquirelock-spin.md +0 -614
  35. package/docs/superpowers/plans/2026-08-27-pty-runner-test-flaky.md +0 -32
  36. package/docs/superpowers/plans/2026-08-29-code-refs-badges.md +0 -223
  37. package/docs/superpowers/plans/2026-08-30-circular-navigation.md +0 -308
  38. package/docs/superpowers/plans/2026-08-30-post-exit-timing-fix.md +0 -37
  39. package/docs/superpowers/plans/2026-08-30-pty-attach-quality-debt.md +0 -311
  40. package/docs/superpowers/plans/2026-08-30-readme-v2.md +0 -294
  41. package/docs/superpowers/plans/2026-09-01-attach-detach-gate-cursor-anchor.md +0 -284
  42. package/docs/superpowers/plans/2026-09-02-attach-detach-editor-state.md +0 -722
  43. package/docs/superpowers/plans/2026-09-03-code-refs-pr-backlink-narrow.md +0 -551
  44. package/docs/superpowers/plans/2026-09-03-detach-gate-glyph-fallback.md +0 -146
  45. package/docs/superpowers/plans/2026-09-04-evidence-outputpreview.md +0 -209
  46. package/docs/superpowers/plans/2026-09-04-warm-host-reclaim.md +0 -796
  47. package/docs/superpowers/plans/2026-09-05-issue-13-drainnextfollowup-pty-probe.md +0 -114
  48. package/docs/superpowers/plans/2026-09-05-issue-38-windows-wezterm-ime-cursor.md +0 -73
  49. package/docs/superpowers/plans/2026-09-05-issue-39-truncate-codepoint-boundary.md +0 -143
  50. package/docs/superpowers/plans/2026-09-05-issue-61-mention-fallback-guards.md +0 -226
  51. package/docs/superpowers/plans/2026-09-05-issue-63-flaky-manual-completion.md +0 -87
  52. package/docs/superpowers/plans/2026-09-05-issue-64-changelog-release-helper.md +0 -53
  53. package/docs/superpowers/plans/2026-09-05-pty-host-stacking-sock-race.md +0 -731
  54. package/docs/superpowers/plans/2026-09-08-attach-ctrl-left-detach.md +0 -30
  55. package/docs/superpowers/plans/2026-09-08-dashboard-shrink-repaint.md +0 -68
  56. package/docs/superpowers/plans/2026-09-08-issue-11-attach-runtime-desync-heal.md +0 -917
  57. package/docs/superpowers/plans/2026-09-08-legacy-stale-host-recovery.md +0 -125
  58. package/docs/superpowers/plans/2026-09-08-spawn-async-error-swallow.md +0 -56
  59. package/docs/superpowers/plans/2026-09-08-stale-model-attach-guard.md +0 -96
  60. package/docs/superpowers/plans/2026-09-09-claimpid-blocks-replace.md +0 -267
  61. package/docs/superpowers/plans/2026-09-09-harden-runner-architecture.md +0 -603
  62. package/docs/superpowers/plans/2026-09-09-single-writer-completion.md +0 -252
  63. package/docs/superpowers/plans/2026-09-10-reader-consistency.md +0 -115
  64. package/docs/superpowers/plans/2026-09-14-attach-cursor-dectcem-gate.md +0 -469
  65. package/docs/superpowers/plans/2026-09-14-attach-snapshot.md +0 -92
  66. package/docs/superpowers/plans/2026-09-14-host-meta-orphan-lock.md +0 -771
  67. package/docs/superpowers/plans/2026-09-14-issue-106-terminal-frame-cognition.md +0 -299
  68. package/docs/superpowers/plans/2026-09-14-issue-113-foreground-preview-race.md +0 -609
  69. package/docs/superpowers/plans/2026-09-14-terminal-model.md +0 -145
  70. package/docs/superpowers/plans/2026-09-15-coordinator-pipe-root-normalize.md +0 -224
  71. package/docs/superpowers/plans/2026-09-15-lease-publish-eprem-reclaim.md +0 -341
  72. package/docs/superpowers/plans/2026-09-18-detach-anchor-reporter-endpoint.md +0 -875
  73. package/docs/superpowers/plans/2026-09-20-control-lifecycle.md +0 -116
  74. package/docs/superpowers/plans/2026-09-20-issue-121-perf-gate-out-of-coverage.md +0 -517
  75. package/docs/superpowers/plans/2026-09-23-a5-mid-stream-assertion.md +0 -25
  76. package/docs/superpowers/plans/2026-09-23-cwd-browse-tab-drill.md +0 -393
  77. package/docs/superpowers/plans/2026-09-23-terminal-query-forwarding.md +0 -51
  78. package/docs/superpowers/plans/2026-09-23-unconditional-detach-key.md +0 -58
  79. package/docs/superpowers/plans/2026-09-24-control-reconcile-flake.md +0 -698
  80. package/docs/superpowers/plans/2026-09-24-probe-attached-clients.md +0 -605
  81. package/docs/superpowers/plans/2026-09-29-issue-145-holding-semantic-state.md +0 -1183
  82. package/docs/superpowers/plans/2026-09-29-issue-145-user-verification.md +0 -66
  83. package/docs/superpowers/plans/2026-09-30-board-delete-key-x-y-confirm.md +0 -649
  84. package/docs/superpowers/plans/2026-09-30-issue-153-runner-stop-boot-window.md +0 -618
  85. package/docs/superpowers/plans/2026-09-30-issue-95-test-discipline.md +0 -555
  86. package/docs/superpowers/plans/2026-09-30-publish-dispatch-tag-check.md +0 -259
  87. package/docs/superpowers/plans/2026-10-06-attach-settle-scheme-delivery.md +0 -751
  88. package/docs/superpowers/plans/2026-10-09-issue-167-attach-middle-paste.md +0 -509
  89. package/docs/superpowers/plans/2026-10-09-issue-169-fullscreen-mouse-ownership.md +0 -346
  90. package/docs/superpowers/plans/2026-10-10-attach-delete-in-place.md +0 -832
  91. package/docs/superpowers/plans/2026-10-10-issue-174-selection-mirror-paste-source.md +0 -510
  92. package/docs/superpowers/plans/2026-10-14-issue-170-attach-reply-guard.md +0 -771
  93. package/docs/superpowers/plans/2026-10-14-issue-178-accept-registration-race.md +0 -1257
  94. package/docs/superpowers/plans/2026-10-14-issue-184-snapshot-window-contract.md +0 -657
  95. package/docs/superpowers/plans/2026-10-14-issue-185-attach-wheel-alt-screen.md +0 -47
  96. package/docs/superpowers/plans/2026-10-14-issue-187-motionless-drag.md +0 -931
  97. package/docs/superpowers/plans/2026-10-14-issue-189-mixed-input-segments.md +0 -823
  98. package/docs/superpowers/plans/2026-10-15-issue-188-x10-mouse-release.md +0 -526
  99. package/docs/superpowers/plans/2026-10-16-issue-198-attach-wheel-forward-fallback.md +0 -32
  100. package/docs/superpowers/plans/2026-10-18-attach-wheel-replay-pseudo-scrollback.md +0 -437
  101. package/docs/superpowers/plans/2026-10-19-issue-213-reply-guard-csi-key.md +0 -257
  102. package/docs/superpowers/plans/2026-10-19-issue-214-attach-forward-alt-modifier.md +0 -202
  103. package/docs/superpowers/plans/2026-10-21-issue-221-ask-user-question.md +0 -198
  104. package/docs/superpowers/plans/2026-10-23-issue-222-attach-ready.md +0 -290
  105. package/docs/superpowers/plans/2026-10-23-issue-225-monotonic-foreground-state.md +0 -450
  106. package/docs/superpowers/plans/2026-10-23-issue-229-vim-jkl.md +0 -449
  107. package/docs/superpowers/plans/2026-10-23-issue-232-attach-bg-only-cells.md +0 -153
  108. package/docs/superpowers/plans/2026-10-23-lease-heartbeat-staleness.md +0 -537
  109. package/docs/superpowers/plans/2026-10-23-selected-row-highlight.md +0 -405
  110. package/docs/superpowers/plans/2026-10-24-issue-217-windows-pid-reuse-stopping.md +0 -367
  111. package/docs/superpowers/plans/2026-10-24-issue-230-warm-host-background-runs.md +0 -806
  112. package/docs/superpowers/plans/2026-10-24-issue-238-windows-process-identity-token.md +0 -490
  113. package/docs/superpowers/plans/2026-10-24-issue-241-coordinator-root-exit.md +0 -461
  114. package/docs/superpowers/plans/2026-10-25-issue-239-coordinator-replacement-identity.md +0 -504
  115. package/docs/superpowers/plans/2026-10-26-issue-245-key-hints-doc-sync.md +0 -244
  116. package/docs/superpowers/plans/2026-10-27-issue-172-fullscreen-selection-clear.md +0 -344
  117. package/docs/superpowers/plans/2026-10-27-issue-252-select-key-hints.md +0 -209
  118. package/docs/superpowers/plans/2026-10-28-issue-255-coordinator-endpoint-zombie.md +0 -442
  119. package/docs/superpowers/plans/2026-10-28-issue-257-legacy-pty-runner-endpoint-cleanup.md +0 -256
  120. package/docs/superpowers/plans/2026-11-03-cwd-favorites-full-pool.md +0 -266
  121. package/docs/superpowers/specs/2026-08-15-screenlog-gc-design.md +0 -105
  122. package/docs/superpowers/specs/2026-08-16-attach-double-cursor-jiggle-retry-design.md +0 -142
  123. package/docs/superpowers/specs/2026-08-21-attach-coldstart-jiggle-rearm-design.md +0 -110
  124. package/docs/superpowers/specs/2026-08-21-dashboard-keypress-lag-design.md +0 -59
  125. package/docs/superpowers/specs/2026-08-21-issue-14-needs-input-no-auto-done-design.md +0 -109
  126. package/docs/superpowers/specs/2026-08-22-cwd-favorites-design.md +0 -131
  127. package/docs/superpowers/specs/2026-08-22-jiggle-shrink-and-hold-design.md +0 -111
  128. package/docs/superpowers/specs/2026-08-22-question-tool-grouping-design.md +0 -114
  129. package/docs/superpowers/specs/2026-08-22-rename-state-labels-design.md +0 -80
  130. package/docs/superpowers/specs/2026-08-27-locks-acquirelock-spin-design.md +0 -97
  131. package/docs/superpowers/specs/2026-08-27-pty-runner-test-flaky-design.md +0 -35
  132. package/docs/superpowers/specs/2026-08-29-code-refs-badges-design.md +0 -128
  133. package/docs/superpowers/specs/2026-08-30-circular-navigation-design.md +0 -47
  134. package/docs/superpowers/specs/2026-08-30-eprm-atomicwrite-race-design.md +0 -77
  135. package/docs/superpowers/specs/2026-08-30-post-exit-timing-fix-design.md +0 -80
  136. package/docs/superpowers/specs/2026-08-30-pty-attach-quality-debt-design.md +0 -105
  137. package/docs/superpowers/specs/2026-08-30-readme-v2-design.md +0 -115
  138. package/docs/superpowers/specs/2026-09-01-attach-detach-gate-cursor-anchor-design.md +0 -78
  139. package/docs/superpowers/specs/2026-09-02-attach-detach-editor-state-design.md +0 -120
  140. package/docs/superpowers/specs/2026-09-03-code-refs-pr-backlink-narrow-design.md +0 -92
  141. package/docs/superpowers/specs/2026-09-03-detach-gate-glyph-fallback-design.md +0 -99
  142. package/docs/superpowers/specs/2026-09-04-evidence-outputpreview-design.md +0 -50
  143. package/docs/superpowers/specs/2026-09-04-warm-host-reclaim-design.md +0 -106
  144. package/docs/superpowers/specs/2026-09-05-issue-13-drainnextfollowup-pty-probe-design.md +0 -64
  145. package/docs/superpowers/specs/2026-09-05-issue-38-windows-wezterm-ime-design.md +0 -48
  146. package/docs/superpowers/specs/2026-09-05-issue-39-truncate-codepoint-boundary-design.md +0 -64
  147. package/docs/superpowers/specs/2026-09-05-issue-61-mention-fallback-design.md +0 -71
  148. package/docs/superpowers/specs/2026-09-05-issue-63-flaky-manual-completion-design.md +0 -49
  149. package/docs/superpowers/specs/2026-09-05-issue-64-changelog-helper-design.md +0 -76
  150. package/docs/superpowers/specs/2026-09-05-pty-host-stacking-sock-race-design.md +0 -510
  151. package/docs/superpowers/specs/2026-09-07-issue-11-attach-runtime-desync-heal-design.md +0 -130
  152. package/docs/superpowers/specs/2026-09-08-attach-ctrl-left-detach-design.md +0 -58
  153. package/docs/superpowers/specs/2026-09-08-dashboard-shrink-repaint-design.md +0 -52
  154. package/docs/superpowers/specs/2026-09-08-legacy-stale-host-recovery-design.md +0 -87
  155. package/docs/superpowers/specs/2026-09-08-spawn-async-error-swallow-design.md +0 -56
  156. package/docs/superpowers/specs/2026-09-08-stale-model-attach-guard-design.md +0 -79
  157. package/docs/superpowers/specs/2026-09-09-claimpid-blocks-replace-design.md +0 -147
  158. package/docs/superpowers/specs/2026-09-09-harden-runner-architecture-design.md +0 -304
  159. package/docs/superpowers/specs/2026-09-14-attach-cursor-dectcem-gate-design.md +0 -114
  160. package/docs/superpowers/specs/2026-09-14-host-meta-orphan-lock-design.md +0 -120
  161. package/docs/superpowers/specs/2026-09-14-issue-106-terminal-frame-cognition-design.md +0 -146
  162. package/docs/superpowers/specs/2026-09-14-issue-113-foreground-preview-race-design.md +0 -116
  163. package/docs/superpowers/specs/2026-09-15-coordinator-pipe-root-normalize-design.md +0 -84
  164. package/docs/superpowers/specs/2026-09-15-lease-publish-eprem-reclaim-design.md +0 -92
  165. package/docs/superpowers/specs/2026-09-18-detach-anchor-reporter-endpoint-design.md +0 -123
  166. package/docs/superpowers/specs/2026-09-20-issue-121-perf-gate-out-of-coverage-design.md +0 -204
  167. package/docs/superpowers/specs/2026-09-23-a5-mid-stream-assertion-design.md +0 -43
  168. package/docs/superpowers/specs/2026-09-23-cwd-browse-tab-drill-design.md +0 -95
  169. package/docs/superpowers/specs/2026-09-23-terminal-query-forwarding-design.md +0 -63
  170. package/docs/superpowers/specs/2026-09-23-unconditional-detach-key-design.md +0 -57
  171. package/docs/superpowers/specs/2026-09-24-control-reconcile-flake-design.md +0 -98
  172. package/docs/superpowers/specs/2026-09-24-probe-attached-clients-design.md +0 -190
  173. package/docs/superpowers/specs/2026-09-29-issue-145-holding-semantic-state-design.md +0 -394
  174. package/docs/superpowers/specs/2026-09-30-board-delete-key-x-y-confirm-design.md +0 -86
  175. package/docs/superpowers/specs/2026-09-30-issue-153-runner-stop-boot-window-design.md +0 -75
  176. package/docs/superpowers/specs/2026-09-30-issue-95-test-discipline-design.md +0 -226
  177. package/docs/superpowers/specs/2026-09-30-publish-dispatch-tag-check-design.md +0 -129
  178. package/docs/superpowers/specs/2026-10-06-attach-settle-scheme-delivery-design.md +0 -196
  179. package/docs/superpowers/specs/2026-10-09-issue-167-attach-middle-paste-design.md +0 -125
  180. package/docs/superpowers/specs/2026-10-09-issue-169-fullscreen-mouse-ownership-design.md +0 -130
  181. package/docs/superpowers/specs/2026-10-10-attach-delete-in-place-design.md +0 -224
  182. package/docs/superpowers/specs/2026-10-10-issue-174-selection-mirror-paste-source-design.md +0 -154
  183. package/docs/superpowers/specs/2026-10-14-issue-170-attach-reply-guard-design.md +0 -195
  184. package/docs/superpowers/specs/2026-10-14-issue-178-accept-registration-race-design.md +0 -287
  185. package/docs/superpowers/specs/2026-10-14-issue-184-snapshot-window-contract-design.md +0 -288
  186. package/docs/superpowers/specs/2026-10-14-issue-185-attach-wheel-alt-screen-design.md +0 -126
  187. package/docs/superpowers/specs/2026-10-14-issue-187-motionless-drag-design.md +0 -269
  188. package/docs/superpowers/specs/2026-10-14-issue-189-mixed-input-segments-design.md +0 -369
  189. package/docs/superpowers/specs/2026-10-15-issue-188-x10-mouse-release-design.md +0 -252
  190. package/docs/superpowers/specs/2026-10-16-issue-198-attach-wheel-forward-fallback-design.md +0 -67
  191. package/docs/superpowers/specs/2026-10-18-attach-wheel-replay-pseudo-scrollback-design.md +0 -250
  192. package/docs/superpowers/specs/2026-10-19-issue-213-reply-guard-csi-key-design.md +0 -165
  193. package/docs/superpowers/specs/2026-10-19-issue-214-attach-forward-alt-modifier-design.md +0 -131
  194. package/docs/superpowers/specs/2026-10-20-issue-221-ask-user-question-design.md +0 -270
  195. package/docs/superpowers/specs/2026-10-22-issue-225-monotonic-foreground-state-design.md +0 -225
  196. package/docs/superpowers/specs/2026-10-23-issue-222-attach-ready-design.md +0 -204
  197. package/docs/superpowers/specs/2026-10-23-issue-229-vim-jkl-design.md +0 -90
  198. package/docs/superpowers/specs/2026-10-23-issue-232-attach-bg-only-cells-design.md +0 -146
  199. package/docs/superpowers/specs/2026-10-23-lease-heartbeat-staleness-design.md +0 -271
  200. package/docs/superpowers/specs/2026-10-23-selected-row-highlight-design.md +0 -191
  201. package/docs/superpowers/specs/2026-10-24-issue-217-windows-pid-reuse-stopping-design.md +0 -334
  202. package/docs/superpowers/specs/2026-10-24-issue-230-warm-host-background-runs-design.md +0 -283
  203. package/docs/superpowers/specs/2026-10-24-issue-238-windows-process-identity-token-design.md +0 -286
  204. package/docs/superpowers/specs/2026-10-24-issue-241-coordinator-root-exit-design.md +0 -381
  205. package/docs/superpowers/specs/2026-10-25-issue-239-coordinator-replacement-identity-design.md +0 -331
  206. package/docs/superpowers/specs/2026-10-26-issue-245-key-hints-doc-sync-design.md +0 -72
  207. package/docs/superpowers/specs/2026-10-27-issue-172-fullscreen-selection-clear-design.md +0 -248
  208. package/docs/superpowers/specs/2026-10-27-issue-252-select-key-hints-design.md +0 -95
  209. package/docs/superpowers/specs/2026-10-28-issue-255-coordinator-endpoint-zombie-design.md +0 -380
  210. package/docs/superpowers/specs/2026-10-28-issue-257-legacy-pty-runner-endpoint-cleanup-design.md +0 -197
  211. package/docs/superpowers/specs/2026-11-03-cwd-favorites-full-pool-design.md +0 -106
  212. package/scripts/budget-audit.mjs +0 -135
  213. package/scripts/release.mjs +0 -446
  214. package/scripts/release_helper.mjs +0 -309
  215. package/scripts/run-perf-gate.mjs +0 -40
  216. package/scripts/run-tests.mjs +0 -375
@@ -1,551 +0,0 @@
1
- # code-refs PR Back-Link Narrowing Implementation Plan
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** Stop code-review report text (e.g. "上轮 issue #1") from being mis-extracted as a claim-strength PR back-link, by splitting the back-link grammar by evidence context (PR-create command vs. later assistant text) and removing the unbounded follow-up command scan (issue #65).
6
-
7
- **Architecture:** All behavior changes live in the pure engine `src/core/code-refs.mjs`. One shared regex (`PR_BACKLINK_RE`) becomes two context-specific matchers: `PR_CREATE_BACKLINK_RE` (explicit `pr create` body, keeps the legacy bare `issue #N` form) and `PR_FOLLOWUP_BACKLINK_RE` (later assistant text, canonical `Closes/Fixes/Resolves #N` only). Rule 4b's resolver becomes assistant-only and runs only when exactly one distinct PR-create command index exists. Store/render layers are untouched.
8
-
9
- **Tech Stack:** Node.js ≥20 ESM (`node --test`), zero new dependencies.
10
-
11
- **Spec:** `docs/superpowers/specs/2026-09-03-code-refs-pr-backlink-narrow-design.md` (approved 2026-09-03).
12
-
13
- ## Global Constraints
14
-
15
- - All edits happen in the worktree `/home/elling/git-repo/github/pi-agent-board/.pi/worktrees/issue-65-code-refs-pr-backlink-narrow` (branch `issue-65-code-refs-pr-backlink-narrow`). Never touch the main checkout.
16
- - Commit messages: English, conventional commits, reference `issue #65`. Stage by exact file path, never `git add -A`.
17
- - No new exports from `code-refs.mjs` (internal helpers stay module-private; tests go through `extractCodeRefs`).
18
- - Do not modify `code-refs-store.mjs` runtime logic, `github.json` schema, `mergeWithExisting`, providers.json schema, or the mention fallback (issue #61).
19
- - No network calls, no I/O in the engine — it stays a pure function module.
20
- - Coverage gates from `.c8rc.json`: lines ≥85%, functions ≥80%, branches ≥70% (`npm run verify` enforces).
21
- - Test commands run from the worktree root: `node --test test/code-refs-extract.test.mjs` / `node --test test/code-refs-store.test.mjs`. (NOT `npm test -- <file>` — that script keeps its glob and runs everything.)
22
-
23
- **Acceptance mapping:** Task 1 → A2; Task 2 → A1, A2, A3; Task 3 → A4; Task 4 → A5. Spec IDs are quoted in each task.
24
-
25
- ---
26
-
27
- ### Task 1: Split the back-link regex into create/followup matchers
28
-
29
- **Files:**
30
- - Modify: `src/core/code-refs.mjs:509-510` (constant), `src/core/code-refs.mjs:637-640` (`applyPrBacklink`), `src/core/code-refs.mjs:651-660` (`resolveBacklinkAfter` body — matcher swap only, signature unchanged in this task)
31
- - Test: `test/code-refs-extract.test.mjs` (append new test)
32
-
33
- **Interfaces:**
34
- - Consumes: existing `applyPrBacklink(text, index, candidates)` call site at `src/core/code-refs.mjs:571`; existing `resolveBacklinkAfter(marker, commands, assistantTexts, stopBefore)` (Task 1 only swaps the regex used inside it).
35
- - Produces (module-private, used by Task 2): `matchPrCreateBacklink(text) → number|null`, `matchPrFollowupBacklink(text) → number|null`, constants `PR_CREATE_BACKLINK_RE`, `PR_FOLLOWUP_BACKLINK_RE`. `PR_BACKLINK_RE` is deleted.
36
-
37
- Covers spec A2: create body keeps bare `issue #40`; both regexes gain word boundaries and the `(?!\w)` number guard.
38
-
39
- - [ ] **Step 1: Write the failing test**
40
-
41
- Append to `test/code-refs-extract.test.mjs` (after the "pr-body back-link is case-insensitive" test):
42
-
43
- ```js
44
- test("pr create body back-link word boundaries and number guard (issue #65)", () => {
45
- const run = (body) =>
46
- extractCodeRefs(
47
- {
48
- commands: [{ command: `gh pr create --title t --body "${body}"` }],
49
- assistantTexts: [],
50
- worktreePath: null,
51
- branch: null,
52
- repoUrl: "owner/repo",
53
- host: "github.com",
54
- },
55
- github()
56
- );
57
- // Embedded-keyword prose must not match.
58
- assert.equal(run("prefix #1 disclose #2 unresolved #3").issue, null);
59
- // 8-digit numbers are rejected wholesale, not truncated to 7 digits.
60
- assert.equal(run("closes #12345678").issue, null);
61
- // Canonical and legacy forms keep working.
62
- assert.equal(run("fixes issue #40").issue?.number, 40);
63
- assert.equal(run("fixes issue #40").issue?.source, "pr-body");
64
- });
65
- ```
66
-
67
- - [ ] **Step 2: Run test to verify it fails**
68
-
69
- Run: `node --test test/code-refs-extract.test.mjs`
70
- Expected: FAIL — the old regex matches `fix #1` inside `"prefix #1 ..."` so `run("prefix #1 ...").issue` is `1`, not `null` (assert diff shows `1 !== null`).
71
-
72
- - [ ] **Step 3: Implement the split**
73
-
74
- In `src/core/code-refs.mjs`, replace lines 509-510:
75
-
76
- ```js
77
- /** `closes #N` / `fixes #N` / `issue #N` back-link inside a `pr create` body. */
78
- const PR_BACKLINK_RE = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?|issue)\s+#(\d{1,7})/i;
79
- ```
80
-
81
- with:
82
-
83
- ```js
84
- /**
85
- * Back-link inside an explicit `pr create` command body: closing keywords
86
- * (optionally followed by "issue") or the legacy bare `issue #N` form.
87
- * Word boundaries keep embedded keywords (prefix/disclose/unresolved) out;
88
- * `(?!\w)` rejects longer numbers instead of truncating them to 7 digits.
89
- */
90
- const PR_CREATE_BACKLINK_RE =
91
- /\b(?:(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b\s+(?:issue\s+)?|issue\s+)#(\d{1,7})(?!\w)/i;
92
- /**
93
- * Back-link in later assistant evidence: canonical closing-keyword syntax
94
- * only (`closes #N` etc.). A bare `issue #N` mention — e.g. a code-review
95
- * report's finding number — never matches here (issue #65).
96
- */
97
- const PR_FOLLOWUP_BACKLINK_RE =
98
- /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b\s+#(\d{1,7})(?!\w)/i;
99
- ```
100
-
101
- Add the two module-private matchers right after the constants (before `WORKTREE_RE`):
102
-
103
- ```js
104
- /**
105
- * Match a PR→issue back-link in the text of an explicit `pr create` command
106
- * (closing keywords or the legacy bare `issue #N` body form).
107
- * @param {string} text
108
- * @returns {number|null}
109
- */
110
- function matchPrCreateBacklink(text) {
111
- const m = PR_CREATE_BACKLINK_RE.exec(text);
112
- return m ? Number(m[1]) : null;
113
- }
114
-
115
- /**
116
- * Match a PR→issue back-link in later assistant evidence — canonical
117
- * closing-keyword syntax only, never a bare `issue #N` (issue #65).
118
- * @param {string} text
119
- * @returns {number|null}
120
- */
121
- function matchPrFollowupBacklink(text) {
122
- const m = PR_FOLLOWUP_BACKLINK_RE.exec(text);
123
- return m ? Number(m[1]) : null;
124
- }
125
- ```
126
-
127
- Rewrite `applyPrBacklink` (currently lines 637-640):
128
-
129
- ```js
130
- function applyPrBacklink(text, index, candidates) {
131
- const number = matchPrCreateBacklink(text);
132
- if (number !== null) addCandidate(candidates, "issue", number, "claim", "pr-body", index);
133
- }
134
- ```
135
-
136
- Inside `resolveBacklinkAfter` (lines 651-660), replace the matching lines
137
-
138
- ```js
139
- const m = PR_BACKLINK_RE.exec(text);
140
- if (m) return { number: Number(m[1]), index };
141
- ```
142
-
143
- with:
144
-
145
- ```js
146
- const number = matchPrFollowupBacklink(text);
147
- if (number !== null) return { number, index };
148
- ```
149
-
150
- (Signature, loop bounds, and `stopBefore` stay as-is in this task — Task 2 restructures them.)
151
-
152
- - [ ] **Step 4: Run tests to verify pass**
153
-
154
- Run: `node --test test/code-refs-extract.test.mjs`
155
- Expected: PASS — new test plus all 19 existing tests (legacy `issue #40` body at :54, case-insensitive `Closes #40` at :77, later-assistant-message back-link at :150 all stay green because their forms are preserved by the split).
156
-
157
- - [ ] **Step 5: Commit**
158
-
159
- ```bash
160
- git add src/core/code-refs.mjs test/code-refs-extract.test.mjs
161
- git commit -m "fix(code-refs): split PR back-link regex into create/followup matchers with word boundaries (issue #65)"
162
- ```
163
-
164
- ---
165
-
166
- ### Task 2: Assistant-only follow-up scan, gated on a single PR create
167
-
168
- **Files:**
169
- - Modify: `src/core/code-refs.mjs:590-608` (Rule 3 loop + Rule 4b call site), `src/core/code-refs.mjs:642-660` (`resolveBacklinkAfter` rewrite; `evidenceTextAt` callers)
170
- - Test: `test/code-refs-extract.test.mjs` (2 existing tests rewritten, 4 new tests)
171
-
172
- **Interfaces:**
173
- - Consumes: `matchPrFollowupBacklink(text)` from Task 1.
174
- - Produces: `resolveBacklinkAfter(assistantTexts, baseIndex)` → `{ number: number, index: number } | null` (module-private). `evidenceTextAt` is deleted if it has no remaining callers after this task — verify with `rg -n "evidenceTextAt" src/core/code-refs.mjs` and remove it only when unused (its other caller `resolveCreate` still needs it — check first; if `resolveCreate` keeps it, leave `evidenceTextAt` in place).
175
-
176
- Covers spec A1 (real false-positive fixture), A3 (commands never promoted; multi-PR skips), and the follow-up half of A2 (assistant negative forms).
177
-
178
- - [ ] **Step 1: Rewrite the two behavior-contract tests (they must fail before implementation)**
179
-
180
- In `test/code-refs-extract.test.mjs`, replace the test at :110 ("back-link between two pr creates belongs to the first create only") with:
181
-
182
- ```js
183
- test("echo back-link command between two pr creates is ignored (issue #65)", () => {
184
- const result = extractCodeRefs(
185
- {
186
- commands: [
187
- { command: "gh pr create --title A" },
188
- { command: 'echo "closes #40"' },
189
- { command: "gh pr create --title B" },
190
- ],
191
- assistantTexts: [],
192
- worktreePath: null,
193
- branch: null,
194
- repoUrl: "owner/repo",
195
- host: "github.com",
196
- },
197
- github()
198
- );
199
- // Later commands are never scanned as PR back-links, and two PR creates
200
- // disable the assistant scan — so nothing is extracted here.
201
- assert.equal(result.issue, null);
202
- });
203
- ```
204
-
205
- Replace the test at :131 ("second pr create absorbs only the back-link that follows it") with:
206
-
207
- ```js
208
- test("assistant back-link with two pr creates produces no pr-backlink (issue #65)", () => {
209
- const result = extractCodeRefs(
210
- {
211
- commands: [{ command: "gh issue comment 40 --body hi" }, { command: "gh pr create --title A" }, { command: "gh pr create --title B" }],
212
- assistantTexts: ["PR B closes #60"],
213
- worktreePath: null,
214
- branch: null,
215
- repoUrl: "owner/repo",
216
- host: "github.com",
217
- },
218
- github()
219
- );
220
- // Ambiguous attribution (two PR creates) → assistant scan skipped; the
221
- // issue falls back to the plain command action, never a guessed PR link.
222
- assert.equal(result.issue?.number, 40);
223
- assert.equal(result.issue?.strength, "action");
224
- assert.equal(result.issue?.source, "command");
225
- assert.ok(!result.allRefs.some((r) => r.source === "pr-backlink"));
226
- });
227
- ```
228
-
229
- - [ ] **Step 2: Add the four new tests (A1 + A3 + follow-up negatives)**
230
-
231
- Append to `test/code-refs-extract.test.mjs`:
232
-
233
- ```js
234
- test("issue 65 regression: CR-report finding numbers never become pr-backlinks", () => {
235
- const result = extractCodeRefs(
236
- {
237
- commands: [{ command: 'gh pr create --title fix --body "Closes #19"' }],
238
- assistantTexts: [
239
- "CR 报告:本轮仅验证上轮 issue #1(no-pushback)",
240
- "pushback verdict for issue #1",
241
- ],
242
- worktreePath: "/repo/.pi/worktrees/issue-19-fix-thing",
243
- branch: null,
244
- repoUrl: "owner/repo",
245
- host: "github.com",
246
- },
247
- github()
248
- );
249
- assert.equal(result.issue?.number, 19);
250
- assert.ok(!result.allRefs.some((r) => r.kind === "issue" && r.number === 1));
251
- });
252
-
253
- test("later assistant bare issue mentions and non-canonical forms are not pr back-links", () => {
254
- const result = extractCodeRefs(
255
- {
256
- commands: [{ command: "gh pr create --title t" }],
257
- assistantTexts: [
258
- "Progress note: 上轮 issue #1 已验证",
259
- "pushback verdict for issue #1, plus prefix #2 disclose #3",
260
- ],
261
- worktreePath: null,
262
- branch: null,
263
- repoUrl: "owner/repo",
264
- host: "github.com",
265
- },
266
- github()
267
- );
268
- assert.equal(result.issue, null);
269
- assert.ok(!result.allRefs.some((r) => r.source === "pr-backlink"));
270
- });
271
-
272
- test("later close/comment/echo commands are not promoted to pr back-links", () => {
273
- const result = extractCodeRefs(
274
- {
275
- commands: [
276
- { command: 'gh pr create --title t --body "Closes #19"' },
277
- { command: "gh issue close #21" },
278
- { command: 'gh pr comment 20 --body "fixes #21"' },
279
- { command: 'echo "closes #21"' },
280
- ],
281
- assistantTexts: [],
282
- worktreePath: null,
283
- branch: null,
284
- repoUrl: "owner/repo",
285
- host: "github.com",
286
- },
287
- github()
288
- );
289
- assert.equal(result.issue?.number, 19);
290
- assert.ok(!result.allRefs.some((r) => r.source === "pr-backlink"));
291
- // #21 keeps its own plain command-action semantics (not a PR back-link).
292
- const ref21 = result.allRefs.find((r) => r.kind === "issue" && r.number === 21);
293
- assert.equal(ref21?.source, "command");
294
- });
295
-
296
- test("follow-up back-link still found in later assistant message with a single pr create", () => {
297
- const result = extractCodeRefs(
298
- {
299
- commands: [{ command: "gh pr create --title t --body-file /tmp/body.md" }],
300
- assistantTexts: ["Opened the PR. This PR closes #40."],
301
- worktreePath: null,
302
- branch: null,
303
- repoUrl: "owner/repo",
304
- host: "github.com",
305
- },
306
- github()
307
- );
308
- assert.equal(result.issue?.number, 40);
309
- assert.equal(result.issue?.source, "pr-backlink");
310
- });
311
- ```
312
-
313
- (The last test duplicates coverage of the existing :150 test but pins the new single-create gate explicitly; keep both.)
314
-
315
- - [ ] **Step 3: Run tests to verify the new expectations fail**
316
-
317
- Run: `node --test test/code-refs-extract.test.mjs`
318
- Expected: FAIL — the two rewritten tests fail because the current code still scans commands (`echo "closes #40"` yields issue 40) and still attributes `PR B closes #60` to create B; the A3 command-promotion test fails because `gh issue close #21` currently becomes a `pr-backlink` claim that beats #19.
319
-
320
- - [ ] **Step 4: Implement the gate and the assistant-only resolver**
321
-
322
- In `src/core/code-refs.mjs`, restructure the Rule 3 loop (lines 590-608). Replace:
323
-
324
- ```js
325
- // Rule 3: resolve pending create markers against subsequent evidence.
326
- for (let mi = 0; mi < pendingCreates.length; mi++) {
327
- const marker = pendingCreates[mi];
328
- const resolved = resolveCreate(marker, commands, assistantTexts, urlRules);
329
- if (resolved) {
330
- addCandidate(candidates, marker.kind, resolved.number, "action", "create-url", resolved.index);
331
- }
332
- // Rule 4b: the issue back-link of a created PR may live in a later
333
- // assistant message ("This PR closes #40") or in --body-file content
334
- // that never appears in the command string — scan subsequent evidence
335
- // for the back-link pattern as well (not just the command itself).
336
- // The scan stops at the NEXT pr-create marker so an earlier create
337
- // never absorbs a later PR's back-link.
338
- if (marker.kind === "pr") {
339
- const nextPr = pendingCreates.slice(mi + 1).find((m) => m.kind === "pr");
340
- const backlink = resolveBacklinkAfter(marker, commands, assistantTexts, nextPr?.index ?? Infinity);
341
- if (backlink) addCandidate(candidates, "issue", backlink.number, "claim", "pr-backlink", backlink.index);
342
- }
343
- }
344
- ```
345
-
346
- with:
347
-
348
- ```js
349
- // Rule 3: resolve pending create markers against subsequent evidence.
350
- for (const marker of pendingCreates) {
351
- const resolved = resolveCreate(marker, commands, assistantTexts, urlRules);
352
- if (resolved) {
353
- addCandidate(candidates, marker.kind, resolved.number, "action", "create-url", resolved.index);
354
- }
355
- }
356
- // Rule 4b: the issue back-link of a created PR may live in a later
357
- // assistant message ("This PR closes #40") or in --body-file content that
358
- // never appears in the command string. The flattened evidence input keeps
359
- // no interleaving timestamps, so a follow-up back-link can be attributed
360
- // only when exactly one distinct PR-create command exists; with zero or
361
- // multiple PR creates the assistant scan is skipped rather than guessing.
362
- // Later commands are never scanned: `gh issue close #N` or
363
- // `gh pr comment ... fixes #N` are their own signals, not this PR's
364
- // back-link (issue #65).
365
- const prCreateIndexes = new Set(pendingCreates.filter((m) => m.kind === "pr").map((m) => m.index));
366
- if (prCreateIndexes.size === 1) {
367
- const backlink = resolveBacklinkAfter(assistantTexts, commands.length);
368
- if (backlink) addCandidate(candidates, "issue", backlink.number, "claim", "pr-backlink", backlink.index);
369
- }
370
- ```
371
-
372
- Replace `resolveBacklinkAfter` (lines 642-660) entirely with:
373
-
374
- ```js
375
- /**
376
- * Find the first PR→issue back-link in later assistant texts — canonical
377
- * closing-keyword syntax only ("Closes #N" etc., see
378
- * PR_FOLLOWUP_BACKLINK_RE). Commands are never scanned. `baseIndex` (the
379
- * command count) keeps the existing ordering contract; it is not a real
380
- * timestamp.
381
- * @param {string[]} assistantTexts
382
- * @param {number} baseIndex
383
- * @returns {{number: number, index: number}|null}
384
- */
385
- function resolveBacklinkAfter(assistantTexts, baseIndex) {
386
- for (let i = 0; i < assistantTexts.length; i++) {
387
- const text = assistantTexts[i];
388
- if (typeof text !== "string" || !text) continue;
389
- const number = matchPrFollowupBacklink(text);
390
- if (number !== null) return { number, index: baseIndex + i };
391
- }
392
- return null;
393
- }
394
- ```
395
-
396
- Then check `evidenceTextAt`: `resolveCreate` still uses it — leave it in place. Verify with `rg -n "evidenceTextAt" src/core/code-refs.mjs` (expect 2 hits: definition + `resolveCreate`).
397
-
398
- - [ ] **Step 5: Run tests to verify pass**
399
-
400
- Run: `node --test test/code-refs-extract.test.mjs`
401
- Expected: PASS — all tests green, including the two rewritten contract tests and the four new tests.
402
-
403
- - [ ] **Step 6: Commit**
404
-
405
- ```bash
406
- git add src/core/code-refs.mjs test/code-refs-extract.test.mjs
407
- git commit -m "fix(code-refs): scan only assistant texts for follow-up back-links, gated on a single PR create (issue #65)"
408
- ```
409
-
410
- ---
411
-
412
- ### Task 3: Store-level regression tests (persistence path)
413
-
414
- **Files:**
415
- - Test only: `test/code-refs-store.test.mjs` (append two tests after "partial re-trigger carries forward the untouched kind's earned ref")
416
-
417
- **Interfaces:**
418
- - Consumes: existing helpers `freshRoot()`, `makeRepo()`, `gitAvailable()` (defined at the top of the test file, lines 18-40); existing exports `updateCodeRefsFromEvidence`, `readCodeRefs`, `writeCodeRefs` from `src/core/code-refs-store.mjs`; engine behavior from Tasks 1-2.
419
- - Produces: nothing (pure test additions — proves spec A4).
420
-
421
- Covers spec A4: the persisted `github.json` never gains a new `pr-backlink #1` from CR-report evidence, and a pre-existing stale `pr-backlink` ref is explicitly NOT retroactively cleaned (documented non-goal).
422
-
423
- - [ ] **Step 1: Write the two failing tests**
424
-
425
- Append to `test/code-refs-store.test.mjs`:
426
-
427
- ```js
428
- test("CR-report finding numbers never surface as issue refs through the store hook (issue #65)", { skip: !gitAvailable() }, () => {
429
- const root = freshRoot();
430
- const repo = makeRepo();
431
- try {
432
- const evidence = {
433
- viewId: "v1",
434
- commands: [{ id: "c1", command: 'gh pr create --title fix --body "Closes #19"' }],
435
- assistantEvidence: [
436
- { at: 1, text: "CR 报告:本轮仅验证上轮 issue #1(no-pushback)" },
437
- { at: 2, text: "pushback verdict for issue #1" },
438
- ],
439
- };
440
- assert.equal(updateCodeRefsFromEvidence(root, "v1", evidence, { cwd: repo, repoRoot: repo, worktreePath: "issue-19-fix-thing" }), true);
441
- const snap = readCodeRefs(root, "v1");
442
- assert.equal(snap.provider, "github");
443
- assert.equal(snap.issue?.number, 19);
444
- assert.equal(snap.issue?.source, "pr-body");
445
- assert.ok(!snap.allRefs.some((r) => r.kind === "issue" && r.number === 1));
446
- } finally {
447
- rmSync(root, { recursive: true, force: true });
448
- rmSync(repo, { recursive: true, force: true });
449
- }
450
- });
451
-
452
- test("pre-existing stale pr-backlink ref is not retroactively cleaned (issue #65 non-goal)", { skip: !gitAvailable() }, () => {
453
- const root = freshRoot();
454
- const repo = makeRepo();
455
- try {
456
- const stale = {
457
- kind: "issue",
458
- number: 1,
459
- strength: "claim",
460
- confidence: "high",
461
- source: "pr-backlink",
462
- url: null,
463
- lastIndex: 3,
464
- };
465
- writeCodeRefs(root, { version: 1, viewId: "v1", updatedAt: 1, provider: "github", issue: stale, pr: null, allRefs: [stale] });
466
- const evidence = {
467
- viewId: "v1",
468
- commands: [{ id: "c1", command: 'gh pr create --title fix --body "Closes #19"' }],
469
- assistantEvidence: [],
470
- };
471
- assert.equal(updateCodeRefsFromEvidence(root, "v1", evidence, { cwd: repo, repoRoot: repo }), true);
472
- const after = readCodeRefs(root, "v1");
473
- // Fresh extraction wins the badge...
474
- assert.equal(after.issue?.number, 19);
475
- // ...but the historical stale ref carries forward (documented non-goal:
476
- // no retroactive artifact cleanup in this issue).
477
- assert.ok(after.allRefs.some((r) => r.kind === "issue" && r.number === 1));
478
- } finally {
479
- rmSync(root, { recursive: true, force: true });
480
- rmSync(repo, { recursive: true, force: true });
481
- }
482
- });
483
- ```
484
-
485
- - [ ] **Step 2: Run tests to verify they pass already (engine fix landed in Task 2)**
486
-
487
- Run: `node --test test/code-refs-store.test.mjs`
488
- Expected: PASS. These are persistence-path proofs: on the unfixed engine the first test would fail with `snap.issue.number === 1`; now the engine from Tasks 1-2 makes them green. If either fails, the engine regression (not these tests) is what to investigate.
489
-
490
- - [ ] **Step 3: Commit**
491
-
492
- ```bash
493
- git add test/code-refs-store.test.mjs
494
- git commit -m "test(code-refs): store-level regression — CR findings never surface as issue refs (issue #65)"
495
- ```
496
-
497
- ---
498
-
499
- ### Task 4: Documentation sync + full verification
500
-
501
- **Files:**
502
- - Modify: `src/core/code-refs.mjs` (doc comments only — verify no stale references), `docs/superpowers/specs/2026-08-29-code-refs-badges-design.md:66` (C2 claim row)
503
-
504
- **Interfaces:**
505
- - Consumes: final engine behavior from Tasks 1-2.
506
- - Produces: docs consistent with the code; `npm run verify` green (spec A5).
507
-
508
- Covers spec F3 and A5.
509
-
510
- - [ ] **Step 1: Update the original design doc's C2 claim row**
511
-
512
- In `docs/superpowers/specs/2026-08-29-code-refs-badges-design.md`, replace the row:
513
-
514
- ```markdown
515
- | claim | PR 回链:`gh pr create` 的 body/后续文本中的 `issue #N` / `Closes #N`(同时定 issue + PR 两个值) | commands + assistantTexts |
516
- ```
517
-
518
- with:
519
-
520
- ```markdown
521
- | claim | PR 回链(按证据上下文拆分,issue #65):`gh pr create` body 中的 `Closes #N` / `fixes issue #N` / 兼容裸 `issue #N`;后续 assistant 文本仅认 canonical `Closes/Fixes/Resolves #N`(带单词边界与 7 位编号边界);仅在恰好一个 PR create 命令时扫描 assistant,后续 command 不参与回链 | create 命令自身 + assistantTexts |
522
- ```
523
-
524
- - [ ] **Step 2: Verify no stale references remain in the engine**
525
-
526
- Run: `rg -n "PR_BACKLINK_RE" src/ test/`
527
- Expected: no hits (only `PR_CREATE_BACKLINK_RE` / `PR_FOLLOWUP_BACKLINK_RE` exist). Also run `rg -n "next pr create|stopBefore" src/core/code-refs.mjs` — expected: no hits (Task 2 removed them; if any comment still mentions them, update the comment).
528
-
529
- - [ ] **Step 3: Full verification (spec A5)**
530
-
531
- Run: `npm run verify`
532
- Expected: typecheck clean, all tests pass (including service / runner integration end-to-end badge tests, which use `gh issue edit` + URL paths unaffected by this change), c8 coverage gates met (lines ≥85%, functions ≥80%, branches ≥70%), `npm pack --dry-run` succeeds.
533
-
534
- - [ ] **Step 4: Commit**
535
-
536
- ```bash
537
- git add docs/superpowers/specs/2026-08-29-code-refs-badges-design.md src/core/code-refs.mjs
538
- git commit -m "docs(code-refs): sync back-link grammar in design spec and comments (issue #65)"
539
- ```
540
-
541
- ---
542
-
543
- ## Verification checklist (spec acceptance matrix)
544
-
545
- | Spec ID | Verified by | Task |
546
- |---------|-------------|------|
547
- | A1 | `issue 65 regression` extractor test (winner #19, allRefs has no issue 1) + store hook test | 2, 3 |
548
- | A2 | create-body word-boundary/number-guard test + rewritten legacy-compatible tests + assistant negative-forms test | 1, 2 |
549
- | A3 | command-promotion test + two-pr-create skip tests (rewritten ×2, new ×0) | 2 |
550
- | A4 | two store tests: no new `pr-backlink #1`; stale ref carries forward (non-goal documented) | 3 |
551
- | A5 | `npm run verify` (typecheck + tests + coverage gates + pack dry-run) | 4 |