peaks-loop 4.0.46 → 4.0.48

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 (207) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README-en.md +1 -1
  3. package/README.md +1 -1
  4. package/agents/karpathy-reviewer.md +11 -10
  5. package/dist/cli/cli-helpers.d.ts +34 -0
  6. package/dist/cli/cli-helpers.js +57 -0
  7. package/dist/cli/commands/code-job-shape-commands.js +8 -0
  8. package/dist/cli/commands/code-runtime-commands.d.ts +22 -0
  9. package/dist/cli/commands/code-runtime-commands.js +139 -16
  10. package/dist/cli/commands/compact-command.js +241 -1
  11. package/dist/cli/commands/config-commands.js +15 -9
  12. package/dist/cli/commands/container-commands.js +3 -3
  13. package/dist/cli/commands/core/skill-command.js +45 -10
  14. package/dist/cli/commands/cron-commands.js +2 -1
  15. package/dist/cli/commands/dashboard-long-run.js +6 -0
  16. package/dist/cli/commands/dispatch-commands.js +11 -1
  17. package/dist/cli/commands/doctor/invoke-from-code.js +6 -0
  18. package/dist/cli/commands/e2e-verify.js +3 -3
  19. package/dist/cli/commands/governance-classify-contract-commands.js +1 -0
  20. package/dist/cli/commands/hooks-commands.js +14 -5
  21. package/dist/cli/commands/job-commands.js +8 -0
  22. package/dist/cli/commands/loop-commands.js +1 -0
  23. package/dist/cli/commands/loop-eval-commands.js +15 -0
  24. package/dist/cli/commands/perf-audit-commands.js +2 -0
  25. package/dist/cli/commands/playwright-commands.js +14 -1
  26. package/dist/cli/commands/prd-commands.js +1 -1
  27. package/dist/cli/commands/qa-commands.js +22 -0
  28. package/dist/cli/commands/reinject-command.d.ts +72 -0
  29. package/dist/cli/commands/reinject-command.js +174 -0
  30. package/dist/cli/commands/request-commands.js +14 -3
  31. package/dist/cli/commands/scan-commands.js +1 -1
  32. package/dist/cli/commands/security-audit-commands.js +2 -0
  33. package/dist/cli/commands/shadcn-commands.js +1 -0
  34. package/dist/cli/commands/slice-integrate-commands.js +5 -0
  35. package/dist/cli/commands/statusline-commands.js +44 -4
  36. package/dist/cli/commands/sub-agent/detached.d.ts +14 -1
  37. package/dist/cli/commands/sub-agent/detached.js +47 -22
  38. package/dist/cli/commands/sub-agent-shutdown-commands.js +11 -0
  39. package/dist/cli/commands/test-commands.js +2 -1
  40. package/dist/cli/commands/verdict-aggregate-command.js +95 -13
  41. package/dist/cli/commands/vm-commands.js +7 -7
  42. package/dist/cli/commands/workflow-commands.js +1 -1
  43. package/dist/cli/commands/workspace/init-command.js +24 -2
  44. package/dist/cli/commands/worktree-lease-commands.js +4 -4
  45. package/dist/cli/index.js +10 -3
  46. package/dist/cli/program.js +5 -0
  47. package/dist/hooks/pre-tool-use-sub-agent.js +1 -1
  48. package/dist/services/adapter/adapter-registry.js +1 -1
  49. package/dist/services/artifacts/artifact-prerequisites.d.ts +38 -7
  50. package/dist/services/artifacts/artifact-prerequisites.js +130 -65
  51. package/dist/services/artifacts/artifact-service.js +1 -1
  52. package/dist/services/artifacts/request-artifact-service.d.ts +8 -0
  53. package/dist/services/artifacts/request-artifact-service.js +18 -8
  54. package/dist/services/artifacts/request-artifact-state-helpers.d.ts +57 -0
  55. package/dist/services/artifacts/request-artifact-state-helpers.js +91 -10
  56. package/dist/services/audit-independent/perf-audit-service.d.ts +9 -0
  57. package/dist/services/audit-independent/perf-audit-service.js +27 -5
  58. package/dist/services/audit-independent/security-audit-service.d.ts +12 -2
  59. package/dist/services/audit-independent/security-audit-service.js +28 -6
  60. package/dist/services/capability-guard-runner/contracts/J01.js +2 -1
  61. package/dist/services/capability-guard-runner/contracts/J02.js +3 -3
  62. package/dist/services/capability-guard-runner/contracts/J04.js +4 -2
  63. package/dist/services/capability-guard-runner/contracts/J07.js +2 -1
  64. package/dist/services/code/auto-compact-lifecycle.d.ts +130 -1
  65. package/dist/services/code/auto-compact-lifecycle.js +180 -4
  66. package/dist/services/code/auto-compact-orchestrator.d.ts +53 -9
  67. package/dist/services/code/auto-compact-orchestrator.js +166 -34
  68. package/dist/services/code/compact-event-settle.d.ts +122 -0
  69. package/dist/services/code/compact-event-settle.js +219 -0
  70. package/dist/services/code/orchestrator-can-do.d.ts +4 -2
  71. package/dist/services/code/orchestrator-can-do.js +37 -5
  72. package/dist/services/codegraph/codegraph-exclude-reconciler.js +2 -1
  73. package/dist/services/codegraph/codegraph-process-runner.js +3 -2
  74. package/dist/services/compact/request-transition-hook.js +5 -2
  75. package/dist/services/compact-history/compact-history-service.d.ts +75 -0
  76. package/dist/services/compact-history/compact-history-service.js +49 -0
  77. package/dist/services/config/config-restore.d.ts +12 -1
  78. package/dist/services/config/config-restore.js +35 -4
  79. package/dist/services/config/config-rollback.js +6 -1
  80. package/dist/services/config/config-safety.d.ts +52 -0
  81. package/dist/services/config/config-safety.js +75 -1
  82. package/dist/services/context/auto-compact-dispatcher.d.ts +7 -37
  83. package/dist/services/context/auto-compact-dispatcher.js +113 -40
  84. package/dist/services/context/auto-compact-reader.d.ts +68 -28
  85. package/dist/services/context/auto-compact-reader.js +155 -1
  86. package/dist/services/context/auto-compact-types.d.ts +89 -12
  87. package/dist/services/context/auto-compact-types.js +16 -32
  88. package/dist/services/context/harness-context-witness.d.ts +310 -0
  89. package/dist/services/context/harness-context-witness.js +606 -0
  90. package/dist/services/context/harness-window-config.d.ts +412 -0
  91. package/dist/services/context/harness-window-config.js +607 -0
  92. package/dist/services/context/main-session-monitor.d.ts +27 -0
  93. package/dist/services/context/main-session-monitor.js +32 -1
  94. package/dist/services/context/post-compact-reinjection.d.ts +221 -0
  95. package/dist/services/context/post-compact-reinjection.js +491 -0
  96. package/dist/services/dispatch/merge-back-runner.js +5 -5
  97. package/dist/services/dispatch/service-shutdown.js +3 -3
  98. package/dist/services/doc/doc-generator.js +2 -1
  99. package/dist/services/env/shell-probe.js +1 -1
  100. package/dist/services/evidence/evidence-generator.js +86 -49
  101. package/dist/services/final-review/final-review-service.d.ts +9 -0
  102. package/dist/services/final-review/final-review-service.js +36 -12
  103. package/dist/services/fuzzy-matching/fzf-pick-service.js +2 -0
  104. package/dist/services/hooks/auto-compact-hook-install.d.ts +10 -2
  105. package/dist/services/hooks/auto-compact-hook-install.js +8 -0
  106. package/dist/services/ide/adapters/claude-code-adapter.d.ts +107 -3
  107. package/dist/services/ide/adapters/claude-code-adapter.js +154 -7
  108. package/dist/services/ide/ide-registry.d.ts +31 -0
  109. package/dist/services/ide/ide-registry.js +35 -0
  110. package/dist/services/ide/ide-types.d.ts +59 -0
  111. package/dist/services/job/job-state-store.js +7 -0
  112. package/dist/services/lint/detect-eslint.js +2 -2
  113. package/dist/services/lint/eslint-runner.js +3 -1
  114. package/dist/services/loop/evaluator-dispatcher.js +2 -1
  115. package/dist/services/memory/project-memory-service/index/kind-dispatch.js +1 -1
  116. package/dist/services/memory/project-memory-service/store/paths.d.ts +9 -1
  117. package/dist/services/memory/project-memory-service/store/paths.js +15 -6
  118. package/dist/services/polyrepo/polyrepo-dispatcher.js +11 -0
  119. package/dist/services/prd/best-practice-auto-trigger.js +1 -0
  120. package/dist/services/prd/handoff-auto-regen.js +31 -27
  121. package/dist/services/prd/handoff-frontmatter.d.ts +44 -0
  122. package/dist/services/prd/handoff-frontmatter.js +75 -0
  123. package/dist/services/prd/handoff-service.d.ts +41 -2
  124. package/dist/services/prd/handoff-service.js +81 -8
  125. package/dist/services/prd/handoff-types.d.ts +3 -2
  126. package/dist/services/prd/handoff-types.js +3 -2
  127. package/dist/services/qa/qa-business-review-state.js +9 -0
  128. package/dist/services/release/version-precheck-service.d.ts +2 -1
  129. package/dist/services/release/version-precheck-service.js +82 -12
  130. package/dist/services/runtime/vendor-adapter.d.ts +29 -4
  131. package/dist/services/runtime/vendors/claude-code.js +1 -1
  132. package/dist/services/runtime/vendors/codex.js +1 -1
  133. package/dist/services/runtime/vendors/copilot.js +1 -1
  134. package/dist/services/sc/sc-service.js +1 -1
  135. package/dist/services/scan/diff-scope-service.js +2 -2
  136. package/dist/services/scan/file-size-scan.js +2 -2
  137. package/dist/services/scan/karpathy-service.js +2 -2
  138. package/dist/services/scan/orphan-service.js +2 -1
  139. package/dist/services/scan/type-sanity-service.js +2 -2
  140. package/dist/services/session/session-checkpoint-service.js +8 -0
  141. package/dist/services/skill/resume-detector.js +29 -11
  142. package/dist/services/skillhub/tar-runtime.js +1 -0
  143. package/dist/services/skills/hooks-codegate-superpowers.d.ts +14 -0
  144. package/dist/services/skills/hooks-codegate-superpowers.js +99 -3
  145. package/dist/services/skills/hooks-settings-service.d.ts +12 -0
  146. package/dist/services/skills/hooks-settings-service.js +91 -14
  147. package/dist/services/skills/session-start-hook-constants.d.ts +86 -0
  148. package/dist/services/skills/session-start-hook-constants.js +86 -0
  149. package/dist/services/skills/skill-presence-service.js +9 -0
  150. package/dist/services/skills/skill-statusline-service.d.ts +14 -0
  151. package/dist/services/slice/slice-check-service.js +31 -12
  152. package/dist/services/slice/slice-decompose-runners.js +2 -1
  153. package/dist/services/slice/slice-review-state.js +8 -0
  154. package/dist/services/upgrade/upgrade-service.js +1 -0
  155. package/dist/services/workflow/pipeline-verify-gate-support.d.ts +47 -10
  156. package/dist/services/workflow/pipeline-verify-gate-support.js +212 -93
  157. package/dist/services/workflow/pipeline-verify-service.js +24 -23
  158. package/dist/services/workflow/pipeline-verify-types.d.ts +10 -3
  159. package/dist/services/workflow/workflow-skip-service.js +2 -1
  160. package/dist/services/workspace/claude-settings-template.d.ts +56 -8
  161. package/dist/services/workspace/claude-settings-template.js +98 -20
  162. package/dist/services/workspace/migrate-service.js +1 -1
  163. package/dist/services/workspace/workspace-claude-settings-materializer.js +124 -9
  164. package/dist/services/workspace/workspace-service.js +8 -0
  165. package/dist/services/worktree/host-worktree-reconciler.js +1 -0
  166. package/dist/services/worktree/long-path-cleanup.js +3 -2
  167. package/dist/shared/process.js +1 -1
  168. package/package.json +6 -6
  169. package/scripts/install-skills.mjs +1 -0
  170. package/scripts/watch.mjs +3 -1
  171. package/skills/bee/peaks-perf-audit/SKILL.md +1 -1
  172. package/skills/bee/peaks-prd/SKILL.md +8 -6
  173. package/skills/bee/peaks-qa/SKILL.md +7 -7
  174. package/skills/bee/peaks-qa/references/qa-runbook.md +2 -2
  175. package/skills/bee/peaks-qa/references/qa-transition-gates.md +7 -7
  176. package/skills/bee/peaks-rd/SKILL.md +10 -8
  177. package/skills/bee/peaks-rd/references/artifact-per-request.md +2 -2
  178. package/skills/bee/peaks-rd/references/parallel-review-fanout.md +7 -5
  179. package/skills/bee/peaks-rd/references/rd-fanout-contracts.md +13 -13
  180. package/skills/bee/peaks-rd/references/rd-runbook.md +9 -5
  181. package/skills/bee/peaks-rd/references/rd-transition-gates.md +9 -7
  182. package/skills/bee/peaks-rd/references/writing-handoff-frontmatter.md +6 -6
  183. package/skills/bee/peaks-reviewer/SKILL.md +1 -1
  184. package/skills/bee/peaks-sc/SKILL.md +1 -1
  185. package/skills/bee/peaks-security-audit/SKILL.md +1 -1
  186. package/skills/bee/peaks-txt/SKILL.md +1 -1
  187. package/skills/bee/peaks-ui/SKILL.md +1 -1
  188. package/skills/peaks-audit/SKILL.md +1 -1
  189. package/skills/peaks-code/SKILL.md +3 -3
  190. package/skills/peaks-code/references/a2a-artifact-mapping.md +3 -3
  191. package/skills/peaks-code/references/local-artifact-workspace.md +1 -1
  192. package/skills/peaks-code/references/resume-detection.md +13 -7
  193. package/skills/peaks-code/references/runbook.md +3 -2
  194. package/skills/peaks-code/references/session-overload-signal-index.md +2 -1
  195. package/skills/peaks-code/references/sub-agent-dispatch.md +1 -1
  196. package/skills/peaks-code/references/workflow-gates-and-types.md +8 -6
  197. package/skills/peaks-content/SKILL.md +1 -1
  198. package/skills/peaks-doctor/SKILL.md +1 -1
  199. package/skills/peaks-final-review/SKILL.md +1 -1
  200. package/skills/peaks-ide/SKILL.md +1 -1
  201. package/skills/peaks-issue-fix-orchestrator/SKILL.md +1 -1
  202. package/skills/peaks-resume/SKILL.md +1 -1
  203. package/skills/peaks-slice-decompose/SKILL.md +1 -1
  204. package/skills/peaks-solo/SKILL.md +1 -1
  205. package/skills/peaks-sop/SKILL.md +1 -1
  206. package/skills/peaks-status/SKILL.md +1 -1
  207. package/skills/peaks-test/SKILL.md +1 -1
@@ -25,6 +25,47 @@
25
25
  */
26
26
  /** Sentinel substring identifying a SessionStart outer-cache hook entry. */
27
27
  export declare const HOOK_OUTER_CACHE_SENTINEL = "peaks outer-cache write";
28
+ /**
29
+ * rid `2026-09-13-a2-post-compact-reinject` — SessionStart entry scoped to
30
+ * `matcher: 'compact'` that puts the engineering state back into the context
31
+ * a compaction just emptied.
32
+ *
33
+ * This is the official mechanism, and the `matcher` is the load-bearing part
34
+ * of it: Claude Code adds a `SessionStart` hook's plain-text stdout to the
35
+ * context, and scoping to `compact` means the card is re-injected AFTER a
36
+ * compaction rather than on every fresh session. Compaction itself cannot be
37
+ * initiated from here — the harness performs it, and a hook can only observe
38
+ * or veto. Re-injection is the half that IS available to us.
39
+ *
40
+ * Why a separate entry instead of folding this into the `peaks session
41
+ * primer` entry that already runs on every SessionStart: the primer's own
42
+ * contract is "rotation + presence cleanup", it fires on `startup` too (where
43
+ * the dispatch context is still in the history and the card would be noise),
44
+ * and its output is a rotation envelope rather than an engineering-state
45
+ * card. Two entries, two intents — each one's output means exactly one thing.
46
+ */
47
+ export declare const HOOK_POST_COMPACT_REINJECT_SENTINEL = "peaks session reinject";
48
+ /**
49
+ * The reinject hook command. `--project "${CLAUDE_PROJECT_DIR}"` matches the
50
+ * other two SessionStart entries: `${CLAUDE_PROJECT_DIR}` is Claude Code's
51
+ * standard project-root convention, and the CLI resolves it strictly (a
52
+ * SessionStart payload is env-driven and must not be trusted as a path).
53
+ *
54
+ * `--quiet-failure` is NOT a flag and deliberately so: printing nothing on
55
+ * failure is this command's unconditional behaviour, not something a caller
56
+ * opts into. See `reinject-command.ts` — stdout IS context here, so an error
57
+ * message on stdout would be injected into the model's context as though
58
+ * peaks-loop meant it.
59
+ */
60
+ export declare const HOOK_POST_COMPACT_REINJECT_COMMAND = "peaks session reinject --project \"${CLAUDE_PROJECT_DIR}\"";
61
+ /** SessionStart hook event key (same as outer-cache + primer). */
62
+ export declare const HOOK_POST_COMPACT_REINJECT_EVENT = "SessionStart";
63
+ /**
64
+ * The SessionStart `source` value the re-injection is scoped to. Claude Code
65
+ * reports `compact` as the SessionStart source when the session is resuming
66
+ * from a compaction; the hook entry's `matcher` is matched against it.
67
+ */
68
+ export declare const HOOK_POST_COMPACT_REINJECT_MATCHER = "compact";
28
69
  /** Default (claude-code) SessionStart hook command. */
29
70
  export declare const HOOK_OUTER_CACHE_COMMAND = "peaks outer-cache write --project \"${CLAUDE_PROJECT_DIR}\"";
30
71
  /** SessionStart hook event key for Claude Code. */
@@ -42,3 +83,48 @@ export declare const HOOK_WORKSPACE_INIT_SENTINEL = "peaks session primer";
42
83
  export declare const HOOK_WORKSPACE_INIT_COMMAND = "peaks session primer --project \"${CLAUDE_PROJECT_DIR}\"";
43
84
  /** SessionStart hook event key (same as outer-cache). */
44
85
  export declare const HOOK_WORKSPACE_INIT_EVENT = "SessionStart";
86
+ /**
87
+ * rid `2026-09-13-compact-event-settle` — the `PostCompact` entry that lets the
88
+ * harness's own event settle a compact, instead of the next `context-now` probe
89
+ * inferring one from a ratio that fell.
90
+ *
91
+ * WHY THIS ENTRY IS NOT A `SessionStart` ONE, despite living in this file: the
92
+ * three entries above all ride `SessionStart` and differ only by matcher. A
93
+ * `PostCompact` hook is a different EVENT that carries the one fact no
94
+ * `SessionStart` payload has — whether the compaction the harness just
95
+ * completed was `auto` or `manual`. That distinction is the whole question
96
+ * ("has this machine ever auto-compacted?"), and without it peaks-loop can only
97
+ * ever see that SOMETHING compacted. See `compact-event-settle.ts` for what the
98
+ * command does with it.
99
+ *
100
+ * WHY THE MATCHER IS THE EMPTY STRING and not the documented `auto|manual`:
101
+ * both trigger values are wanted, so the matcher must filter nothing. An empty
102
+ * matcher is the convention the three `SessionStart` entries already rely on to
103
+ * match every source, and it is the only form that cannot fail SILENTLY — an
104
+ * alternation string is a match-everything pattern under regex semantics but
105
+ * matches NEITHER value under exact-equality semantics, and a hook that never
106
+ * fires looks exactly like a hook with nothing to report.
107
+ */
108
+ export declare const HOOK_COMPACT_SETTLE_SENTINEL = "peaks compact settle";
109
+ /**
110
+ * The settle hook command. `--project "${CLAUDE_PROJECT_DIR}"` is byte-for-byte
111
+ * the shape of the three `SessionStart` entries above — Claude Code's standard
112
+ * project-root convention, resolved strictly on the CLI side (a hook payload is
113
+ * env-driven and must not be trusted as a path).
114
+ *
115
+ * The command prints NOTHING on the hook path and exits 0 for every outcome.
116
+ * `PostCompact`'s stdin/stdout contract is truncated in the retrievable docs,
117
+ * so the safe assumption is the `SessionStart` one — stdout may be added to the
118
+ * model's context. An error message there would be read as a fact. See
119
+ * `compact-event-settle.ts`.
120
+ *
121
+ * No `shell` pin, deliberately: this entry lands in the shared, committed
122
+ * `.claude/settings.json`, and a `powershell` pin there would break every
123
+ * macOS / Linux reader of the file. See `resolveHookEntries`' comment block for
124
+ * the full reason the three `SessionStart` entries are unpinned too.
125
+ */
126
+ export declare const HOOK_COMPACT_SETTLE_COMMAND = "peaks compact settle --project \"${CLAUDE_PROJECT_DIR}\"";
127
+ /** The event this entry rides. Claude Code fires it after a compaction completes. */
128
+ export declare const HOOK_COMPACT_SETTLE_EVENT = "PostCompact";
129
+ /** Matcher: empty = every `trigger` (`auto` and `manual`). See the sentinel doc. */
130
+ export declare const HOOK_COMPACT_SETTLE_MATCHER = "";
@@ -25,6 +25,47 @@
25
25
  */
26
26
  /** Sentinel substring identifying a SessionStart outer-cache hook entry. */
27
27
  export const HOOK_OUTER_CACHE_SENTINEL = 'peaks outer-cache write';
28
+ /**
29
+ * rid `2026-09-13-a2-post-compact-reinject` — SessionStart entry scoped to
30
+ * `matcher: 'compact'` that puts the engineering state back into the context
31
+ * a compaction just emptied.
32
+ *
33
+ * This is the official mechanism, and the `matcher` is the load-bearing part
34
+ * of it: Claude Code adds a `SessionStart` hook's plain-text stdout to the
35
+ * context, and scoping to `compact` means the card is re-injected AFTER a
36
+ * compaction rather than on every fresh session. Compaction itself cannot be
37
+ * initiated from here — the harness performs it, and a hook can only observe
38
+ * or veto. Re-injection is the half that IS available to us.
39
+ *
40
+ * Why a separate entry instead of folding this into the `peaks session
41
+ * primer` entry that already runs on every SessionStart: the primer's own
42
+ * contract is "rotation + presence cleanup", it fires on `startup` too (where
43
+ * the dispatch context is still in the history and the card would be noise),
44
+ * and its output is a rotation envelope rather than an engineering-state
45
+ * card. Two entries, two intents — each one's output means exactly one thing.
46
+ */
47
+ export const HOOK_POST_COMPACT_REINJECT_SENTINEL = 'peaks session reinject';
48
+ /**
49
+ * The reinject hook command. `--project "${CLAUDE_PROJECT_DIR}"` matches the
50
+ * other two SessionStart entries: `${CLAUDE_PROJECT_DIR}` is Claude Code's
51
+ * standard project-root convention, and the CLI resolves it strictly (a
52
+ * SessionStart payload is env-driven and must not be trusted as a path).
53
+ *
54
+ * `--quiet-failure` is NOT a flag and deliberately so: printing nothing on
55
+ * failure is this command's unconditional behaviour, not something a caller
56
+ * opts into. See `reinject-command.ts` — stdout IS context here, so an error
57
+ * message on stdout would be injected into the model's context as though
58
+ * peaks-loop meant it.
59
+ */
60
+ export const HOOK_POST_COMPACT_REINJECT_COMMAND = `peaks session reinject --project "\${CLAUDE_PROJECT_DIR}"`;
61
+ /** SessionStart hook event key (same as outer-cache + primer). */
62
+ export const HOOK_POST_COMPACT_REINJECT_EVENT = 'SessionStart';
63
+ /**
64
+ * The SessionStart `source` value the re-injection is scoped to. Claude Code
65
+ * reports `compact` as the SessionStart source when the session is resuming
66
+ * from a compaction; the hook entry's `matcher` is matched against it.
67
+ */
68
+ export const HOOK_POST_COMPACT_REINJECT_MATCHER = 'compact';
28
69
  /** Default (claude-code) SessionStart hook command. */
29
70
  export const HOOK_OUTER_CACHE_COMMAND = `peaks outer-cache write --project "\${CLAUDE_PROJECT_DIR}"`;
30
71
  /** SessionStart hook event key for Claude Code. */
@@ -42,3 +83,48 @@ export const HOOK_WORKSPACE_INIT_SENTINEL = 'peaks session primer';
42
83
  export const HOOK_WORKSPACE_INIT_COMMAND = `peaks session primer --project "\${CLAUDE_PROJECT_DIR}"`;
43
84
  /** SessionStart hook event key (same as outer-cache). */
44
85
  export const HOOK_WORKSPACE_INIT_EVENT = 'SessionStart';
86
+ /**
87
+ * rid `2026-09-13-compact-event-settle` — the `PostCompact` entry that lets the
88
+ * harness's own event settle a compact, instead of the next `context-now` probe
89
+ * inferring one from a ratio that fell.
90
+ *
91
+ * WHY THIS ENTRY IS NOT A `SessionStart` ONE, despite living in this file: the
92
+ * three entries above all ride `SessionStart` and differ only by matcher. A
93
+ * `PostCompact` hook is a different EVENT that carries the one fact no
94
+ * `SessionStart` payload has — whether the compaction the harness just
95
+ * completed was `auto` or `manual`. That distinction is the whole question
96
+ * ("has this machine ever auto-compacted?"), and without it peaks-loop can only
97
+ * ever see that SOMETHING compacted. See `compact-event-settle.ts` for what the
98
+ * command does with it.
99
+ *
100
+ * WHY THE MATCHER IS THE EMPTY STRING and not the documented `auto|manual`:
101
+ * both trigger values are wanted, so the matcher must filter nothing. An empty
102
+ * matcher is the convention the three `SessionStart` entries already rely on to
103
+ * match every source, and it is the only form that cannot fail SILENTLY — an
104
+ * alternation string is a match-everything pattern under regex semantics but
105
+ * matches NEITHER value under exact-equality semantics, and a hook that never
106
+ * fires looks exactly like a hook with nothing to report.
107
+ */
108
+ export const HOOK_COMPACT_SETTLE_SENTINEL = 'peaks compact settle';
109
+ /**
110
+ * The settle hook command. `--project "${CLAUDE_PROJECT_DIR}"` is byte-for-byte
111
+ * the shape of the three `SessionStart` entries above — Claude Code's standard
112
+ * project-root convention, resolved strictly on the CLI side (a hook payload is
113
+ * env-driven and must not be trusted as a path).
114
+ *
115
+ * The command prints NOTHING on the hook path and exits 0 for every outcome.
116
+ * `PostCompact`'s stdin/stdout contract is truncated in the retrievable docs,
117
+ * so the safe assumption is the `SessionStart` one — stdout may be added to the
118
+ * model's context. An error message there would be read as a fact. See
119
+ * `compact-event-settle.ts`.
120
+ *
121
+ * No `shell` pin, deliberately: this entry lands in the shared, committed
122
+ * `.claude/settings.json`, and a `powershell` pin there would break every
123
+ * macOS / Linux reader of the file. See `resolveHookEntries`' comment block for
124
+ * the full reason the three `SessionStart` entries are unpinned too.
125
+ */
126
+ export const HOOK_COMPACT_SETTLE_COMMAND = `peaks compact settle --project "\${CLAUDE_PROJECT_DIR}"`;
127
+ /** The event this entry rides. Claude Code fires it after a compaction completes. */
128
+ export const HOOK_COMPACT_SETTLE_EVENT = 'PostCompact';
129
+ /** Matcher: empty = every `trigger` (`auto` and `manual`). See the sentinel doc. */
130
+ export const HOOK_COMPACT_SETTLE_MATCHER = '';
@@ -604,6 +604,15 @@ export function clearSkillPresence(projectRootOverride) {
604
604
  // shim; the LLM runner calls `peaks workflow terminalize` or
605
605
  // `terminalizePresenceLease` directly).
606
606
  //
607
+ // That rule is the surrounding DESIGN, not a description of this
608
+ // function: nothing below routes anywhere. This shim has no session
609
+ // lock, no lease argument and no workflow id, so it cannot route —
610
+ // it cleans up deprecated files and returns whether it removed any.
611
+ // The truthful report of what remains is the caller's job
612
+ // (`skill-command.ts` re-reads the live projection and emits
613
+ // `cleared` / `reason`). Do not read the paragraph above as a
614
+ // promise about this function.
615
+ //
607
616
  // The shim still removes the legacy `active-skill.json` /
608
617
  // `.peaks/.active-skill.json` so a stale marker from a prior CLI
609
618
  // version cannot resurrect after a fresh `clear`. The canonical
@@ -7,6 +7,20 @@ export type StatusLineStdin = {
7
7
  cwd?: string;
8
8
  session_id?: string;
9
9
  caller_id?: string;
10
+ /**
11
+ * The harness's own context numbers. Declared here because this type IS the
12
+ * documented shape of the payload the harness pipes in; omitting a documented
13
+ * field would make the type lie by omission, and a consumer that reached for
14
+ * it would have to cast. Read (never written) by
15
+ * `harness-context-witness.ts` — see that module for why
16
+ * `context_window_size` is NOT a denominator.
17
+ */
18
+ context_window?: {
19
+ context_window_size?: unknown;
20
+ used_percentage?: unknown;
21
+ remaining_percentage?: unknown;
22
+ current_usage?: Record<string, unknown> | undefined;
23
+ } | undefined;
10
24
  };
11
25
  export type StatusLineState = 'active' | 'idle' | 'stale' | 'invalid-presence';
12
26
  export type StatusLinePresence = {
@@ -8,6 +8,7 @@ import { isDirectory } from 'peaks-loop-shared/fs';
8
8
  // is no longer read. Path-safety helpers now live at
9
9
  // `shared/path-safety.ts` if this module ever needs them.
10
10
  import { verifyPipeline } from '../workflow/pipeline-verify-service.js';
11
+ import { REQUEST_ID_PATTERN } from '../artifacts/request-artifact-service.js';
11
12
  import { findMockViolations } from '../audit/enforcers/mock-placement.js';
12
13
  import { runRedLinesAudit } from '../audit/red-lines-service.js';
13
14
  /**
@@ -96,7 +97,8 @@ function runCommand(command, args, cwd, timeoutMs) {
96
97
  cwd,
97
98
  stdio: ['ignore', 'pipe', 'pipe'],
98
99
  timeout: timeoutMs,
99
- maxBuffer: EXEC_MAX_BUFFER_BYTES
100
+ maxBuffer: EXEC_MAX_BUFFER_BYTES,
101
+ windowsHide: true
100
102
  }).toString('utf8');
101
103
  return {
102
104
  status: 'pass',
@@ -238,20 +240,29 @@ async function runUnitTests(projectRoot, runTests) {
238
240
  }
239
241
  };
240
242
  }
243
+ // Slice `2026-09-14-audit-artifact-rid-scoping`: the evidence filenames
244
+ // carry the rid now. Candidate order is canonical-first, then the
245
+ // back-compat tiers — the same order `artifact-prerequisites.ts` resolves
246
+ // in, so this boundary gate and the transition gate agree on which file is
247
+ // a slice's evidence. `<rid>` is substituted at probe time.
241
248
  const REVIEW_FILES = [
242
- { name: 'code-review', path: 'rd/code-review.md', label: 'code-review' },
249
+ {
250
+ name: 'code-review',
251
+ paths: ['rd/code-review-<rid>.md', 'rd/code-review.md'],
252
+ label: 'code-review'
253
+ },
243
254
  // v2.12.0 collapse: security + perf moved to standalone audit skills.
244
- // `slice check` accepts EITHER the v2.11.x legacy path OR the v2.12.0
245
- // canonical audit path during the 1-minor-release back-compat window
246
- // (v2.13.0 hard-deletes the legacy paths — see CHANGELOG [2.12.0]).
255
+ // `slice check` accepts the rid-scoped audit path, the bare v2.12.0 path
256
+ // OR the v2.11.x legacy path during the 1-minor-release back-compat
257
+ // window (v2.13.0 hard-deletes the legacy paths — see CHANGELOG [2.12.0]).
247
258
  {
248
259
  name: 'security-review',
249
- paths: ['audit/security.md', 'rd/security-review.md'],
260
+ paths: ['audit/security-<rid>.md', 'audit/security.md', 'rd/security-review.md'],
250
261
  label: 'security-review'
251
262
  },
252
263
  {
253
264
  name: 'perf-baseline',
254
- paths: ['audit/perf.md', 'rd/perf-baseline.md'],
265
+ paths: ['audit/perf-<rid>.md', 'audit/perf.md', 'rd/perf-baseline.md'],
255
266
  label: 'perf-baseline'
256
267
  }
257
268
  ];
@@ -283,11 +294,11 @@ async function runReviewFanout(projectRoot, rid, refresh) {
283
294
  const found = [];
284
295
  for (const review of REVIEW_FILES) {
285
296
  let hit = null;
286
- // v2.12.0 back-compat: each entry may list multiple candidate paths.
287
- // First hit (in declared order) wins; canonical paths come first so
288
- // v2.12.0+ slices preferentially report the new path even when both
289
- // are present during migration.
290
- const candidates = 'path' in review ? [review.path] : review.paths;
297
+ // Back-compat: each entry lists multiple candidate paths. First hit (in
298
+ // declared order) wins; canonical paths come first so a current slice
299
+ // preferentially reports its own rid-scoped evidence even when a legacy
300
+ // file is also present during migration.
301
+ const candidates = review.paths.map((candidate) => candidate.replace('<rid>', rid));
291
302
  for (const candidate of candidates) {
292
303
  for (const scope of scopes) {
293
304
  const abs = join(projectRoot, '.peaks', scope, candidate);
@@ -366,6 +377,14 @@ export async function sliceCheck(options) {
366
377
  throw new Error('No --rid supplied. Pass --rid <id> on the CLI to identify which slice to check.');
367
378
  }
368
379
  const rid = options.rid;
380
+ // The rid becomes a filename in `runReviewFanout`'s candidate list and a
381
+ // directory segment in its `scopes` — both joined onto the project root. The
382
+ // rid is the repo's own request-id shape, and `request-artifact-service.ts`
383
+ // already refuses anything else; apply the same guard here rather than
384
+ // probing paths a hostile `--rid` steers.
385
+ if (!REQUEST_ID_PATTERN.test(rid)) {
386
+ throw new Error(`Invalid request id: ${rid} (expected letters, digits, dots, underscores, or dashes)`);
387
+ }
369
388
  const totalStart = Date.now();
370
389
  const stages = [];
371
390
  let unitTestsRunMode = 'skipped';
@@ -98,7 +98,8 @@ function runCodegraph(args, projectRoot) {
98
98
  cwd: projectRoot,
99
99
  stdio: ['ignore', 'pipe', 'pipe'],
100
100
  timeout: 60_000,
101
- maxBuffer: 32 * 1024 * 1024
101
+ maxBuffer: 32 * 1024 * 1024,
102
+ windowsHide: true
102
103
  };
103
104
  // Use `peaks codegraph` (the peaks wrapper), which adds --project support.
104
105
  // 2026-09-10: no shell. `peaks` on Windows is a `.cmd` shim, which Node >= 20
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
16
16
  import { dirname, join, resolve } from 'node:path';
17
+ import { isUnsafePathInput } from '../../shared/path-safety.js';
17
18
  /** The 5 default review items per slice (the 12 Gaps memory checklist). */
18
19
  export const DEFAULT_REVIEW_ITEMS = [
19
20
  { id: 'business-match', question: '这个 slice 做完,业务流程对吗?(跟产品最初给的需求匹配)' },
@@ -32,6 +33,13 @@ export function buildEmptySliceReview(sliceId, sessionId, now = new Date()) {
32
33
  };
33
34
  }
34
35
  export function getReviewDir(projectRoot, sessionId) {
36
+ // Sid axis. Every `peaks slice-review|score|accept|reject` subcommand reaches
37
+ // the runtime tree through this one constructor. Measured: `--session-id
38
+ // ../../../../…/PWNED` wrote `slice-reviews/<slice-id>.json` outside every
39
+ // project root under an `ok: true` envelope (RD sweep case A26).
40
+ if (isUnsafePathInput(sessionId)) {
41
+ throw new Error(`Invalid session id: ${sessionId} (must be a single path segment)`);
42
+ }
35
43
  return resolve(projectRoot, '.peaks', '_runtime', sessionId, 'slice-reviews');
36
44
  }
37
45
  export function getReviewPath(projectRoot, sessionId, sliceId) {
@@ -47,6 +47,7 @@ export const defaultSubstepExecutor = (command, args, timeoutMs) => {
47
47
  encoding: 'utf8',
48
48
  stdio: ['ignore', 'pipe', 'pipe'],
49
49
  timeout: timeoutMs,
50
+ windowsHide: true,
50
51
  });
51
52
  return {
52
53
  status: result.status,
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * File budget: ≤ 400 lines (rid-006 split).
10
10
  */
11
- import type { RequestType } from '../artifacts/artifact-prerequisites.js';
11
+ import { type ArtifactPrerequisite, type RequestType } from '../artifacts/artifact-prerequisites.js';
12
+ import type { RequestArtifactRole, RequestArtifactState } from '../artifacts/request-artifact-service.js';
12
13
  import type { PipelineGate } from './pipeline-verify-types.js';
13
14
  export declare function extractState(markdown: string): string;
14
15
  /**
@@ -24,6 +25,38 @@ export declare function findRequestFile(projectRoot: string, role: string, rid:
24
25
  content: string;
25
26
  sessionId: string;
26
27
  } | null>;
28
+ /**
29
+ * Where the CURRENT contract puts one gate's evidence.
30
+ *
31
+ * The contract is the `artifact-prerequisites.ts` table — the table
32
+ * `peaks request transition` enforces and the one the peaks-qa prose
33
+ * contract mirrors (`skills/bee/peaks-qa/references/qa-transition-gates.md`).
34
+ * `probeName` is the location this checker probes today. The contract's
35
+ * `relativePath` is returned first, then its accepted historical locations in
36
+ * the table's own declared order — `legacyRelativePath`, then
37
+ * `legacyRelativePaths` (the same composition `artifact-prerequisites.ts`' own
38
+ * resolver performs, so a hit here and a hit there land on the same file).
39
+ *
40
+ * Returns `null` when the contract carries no prerequisite for that name at
41
+ * all — the artifact was retired and no gate may fail on it.
42
+ *
43
+ * This lookup exists because hard-coding the paths here is what let
44
+ * `verify-pipeline` fall a minor release behind the gate: it kept demanding
45
+ * `rd/security-review.md` as mandatory after the table had demoted that file
46
+ * to a `legacyRelativePath` fallback of `audit/security.md`, and it kept
47
+ * demanding `qa/security-findings-<rid>.md` / `qa/performance-findings-<rid>.md`
48
+ * after the v2.11.0 D1/D4 trim dropped them from `qa:verdict-issued`
49
+ * altogether (rid 2026-09-14-verify-pipeline-contract-drift).
50
+ */
51
+ /**
52
+ * The prerequisite the contract carries for `probeName`, or null when it
53
+ * carries none. `contractEvidencePaths` is this object's path projection; the
54
+ * BODY contract (`mustContain` / `mustContainAny` / `headingMustContain`) rides
55
+ * on the same object, which is why `contractBodyViolations` below consults it
56
+ * instead of probing for the file's existence alone.
57
+ */
58
+ export declare function contractPrerequisite(role: RequestArtifactRole, state: RequestArtifactState, requestType: RequestType, probeName: string): ArtifactPrerequisite | null;
59
+ export declare function contractEvidencePaths(role: RequestArtifactRole, state: RequestArtifactState, requestType: RequestType, probeName: string): string[] | null;
27
60
  export declare function rdGatesForType(requestType: RequestType): PipelineGate[];
28
61
  export declare function qaGatesForType(requestType: RequestType): PipelineGate[];
29
62
  export declare const RD_QA_HANDOFF_STATES: Set<string>;
@@ -33,15 +66,19 @@ export interface CanonicalPathTracker {
33
66
  anyEvidenceResolved: boolean;
34
67
  allResolvedPathsCanonical: boolean;
35
68
  }
36
- /** Resolve RD evidence files (tech-doc / bug-analysis / code-review / security-review)
69
+ /** Resolve RD evidence files (prd-handoff / bug-analysis / code-review / security-review / perf-baseline)
37
70
  * by probing canonical + legacy paths for each gate. Mutates the gate.passed /
38
71
  * gate.detail fields in place and pushes violations / nextActions. Returns the
39
72
  * updated tracker. Verbatim-move from `pipeline-verify-service.ts`. */
40
- export declare function resolveRdEvidencePaths(gates: PipelineGate[], rdEvidenceDir: string, projectRoot: string, violations: string[], nextActions: string[], tracker: CanonicalPathTracker): CanonicalPathTracker;
41
- /** Resolve QA evidence files (test-cases / test-report / security-findings /
42
- * performance-findings) by probing canonical + legacy paths for each gate.
43
- * For security/perf findings, delegates to the artifact-paths resolver.
44
- * Mutates the gate.passed / gate.detail fields in place and pushes
45
- * violations / nextActions. Returns the updated tracker. Verbatim-move
46
- * from `pipeline-verify-service.ts`. */
47
- export declare function resolveQaEvidencePaths(gates: PipelineGate[], projectRoot: string, rdEvidenceDir: string, changeIdForResolver: string, rid: string, violations: string[], nextActions: string[], tracker: CanonicalPathTracker): CanonicalPathTracker;
73
+ export declare function resolveRdEvidencePaths(gates: PipelineGate[], rdEvidenceDir: string, projectRoot: string, rid: string, requestType: RequestType, violations: string[], nextActions: string[], tracker: CanonicalPathTracker): CanonicalPathTracker;
74
+ /** Resolve QA evidence files (test-cases / test-report) by probing canonical
75
+ * + legacy paths for each gate. Mutates the gate.passed / gate.detail fields
76
+ * in place and pushes violations / nextActions. Returns the updated tracker.
77
+ * Verbatim-move from `pipeline-verify-service.ts`.
78
+ *
79
+ * The `security-findings` / `performance-findings` branches that used to live
80
+ * here are gone: those artifacts are not in any `qa:verdict-issued` table
81
+ * (v2.11.0 D1/D4), and the evidence they stood for is resolved on the RD side
82
+ * at the contract's own paths (`audit/security-<rid>.md`,
83
+ * `audit/perf-<rid>.md`). */
84
+ export declare function resolveQaEvidencePaths(gates: PipelineGate[], projectRoot: string, rdEvidenceDir: string, requestType: RequestType, rid: string, violations: string[], nextActions: string[], tracker: CanonicalPathTracker): CanonicalPathTracker;