peaks-loop 4.0.46 → 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.
- package/CHANGELOG.md +30 -0
- package/README-en.md +1 -1
- package/README.md +1 -1
- package/dist/cli/commands/code-runtime-commands.d.ts +22 -0
- package/dist/cli/commands/code-runtime-commands.js +99 -16
- package/dist/cli/commands/compact-command.js +129 -1
- package/dist/cli/commands/container-commands.js +3 -3
- package/dist/cli/commands/core/skill-command.js +45 -10
- package/dist/cli/commands/cron-commands.js +2 -1
- package/dist/cli/commands/e2e-verify.js +3 -3
- package/dist/cli/commands/governance-classify-contract-commands.js +1 -0
- package/dist/cli/commands/hooks-commands.js +10 -1
- package/dist/cli/commands/loop-commands.js +1 -0
- package/dist/cli/commands/playwright-commands.js +2 -1
- package/dist/cli/commands/reinject-command.d.ts +72 -0
- package/dist/cli/commands/reinject-command.js +174 -0
- package/dist/cli/commands/request-commands.js +6 -3
- package/dist/cli/commands/shadcn-commands.js +1 -0
- package/dist/cli/commands/test-commands.js +2 -1
- package/dist/cli/commands/vm-commands.js +7 -7
- package/dist/cli/commands/workspace/init-command.js +24 -2
- package/dist/cli/commands/worktree-lease-commands.js +4 -4
- package/dist/cli/index.js +49 -2
- package/dist/cli/program.js +5 -0
- package/dist/hooks/pre-tool-use-sub-agent.js +1 -1
- package/dist/services/adapter/adapter-registry.js +1 -1
- package/dist/services/artifacts/artifact-service.js +1 -1
- package/dist/services/capability-guard-runner/contracts/J01.js +2 -1
- package/dist/services/capability-guard-runner/contracts/J02.js +3 -3
- package/dist/services/capability-guard-runner/contracts/J04.js +4 -2
- package/dist/services/capability-guard-runner/contracts/J07.js +2 -1
- package/dist/services/code/auto-compact-lifecycle.d.ts +11 -1
- package/dist/services/code/auto-compact-lifecycle.js +11 -4
- package/dist/services/code/auto-compact-orchestrator.d.ts +53 -9
- package/dist/services/code/auto-compact-orchestrator.js +153 -32
- package/dist/services/code/orchestrator-can-do.d.ts +4 -2
- package/dist/services/code/orchestrator-can-do.js +37 -5
- package/dist/services/codegraph/codegraph-exclude-reconciler.js +2 -1
- package/dist/services/codegraph/codegraph-process-runner.js +3 -2
- package/dist/services/compact/request-transition-hook.js +5 -2
- package/dist/services/compact-history/compact-history-service.d.ts +61 -0
- package/dist/services/compact-history/compact-history-service.js +49 -0
- package/dist/services/config/config-safety.d.ts +52 -0
- package/dist/services/config/config-safety.js +75 -1
- package/dist/services/context/auto-compact-dispatcher.d.ts +7 -37
- package/dist/services/context/auto-compact-dispatcher.js +113 -40
- package/dist/services/context/auto-compact-reader.d.ts +68 -28
- package/dist/services/context/auto-compact-reader.js +155 -1
- package/dist/services/context/auto-compact-types.d.ts +89 -12
- package/dist/services/context/auto-compact-types.js +16 -32
- package/dist/services/context/harness-window-config.d.ts +412 -0
- package/dist/services/context/harness-window-config.js +607 -0
- package/dist/services/context/main-session-monitor.d.ts +27 -0
- package/dist/services/context/main-session-monitor.js +32 -1
- package/dist/services/context/post-compact-reinjection.d.ts +221 -0
- package/dist/services/context/post-compact-reinjection.js +491 -0
- package/dist/services/dispatch/merge-back-runner.js +5 -5
- package/dist/services/dispatch/service-shutdown.js +3 -3
- package/dist/services/doc/doc-generator.js +2 -1
- package/dist/services/env/shell-probe.js +1 -1
- package/dist/services/fuzzy-matching/fzf-pick-service.js +2 -0
- package/dist/services/hooks/auto-compact-hook-install.d.ts +10 -2
- package/dist/services/hooks/auto-compact-hook-install.js +8 -0
- package/dist/services/ide/adapters/claude-code-adapter.d.ts +107 -3
- package/dist/services/ide/adapters/claude-code-adapter.js +154 -7
- package/dist/services/ide/ide-registry.d.ts +12 -0
- package/dist/services/ide/ide-registry.js +14 -0
- package/dist/services/ide/ide-types.d.ts +59 -0
- package/dist/services/lint/detect-eslint.js +2 -2
- package/dist/services/lint/eslint-runner.js +3 -1
- package/dist/services/loop/evaluator-dispatcher.js +2 -1
- package/dist/services/memory/project-memory-service/index/kind-dispatch.js +1 -1
- package/dist/services/memory/project-memory-service/store/paths.d.ts +9 -1
- package/dist/services/memory/project-memory-service/store/paths.js +15 -6
- package/dist/services/prd/best-practice-auto-trigger.js +1 -0
- package/dist/services/release/version-precheck-service.d.ts +2 -1
- package/dist/services/release/version-precheck-service.js +82 -12
- package/dist/services/runtime/vendor-adapter.d.ts +29 -4
- package/dist/services/runtime/vendors/claude-code.js +1 -1
- package/dist/services/runtime/vendors/codex.js +1 -1
- package/dist/services/runtime/vendors/copilot.js +1 -1
- package/dist/services/sc/sc-service.js +1 -1
- package/dist/services/scan/diff-scope-service.js +2 -2
- package/dist/services/scan/file-size-scan.js +2 -2
- package/dist/services/scan/orphan-service.js +2 -1
- package/dist/services/scan/type-sanity-service.js +2 -2
- package/dist/services/skillhub/tar-runtime.js +1 -0
- package/dist/services/skills/hooks-codegate-superpowers.d.ts +8 -0
- package/dist/services/skills/hooks-codegate-superpowers.js +40 -3
- package/dist/services/skills/hooks-settings-service.d.ts +12 -0
- package/dist/services/skills/hooks-settings-service.js +77 -10
- package/dist/services/skills/session-start-hook-constants.d.ts +41 -0
- package/dist/services/skills/session-start-hook-constants.js +41 -0
- package/dist/services/skills/skill-presence-service.js +9 -0
- package/dist/services/slice/slice-check-service.js +2 -1
- package/dist/services/slice/slice-decompose-runners.js +2 -1
- package/dist/services/upgrade/upgrade-service.js +1 -0
- package/dist/services/workflow/workflow-skip-service.js +2 -1
- package/dist/services/workspace/migrate-service.js +1 -1
- package/dist/services/workspace/workspace-claude-settings-materializer.js +51 -7
- package/dist/services/workspace/workspace-service.js +8 -0
- package/dist/services/worktree/host-worktree-reconciler.js +1 -0
- package/dist/services/worktree/long-path-cleanup.js +3 -2
- package/dist/shared/process.js +1 -1
- package/package.json +5 -5
- package/scripts/install-skills.mjs +1 -0
- package/scripts/watch.mjs +3 -1
- package/skills/bee/peaks-perf-audit/SKILL.md +1 -1
- package/skills/bee/peaks-prd/SKILL.md +1 -1
- package/skills/bee/peaks-qa/SKILL.md +2 -2
- package/skills/bee/peaks-rd/SKILL.md +2 -2
- package/skills/bee/peaks-reviewer/SKILL.md +1 -1
- package/skills/bee/peaks-sc/SKILL.md +1 -1
- package/skills/bee/peaks-security-audit/SKILL.md +1 -1
- package/skills/bee/peaks-txt/SKILL.md +1 -1
- package/skills/bee/peaks-ui/SKILL.md +1 -1
- package/skills/peaks-audit/SKILL.md +1 -1
- package/skills/peaks-code/SKILL.md +2 -2
- package/skills/peaks-code/references/sub-agent-dispatch.md +1 -1
- package/skills/peaks-content/SKILL.md +1 -1
- package/skills/peaks-doctor/SKILL.md +1 -1
- package/skills/peaks-final-review/SKILL.md +1 -1
- package/skills/peaks-ide/SKILL.md +1 -1
- package/skills/peaks-issue-fix-orchestrator/SKILL.md +1 -1
- package/skills/peaks-resume/SKILL.md +1 -1
- package/skills/peaks-slice-decompose/SKILL.md +1 -1
- package/skills/peaks-solo/SKILL.md +1 -1
- package/skills/peaks-sop/SKILL.md +1 -1
- package/skills/peaks-status/SKILL.md +1 -1
- package/skills/peaks-test/SKILL.md +1 -1
|
@@ -1,6 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC-1 — auto context-percent probe.
|
|
3
|
+
*
|
|
4
|
+
* Reads the current AI CLI context-fill ratio without requiring the
|
|
5
|
+
* LLM to pass `--prompt-size <bytes>` manually. Strategy: ask the
|
|
6
|
+
* registered `IdeAdapter.compact` profile which env-var to read and,
|
|
7
|
+
* when that misses, ask the adapter for a vendor-specific fallback —
|
|
8
|
+
* no hard-coded IDE names. Per-adapter:
|
|
9
|
+
*
|
|
10
|
+
* - claude-code: its adapter-declared env-var (MVP) + a
|
|
11
|
+
* `readContextPercentFallback` that polls the statusline /
|
|
12
|
+
* transcript (see claude-code-adapter.ts).
|
|
13
|
+
* - trae / codex / cursor / qoder / tongyi-lingma / hermes /
|
|
14
|
+
* openclaw / zcode: each adapter fills its own env-var; until
|
|
15
|
+
* L2-dogfood verifies each surface, adapters may omit `compact`
|
|
16
|
+
* and the probe returns `source: 'conservative-fallback'`.
|
|
17
|
+
*
|
|
18
|
+
* Resolution order (user-overridden → env-var → adapter fallback →
|
|
19
|
+
* conservative-fallback):
|
|
20
|
+
* 1. `promptSizeBytes` (P0 `--prompt-size <bytes>` escape hatch) →
|
|
21
|
+
* `source: 'user-overridden'`.
|
|
22
|
+
* 2. `adapter.compact.envVarForContextPercent` env-var →
|
|
23
|
+
* `source: '<ideId>-env'`.
|
|
24
|
+
* 3. `adapter.compact.readContextPercentFallback?.(input)` — the
|
|
25
|
+
* adapter owns any vendor-specific statusline / transcript probe.
|
|
26
|
+
* 4. `ratio: 0` with `source: 'conservative-fallback'` — the
|
|
27
|
+
* orchestrator MUST NOT auto-fire compact on this signal.
|
|
28
|
+
*/
|
|
29
|
+
import { join } from 'node:path';
|
|
1
30
|
import { detectIdeFromEnv } from './ide-detect.js';
|
|
2
31
|
import { getAdapter } from '../ide/ide-registry.js';
|
|
3
32
|
import { readContextWindowTokensOverride } from '../config/config-service.js';
|
|
33
|
+
import { isHarnessWindowInRange, parseHarnessWindowTokens, readHarnessWindow, syncHarnessWindow } from './harness-window-config.js';
|
|
34
|
+
/**
|
|
35
|
+
* Resolve WHERE the harness auto-compact window lives, for the IDE the
|
|
36
|
+
* current env selects. Returns `null` when either half is undeclared:
|
|
37
|
+
* - the adapter exposes no `compact` profile, or
|
|
38
|
+
* - the adapter's `compact` profile declares no
|
|
39
|
+
* `autoCompactWindowEnvVar` (the IDE has no such knob), or
|
|
40
|
+
* - the adapter declares no machine-local settings layer.
|
|
41
|
+
*
|
|
42
|
+
* Both the path and the key name come from the adapter's OWN declarations,
|
|
43
|
+
* so this module names no IDE and no settings literal — the vendor-neutrality
|
|
44
|
+
* guard's shape-3 rule applies to every registry consumer, and this is one.
|
|
45
|
+
*
|
|
46
|
+
* Slice 2026-09-13-auto-compact-trigger-ownership.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveHarnessWindowLocation(input) {
|
|
49
|
+
const env = input.env ?? process.env;
|
|
50
|
+
const detected = detectIdeFromEnv(env);
|
|
51
|
+
const ideId = (detected === 'unknown' ? 'claude-code' : detected);
|
|
52
|
+
const adapter = getAdapter(ideId);
|
|
53
|
+
const envVar = adapter.compact?.autoCompactWindowEnvVar;
|
|
54
|
+
const fileName = adapter.settings.localSettingsFileName ?? adapter.settings.settingsFileName;
|
|
55
|
+
if (envVar === undefined || fileName === undefined)
|
|
56
|
+
return null;
|
|
57
|
+
return {
|
|
58
|
+
settingsPath: join(input.projectRoot, adapter.settings.dirName, fileName),
|
|
59
|
+
envVar,
|
|
60
|
+
// Carried so the writer can refuse to target the user's own home directory
|
|
61
|
+
// (`--project .` from a fresh terminal): the path alone cannot say which
|
|
62
|
+
// root it came from, and this is the only place a location is built.
|
|
63
|
+
projectRoot: input.projectRoot
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Read the window peaks-loop last configured for the harness, plus whether
|
|
68
|
+
* the user has opted out of peaks-loop managing it. Returns `null` when the
|
|
69
|
+
* active adapter exposes no window knob at all.
|
|
70
|
+
*/
|
|
71
|
+
export function readHarnessWindowState(input) {
|
|
72
|
+
const location = resolveHarnessWindowLocation(input);
|
|
73
|
+
if (location === null)
|
|
74
|
+
return null;
|
|
75
|
+
return readHarnessWindow({ location, env: input.env ?? process.env });
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The RAW window peaks-loop's context ratio must divide by — T1's number.
|
|
79
|
+
*
|
|
80
|
+
* The SETTINGS FILE is the source of truth, so its value wins whenever it has
|
|
81
|
+
* one; the env-first read is consulted only when the file is silent (no key
|
|
82
|
+
* yet, or the IDE injects the value from an outer layer).
|
|
83
|
+
*
|
|
84
|
+
* Why not "whatever the read returned" (the round-2 shape): the process env is
|
|
85
|
+
* a snapshot the harness froze at session start, so it is stale by exactly one
|
|
86
|
+
* write. Trusting it over the file is what let a stale env revert a human's
|
|
87
|
+
* hand-edited window (B1) and downgrade a 1M file to a 200K one (a second
|
|
88
|
+
* session's frozen env), and it is also what made T1's consistency depend on
|
|
89
|
+
* *rewriting the file* — the same unconditional write that destroyed the human's
|
|
90
|
+
* value. Dividing by the file instead makes peaks-loop's ratio and the harness's
|
|
91
|
+
* configured window one number BY CONSTRUCTION, with no write required. The
|
|
92
|
+
* write is then free to be gated on provenance (see `syncHarnessWindow`).
|
|
93
|
+
*
|
|
94
|
+
* Falls back to `undefined` (no harness layer at all) when the adapter
|
|
95
|
+
* declares no knob or neither side carries the key — the adapter then resolves
|
|
96
|
+
* its own window exactly as it did before this slice.
|
|
97
|
+
*/
|
|
98
|
+
export function resolveHarnessRatioWindow(state) {
|
|
99
|
+
if (state === null)
|
|
100
|
+
return undefined;
|
|
101
|
+
// E1 (rid 2026-09-13-defects-e): a value outside the band the harness accepts
|
|
102
|
+
// is not a window, however well-formed an integer it is — the harness ignores
|
|
103
|
+
// or caps it, so handing it over here would make the ratio's denominator a
|
|
104
|
+
// number the harness is not compacting on. This is the read half of the same
|
|
105
|
+
// guard the writer applies before planting one; without it, a value already on
|
|
106
|
+
// disk (hand-planted, or written by a release that predates the band) would
|
|
107
|
+
// keep poisoning the ratio on every probe.
|
|
108
|
+
//
|
|
109
|
+
// The two NULLs are deliberate and different: an out-of-band value is refused
|
|
110
|
+
// here (the adapter falls through to its own resolution and the writer's
|
|
111
|
+
// notice names the skipped number), while an UNPARSEABLE one is still handed
|
|
112
|
+
// over — the adapter validates it and warns about a hand-edited `500k`, which
|
|
113
|
+
// is a closer reading of the user's intent than silently ignoring it.
|
|
114
|
+
const raw = state.fileRaw !== undefined ? state.fileRaw : state.raw;
|
|
115
|
+
const tokens = parseHarnessWindowTokens(raw);
|
|
116
|
+
if (tokens !== null && !isHarnessWindowInRange(tokens))
|
|
117
|
+
return undefined;
|
|
118
|
+
return raw;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Materialize a window into the harness's own settings, so the number
|
|
122
|
+
* peaks-loop divides by and the number the harness compacts against are one
|
|
123
|
+
* value rather than two resolutions (slice
|
|
124
|
+
* 2026-09-13-auto-compact-trigger-ownership).
|
|
125
|
+
*
|
|
126
|
+
* The caller passes the denominator it JUST USED (`probe.capacityTokens`), not
|
|
127
|
+
* a re-derived one — that is what makes the two sides structurally identical.
|
|
128
|
+
* `tokens: null` (a percent-only probe carries no token window) is a
|
|
129
|
+
* deliberate no-op: peaks-loop never invents a window it did not measure.
|
|
130
|
+
*
|
|
131
|
+
* Returns `null` when the active adapter declares no window knob at all.
|
|
132
|
+
*/
|
|
133
|
+
export function syncHarnessWindowForProject(input) {
|
|
134
|
+
const location = resolveHarnessWindowLocation(input);
|
|
135
|
+
if (location === null)
|
|
136
|
+
return null;
|
|
137
|
+
return syncHarnessWindow({ location, tokens: input.tokens, env: input.env ?? process.env });
|
|
138
|
+
}
|
|
4
139
|
/**
|
|
5
140
|
* Read env-var-based context percentage. Returns `null` when the env
|
|
6
141
|
* is absent or unparseable. Adapter-driven: the caller passes the
|
|
@@ -61,6 +196,17 @@ export function readContextPercent(input) {
|
|
|
61
196
|
};
|
|
62
197
|
}
|
|
63
198
|
if (adapter.compact) {
|
|
199
|
+
// Slice 2026-09-13-auto-compact-trigger-ownership: the window peaks-loop
|
|
200
|
+
// configured for the harness, read from the adapter's declared settings
|
|
201
|
+
// path + key. `null` (no knob declared, or the key absent) leaves the
|
|
202
|
+
// adapter's chain byte-identical to before this slice.
|
|
203
|
+
//
|
|
204
|
+
// The RAW value is handed over, not the parsed one: the adapter validates
|
|
205
|
+
// it (`parseContextWindowOverride`) and warns on a bad hand-edited value,
|
|
206
|
+
// so parsing here too would be a second, silently-disagreeing parser —
|
|
207
|
+
// exactly the duplicated-resolution shape this slice exists to delete.
|
|
208
|
+
const harnessWindowState = readHarnessWindowState({ projectRoot: input.projectRoot, env });
|
|
209
|
+
const harnessWindowTokens = resolveHarnessRatioWindow(harnessWindowState);
|
|
64
210
|
// Primary: read the adapter-declared env-var (no hard-coded IDE names).
|
|
65
211
|
const primary = readEnvPercent(env, adapter.compact.envVarForContextPercent);
|
|
66
212
|
if (primary !== null) {
|
|
@@ -85,7 +231,15 @@ export function readContextPercent(input) {
|
|
|
85
231
|
sessionId: input.sessionId,
|
|
86
232
|
outerSessionId: input.outerSessionId,
|
|
87
233
|
env,
|
|
88
|
-
configWindowTokens: readContextWindowTokensOverride(input.projectRoot)
|
|
234
|
+
configWindowTokens: readContextWindowTokensOverride(input.projectRoot),
|
|
235
|
+
// Slice 2026-09-13-auto-compact-trigger-ownership: hand the adapter the
|
|
236
|
+
// window peaks-loop configured for the harness, so the ratio it reports
|
|
237
|
+
// divides by the very number the harness compacts against — plus whether
|
|
238
|
+
// peaks-loop is the one that wrote it, so the adapter may self-correct
|
|
239
|
+
// its own earlier resolution without ever overruling a human's pin.
|
|
240
|
+
...(harnessWindowTokens !== undefined
|
|
241
|
+
? { harnessWindowTokens, harnessWindowPeakWritten: harnessWindowState?.peakWritten === true }
|
|
242
|
+
: {})
|
|
89
243
|
});
|
|
90
244
|
if (fallback)
|
|
91
245
|
return fallback;
|
|
@@ -14,22 +14,28 @@
|
|
|
14
14
|
* toolkit is "ready to use" so the
|
|
15
15
|
* LLM doesn't lose context to a
|
|
16
16
|
* last-second `/compact` panic.
|
|
17
|
-
* - 95% RED LINE — peaks-loop
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* keeps working with context < 95%.
|
|
17
|
+
* - 95% RED LINE — peaks-loop asks the harness to
|
|
18
|
+
* compact and says it is waiting.
|
|
19
|
+
* Nothing is blocked: peaks-loop has
|
|
20
|
+
* no executor for a running session,
|
|
21
|
+
* so it cannot gate dispatch — and
|
|
22
|
+
* claiming to was the deadlock. See
|
|
23
|
+
* the correction note below.
|
|
25
24
|
*
|
|
26
25
|
* Why 0.85 / 0.95 split: the LLM uses the 0.85–0.95 zone to do
|
|
27
26
|
* intelligent convergence — wait for in-flight sub-agents, finish
|
|
28
27
|
* the current todo row, persist a checkpoint, then compact. peaks-loop
|
|
29
|
-
* provides the toolkit; the LLM picks the moment. At 0.95
|
|
30
|
-
*
|
|
31
|
-
*
|
|
28
|
+
* provides the toolkit; the LLM picks the moment. At 0.95 peaks-loop
|
|
29
|
+
* requests the compact outright and says it is waiting.
|
|
30
|
+
*
|
|
31
|
+
* Slice 2026-09-13-auto-compact-trigger-ownership corrected two claims that
|
|
32
|
+
* used to head this file: the red line does NOT "refuse to dispatch any
|
|
33
|
+
* further sub-agent" (peaks-loop has no way to compact a running session, so
|
|
34
|
+
* such a refusal gated nothing and deadlocked the runner), and the window
|
|
35
|
+
* these ratios divide by is now the same one peaks-loop configures for the
|
|
36
|
+
* harness — see `harness-window-config.ts`.
|
|
32
37
|
*/
|
|
38
|
+
import type { HarnessWindowSyncResult } from './harness-window-config.js';
|
|
33
39
|
export declare const AUTO_COMPACT_SOFT_WARN_RATIO = 0.5;
|
|
34
40
|
export declare const AUTO_COMPACT_AUTO_FIRE_RATIO = 0.8;
|
|
35
41
|
export declare const AUTO_COMPACT_PRE_COMPACT_RATIO = 0.85;
|
|
@@ -67,7 +73,10 @@ export type CompactTrigger = {
|
|
|
67
73
|
message: string;
|
|
68
74
|
toolkitReady: true;
|
|
69
75
|
}
|
|
70
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Red line (ratio ≥ 0.95): peaks-loop asks the harness to compact and says
|
|
78
|
+
* it is waiting. Dispatch is NOT blocked — see `redLineRequested`.
|
|
79
|
+
*/
|
|
71
80
|
| {
|
|
72
81
|
kind: 'red-line';
|
|
73
82
|
ratio: number;
|
|
@@ -97,6 +106,20 @@ export interface CompactDispatchResult {
|
|
|
97
106
|
readonly pathway: 'ide-native' | 'llm-self-compress' | 'shell-exec' | 'noop';
|
|
98
107
|
readonly message: string;
|
|
99
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Old → new map of envelope fields that were renamed but are still emitted
|
|
111
|
+
* under their old name as deprecated aliases.
|
|
112
|
+
*
|
|
113
|
+
* One definition, used both as the `deprecatedFields` value the envelopes
|
|
114
|
+
* carry and as the registry the type's `@deprecated` tags describe, so the
|
|
115
|
+
* alias and its record cannot drift apart into two lists.
|
|
116
|
+
*
|
|
117
|
+
* `redLineGated` → `redLineRequested` (slice
|
|
118
|
+
* 2026-09-13-auto-compact-trigger-ownership): nothing was ever gated. See
|
|
119
|
+
* `redLineGated` on the dispatch branches for why the alias is kept rather
|
|
120
|
+
* than deleted.
|
|
121
|
+
*/
|
|
122
|
+
export declare const DEPRECATED_ENVELOPE_FIELDS: Readonly<Record<string, string>>;
|
|
100
123
|
/** Final envelope returned by `runAutoCompact`. */
|
|
101
124
|
export type AutoCompactResult = {
|
|
102
125
|
readonly ok: false;
|
|
@@ -112,6 +135,13 @@ export type AutoCompactResult = {
|
|
|
112
135
|
readonly ratio: number;
|
|
113
136
|
readonly source: string;
|
|
114
137
|
readonly decision: 'below-threshold' | 'in-flight-batch';
|
|
138
|
+
/**
|
|
139
|
+
* Slice 2026-09-13-auto-compact-trigger-ownership: what syncing the
|
|
140
|
+
* harness auto-compact window did on this probe. `null` = the active
|
|
141
|
+
* adapter declares no such knob. Present so the write is VISIBLE —
|
|
142
|
+
* the harness reports an override silently, so peaks-loop must not.
|
|
143
|
+
*/
|
|
144
|
+
readonly harnessWindow?: HarnessWindowSyncResult | null;
|
|
115
145
|
};
|
|
116
146
|
} | {
|
|
117
147
|
readonly ok: boolean;
|
|
@@ -139,7 +169,54 @@ export type AutoCompactResult = {
|
|
|
139
169
|
* caller passes `--mode partial`.
|
|
140
170
|
*/
|
|
141
171
|
readonly mode?: 'standard' | 'partial';
|
|
172
|
+
/**
|
|
173
|
+
* True when the ratio had crossed the red line and peaks-loop asked
|
|
174
|
+
* the harness to compact.
|
|
175
|
+
*
|
|
176
|
+
* Renamed from `redLineGated` in slice
|
|
177
|
+
* 2026-09-13-auto-compact-trigger-ownership: nothing is gated. The
|
|
178
|
+
* old name asserted a block peaks-loop cannot enforce (it has no
|
|
179
|
+
* executor for a running session), and acting on that assertion is
|
|
180
|
+
* what deadlocked the runner.
|
|
181
|
+
*/
|
|
182
|
+
readonly redLineRequested?: boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Deprecated alias of `redLineRequested` — same value, written by the
|
|
185
|
+
* same statement, so the two can never disagree.
|
|
186
|
+
*
|
|
187
|
+
* Kept because the old name SHIPPED: `redLineGated` is in every release
|
|
188
|
+
* from 2.13.0 through 4.0.46, so a script outside this repo that reads
|
|
189
|
+
* it exists in the wild. Dropping the key would hand that script
|
|
190
|
+
* `undefined` instead of the boolean it branches on — no error, no log,
|
|
191
|
+
* just a silently different branch. This is the same call this slice
|
|
192
|
+
* already made for `--bypass-red-line`: stop advertising a
|
|
193
|
+
* wrong-named surface, do not delete it out from under a published
|
|
194
|
+
* caller. That flag is likewise kept with nothing reading it.
|
|
195
|
+
*
|
|
196
|
+
* There is deliberately NO removal date here. A date would be a promise
|
|
197
|
+
* with no mechanism behind it; removing a published field is a MAJOR
|
|
198
|
+
* decision to be taken on purpose, not one this comment can schedule.
|
|
199
|
+
*
|
|
200
|
+
* `deprecatedFields` (below) is the part a runtime consumer can
|
|
201
|
+
* actually see — a `@deprecated` tag is not.
|
|
202
|
+
*/
|
|
142
203
|
readonly redLineGated?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Old → new map of the envelope fields still emitted as deprecated
|
|
206
|
+
* aliases, so a consumer that parses JSON can discover the rename
|
|
207
|
+
* without reading this file.
|
|
208
|
+
*
|
|
209
|
+
* Why it has to exist: the consumers a rename breaks are precisely the
|
|
210
|
+
* ones that never read `auto-compact-types.ts`. A type comment reaches
|
|
211
|
+
* the compiler and the next editor, not a script parsing a CLI
|
|
212
|
+
* envelope, which is what made the rename silent in the first place.
|
|
213
|
+
* This puts the fact in the envelope they already read.
|
|
214
|
+
*
|
|
215
|
+
* Absent on the branches that carry no renamed field.
|
|
216
|
+
*/
|
|
217
|
+
readonly deprecatedFields?: Readonly<Record<string, string>>;
|
|
218
|
+
/** See the `AUTO_COMPACT_SKIP` data shape above. */
|
|
219
|
+
readonly harnessWindow?: HarnessWindowSyncResult | null;
|
|
143
220
|
};
|
|
144
221
|
};
|
|
145
222
|
/**
|
|
@@ -1,35 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auto-compact shared types (v2.13.0 AC-1..AC-4).
|
|
3
|
-
*
|
|
4
|
-
* Two-tier threshold model — peaks-loop is project-aware and the LLM
|
|
5
|
-
* is the decision-maker:
|
|
6
|
-
*
|
|
7
|
-
* - 50% soft warn — log a one-line info row; continue.
|
|
8
|
-
* - 85% pre-compact zone — peaks-loop prepares the convergence
|
|
9
|
-
* toolkit (checkpoint + convergence
|
|
10
|
-
* plan + auto-decisions log +
|
|
11
|
-
* IDE-compact dispatcher). The LLM
|
|
12
|
-
* DECIDES when (or whether) to fire
|
|
13
|
-
* compact during this zone. The
|
|
14
|
-
* toolkit is "ready to use" so the
|
|
15
|
-
* LLM doesn't lose context to a
|
|
16
|
-
* last-second `/compact` panic.
|
|
17
|
-
* - 95% RED LINE — peaks-loop refuses to dispatch any
|
|
18
|
-
* further sub-agent and synchronously
|
|
19
|
-
* triggers IDE-side compact. At 95%+
|
|
20
|
-
* the context window is too tight to
|
|
21
|
-
* continue safely; the LLM cannot
|
|
22
|
-
* opt out. This is the compact red
|
|
23
|
-
* line that guarantees the LLM-runner
|
|
24
|
-
* keeps working with context < 95%.
|
|
25
|
-
*
|
|
26
|
-
* Why 0.85 / 0.95 split: the LLM uses the 0.85–0.95 zone to do
|
|
27
|
-
* intelligent convergence — wait for in-flight sub-agents, finish
|
|
28
|
-
* the current todo row, persist a checkpoint, then compact. peaks-loop
|
|
29
|
-
* provides the toolkit; the LLM picks the moment. At 0.95 the window
|
|
30
|
-
* is gone and peaks-loop takes over synchronously to keep the runner
|
|
31
|
-
* alive.
|
|
32
|
-
*/
|
|
33
1
|
export const AUTO_COMPACT_SOFT_WARN_RATIO = 0.5;
|
|
34
2
|
// Part 22: auto-fire threshold (was 0.85 pre-compact zone where
|
|
35
3
|
// the LLM had to decide; LLM misjudged 0.85–0.95 and only fired
|
|
@@ -41,3 +9,19 @@ export const AUTO_COMPACT_AUTO_FIRE_RATIO = 0.80;
|
|
|
41
9
|
export const AUTO_COMPACT_PRE_COMPACT_RATIO = 0.85;
|
|
42
10
|
export const AUTO_COMPACT_RED_LINE_RATIO = 0.95;
|
|
43
11
|
export const AUTO_COMPACT_THRESHOLD_RATIO = AUTO_COMPACT_AUTO_FIRE_RATIO;
|
|
12
|
+
/**
|
|
13
|
+
* Old → new map of envelope fields that were renamed but are still emitted
|
|
14
|
+
* under their old name as deprecated aliases.
|
|
15
|
+
*
|
|
16
|
+
* One definition, used both as the `deprecatedFields` value the envelopes
|
|
17
|
+
* carry and as the registry the type's `@deprecated` tags describe, so the
|
|
18
|
+
* alias and its record cannot drift apart into two lists.
|
|
19
|
+
*
|
|
20
|
+
* `redLineGated` → `redLineRequested` (slice
|
|
21
|
+
* 2026-09-13-auto-compact-trigger-ownership): nothing was ever gated. See
|
|
22
|
+
* `redLineGated` on the dispatch branches for why the alias is kept rather
|
|
23
|
+
* than deleted.
|
|
24
|
+
*/
|
|
25
|
+
export const DEPRECATED_ENVELOPE_FIELDS = {
|
|
26
|
+
redLineGated: 'redLineRequested'
|
|
27
|
+
};
|