peaks-loop 4.0.45 → 4.0.47

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 (137) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README-en.md +1 -1
  3. package/README.md +1 -1
  4. package/dist/cli/commands/code-runtime-commands.d.ts +22 -0
  5. package/dist/cli/commands/code-runtime-commands.js +128 -34
  6. package/dist/cli/commands/compact-command.js +129 -1
  7. package/dist/cli/commands/container-commands.js +3 -3
  8. package/dist/cli/commands/core/skill-command.js +45 -10
  9. package/dist/cli/commands/cron-commands.js +2 -1
  10. package/dist/cli/commands/e2e-verify.js +3 -3
  11. package/dist/cli/commands/governance-classify-contract-commands.js +1 -0
  12. package/dist/cli/commands/hooks-commands.js +10 -1
  13. package/dist/cli/commands/loop-commands.js +1 -0
  14. package/dist/cli/commands/playwright-commands.js +2 -1
  15. package/dist/cli/commands/reinject-command.d.ts +72 -0
  16. package/dist/cli/commands/reinject-command.js +174 -0
  17. package/dist/cli/commands/request-commands.js +6 -3
  18. package/dist/cli/commands/shadcn-commands.js +1 -0
  19. package/dist/cli/commands/test-commands.js +2 -1
  20. package/dist/cli/commands/vm-commands.js +7 -7
  21. package/dist/cli/commands/workspace/init-command.js +24 -2
  22. package/dist/cli/commands/worktree-lease-commands.js +4 -4
  23. package/dist/cli/index.js +49 -2
  24. package/dist/cli/program.js +5 -0
  25. package/dist/hooks/pre-tool-use-sub-agent.js +1 -1
  26. package/dist/services/adapter/adapter-registry.js +1 -1
  27. package/dist/services/artifacts/artifact-service.js +1 -1
  28. package/dist/services/capability-guard-runner/contracts/J01.js +2 -1
  29. package/dist/services/capability-guard-runner/contracts/J02.js +3 -3
  30. package/dist/services/capability-guard-runner/contracts/J04.js +4 -2
  31. package/dist/services/capability-guard-runner/contracts/J07.js +2 -1
  32. package/dist/services/code/auto-compact-lifecycle.d.ts +50 -4
  33. package/dist/services/code/auto-compact-lifecycle.js +52 -10
  34. package/dist/services/code/auto-compact-orchestrator.d.ts +53 -9
  35. package/dist/services/code/auto-compact-orchestrator.js +173 -43
  36. package/dist/services/code/orchestrator-can-do.d.ts +4 -2
  37. package/dist/services/code/orchestrator-can-do.js +37 -5
  38. package/dist/services/codegraph/codegraph-exclude-reconciler.js +2 -1
  39. package/dist/services/codegraph/codegraph-process-runner.js +3 -2
  40. package/dist/services/compact/request-transition-hook.js +5 -2
  41. package/dist/services/compact-history/compact-history-service.d.ts +61 -0
  42. package/dist/services/compact-history/compact-history-service.js +49 -0
  43. package/dist/services/compact-statusline/compact-lifecycle-store.d.ts +11 -2
  44. package/dist/services/compact-statusline/compact-lifecycle-store.js +19 -1
  45. package/dist/services/compact-statusline/compact-statusline-service.d.ts +1 -1
  46. package/dist/services/compact-statusline/compact-statusline-service.js +22 -0
  47. package/dist/services/config/config-safety.d.ts +52 -0
  48. package/dist/services/config/config-safety.js +75 -1
  49. package/dist/services/context/auto-compact-dispatcher.d.ts +7 -37
  50. package/dist/services/context/auto-compact-dispatcher.js +113 -40
  51. package/dist/services/context/auto-compact-reader.d.ts +68 -28
  52. package/dist/services/context/auto-compact-reader.js +155 -1
  53. package/dist/services/context/auto-compact-types.d.ts +89 -12
  54. package/dist/services/context/auto-compact-types.js +16 -32
  55. package/dist/services/context/harness-window-config.d.ts +412 -0
  56. package/dist/services/context/harness-window-config.js +607 -0
  57. package/dist/services/context/main-session-monitor.d.ts +27 -0
  58. package/dist/services/context/main-session-monitor.js +32 -1
  59. package/dist/services/context/post-compact-reinjection.d.ts +221 -0
  60. package/dist/services/context/post-compact-reinjection.js +491 -0
  61. package/dist/services/dispatch/merge-back-runner.js +5 -5
  62. package/dist/services/dispatch/service-shutdown.js +3 -3
  63. package/dist/services/doc/doc-generator.js +2 -1
  64. package/dist/services/env/shell-probe.js +1 -1
  65. package/dist/services/fuzzy-matching/fzf-pick-service.js +2 -0
  66. package/dist/services/hooks/auto-compact-hook-install.d.ts +10 -2
  67. package/dist/services/hooks/auto-compact-hook-install.js +8 -0
  68. package/dist/services/ide/adapters/claude-code-adapter.d.ts +107 -3
  69. package/dist/services/ide/adapters/claude-code-adapter.js +154 -7
  70. package/dist/services/ide/ide-registry.d.ts +12 -0
  71. package/dist/services/ide/ide-registry.js +14 -0
  72. package/dist/services/ide/ide-types.d.ts +59 -0
  73. package/dist/services/lint/detect-eslint.js +2 -2
  74. package/dist/services/lint/eslint-runner.js +3 -1
  75. package/dist/services/loop/evaluator-dispatcher.js +2 -1
  76. package/dist/services/memory/project-memory-service/index/kind-dispatch.js +1 -1
  77. package/dist/services/memory/project-memory-service/store/paths.d.ts +9 -1
  78. package/dist/services/memory/project-memory-service/store/paths.js +15 -6
  79. package/dist/services/prd/best-practice-auto-trigger.js +1 -0
  80. package/dist/services/release/version-precheck-service.d.ts +2 -1
  81. package/dist/services/release/version-precheck-service.js +82 -12
  82. package/dist/services/runtime/vendor-adapter.d.ts +29 -4
  83. package/dist/services/runtime/vendors/claude-code.js +1 -1
  84. package/dist/services/runtime/vendors/codex.js +1 -1
  85. package/dist/services/runtime/vendors/copilot.js +1 -1
  86. package/dist/services/sc/sc-service.js +1 -1
  87. package/dist/services/scan/diff-scope-service.js +2 -2
  88. package/dist/services/scan/file-size-scan.js +2 -2
  89. package/dist/services/scan/orphan-service.js +2 -1
  90. package/dist/services/scan/type-sanity-service.js +2 -2
  91. package/dist/services/skillhub/tar-runtime.js +1 -0
  92. package/dist/services/skills/hooks-codegate-superpowers.d.ts +8 -0
  93. package/dist/services/skills/hooks-codegate-superpowers.js +40 -3
  94. package/dist/services/skills/hooks-settings-service.d.ts +12 -0
  95. package/dist/services/skills/hooks-settings-service.js +77 -10
  96. package/dist/services/skills/session-start-hook-constants.d.ts +41 -0
  97. package/dist/services/skills/session-start-hook-constants.js +41 -0
  98. package/dist/services/skills/skill-presence-service.js +9 -0
  99. package/dist/services/skills/skill-statusline-renderer.js +30 -5
  100. package/dist/services/skills/statusline-palette.d.ts +6 -0
  101. package/dist/services/skills/statusline-palette.js +4 -1
  102. package/dist/services/slice/slice-check-service.js +2 -1
  103. package/dist/services/slice/slice-decompose-runners.js +2 -1
  104. package/dist/services/upgrade/upgrade-service.js +1 -0
  105. package/dist/services/workflow/workflow-skip-service.js +2 -1
  106. package/dist/services/workspace/migrate-service.js +1 -1
  107. package/dist/services/workspace/workspace-claude-settings-materializer.js +51 -7
  108. package/dist/services/workspace/workspace-service.js +8 -0
  109. package/dist/services/worktree/host-worktree-reconciler.js +1 -0
  110. package/dist/services/worktree/long-path-cleanup.js +3 -2
  111. package/dist/shared/process.js +1 -1
  112. package/package.json +5 -5
  113. package/scripts/install-skills.mjs +1 -0
  114. package/scripts/watch.mjs +3 -1
  115. package/skills/bee/peaks-perf-audit/SKILL.md +1 -1
  116. package/skills/bee/peaks-prd/SKILL.md +1 -1
  117. package/skills/bee/peaks-qa/SKILL.md +2 -2
  118. package/skills/bee/peaks-rd/SKILL.md +2 -2
  119. package/skills/bee/peaks-reviewer/SKILL.md +1 -1
  120. package/skills/bee/peaks-sc/SKILL.md +1 -1
  121. package/skills/bee/peaks-security-audit/SKILL.md +1 -1
  122. package/skills/bee/peaks-txt/SKILL.md +1 -1
  123. package/skills/bee/peaks-ui/SKILL.md +1 -1
  124. package/skills/peaks-audit/SKILL.md +1 -1
  125. package/skills/peaks-code/SKILL.md +4 -4
  126. package/skills/peaks-code/references/sub-agent-dispatch.md +1 -1
  127. package/skills/peaks-content/SKILL.md +1 -1
  128. package/skills/peaks-doctor/SKILL.md +1 -1
  129. package/skills/peaks-final-review/SKILL.md +1 -1
  130. package/skills/peaks-ide/SKILL.md +1 -1
  131. package/skills/peaks-issue-fix-orchestrator/SKILL.md +1 -1
  132. package/skills/peaks-resume/SKILL.md +1 -1
  133. package/skills/peaks-slice-decompose/SKILL.md +1 -1
  134. package/skills/peaks-solo/SKILL.md +1 -1
  135. package/skills/peaks-sop/SKILL.md +1 -1
  136. package/skills/peaks-status/SKILL.md +1 -1
  137. package/skills/peaks-test/SKILL.md +1 -1
@@ -6,10 +6,10 @@ const STATES = ['spec-locked', 'implemented', 'qa-handoff', 'handed-off'];
6
6
  export async function runJ02Contract(ctx, projectRoot = ctx.projectRoot) {
7
7
  const bin = join(ctx.projectRoot, 'bin', 'peaks.js');
8
8
  const tmp = mkdtempSync(join(tmpdir(), 'cbl-J02-'));
9
- const ws = execFileSync('node', [bin, 'workspace', 'init', '--project', tmp, '--json'], { cwd: tmp }).toString('utf8');
9
+ const ws = execFileSync('node', [bin, 'workspace', 'init', '--project', tmp, '--json'], { cwd: tmp, windowsHide: true }).toString('utf8');
10
10
  const { data: { sessionId } } = JSON.parse(ws);
11
11
  const rid = '2026-08-03-j02-fixture';
12
- const initOut = execFileSync('node', [bin, 'request', 'init', '--role', 'rd', '--id', rid, '--project', tmp, '--session-id', sessionId, '--apply', '--json'], { cwd: tmp }).toString('utf8');
12
+ const initOut = execFileSync('node', [bin, 'request', 'init', '--role', 'rd', '--id', rid, '--project', tmp, '--session-id', sessionId, '--apply', '--json'], { cwd: tmp, windowsHide: true }).toString('utf8');
13
13
  const initEnv = JSON.parse(initOut);
14
14
  // `request init` writes the file as `NNN-<id-slug>.md`. The transition CLI accepts
15
15
  // the file's basename (without .md) as the requestId. Derive it from data.path.
@@ -19,7 +19,7 @@ export async function runJ02Contract(ctx, projectRoot = ctx.projectRoot) {
19
19
  for (const s of STATES) {
20
20
  const out = execFileSync('node', [bin, 'request', 'transition', requestId, '--role', 'rd', '--state', s,
21
21
  '--project', tmp, '--session-id', sessionId, '--confirm', '--allow-incomplete',
22
- '--reason', 'J02 contract fixture', '--json'], { cwd: tmp }).toString('utf8');
22
+ '--reason', 'J02 contract fixture', '--json'], { cwd: tmp, windowsHide: true }).toString('utf8');
23
23
  const env = JSON.parse(out);
24
24
  last = env.data.state;
25
25
  }
@@ -10,7 +10,8 @@ export async function runJ04Contract(ctx) {
10
10
  try {
11
11
  const stdout = execFileSync('node', [bin, 'audit', 'goal', '--help'], {
12
12
  cwd: ctx.projectRoot,
13
- env: { ...process.env, PEAKS_CALLER_ID: `guard-J04-${ctx.sessionId}` }
13
+ env: { ...process.env, PEAKS_CALLER_ID: `guard-J04-${ctx.sessionId}` },
14
+ windowsHide: true
14
15
  }).toString('utf8');
15
16
  helpOk = stdout.length > 0 && !stdout.includes('unknown command');
16
17
  }
@@ -23,7 +24,8 @@ export async function runJ04Contract(ctx) {
23
24
  execFileSync('node', [bin, 'audit', 'goal', '--project', tmp, '--json'], {
24
25
  cwd: ctx.projectRoot,
25
26
  env: { ...process.env, PEAKS_CALLER_ID: `guard-J04-${ctx.sessionId}` },
26
- stdio: ['ignore', 'pipe', 'pipe']
27
+ stdio: ['ignore', 'pipe', 'pipe'],
28
+ windowsHide: true
27
29
  });
28
30
  }
29
31
  catch (e) {
@@ -19,7 +19,8 @@ export async function runJ07Contract(ctx) {
19
19
  const out = execFileSync('node', [bin, 'test', '--help'], {
20
20
  cwd: ctx.projectRoot,
21
21
  env: { ...process.env, PEAKS_CALLER_ID: `guard-J07-${ctx.sessionId}` },
22
- stdio: ['ignore', 'pipe', 'pipe']
22
+ stdio: ['ignore', 'pipe', 'pipe'],
23
+ windowsHide: true
23
24
  }).toString('utf8');
24
25
  helpOk = out.length > 0 && !out.includes('unknown command');
25
26
  }
@@ -16,8 +16,35 @@ import { type CompactLifecycleRecord, type CompactLifecycleStage } from '../comp
16
16
  * Stages a compact *attempt* can prove from inside the dispatching
17
17
  * process. `verifying` / `completed` are deliberately absent — see
18
18
  * `CompactLifecyclePublisher` and `settleOpenLifecycleRun` for why.
19
+ *
20
+ * `armed` is the honest resting stage for a dispatch that only
21
+ * REGISTERED a trigger (slice 2026-09-12-compact-band-policy, defect B)
22
+ * — see `resolveDispatchedStage`.
23
+ */
24
+ type ObservableDispatchStage = Extract<CompactLifecycleStage, 'queued' | 'preparing' | 'compacting' | 'armed'>;
25
+ /** Stage a failure is attributed to (mirrors the store's `failedAt` domain). */
26
+ type FailableStage = Exclude<CompactLifecycleStage, 'failed' | 'completed'>;
27
+ /**
28
+ * Slice 2026-09-12-compact-band-policy (defect B): which stage a
29
+ * *successful* dispatch can honestly claim.
30
+ *
31
+ * A dispatch is only evidence that a compact is IN FLIGHT when the
32
+ * adapter's own trigger is already satisfied. claude-code's
33
+ * `ide-native` pathway installs a PreToolUse hook that compacts
34
+ * in-band at ratio ≥ 0.95 (`AUTO_COMPACT_RED_LINE_RATIO`); at or above
35
+ * that ratio the very next tool call fires it, so `compacting` (and
36
+ * therefore `stalled` if it never lands) is the truthful reading.
37
+ *
38
+ * Below it — and for every pathway that only writes an intent
39
+ * (`llm-self-compress`), or whose shell-exec branch is a deprecated
40
+ * no-op — NOTHING is compacting. The process merely ARMED a trigger.
41
+ * Recording `compacting` there published a heartbeat nobody would ever
42
+ * send, which is what pinned the statusline at `stalled` forever.
19
43
  */
20
- type ObservableDispatchStage = Extract<CompactLifecycleStage, 'queued' | 'preparing' | 'compacting'>;
44
+ export declare function resolveDispatchedStage(input: {
45
+ readonly pathway: string;
46
+ readonly ratio: number;
47
+ }): Extract<CompactLifecycleStage, 'compacting' | 'armed'>;
21
48
  /**
22
49
  * One id per compact attempt. Timestamp-prefixed so a human reading
23
50
  * the raw record can order runs by eye; the random suffix keeps two
@@ -53,8 +80,17 @@ export declare class CompactLifecyclePublisher {
53
80
  });
54
81
  /** Publish an active stage the process has proved. */
55
82
  advance(stage: ObservableDispatchStage): void;
56
- /** Publish the terminal failure, attributed to the last stage reached. */
57
- fail(error: unknown): void;
83
+ /**
84
+ * Publish the terminal failure, attributed to the last stage reached.
85
+ *
86
+ * `at` overrides that attribution for the case where the failure
87
+ * happened INSIDE a phase that is only named after its outcome
88
+ * (slice 2026-09-12-compact-band-policy): the dispatch call is the
89
+ * compacting phase even though the resting stage is now chosen from
90
+ * the pathway the dispatch returned. `failedAt` names the phase the
91
+ * attempt died in — it is not a published heartbeat.
92
+ */
93
+ fail(error: unknown, at?: FailableStage): void;
58
94
  private write;
59
95
  }
60
96
  /**
@@ -90,6 +126,12 @@ export declare function summarizeLifecycleError(error: unknown): string;
90
126
  * `afterRatio: 0` there would publish a fabricated number;
91
127
  * - the ratio is still at or above the auto-fire threshold — the
92
128
  * compact has not landed, so the run stays open.
129
+ *
130
+ * Returns the settled record, or `null` when nothing settled. Slice
131
+ * 2026-09-13-auto-compact-trigger-ownership: the caller needs the settled
132
+ * `afterRatio` to append the "observed compaction point" row that makes the
133
+ * intent-vs-observed gap readable after a real session. The return value is
134
+ * telemetry only — callers that ignore it are unaffected.
93
135
  */
94
136
  export declare function settleOpenLifecycleRun(input: {
95
137
  readonly projectRoot: string;
@@ -98,5 +140,9 @@ export declare function settleOpenLifecycleRun(input: {
98
140
  readonly source: string;
99
141
  readonly autoFireThreshold: number;
100
142
  readonly onLifecycleStage?: ((stage: CompactLifecycleStage, record: CompactLifecycleRecord) => void) | undefined;
101
- }): void;
143
+ }): {
144
+ readonly runId: string;
145
+ readonly triggerRatio: number;
146
+ readonly afterRatio: number;
147
+ } | null;
102
148
  export {};
@@ -12,6 +12,7 @@
12
12
  * returned envelope.
13
13
  */
14
14
  import { readCompactLifecycle, writeCompactLifecycle } from '../compact-statusline/compact-lifecycle-store.js';
15
+ import { AUTO_COMPACT_RED_LINE_RATIO } from '../context/auto-compact-types.js';
15
16
  /**
16
17
  * PRD-002b slice 2 — extract the few cross-cutting magic numbers
17
18
  * that actually appear at runtime call sites in this orchestrator.
@@ -20,6 +21,28 @@ import { readCompactLifecycle, writeCompactLifecycle } from '../compact-statusli
20
21
  * + spec prose references must keep the literal value visible.
21
22
  */
22
23
  const COLLAPSED_ERROR_MAX_CHARS = 160;
24
+ /**
25
+ * Slice 2026-09-12-compact-band-policy (defect B): which stage a
26
+ * *successful* dispatch can honestly claim.
27
+ *
28
+ * A dispatch is only evidence that a compact is IN FLIGHT when the
29
+ * adapter's own trigger is already satisfied. claude-code's
30
+ * `ide-native` pathway installs a PreToolUse hook that compacts
31
+ * in-band at ratio ≥ 0.95 (`AUTO_COMPACT_RED_LINE_RATIO`); at or above
32
+ * that ratio the very next tool call fires it, so `compacting` (and
33
+ * therefore `stalled` if it never lands) is the truthful reading.
34
+ *
35
+ * Below it — and for every pathway that only writes an intent
36
+ * (`llm-self-compress`), or whose shell-exec branch is a deprecated
37
+ * no-op — NOTHING is compacting. The process merely ARMED a trigger.
38
+ * Recording `compacting` there published a heartbeat nobody would ever
39
+ * send, which is what pinned the statusline at `stalled` forever.
40
+ */
41
+ export function resolveDispatchedStage(input) {
42
+ return input.pathway === 'ide-native' && input.ratio >= AUTO_COMPACT_RED_LINE_RATIO
43
+ ? 'compacting'
44
+ : 'armed';
45
+ }
23
46
  /**
24
47
  * One id per compact attempt. Timestamp-prefixed so a human reading
25
48
  * the raw record can order runs by eye; the random suffix keeps two
@@ -100,8 +123,17 @@ export class CompactLifecyclePublisher {
100
123
  redLine: this.ctx.redLine
101
124
  });
102
125
  }
103
- /** Publish the terminal failure, attributed to the last stage reached. */
104
- fail(error) {
126
+ /**
127
+ * Publish the terminal failure, attributed to the last stage reached.
128
+ *
129
+ * `at` overrides that attribution for the case where the failure
130
+ * happened INSIDE a phase that is only named after its outcome
131
+ * (slice 2026-09-12-compact-band-policy): the dispatch call is the
132
+ * compacting phase even though the resting stage is now chosen from
133
+ * the pathway the dispatch returned. `failedAt` names the phase the
134
+ * attempt died in — it is not a published heartbeat.
135
+ */
136
+ fail(error, at) {
105
137
  this.write({
106
138
  schemaVersion: 1,
107
139
  runId: this.ctx.runId,
@@ -109,7 +141,7 @@ export class CompactLifecyclePublisher {
109
141
  updatedAt: new Date().toISOString(),
110
142
  triggerRatio: this.ctx.triggerRatio,
111
143
  redLine: this.ctx.redLine,
112
- failedAt: this.lastStage,
144
+ failedAt: at ?? this.lastStage,
113
145
  errorSummary: summarizeLifecycleError(error)
114
146
  });
115
147
  }
@@ -182,25 +214,34 @@ export function summarizeLifecycleError(error) {
182
214
  * `afterRatio: 0` there would publish a fabricated number;
183
215
  * - the ratio is still at or above the auto-fire threshold — the
184
216
  * compact has not landed, so the run stays open.
217
+ *
218
+ * Returns the settled record, or `null` when nothing settled. Slice
219
+ * 2026-09-13-auto-compact-trigger-ownership: the caller needs the settled
220
+ * `afterRatio` to append the "observed compaction point" row that makes the
221
+ * intent-vs-observed gap readable after a real session. The return value is
222
+ * telemetry only — callers that ignore it are unaffected.
185
223
  */
186
224
  export function settleOpenLifecycleRun(input) {
187
225
  // A `conservative-fallback` probe means no signal was available at
188
226
  // all. Its `ratio: 0` is the absence of a measurement, so it can
189
227
  // never be evidence that the context shrank.
190
228
  if (input.source === 'conservative-fallback')
191
- return;
229
+ return null;
192
230
  if (input.measuredRatio >= input.autoFireThreshold)
193
- return;
231
+ return null;
194
232
  const prior = readOpenCompactLifecycle({
195
233
  projectRoot: input.projectRoot,
196
234
  sessionId: input.sessionId
197
235
  });
198
236
  if (prior === null)
199
- return;
200
- // Only a run that was actually dispatched (`compacting`) can be
201
- // completed by a post-compact measurement.
202
- if (prior.stage !== 'compacting')
203
- return;
237
+ return null;
238
+ // Only a run that was actually dispatched can be completed by a
239
+ // post-compact measurement. Both `compacting` (the in-band trigger is
240
+ // satisfied) and `armed` (a trigger was registered and could fire at
241
+ // any time) qualify: the measured drop is proof that SOME compact
242
+ // landed, and this is the only open run to attribute it to.
243
+ if (prior.stage !== 'compacting' && prior.stage !== 'armed')
244
+ return null;
204
245
  const emit = (stage, withAfterRatio) => {
205
246
  const record = {
206
247
  schemaVersion: 1,
@@ -232,4 +273,5 @@ export function settleOpenLifecycleRun(input) {
232
273
  emit('verifying', false);
233
274
  // `completed` = the measurement confirms the drop; publish it.
234
275
  emit('completed', true);
276
+ return { runId: prior.runId, triggerRatio: prior.triggerRatio, afterRatio: input.measuredRatio };
235
277
  }
@@ -31,7 +31,21 @@ export interface AutoCompactInput {
31
31
  * autonomously at 0.85+ with zero human / zero LLM intervention.
32
32
  */
33
33
  readonly force?: boolean | undefined;
34
- /** Skip the 95% red-line gate (test seam — never true in production). */
34
+ /**
35
+ * INERT — nothing reads this. It is threaded from the CLI's
36
+ * `--bypass-red-line` (a published flag, kept for backward compatibility;
37
+ * see the option's own note) down to `evaluateAutoCompactDecision`, where the
38
+ * red-line branch ignores it.
39
+ *
40
+ * Why nothing reads it any more: it used to skip a gate that refused to
41
+ * dispatch below 0.85. That gate was removed (slice
42
+ * 2026-09-13-auto-compact-trigger-ownership, T3/A1) — peaks-loop cannot
43
+ * compact a running session, so the refusal could not shorten the wait it
44
+ * was waiting for, and it deadlocked the runner at the worst moment. With the
45
+ * gate gone, the red line still ASKS the harness to compact (when it always
46
+ * did) and no longer needs a bypass. Kept as a field so the published
47
+ * signature does not change under callers that pass it.
48
+ */
35
49
  readonly bypassRedLine?: boolean | undefined;
36
50
  /** Current session id (default = resolve via session-id-service). */
37
51
  readonly sessionId?: string | undefined;
@@ -93,7 +107,7 @@ export interface AutoCompactTestHooks {
93
107
  *
94
108
  * - ratio < preCompact → 'none' or 'soft-warn'
95
109
  * - ratio ≥ preCompact → 'pre-compact' (async-friendly path)
96
- * - ratio ≥ redLine → 'red-line' (synchronous gate)
110
+ * - ratio ≥ redLine → 'red-line' (ask the harness; dispatch continues)
97
111
  *
98
112
  * Slice 2026-07-28 (rid-027): `mode` selects the threshold table.
99
113
  * Default `'standard'` (0.85/0.95). `'partial'` (0.70/0.85) is used
@@ -109,8 +123,13 @@ export declare function evaluateCompactTrigger(ratio: number, mode?: AutoCompact
109
123
  * - 0.85 ≤ ratio < 0.95 → pre-compact; if in-flight batch
110
124
  * present, defer (D6.e); else dispatch
111
125
  * IDE compact asynchronously.
112
- * - ratio ≥ 0.95 → red-line; ALWAYS dispatch synchronously
113
- * regardless of in-flight batch.
126
+ * - ratio ≥ 0.95 → red-line; ask the harness to compact
127
+ * regardless of in-flight batch. Nothing is
128
+ * gated — dispatch is NOT blocked (slice
129
+ * 2026-09-13-auto-compact-trigger-ownership:
130
+ * peaks-loop cannot compact a running session,
131
+ * so a "block" gated nothing and deadlocked the
132
+ * runner).
114
133
  */
115
134
  export declare function evaluateAutoCompactDecision(input: {
116
135
  ratio: number;
@@ -129,6 +148,7 @@ export declare function evaluateAutoCompactDecision(input: {
129
148
  */
130
149
  inflightBatch?: boolean | InFlightBatchProbe | undefined;
131
150
  force?: boolean | undefined;
151
+ /** Accepted and ignored — see `AutoCompactInput.bypassRedLine`. */
132
152
  bypassRedLine?: boolean | undefined;
133
153
  mode?: AutoCompactMode | undefined;
134
154
  /**
@@ -170,13 +190,14 @@ export declare function buildConvergencePlan(input: {
170
190
  * 5. If trigger.kind === 'pre-compact' AND in-flight batch → wait.
171
191
  * 6. If trigger.kind === 'pre-compact' → async dispatch (write
172
192
  * checkpoint + IDE compact; orchestrator returns immediately).
173
- * 7. If trigger.kind === 'red-line' → synchronous gate: refuse
174
- * sub-agent dispatch, dispatch IDE compact, mark `redLineGated`.
193
+ * 7. If trigger.kind === 'red-line' → dispatch the IDE compact, report
194
+ * that the harness has been asked and that dispatch continues.
175
195
  *
176
196
  * The caller (CLI or skill body) handles the actual return — D7's
177
- * post-compact-detect will pick up the checkpoint on the next turn.
178
- * For red-line, the caller MUST block further tool calls until the
179
- * post-compact probe confirms ratio < 0.85.
197
+ * post-compact-detect will pick up the checkpoint on the next turn. For
198
+ * red-line, the caller keeps working; it re-probes and, if the ratio is
199
+ * still rising with no compact from the harness, reports that instead of
200
+ * stalling.
180
201
  */
181
202
  export declare function runAutoCompact(input: AutoCompactInput): Promise<AutoCompactResult>;
182
203
  /** Re-export for callers that need to surface the trigger shape. */
@@ -200,6 +221,29 @@ export interface CompactHistoryEvent {
200
221
  readonly ok: boolean;
201
222
  readonly checkpointPath: string;
202
223
  readonly dispatchMessage: string;
224
+ /**
225
+ * Slice 2026-09-13-auto-compact-trigger-ownership (T4): the calibration
226
+ * instrument. `windowTokens` is the denominator peaks-loop divided by
227
+ * (`probe.capacityTokens`), so `beforeRatio * windowTokens` is the exact
228
+ * TOKEN POINT peaks-loop asked the harness to compact at. That number is
229
+ * the deliverable — NOT a hand-picked threshold: this slice could not run a
230
+ * real Claude Code session, so the real trigger point of
231
+ * `CLAUDE_CODE_AUTO_COMPACT_WINDOW` (documented as a window, observed to
232
+ * fire near the window's end) has no measured answer yet. Recording the
233
+ * intent lets the first real session produce one.
234
+ */
235
+ readonly windowTokens?: number | null;
236
+ /** Which layer produced `windowTokens` (see `ContextWindowSource`). */
237
+ readonly windowSource?: string | null;
238
+ /**
239
+ * `dispatch` (default, and the only kind earlier releases wrote) or
240
+ * `observed` — a row appended when a later probe MEASURED the ratio after
241
+ * a dispatched compact, proving one landed. The pair is what yields the
242
+ * intent-vs-observed delta.
243
+ */
244
+ readonly kind?: 'dispatch' | 'observed';
245
+ /** `observed` rows only: the measured post-compact ratio. */
246
+ readonly afterRatio?: number;
203
247
  }
204
248
  export declare function appendCompactHistoryEvent(input: {
205
249
  readonly projectRoot: string;