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.
- package/CHANGELOG.md +48 -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 +128 -34
- 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 +50 -4
- package/dist/services/code/auto-compact-lifecycle.js +52 -10
- package/dist/services/code/auto-compact-orchestrator.d.ts +53 -9
- package/dist/services/code/auto-compact-orchestrator.js +173 -43
- 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/compact-statusline/compact-lifecycle-store.d.ts +11 -2
- package/dist/services/compact-statusline/compact-lifecycle-store.js +19 -1
- package/dist/services/compact-statusline/compact-statusline-service.d.ts +1 -1
- package/dist/services/compact-statusline/compact-statusline-service.js +22 -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/skills/skill-statusline-renderer.js +30 -5
- package/dist/services/skills/statusline-palette.d.ts +6 -0
- package/dist/services/skills/statusline-palette.js +4 -1
- 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 +4 -4
- 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
|
@@ -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
|
-
|
|
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
|
-
/**
|
|
57
|
-
|
|
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
|
-
}):
|
|
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
|
-
/**
|
|
104
|
-
|
|
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
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
/**
|
|
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' (
|
|
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;
|
|
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' →
|
|
174
|
-
*
|
|
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
|
-
*
|
|
179
|
-
*
|
|
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;
|