peaks-loop 4.0.29 → 4.0.31
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 +27 -0
- package/dist/cli/commands/_register.js +4 -0
- package/dist/cli/commands/dispatch-commands.d.ts +5 -41
- package/dist/cli/commands/dispatch-commands.js +35 -185
- package/dist/cli/commands/evidence-commands.d.ts +12 -0
- package/dist/cli/commands/evidence-commands.js +43 -0
- package/dist/cli/commands/fresh-context-commands.d.ts +15 -0
- package/dist/cli/commands/fresh-context-commands.js +24 -0
- package/dist/cli/commands/request-commands.js +2 -96
- package/dist/cli/commands/request-format-helpers.d.ts +19 -0
- package/dist/cli/commands/request-format-helpers.js +102 -0
- package/dist/cli/commands/workspace/init-command.js +27 -14
- package/dist/cli/commands/worktree-auth-commands.js +2 -472
- package/dist/cli/commands/worktree-lease-commands.d.ts +21 -0
- package/dist/cli/commands/worktree-lease-commands.js +500 -0
- package/dist/services/artifacts/request-artifact-service.js +13 -3
- package/dist/services/code/auto-compact-lifecycle.d.ts +102 -0
- package/dist/services/code/auto-compact-lifecycle.js +235 -0
- package/dist/services/code/auto-compact-orchestrator.d.ts +1 -1
- package/dist/services/code/auto-compact-orchestrator.js +1 -222
- package/dist/services/codegraph/codegraph-autorefresh.js +44 -6
- package/dist/services/codegraph/codegraph-preflight-service.d.ts +5 -2
- package/dist/services/codegraph/codegraph-preflight-service.js +13 -6
- package/dist/services/codegraph/codegraph-service.d.ts +17 -2
- package/dist/services/codegraph/codegraph-service.js +27 -2
- package/dist/services/context/build-dispatch-system-prompt.d.ts +26 -0
- package/dist/services/context/build-dispatch-system-prompt.js +38 -3
- package/dist/services/dispatch/dispatch-record-types.d.ts +278 -0
- package/dist/services/dispatch/dispatch-record-types.js +15 -0
- package/dist/services/dispatch/dispatch-record-upgrade.d.ts +5 -0
- package/dist/services/dispatch/dispatch-record-upgrade.js +230 -0
- package/dist/services/dispatch/dispatch-record-writer.d.ts +3 -278
- package/dist/services/dispatch/dispatch-record-writer.js +3 -245
- package/dist/services/dispatch/dispatch-sub-agent.d.ts +43 -0
- package/dist/services/dispatch/dispatch-sub-agent.js +55 -0
- package/dist/services/dispatch/isolation-lease.d.ts +43 -0
- package/dist/services/dispatch/isolation-lease.js +129 -0
- package/dist/services/evidence/evidence-generator.d.ts +26 -0
- package/dist/services/evidence/evidence-generator.js +349 -0
- package/dist/services/fresh-context/config.d.ts +1 -0
- package/dist/services/fresh-context/config.js +13 -0
- package/dist/services/fresh-context/fresh-context-block.d.ts +12 -0
- package/dist/services/fresh-context/fresh-context-block.js +40 -0
- package/dist/services/fresh-context/trigger-scan.d.ts +30 -0
- package/dist/services/fresh-context/trigger-scan.js +29 -0
- package/dist/services/skills/hooks-codegate-superpowers.d.ts +65 -0
- package/dist/services/skills/hooks-codegate-superpowers.js +204 -0
- package/dist/services/skills/hooks-settings-service.d.ts +2 -64
- package/dist/services/skills/hooks-settings-service.js +2 -215
- package/dist/services/skills/skill-statusline-renderer.d.ts +2 -34
- package/dist/services/skills/skill-statusline-renderer.js +1 -184
- package/dist/services/skills/statusline-palette.d.ts +62 -0
- package/dist/services/skills/statusline-palette.js +190 -0
- package/dist/services/slice/slice-decompose-import-edges.d.ts +8 -0
- package/dist/services/slice/slice-decompose-import-edges.js +102 -0
- package/dist/services/slice/slice-decompose-service.js +3 -198
- package/dist/services/slice/slice-decompose-tarjan.d.ts +8 -0
- package/dist/services/slice/slice-decompose-tarjan.js +108 -0
- package/dist/services/standards/project-standards-service.d.ts +1 -9
- package/dist/services/standards/project-standards-service.js +3 -232
- package/dist/services/standards/standards-render.d.ts +23 -0
- package/dist/services/standards/standards-render.js +238 -0
- package/dist/services/standards/ui-library-dispatch-block.d.ts +27 -0
- package/dist/services/standards/ui-library-dispatch-block.js +48 -0
- package/dist/services/workspace/reconcile-migrate.d.ts +77 -0
- package/dist/services/workspace/reconcile-migrate.js +230 -0
- package/dist/services/workspace/reconcile-service.d.ts +0 -72
- package/dist/services/workspace/reconcile-service.js +3 -220
- package/dist/services/workspace/workspace-service.js +13 -2
- package/dist/shared/incrementing-number.d.ts +11 -0
- package/dist/shared/incrementing-number.js +16 -3
- package/package.json +5 -5
- package/skills/peaks-code/SKILL.md +6 -2
- package/skills/peaks-code/references/fresh-context-preflight.md +81 -0
- package/skills/peaks-code/references/sub-agent-dispatch.md +27 -8
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-gate hook entries + superpowers-deny surface for the Peaks-managed
|
|
3
|
+
* hooks. Extracted from `hooks-settings-service.ts` to keep that file
|
|
4
|
+
* under the 800 LOC cap (mechanical verbatim move). Also carries the
|
|
5
|
+
* per-IDE hook-spec table (`resolveHookSpec` / `HOOK_COMMAND_BY_IDE`)
|
|
6
|
+
* and `HOOK_ENFORCE_SENTINEL`, which the entry/sentinel resolvers depend
|
|
7
|
+
* on, so this module is self-contained apart from the `PeaksHookEntry`
|
|
8
|
+
* type contract re-exported by the caller.
|
|
9
|
+
*/
|
|
10
|
+
import { getAdapter } from '../ide/ide-registry.js';
|
|
11
|
+
import { HOOK_OUTER_CACHE_COMMAND, HOOK_OUTER_CACHE_EVENT, HOOK_OUTER_CACHE_SENTINEL, HOOK_WORKSPACE_INIT_COMMAND, HOOK_WORKSPACE_INIT_EVENT, HOOK_WORKSPACE_INIT_SENTINEL } from './session-start-hook-constants.js';
|
|
12
|
+
/** Sentinel substring identifying a Claude-Code gate-enforce hook entry. */
|
|
13
|
+
export const HOOK_ENFORCE_SENTINEL = 'peaks gate enforce';
|
|
14
|
+
/**
|
|
15
|
+
* Per-IDE hook command + sentinel. The default (Claude Code) uses the
|
|
16
|
+
* legacy `peaks gate enforce` surface; Trae / Cursor / Codex (Cursor-style
|
|
17
|
+
* siblings with `before*` / `pre_*` hook events) use `peaks hook handle`,
|
|
18
|
+
* the new dispatcher. New adapters register by adding a single line here.
|
|
19
|
+
*
|
|
20
|
+
* Slice #12 + #13 (2.4.0) honor the framework's "fill the table" promise
|
|
21
|
+
* — adding a new IDE does NOT require editing this function's control
|
|
22
|
+
* flow, only adding a line to this table.
|
|
23
|
+
*/
|
|
24
|
+
const HOOK_COMMAND_BY_IDE = {
|
|
25
|
+
'claude-code': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
26
|
+
'trae': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
27
|
+
'cursor': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
28
|
+
'codex': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
29
|
+
'hermes': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
30
|
+
'openclaw': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
31
|
+
// qoder / tongyi-lingma are reserved IdeIds (slice #1) but not yet
|
|
32
|
+
// registered. When a slice adds them, add a HOOK_COMMAND_BY_IDE entry
|
|
33
|
+
// here — the function below fail-closes on missing entries.
|
|
34
|
+
};
|
|
35
|
+
export function resolveHookSpec(ide) {
|
|
36
|
+
// getAdapter throws on unregistered IDEs — the registry is the source of truth.
|
|
37
|
+
const adapter = getAdapter(ide);
|
|
38
|
+
const spec = HOOK_COMMAND_BY_IDE[ide];
|
|
39
|
+
if (!spec) {
|
|
40
|
+
// Defensive fallback: if an adapter is added to the registry without a
|
|
41
|
+
// HOOK_COMMAND_BY_IDE entry, fail-closed with a clear error instead of
|
|
42
|
+
// silently writing a Claude-shaped entry to a non-Claude settings.json.
|
|
43
|
+
throw new Error(`peaks hooks install: unsupported IDE '${ide}' (no HOOK_COMMAND_BY_IDE entry; add one to hooks-settings-service.ts)`);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
hookEnforceCommand: `${spec.command} --project "\${${adapter.envVar}}"`,
|
|
47
|
+
hookEnforceSentinel: spec.sentinel,
|
|
48
|
+
hookEnforceMatcher: adapter.toolMatcher,
|
|
49
|
+
hookEnforceEvent: adapter.hookEvent
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Slice 2026-08-06-codegate-vendor-neutral — code-gate hook entry.
|
|
54
|
+
* Vendor-neutral command (`peaks code-gate --json`); the CLI adapter
|
|
55
|
+
* lives in `src/cli/commands/code-gate-command.ts` and the decision
|
|
56
|
+
* logic lives in `src/services/hooks/pre-tool-code-gate.ts`. The
|
|
57
|
+
* shell-script sibling (`src/services/hooks/pre-tool-code-gate.sh`)
|
|
58
|
+
* encodes the same logic for non-Node harnesses.
|
|
59
|
+
*/
|
|
60
|
+
export const HOOK_CODE_GATE_SENTINEL = 'peaks code-gate';
|
|
61
|
+
export const HOOK_CODE_GATE_MATCHER = 'Edit|Write|MultiEdit';
|
|
62
|
+
export const HOOK_CODE_GATE_EVENT = 'PreToolUse';
|
|
63
|
+
export const HOOK_CODE_GATE_COMMAND = `peaks code-gate --json`;
|
|
64
|
+
export function resolveHookEntries(ide, _skipProgress = false) {
|
|
65
|
+
const spec = resolveHookSpec(ide);
|
|
66
|
+
const entries = [
|
|
67
|
+
{ sentinel: spec.hookEnforceSentinel, matcher: spec.hookEnforceMatcher, command: spec.hookEnforceCommand, event: spec.hookEnforceEvent }
|
|
68
|
+
];
|
|
69
|
+
if (ide === 'claude-code') {
|
|
70
|
+
entries.push({
|
|
71
|
+
sentinel: HOOK_OUTER_CACHE_SENTINEL,
|
|
72
|
+
matcher: '',
|
|
73
|
+
command: HOOK_OUTER_CACHE_COMMAND,
|
|
74
|
+
event: HOOK_OUTER_CACHE_EVENT
|
|
75
|
+
});
|
|
76
|
+
// Slice rid-statusline-stale-ux AC-2: SessionStart outer-cache
|
|
77
|
+
// write is followed by `peaks session primer` entry so that
|
|
78
|
+
// rotation + presence cleanup fire BEFORE the first statusline
|
|
79
|
+
// render of a fresh session. The new subcommand is idempotent
|
|
80
|
+
// and short-circuits when the binding already matches — safe to
|
|
81
|
+
// call on every SessionStart. Order matters conceptually:
|
|
82
|
+
// outer-cache write must come first (the primer's
|
|
83
|
+
// ensureSessionWithRotation reads the current outer session id).
|
|
84
|
+
entries.push({
|
|
85
|
+
sentinel: HOOK_WORKSPACE_INIT_SENTINEL,
|
|
86
|
+
matcher: '',
|
|
87
|
+
command: HOOK_WORKSPACE_INIT_COMMAND,
|
|
88
|
+
event: HOOK_WORKSPACE_INIT_EVENT
|
|
89
|
+
});
|
|
90
|
+
// Slice 2026-08-06-codegate-vendor-neutral: code-gate entry on
|
|
91
|
+
// Edit|Write|MultiEdit matcher. Vendor-neutral command
|
|
92
|
+
// (`peaks code-gate --json`); the CLI adapter lives in
|
|
93
|
+
// `src/cli/commands/code-gate-command.ts` and the underlying
|
|
94
|
+
// decision logic is in `src/services/hooks/pre-tool-code-gate.ts`.
|
|
95
|
+
entries.push({
|
|
96
|
+
sentinel: HOOK_CODE_GATE_SENTINEL,
|
|
97
|
+
matcher: HOOK_CODE_GATE_MATCHER,
|
|
98
|
+
command: HOOK_CODE_GATE_COMMAND,
|
|
99
|
+
event: HOOK_CODE_GATE_EVENT
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return entries;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Legacy sentinel set used by uninstall + status to find and remove stale
|
|
106
|
+
* progress-start entries written by pre-#014 installs. The progress-start
|
|
107
|
+
* sentinel is the literal substring that older installs emitted.
|
|
108
|
+
*/
|
|
109
|
+
const LEGACY_PROGRESS_START_SENTINEL = 'peaks progress start';
|
|
110
|
+
export function resolveLegacySentinels(ide) {
|
|
111
|
+
if (ide === 'trae') {
|
|
112
|
+
return ['peaks hook handle', LEGACY_PROGRESS_START_SENTINEL];
|
|
113
|
+
}
|
|
114
|
+
// Slice 2026-08-06-session-outer-cache: include the SessionStart outer-cache
|
|
115
|
+
// sentinel so uninstall strips it alongside the gate-enforce entry.
|
|
116
|
+
// Slice 2026-08-06-codegate-vendor-neutral: also include the code-gate
|
|
117
|
+
// sentinel so uninstall strips the Edit|Write|MultiEdit entry alongside
|
|
118
|
+
// the rest of the peaks-managed entries.
|
|
119
|
+
const base = [HOOK_ENFORCE_SENTINEL, LEGACY_PROGRESS_START_SENTINEL, HOOK_CODE_GATE_SENTINEL];
|
|
120
|
+
if (ide === 'claude-code') {
|
|
121
|
+
// Slice rid-statusline-stale-ux AC-2: include the SessionStart
|
|
122
|
+
// workspace-init primer sentinel so uninstall strips it alongside
|
|
123
|
+
// the gate-enforce entry, and so hand-added entries matching this
|
|
124
|
+
// sentinel are recognized as peaks-managed (not stripped as
|
|
125
|
+
// non-Peaks).
|
|
126
|
+
return [...base, HOOK_OUTER_CACHE_SENTINEL, HOOK_WORKSPACE_INIT_SENTINEL];
|
|
127
|
+
}
|
|
128
|
+
return base;
|
|
129
|
+
}
|
|
130
|
+
// --- Slice 2026-07-29-worktree-layer3-deny -----------------------------------
|
|
131
|
+
// Layer 3 of the Worktree Governance 3-layer design (see
|
|
132
|
+
// .peaks/memory/2026-07-29-worktree-layer3-deny.md). The gateway is the IDE
|
|
133
|
+
// native `permissions.deny` list — Claude Code refuses to invoke any Skill
|
|
134
|
+
// listed there BEFORE the LLM even sees it. This is the strongest of the three
|
|
135
|
+
// layers because it bypasses the LLM's tool-call decision entirely: the IDE
|
|
136
|
+
// matches the deny entry against the Skill's namespace and returns a
|
|
137
|
+
// permission error, so the LLM observes "skill not available" rather than
|
|
138
|
+
// "skill denied" — true fail-closed.
|
|
139
|
+
//
|
|
140
|
+
// The list is intentionally tiny: only skills that the superpowers chain
|
|
141
|
+
// *forces* downstream from peaks-loop work paths. We do NOT deny every
|
|
142
|
+
// superpowers skill — only the one whose `description` field or SKILL.md body
|
|
143
|
+
// recommends `git worktree add` / native worktree tools as a step. Anything
|
|
144
|
+
// else stays available as a reference (peaks-code's
|
|
145
|
+
// references/external-skill-invocation.md already describes every other
|
|
146
|
+
// superpowers skill as informational).
|
|
147
|
+
//
|
|
148
|
+
// The IDE expects the deny entry in the form `UseSkill(<skill-id>)`. The
|
|
149
|
+
// prefix is fixed; the skill id is the namespace-qualified name. We render
|
|
150
|
+
// the entries at install time and at uninstall time so the sentinel list is
|
|
151
|
+
// the single source of truth.
|
|
152
|
+
/**
|
|
153
|
+
* The set of Skills whose use is denied at the IDE permissions layer for
|
|
154
|
+
* every `peaks hooks install` call. Each entry is the namespace-qualified
|
|
155
|
+
* skill id; the helper `formatSuperpowersDenyEntry` wraps it in the IDE's
|
|
156
|
+
* `UseSkill(...)` envelope.
|
|
157
|
+
*
|
|
158
|
+
* Slice 2026-07-29-worktree-layer3-deny: the list is empty-aware. To deny a
|
|
159
|
+
* new skill, append its id here and re-run `peaks hooks install`. The list
|
|
160
|
+
* is also the inverse for uninstall: `removeHookInstall` rebuilds the deny
|
|
161
|
+
* list by filtering out anything whose wrapped form matches one of these
|
|
162
|
+
* ids.
|
|
163
|
+
*
|
|
164
|
+
* Slice rid-skill-persistence-001 (2026-08-12): four additional skills
|
|
165
|
+
* denied so the superpowers chain cannot silently override peaks-code.
|
|
166
|
+
* All four are referenced by `superpowers:using-superpowers` as the
|
|
167
|
+
* "bug → systematic-debugging / TDD / verification-before-completion /
|
|
168
|
+
* recursion via using-superpowers" auto-routing pattern — denying the
|
|
169
|
+
* trigger removes the auto-routing surface while leaving all four
|
|
170
|
+
* still readable as reference material from
|
|
171
|
+
* `references/external-skill-invocation.md`.
|
|
172
|
+
*/
|
|
173
|
+
export const SUPERPOWERS_DENIED_SKILLS = [
|
|
174
|
+
// superpowers:using-git-worktrees is the chain's "ground zero" — its
|
|
175
|
+
// SKILL.md (lines 47-99) literally instructs the LLM to run
|
|
176
|
+
// `git worktree add`. Denying this Skill at the IDE layer prevents the
|
|
177
|
+
// LLM from ever receiving that prompt.
|
|
178
|
+
'superpowers:using-git-worktrees',
|
|
179
|
+
// Slice rid-skill-persistence-001: deny the "bug → systematic-debugging"
|
|
180
|
+
// auto-route. Without this entry the chain can preempt the current bee
|
|
181
|
+
// any time a bug report surfaces. Reference-only via
|
|
182
|
+
// references/external-skill-invocation.md §systematic-debugging.
|
|
183
|
+
'superpowers:systematic-debugging',
|
|
184
|
+
// Slice rid-skill-persistence-001: deny the TDD trigger that the chain
|
|
185
|
+
// pairs with bug reports (write-a-failing-test-first). Reference-only
|
|
186
|
+
// via references/external-skill-invocation.md §test-driven-development.
|
|
187
|
+
'superpowers:test-driven-development',
|
|
188
|
+
// Slice rid-skill-persistence-001: deny the verification-before-
|
|
189
|
+
// completion trigger that the chain uses to override "declare done"
|
|
190
|
+
// claims from peaks-code. Reference-only via
|
|
191
|
+
// references/external-skill-invocation.md §verification-before-completion.
|
|
192
|
+
'superpowers:verification-before-completion',
|
|
193
|
+
// Slice rid-skill-persistence-001: deny the recursive chain entrypoint
|
|
194
|
+
// itself. Without this entry the chain auto-spawns another
|
|
195
|
+
// "using-superpowers" Skill call right after the previous chain step,
|
|
196
|
+
// creating the recursive override pattern that peaks-loop's L1 guard
|
|
197
|
+
// cannot see through. Reference-only via
|
|
198
|
+
// references/external-skill-invocation.md §using-superpowers.
|
|
199
|
+
'superpowers:using-superpowers'
|
|
200
|
+
];
|
|
201
|
+
export function formatSuperpowersDenyEntry(skillId) {
|
|
202
|
+
return `UseSkill(${skillId})`;
|
|
203
|
+
}
|
|
204
|
+
export const SUPERPOWERS_DENY_SENTINELS = new Set(SUPERPOWERS_DENIED_SKILLS.map(formatSuperpowersDenyEntry));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { IdeId } from '../ide/ide-types.js';
|
|
2
2
|
import type { HookScope } from '../ide/shared/safe-path.js';
|
|
3
|
+
import { type PeaksHookEntry } from './hooks-codegate-superpowers.js';
|
|
4
|
+
export { HOOK_ENFORCE_SENTINEL, HOOK_CODE_GATE_SENTINEL, HOOK_CODE_GATE_MATCHER, HOOK_CODE_GATE_EVENT, HOOK_CODE_GATE_COMMAND, SUPERPOWERS_DENIED_SKILLS, type PeaksHookEntry } from './hooks-codegate-superpowers.js';
|
|
3
5
|
/**
|
|
4
6
|
* Install (and remove) the Peaks-managed hooks in an IDE's settings.json.
|
|
5
7
|
*
|
|
@@ -64,8 +66,6 @@ export type HookInstallOptions = {
|
|
|
64
66
|
*/
|
|
65
67
|
readonly skipProgress?: boolean;
|
|
66
68
|
};
|
|
67
|
-
/** Sentinel substring identifying a Claude-Code gate-enforce hook entry. */
|
|
68
|
-
export declare const HOOK_ENFORCE_SENTINEL = "peaks gate enforce";
|
|
69
69
|
/** Default (claude-code) hook command — kept as a stable export for tests. */
|
|
70
70
|
export declare const HOOK_ENFORCE_COMMAND = "peaks gate enforce --project \"${CLAUDE_PROJECT_DIR}\" --json";
|
|
71
71
|
export type HookInstallPlan = {
|
|
@@ -122,68 +122,6 @@ export declare function readInstalledEntriesFromSettings(settings: Record<string
|
|
|
122
122
|
matcher: string;
|
|
123
123
|
sentinel: string;
|
|
124
124
|
}>;
|
|
125
|
-
/** A typed descriptor for a single peaks-managed hook entry. */
|
|
126
|
-
export type PeaksHookEntry = {
|
|
127
|
-
sentinel: string;
|
|
128
|
-
matcher: string;
|
|
129
|
-
command: string;
|
|
130
|
-
event: string;
|
|
131
|
-
};
|
|
132
|
-
/**
|
|
133
|
-
* Compute the per-IDE peaks hook entries to merge into the settings file.
|
|
134
|
-
* Replaces the slice #1 hardcoded `PEAKS_HOOK_ENTRIES` constant; the constant
|
|
135
|
-
* remains exported (computed for claude-code) for backward compat.
|
|
136
|
-
*
|
|
137
|
-
* Slice #013 (`--no-progress` flag): when `skipProgress` is true, the
|
|
138
|
-
* progress-start entry is omitted from the returned list. Install with this
|
|
139
|
-
* flag will (a) NOT emit the progress hook entry, and (b) will idempotently
|
|
140
|
-
* remove any previously-installed progress entry (sentinel-based merge).
|
|
141
|
-
*
|
|
142
|
-
* Slice #014 (refactor — full removal): only the gate-enforce entry is
|
|
143
|
-
* ever emitted. The `skipProgress` parameter is kept for API stability
|
|
144
|
-
* but is a no-op — the returned list is always single-entry. The progress
|
|
145
|
-
* entry's sentinel is included in the legacy sentinel set so uninstall
|
|
146
|
-
* can find + remove any stale progress-start entry that an older
|
|
147
|
-
* `peaks hooks install` may have written before this slice.
|
|
148
|
-
*
|
|
149
|
-
* Slice 2026-08-06-session-outer-cache: a SessionStart outer-cache primer
|
|
150
|
-
* entry is appended for Claude Code only (SessionStart is a Claude-Code-
|
|
151
|
-
* specific event key today).
|
|
152
|
-
*/
|
|
153
|
-
/**
|
|
154
|
-
* Slice 2026-08-06-codegate-vendor-neutral — code-gate hook entry.
|
|
155
|
-
* Vendor-neutral command (`peaks code-gate --json`); the CLI adapter
|
|
156
|
-
* lives in `src/cli/commands/code-gate-command.ts` and the decision
|
|
157
|
-
* logic lives in `src/services/hooks/pre-tool-code-gate.ts`. The
|
|
158
|
-
* shell-script sibling (`src/services/hooks/pre-tool-code-gate.sh`)
|
|
159
|
-
* encodes the same logic for non-Node harnesses.
|
|
160
|
-
*/
|
|
161
|
-
export declare const HOOK_CODE_GATE_SENTINEL = "peaks code-gate";
|
|
162
|
-
export declare const HOOK_CODE_GATE_MATCHER = "Edit|Write|MultiEdit";
|
|
163
|
-
export declare const HOOK_CODE_GATE_EVENT = "PreToolUse";
|
|
164
|
-
export declare const HOOK_CODE_GATE_COMMAND = "peaks code-gate --json";
|
|
165
|
-
/**
|
|
166
|
-
* The set of Skills whose use is denied at the IDE permissions layer for
|
|
167
|
-
* every `peaks hooks install` call. Each entry is the namespace-qualified
|
|
168
|
-
* skill id; the helper `formatSuperpowersDenyEntry` wraps it in the IDE's
|
|
169
|
-
* `UseSkill(...)` envelope.
|
|
170
|
-
*
|
|
171
|
-
* Slice 2026-07-29-worktree-layer3-deny: the list is empty-aware. To deny a
|
|
172
|
-
* new skill, append its id here and re-run `peaks hooks install`. The list
|
|
173
|
-
* is also the inverse for uninstall: `removeHookInstall` rebuilds the deny
|
|
174
|
-
* list by filtering out anything whose wrapped form matches one of these
|
|
175
|
-
* ids.
|
|
176
|
-
*
|
|
177
|
-
* Slice rid-skill-persistence-001 (2026-08-12): four additional skills
|
|
178
|
-
* denied so the superpowers chain cannot silently override peaks-code.
|
|
179
|
-
* All four are referenced by `superpowers:using-superpowers` as the
|
|
180
|
-
* "bug → systematic-debugging / TDD / verification-before-completion /
|
|
181
|
-
* recursion via using-superpowers" auto-routing pattern — denying the
|
|
182
|
-
* trigger removes the auto-routing surface while leaving all four
|
|
183
|
-
* still readable as reference material from
|
|
184
|
-
* `references/external-skill-invocation.md`.
|
|
185
|
-
*/
|
|
186
|
-
export declare const SUPERPOWERS_DENIED_SKILLS: ReadonlyArray<string>;
|
|
187
125
|
/**
|
|
188
126
|
* Merge the peaks-managed Skill denylist into the existing settings object.
|
|
189
127
|
* Preserves every other `permissions.deny` entry the user (or another tool)
|
|
@@ -4,53 +4,14 @@ import { resolve } from 'node:path';
|
|
|
4
4
|
import { assertSafeSettingsFile } from '../ide/shared/safe-path.js';
|
|
5
5
|
import { atomicWriteJson, readJsonObjectFile } from '../ide/shared/atomic-json.js';
|
|
6
6
|
import { getAdapter } from '../ide/ide-registry.js';
|
|
7
|
-
import {
|
|
7
|
+
import { resolveHookSpec, resolveHookEntries, resolveLegacySentinels, SUPERPOWERS_DENIED_SKILLS, formatSuperpowersDenyEntry, SUPERPOWERS_DENY_SENTINELS } from './hooks-codegate-superpowers.js';
|
|
8
|
+
export { HOOK_ENFORCE_SENTINEL, HOOK_CODE_GATE_SENTINEL, HOOK_CODE_GATE_MATCHER, HOOK_CODE_GATE_EVENT, HOOK_CODE_GATE_COMMAND, SUPERPOWERS_DENIED_SKILLS } from './hooks-codegate-superpowers.js';
|
|
8
9
|
// --- Module-level defaults (claude-code) -----------------------------------
|
|
9
10
|
// These exports remain for backward compat — tests and downstream callers
|
|
10
11
|
// that only care about Claude Code can keep importing them. The per-IDE
|
|
11
12
|
// values are computed lazily inside each public function call.
|
|
12
|
-
/** Sentinel substring identifying a Claude-Code gate-enforce hook entry. */
|
|
13
|
-
export const HOOK_ENFORCE_SENTINEL = 'peaks gate enforce';
|
|
14
13
|
/** Default (claude-code) hook command — kept as a stable export for tests. */
|
|
15
14
|
export const HOOK_ENFORCE_COMMAND = `peaks gate enforce --project "\${CLAUDE_PROJECT_DIR}" --json`;
|
|
16
|
-
/**
|
|
17
|
-
* Per-IDE hook command + sentinel. The default (Claude Code) uses the
|
|
18
|
-
* legacy `peaks gate enforce` surface; Trae / Cursor / Codex (Cursor-style
|
|
19
|
-
* siblings with `before*` / `pre_*` hook events) use `peaks hook handle`,
|
|
20
|
-
* the new dispatcher. New adapters register by adding a single line here.
|
|
21
|
-
*
|
|
22
|
-
* Slice #12 + #13 (2.4.0) honor the framework's "fill the table" promise
|
|
23
|
-
* — adding a new IDE does NOT require editing this function's control
|
|
24
|
-
* flow, only adding a line to this table.
|
|
25
|
-
*/
|
|
26
|
-
const HOOK_COMMAND_BY_IDE = {
|
|
27
|
-
'claude-code': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
28
|
-
'trae': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
29
|
-
'cursor': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
30
|
-
'codex': { command: 'peaks hook handle', sentinel: 'peaks hook handle' },
|
|
31
|
-
'hermes': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
32
|
-
'openclaw': { command: 'peaks gate enforce', sentinel: 'peaks gate enforce' },
|
|
33
|
-
// qoder / tongyi-lingma are reserved IdeIds (slice #1) but not yet
|
|
34
|
-
// registered. When a slice adds them, add a HOOK_COMMAND_BY_IDE entry
|
|
35
|
-
// here — the function below fail-closes on missing entries.
|
|
36
|
-
};
|
|
37
|
-
function resolveHookSpec(ide) {
|
|
38
|
-
// getAdapter throws on unregistered IDEs — the registry is the source of truth.
|
|
39
|
-
const adapter = getAdapter(ide);
|
|
40
|
-
const spec = HOOK_COMMAND_BY_IDE[ide];
|
|
41
|
-
if (!spec) {
|
|
42
|
-
// Defensive fallback: if an adapter is added to the registry without a
|
|
43
|
-
// HOOK_COMMAND_BY_IDE entry, fail-closed with a clear error instead of
|
|
44
|
-
// silently writing a Claude-shaped entry to a non-Claude settings.json.
|
|
45
|
-
throw new Error(`peaks hooks install: unsupported IDE '${ide}' (no HOOK_COMMAND_BY_IDE entry; add one to hooks-settings-service.ts)`);
|
|
46
|
-
}
|
|
47
|
-
return {
|
|
48
|
-
hookEnforceCommand: `${spec.command} --project "\${${adapter.envVar}}"`,
|
|
49
|
-
hookEnforceSentinel: spec.sentinel,
|
|
50
|
-
hookEnforceMatcher: adapter.toolMatcher,
|
|
51
|
-
hookEnforceEvent: adapter.hookEvent
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
15
|
function resolveIde(options) {
|
|
55
16
|
return options?.ide ?? 'claude-code';
|
|
56
17
|
}
|
|
@@ -166,180 +127,6 @@ export function readInstalledEntriesFromSettings(settings, ide) {
|
|
|
166
127
|
}
|
|
167
128
|
return result;
|
|
168
129
|
}
|
|
169
|
-
/**
|
|
170
|
-
* Compute the per-IDE peaks hook entries to merge into the settings file.
|
|
171
|
-
* Replaces the slice #1 hardcoded `PEAKS_HOOK_ENTRIES` constant; the constant
|
|
172
|
-
* remains exported (computed for claude-code) for backward compat.
|
|
173
|
-
*
|
|
174
|
-
* Slice #013 (`--no-progress` flag): when `skipProgress` is true, the
|
|
175
|
-
* progress-start entry is omitted from the returned list. Install with this
|
|
176
|
-
* flag will (a) NOT emit the progress hook entry, and (b) will idempotently
|
|
177
|
-
* remove any previously-installed progress entry (sentinel-based merge).
|
|
178
|
-
*
|
|
179
|
-
* Slice #014 (refactor — full removal): only the gate-enforce entry is
|
|
180
|
-
* ever emitted. The `skipProgress` parameter is kept for API stability
|
|
181
|
-
* but is a no-op — the returned list is always single-entry. The progress
|
|
182
|
-
* entry's sentinel is included in the legacy sentinel set so uninstall
|
|
183
|
-
* can find + remove any stale progress-start entry that an older
|
|
184
|
-
* `peaks hooks install` may have written before this slice.
|
|
185
|
-
*
|
|
186
|
-
* Slice 2026-08-06-session-outer-cache: a SessionStart outer-cache primer
|
|
187
|
-
* entry is appended for Claude Code only (SessionStart is a Claude-Code-
|
|
188
|
-
* specific event key today).
|
|
189
|
-
*/
|
|
190
|
-
/**
|
|
191
|
-
* Slice 2026-08-06-codegate-vendor-neutral — code-gate hook entry.
|
|
192
|
-
* Vendor-neutral command (`peaks code-gate --json`); the CLI adapter
|
|
193
|
-
* lives in `src/cli/commands/code-gate-command.ts` and the decision
|
|
194
|
-
* logic lives in `src/services/hooks/pre-tool-code-gate.ts`. The
|
|
195
|
-
* shell-script sibling (`src/services/hooks/pre-tool-code-gate.sh`)
|
|
196
|
-
* encodes the same logic for non-Node harnesses.
|
|
197
|
-
*/
|
|
198
|
-
export const HOOK_CODE_GATE_SENTINEL = 'peaks code-gate';
|
|
199
|
-
export const HOOK_CODE_GATE_MATCHER = 'Edit|Write|MultiEdit';
|
|
200
|
-
export const HOOK_CODE_GATE_EVENT = 'PreToolUse';
|
|
201
|
-
export const HOOK_CODE_GATE_COMMAND = `peaks code-gate --json`;
|
|
202
|
-
function resolveHookEntries(ide, _skipProgress = false) {
|
|
203
|
-
const spec = resolveHookSpec(ide);
|
|
204
|
-
const entries = [
|
|
205
|
-
{ sentinel: spec.hookEnforceSentinel, matcher: spec.hookEnforceMatcher, command: spec.hookEnforceCommand, event: spec.hookEnforceEvent }
|
|
206
|
-
];
|
|
207
|
-
if (ide === 'claude-code') {
|
|
208
|
-
entries.push({
|
|
209
|
-
sentinel: HOOK_OUTER_CACHE_SENTINEL,
|
|
210
|
-
matcher: '',
|
|
211
|
-
command: HOOK_OUTER_CACHE_COMMAND,
|
|
212
|
-
event: HOOK_OUTER_CACHE_EVENT
|
|
213
|
-
});
|
|
214
|
-
// Slice rid-statusline-stale-ux AC-2: SessionStart outer-cache
|
|
215
|
-
// write is followed by `peaks session primer` entry so that
|
|
216
|
-
// rotation + presence cleanup fire BEFORE the first statusline
|
|
217
|
-
// render of a fresh session. The new subcommand is idempotent
|
|
218
|
-
// and short-circuits when the binding already matches — safe to
|
|
219
|
-
// call on every SessionStart. Order matters conceptually:
|
|
220
|
-
// outer-cache write must come first (the primer's
|
|
221
|
-
// ensureSessionWithRotation reads the current outer session id).
|
|
222
|
-
entries.push({
|
|
223
|
-
sentinel: HOOK_WORKSPACE_INIT_SENTINEL,
|
|
224
|
-
matcher: '',
|
|
225
|
-
command: HOOK_WORKSPACE_INIT_COMMAND,
|
|
226
|
-
event: HOOK_WORKSPACE_INIT_EVENT
|
|
227
|
-
});
|
|
228
|
-
// Slice 2026-08-06-codegate-vendor-neutral: code-gate entry on
|
|
229
|
-
// Edit|Write|MultiEdit matcher. Vendor-neutral command
|
|
230
|
-
// (`peaks code-gate --json`); the CLI adapter lives in
|
|
231
|
-
// `src/cli/commands/code-gate-command.ts` and the underlying
|
|
232
|
-
// decision logic is in `src/services/hooks/pre-tool-code-gate.ts`.
|
|
233
|
-
entries.push({
|
|
234
|
-
sentinel: HOOK_CODE_GATE_SENTINEL,
|
|
235
|
-
matcher: HOOK_CODE_GATE_MATCHER,
|
|
236
|
-
command: HOOK_CODE_GATE_COMMAND,
|
|
237
|
-
event: HOOK_CODE_GATE_EVENT
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
return entries;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Legacy sentinel set used by uninstall + status to find and remove stale
|
|
244
|
-
* progress-start entries written by pre-#014 installs. The progress-start
|
|
245
|
-
* sentinel is the literal substring that older installs emitted.
|
|
246
|
-
*/
|
|
247
|
-
const LEGACY_PROGRESS_START_SENTINEL = 'peaks progress start';
|
|
248
|
-
function resolveLegacySentinels(ide) {
|
|
249
|
-
if (ide === 'trae') {
|
|
250
|
-
return ['peaks hook handle', LEGACY_PROGRESS_START_SENTINEL];
|
|
251
|
-
}
|
|
252
|
-
// Slice 2026-08-06-session-outer-cache: include the SessionStart outer-cache
|
|
253
|
-
// sentinel so uninstall strips it alongside the gate-enforce entry.
|
|
254
|
-
// Slice 2026-08-06-codegate-vendor-neutral: also include the code-gate
|
|
255
|
-
// sentinel so uninstall strips the Edit|Write|MultiEdit entry alongside
|
|
256
|
-
// the rest of the peaks-managed entries.
|
|
257
|
-
const base = [HOOK_ENFORCE_SENTINEL, LEGACY_PROGRESS_START_SENTINEL, HOOK_CODE_GATE_SENTINEL];
|
|
258
|
-
if (ide === 'claude-code') {
|
|
259
|
-
// Slice rid-statusline-stale-ux AC-2: include the SessionStart
|
|
260
|
-
// workspace-init primer sentinel so uninstall strips it alongside
|
|
261
|
-
// the gate-enforce entry, and so hand-added entries matching this
|
|
262
|
-
// sentinel are recognized as peaks-managed (not stripped as
|
|
263
|
-
// non-Peaks).
|
|
264
|
-
return [...base, HOOK_OUTER_CACHE_SENTINEL, HOOK_WORKSPACE_INIT_SENTINEL];
|
|
265
|
-
}
|
|
266
|
-
return base;
|
|
267
|
-
}
|
|
268
|
-
// --- Slice 2026-07-29-worktree-layer3-deny -----------------------------------
|
|
269
|
-
// Layer 3 of the Worktree Governance 3-layer design (see
|
|
270
|
-
// .peaks/memory/2026-07-29-worktree-layer3-deny.md). The gateway is the IDE
|
|
271
|
-
// native `permissions.deny` list — Claude Code refuses to invoke any Skill
|
|
272
|
-
// listed there BEFORE the LLM even sees it. This is the strongest of the three
|
|
273
|
-
// layers because it bypasses the LLM's tool-call decision entirely: the IDE
|
|
274
|
-
// matches the deny entry against the Skill's namespace and returns a
|
|
275
|
-
// permission error, so the LLM observes "skill not available" rather than
|
|
276
|
-
// "skill denied" — true fail-closed.
|
|
277
|
-
//
|
|
278
|
-
// The list is intentionally tiny: only skills that the superpowers chain
|
|
279
|
-
// *forces* downstream from peaks-loop work paths. We do NOT deny every
|
|
280
|
-
// superpowers skill — only the one whose `description` field or SKILL.md body
|
|
281
|
-
// recommends `git worktree add` / native worktree tools as a step. Anything
|
|
282
|
-
// else stays available as a reference (peaks-code's
|
|
283
|
-
// references/external-skill-invocation.md already describes every other
|
|
284
|
-
// superpowers skill as informational).
|
|
285
|
-
//
|
|
286
|
-
// The IDE expects the deny entry in the form `UseSkill(<skill-id>)`. The
|
|
287
|
-
// prefix is fixed; the skill id is the namespace-qualified name. We render
|
|
288
|
-
// the entries at install time and at uninstall time so the sentinel list is
|
|
289
|
-
// the single source of truth.
|
|
290
|
-
/**
|
|
291
|
-
* The set of Skills whose use is denied at the IDE permissions layer for
|
|
292
|
-
* every `peaks hooks install` call. Each entry is the namespace-qualified
|
|
293
|
-
* skill id; the helper `formatSuperpowersDenyEntry` wraps it in the IDE's
|
|
294
|
-
* `UseSkill(...)` envelope.
|
|
295
|
-
*
|
|
296
|
-
* Slice 2026-07-29-worktree-layer3-deny: the list is empty-aware. To deny a
|
|
297
|
-
* new skill, append its id here and re-run `peaks hooks install`. The list
|
|
298
|
-
* is also the inverse for uninstall: `removeHookInstall` rebuilds the deny
|
|
299
|
-
* list by filtering out anything whose wrapped form matches one of these
|
|
300
|
-
* ids.
|
|
301
|
-
*
|
|
302
|
-
* Slice rid-skill-persistence-001 (2026-08-12): four additional skills
|
|
303
|
-
* denied so the superpowers chain cannot silently override peaks-code.
|
|
304
|
-
* All four are referenced by `superpowers:using-superpowers` as the
|
|
305
|
-
* "bug → systematic-debugging / TDD / verification-before-completion /
|
|
306
|
-
* recursion via using-superpowers" auto-routing pattern — denying the
|
|
307
|
-
* trigger removes the auto-routing surface while leaving all four
|
|
308
|
-
* still readable as reference material from
|
|
309
|
-
* `references/external-skill-invocation.md`.
|
|
310
|
-
*/
|
|
311
|
-
export const SUPERPOWERS_DENIED_SKILLS = [
|
|
312
|
-
// superpowers:using-git-worktrees is the chain's "ground zero" — its
|
|
313
|
-
// SKILL.md (lines 47-99) literally instructs the LLM to run
|
|
314
|
-
// `git worktree add`. Denying this Skill at the IDE layer prevents the
|
|
315
|
-
// LLM from ever receiving that prompt.
|
|
316
|
-
'superpowers:using-git-worktrees',
|
|
317
|
-
// Slice rid-skill-persistence-001: deny the "bug → systematic-debugging"
|
|
318
|
-
// auto-route. Without this entry the chain can preempt the current bee
|
|
319
|
-
// any time a bug report surfaces. Reference-only via
|
|
320
|
-
// references/external-skill-invocation.md §systematic-debugging.
|
|
321
|
-
'superpowers:systematic-debugging',
|
|
322
|
-
// Slice rid-skill-persistence-001: deny the TDD trigger that the chain
|
|
323
|
-
// pairs with bug reports (write-a-failing-test-first). Reference-only
|
|
324
|
-
// via references/external-skill-invocation.md §test-driven-development.
|
|
325
|
-
'superpowers:test-driven-development',
|
|
326
|
-
// Slice rid-skill-persistence-001: deny the verification-before-
|
|
327
|
-
// completion trigger that the chain uses to override "declare done"
|
|
328
|
-
// claims from peaks-code. Reference-only via
|
|
329
|
-
// references/external-skill-invocation.md §verification-before-completion.
|
|
330
|
-
'superpowers:verification-before-completion',
|
|
331
|
-
// Slice rid-skill-persistence-001: deny the recursive chain entrypoint
|
|
332
|
-
// itself. Without this entry the chain auto-spawns another
|
|
333
|
-
// "using-superpowers" Skill call right after the previous chain step,
|
|
334
|
-
// creating the recursive override pattern that peaks-loop's L1 guard
|
|
335
|
-
// cannot see through. Reference-only via
|
|
336
|
-
// references/external-skill-invocation.md §using-superpowers.
|
|
337
|
-
'superpowers:using-superpowers'
|
|
338
|
-
];
|
|
339
|
-
function formatSuperpowersDenyEntry(skillId) {
|
|
340
|
-
return `UseSkill(${skillId})`;
|
|
341
|
-
}
|
|
342
|
-
const SUPERPOWERS_DENY_SENTINELS = new Set(SUPERPOWERS_DENIED_SKILLS.map(formatSuperpowersDenyEntry));
|
|
343
130
|
/**
|
|
344
131
|
* Merge the peaks-managed Skill denylist into the existing settings object.
|
|
345
132
|
* Preserves every other `permissions.deny` entry the user (or another tool)
|
|
@@ -2,6 +2,8 @@ import type { StatusLineModel, TwentyFourHourOverlay } from './skill-statusline-
|
|
|
2
2
|
import { computeRootSuffix as computeRootSuffixImpl } from './skill-statusline-sid-suffix.js';
|
|
3
3
|
export { formatShortSid } from './skill-statusline-sid-suffix.js';
|
|
4
4
|
export declare const computeRootSuffix: typeof computeRootSuffixImpl;
|
|
5
|
+
import { type StatusLineCapability, type StatusPalette } from './statusline-palette.js';
|
|
6
|
+
export type { StatusLineCapability } from './statusline-palette.js';
|
|
5
7
|
/**
|
|
6
8
|
* Pure formatting layer for the Peaks statusLine. Takes the read-only status
|
|
7
9
|
* model and produces the single line Claude Code paints at the bottom of the
|
|
@@ -13,43 +15,9 @@ export declare const computeRootSuffix: typeof computeRootSuffixImpl;
|
|
|
13
15
|
* concrete string happens in one place. Adding a fourth capability (e.g. for
|
|
14
16
|
* a future IDE) is a one-table change.
|
|
15
17
|
*/
|
|
16
|
-
export type StatusLineCapability = 'ansi-unicode' | 'unicode' | 'ascii';
|
|
17
18
|
export interface StatusLineRenderOptions {
|
|
18
19
|
readonly capability: StatusLineCapability;
|
|
19
20
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Glyph palette per capability. Status glyphs (active / idle / warning),
|
|
22
|
-
* separators (· / › / ▸ / ASCII variants), and the diagnostic marker
|
|
23
|
-
* (`presence unreadable`). Unicode glyphs use widely-supported characters;
|
|
24
|
-
* ASCII keeps byte-identical shape across encodings.
|
|
25
|
-
*
|
|
26
|
-
* Compact glyphs are the unicode quadrant marks ◐◑◒◓, the check ✓, and the
|
|
27
|
-
* ballot ✕. ASCII uses bracket/plus/star/x. Bar characters are █/░ in
|
|
28
|
-
* unicode and #/- in ASCII. Ratios are joined with `·` (` . ` for ASCII)
|
|
29
|
-
* and the before→after arrow is `→` (-> for ASCII).
|
|
30
|
-
*/
|
|
31
|
-
interface StatusPalette {
|
|
32
|
-
readonly active: string;
|
|
33
|
-
readonly idleStale: string;
|
|
34
|
-
readonly idle: string;
|
|
35
|
-
readonly warning: string;
|
|
36
|
-
readonly inlineSeparator: string;
|
|
37
|
-
readonly trailSeparator: string;
|
|
38
|
-
readonly idleLabel: string;
|
|
39
|
-
readonly invalidMessage: string;
|
|
40
|
-
readonly compact: CompactPalette;
|
|
41
|
-
readonly barFilled: string;
|
|
42
|
-
readonly barEmpty: string;
|
|
43
|
-
readonly ratioArrow: string;
|
|
44
|
-
}
|
|
45
|
-
interface CompactPalette {
|
|
46
|
-
readonly queued: string;
|
|
47
|
-
readonly preparing: string;
|
|
48
|
-
readonly compacting: string;
|
|
49
|
-
readonly verifying: string;
|
|
50
|
-
readonly completed: string;
|
|
51
|
-
readonly failed: string;
|
|
52
|
-
}
|
|
53
21
|
export declare function formatHumanAge(ageMs: number | null): string;
|
|
54
22
|
/**
|
|
55
23
|
* Slice rid-statusline-24h-overlay (2026-08-10): format the 24h-mode
|