peaks-loop 4.0.11 → 4.0.12
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/dist/cli/commands/code-commands.js +2 -0
- package/dist/cli/commands/code-orchestrator-can-do.d.ts +17 -0
- package/dist/cli/commands/code-orchestrator-can-do.js +75 -0
- package/dist/cli/commands/workspace/reconcile-command.js +5 -2
- package/dist/services/code/orchestrator-can-do.d.ts +114 -0
- package/dist/services/code/orchestrator-can-do.js +205 -0
- package/dist/services/doctor/doctor-service/checks/skill-presence.js +1 -1
- package/dist/services/doctor/doctor-service/checks/workspace-layout.d.ts +5 -2
- package/dist/services/doctor/doctor-service/checks/workspace-layout.js +70 -9
- package/dist/services/doctor/doctor-service/types.d.ts +9 -0
- package/dist/services/hooks/presence-marker-detector.d.ts +7 -5
- package/dist/services/hooks/presence-marker-detector.js +45 -85
- package/dist/services/migration/v2-10-to-v2-11-service.js +1 -3
- package/dist/services/sc/sc-service.d.ts +11 -7
- package/dist/services/sc/sc-service.js +29 -26
- package/dist/services/session/binding-store.d.ts +6 -6
- package/dist/services/skills/hooks-settings-service.d.ts +1 -1
- package/dist/services/skills/hooks-settings-service.js +1 -1
- package/dist/services/skills/skill-presence-service.d.ts +0 -1
- package/dist/services/skills/skill-presence-service.js +112 -102
- package/dist/services/skills/skill-statusline-service.js +71 -39
- package/package.json +4 -4
- package/skills/peaks-code/SKILL.md +6 -0
- package/skills/peaks-code/references/session-overload-signal-index.md +60 -0
|
@@ -55,6 +55,15 @@ export type WorkspaceLayoutInspection = {
|
|
|
55
55
|
* to an empty array when the field is missing.
|
|
56
56
|
*/
|
|
57
57
|
perChangeIdDirs?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C — single-slot
|
|
60
|
+
* presence files that are stale after the sid-scoped lease
|
|
61
|
+
* projection shipped in 4.0.8. Reported separately from
|
|
62
|
+
* `legacyDotfiles` so the doctor message names the specific
|
|
63
|
+
* "stale single-slot presence" condition. Optional for back-compat
|
|
64
|
+
* with probes injected by older tests.
|
|
65
|
+
*/
|
|
66
|
+
staleSingleSlotFiles?: string[];
|
|
58
67
|
};
|
|
59
68
|
export type WorkspaceLayoutProbe = () => WorkspaceLayoutInspection;
|
|
60
69
|
/**
|
|
@@ -13,10 +13,12 @@ export declare const PRESENCE_MARKER_WARNING: readonly ["Peaks skill context may
|
|
|
13
13
|
/**
|
|
14
14
|
* Pure read-only presence-marker detection. No I/O side effects.
|
|
15
15
|
*
|
|
16
|
-
* Slice 4.0.
|
|
17
|
-
*
|
|
18
|
-
* `
|
|
19
|
-
* canonical
|
|
20
|
-
*
|
|
16
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: the deprecated
|
|
17
|
+
* `.peaks/_runtime/active-skill.json` (and legacy
|
|
18
|
+
* `.peaks/.active-skill.json`) read paths are removed. The
|
|
19
|
+
* canonical sid-scoped lease projection at
|
|
20
|
+
* `.peaks/_runtime/<sid>/leases/presence-*.json` is the only source.
|
|
21
|
+
* The `warning` field is preserved for downstream consumers
|
|
22
|
+
* (statusline, doctor, hooks).
|
|
21
23
|
*/
|
|
22
24
|
export declare function detectPresenceMarker(input: DetectPresenceMarkerInput): DetectPresenceMarkerResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { getSessionId } from '../session/session-manager.js';
|
|
2
|
+
import { listPresenceLeases } from '../skills/presence-lease-service.js';
|
|
3
3
|
/**
|
|
4
4
|
* Slice 028 (Q1=A): hook-based skill-presence marker detection.
|
|
5
5
|
*
|
|
@@ -17,7 +17,7 @@ import { resolve } from 'node:path';
|
|
|
17
17
|
* `detectPresenceMarker({ project, latestAssistantMessage })`
|
|
18
18
|
* and gets back:
|
|
19
19
|
*
|
|
20
|
-
* - `active`: whether an active
|
|
20
|
+
* - `active`: whether an active lease was found on disk.
|
|
21
21
|
* - `skill?`: the active skill name, if any.
|
|
22
22
|
* - `markerFound`: whether the latest assistant message carries the
|
|
23
23
|
* expected `Peaks-Loop Skill:` / `Peaks-Loop Gate:`
|
|
@@ -30,94 +30,52 @@ import { resolve } from 'node:path';
|
|
|
30
30
|
* expected to provide the absolute project root (peaks-loop convention
|
|
31
31
|
* from the standards-commands family — see dev-preference rule
|
|
32
32
|
* `project-option-is-canonical-project-root-source`).
|
|
33
|
+
*
|
|
34
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: the deprecated
|
|
35
|
+
* project-level `active-skill.json` single-slot file is REMOVED
|
|
36
|
+
* from this module. The canonical sid-scoped lease projection
|
|
37
|
+
* (`.peaks/_runtime/<sid>/leases/presence-*.json`) is the only
|
|
38
|
+
* source of truth; no legacy fallback is retained.
|
|
33
39
|
*/
|
|
34
|
-
const PRESENCE_CANONICAL_PATH = '.peaks/_runtime/active-skill.json';
|
|
35
|
-
const PRESENCE_LEGACY_PATH = '.peaks/.active-skill.json';
|
|
36
40
|
const MARKER_PRIMARY = 'Peaks-Loop Skill:';
|
|
37
41
|
const MARKER_SECONDARY = 'Peaks-Loop Gate:';
|
|
38
|
-
const SKILL_NAME_RE = /"skill"\s*:\s*"([^"\\]*(?:\\.[^"\\]*)*)"/;
|
|
39
42
|
export const PRESENCE_MARKER_WARNING = [
|
|
40
43
|
'Peaks skill context may have been lost from this conversation; please re-invoke /peaks-<skill>.'
|
|
41
44
|
];
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (err instanceof SyntaxError)
|
|
53
|
-
throw err; // surface parse bugs
|
|
54
|
-
return null; // only swallow IO errors
|
|
55
|
-
}
|
|
56
|
-
let parsed;
|
|
57
|
-
try {
|
|
58
|
-
parsed = JSON.parse(raw);
|
|
59
|
-
}
|
|
60
|
-
catch (err) { // TODO(g2): legacy silent catch — now narrows to IO errors only (grace: 1 minor release, v2.14.0)
|
|
61
|
-
if (err instanceof ReferenceError)
|
|
62
|
-
throw err; // surface module-load bugs
|
|
63
|
-
if (err instanceof SyntaxError)
|
|
64
|
-
throw err; // surface parse bugs
|
|
65
|
-
return null; // only swallow IO errors
|
|
66
|
-
}
|
|
67
|
-
if (parsed === null || typeof parsed !== 'object')
|
|
45
|
+
/**
|
|
46
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: read the canonical
|
|
47
|
+
* sid-scoped lease projection. Returns the in-flight lease with the
|
|
48
|
+
* most recent `lastHeartbeat`, or null when no leases exist for the
|
|
49
|
+
* bound session. Picked the most-recent-in-flight lease (mirrors the
|
|
50
|
+
* statusline `callerId === null` back-compat path).
|
|
51
|
+
*/
|
|
52
|
+
function readCanonicalLease(projectRoot) {
|
|
53
|
+
const sessionId = getSessionId(projectRoot);
|
|
54
|
+
if (sessionId === null)
|
|
68
55
|
return null;
|
|
69
|
-
const
|
|
70
|
-
|
|
56
|
+
const leases = listPresenceLeases(projectRoot, sessionId);
|
|
57
|
+
const inFlight = leases.filter((l) => l.status === 'running' || l.status === 'preparing');
|
|
58
|
+
if (inFlight.length === 0)
|
|
71
59
|
return null;
|
|
72
|
-
|
|
60
|
+
// Sort by lastHeartbeat desc, return the freshest.
|
|
61
|
+
inFlight.sort((a, b) => b.lastHeartbeat.localeCompare(a.lastHeartbeat));
|
|
62
|
+
const freshest = inFlight[0];
|
|
63
|
+
if (freshest === undefined)
|
|
73
64
|
return null;
|
|
74
|
-
return { skill:
|
|
65
|
+
return { skill: freshest.skill };
|
|
75
66
|
}
|
|
76
67
|
/**
|
|
77
|
-
* Slice 4.0.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* `
|
|
82
|
-
*
|
|
83
|
-
*
|
|
68
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: the deprecated
|
|
69
|
+
* broken-graph diagnostic walked the legacy `active-skill.json`
|
|
70
|
+
* `graphRef` field. The canonical lease projection surfaces broken
|
|
71
|
+
* graphs as a typed `PEAKS_GRAPH_REF_BROKEN` lease status at read
|
|
72
|
+
* time (see `presence-lease-service.readJsonStrict`), so a separate
|
|
73
|
+
* diagnostic walk is no longer needed. Kept as a no-op for the
|
|
74
|
+
* public-surface stability of `detectPresenceMarker` (the warning
|
|
75
|
+
* field shape stays the same); returns null unless the canonical
|
|
76
|
+
* graph lookup is wired in a future slice.
|
|
84
77
|
*/
|
|
85
|
-
function tryDetectBrokenGraph(
|
|
86
|
-
try {
|
|
87
|
-
const presenceIndexDir = resolve(projectRoot, '.peaks', '_runtime');
|
|
88
|
-
if (!existsSync(presenceIndexDir))
|
|
89
|
-
return null;
|
|
90
|
-
// Best-effort: walk a single directory level for the legacy
|
|
91
|
-
// `active-skill.json` indicator. A broken graphRef would be
|
|
92
|
-
// surfaced by the canonical lease service (PEAKS_GRAPH_REF_BROKEN
|
|
93
|
-
// is the typed error), but the marker detector is a *read* —
|
|
94
|
-
// we don't import the lease service here. The diagnostic is
|
|
95
|
-
// best-effort: we report the index file's `graphRef` field
|
|
96
|
-
// when it names a missing file.
|
|
97
|
-
const legacyPath = resolve(projectRoot, '.peaks', '_runtime', 'active-skill.json');
|
|
98
|
-
if (!existsSync(legacyPath))
|
|
99
|
-
return null;
|
|
100
|
-
const raw = readFileSync(legacyPath, 'utf8');
|
|
101
|
-
const parsed = JSON.parse(raw);
|
|
102
|
-
if (typeof parsed.graphRef !== 'string')
|
|
103
|
-
return null;
|
|
104
|
-
const graphPath = resolve(projectRoot, '.peaks', '_runtime', parsed.graphRef);
|
|
105
|
-
if (!existsSync(graphPath))
|
|
106
|
-
return 'PEAKS_GRAPH_REF_BROKEN';
|
|
107
|
-
}
|
|
108
|
-
catch { /* swallow — diagnostic only */ }
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
function readPresenceBackCompat(project) {
|
|
112
|
-
const projectRoot = resolve(project);
|
|
113
|
-
const canonicalPath = resolve(projectRoot, PRESENCE_CANONICAL_PATH);
|
|
114
|
-
const legacyPath = resolve(projectRoot, PRESENCE_LEGACY_PATH);
|
|
115
|
-
for (const candidate of [canonicalPath, legacyPath]) {
|
|
116
|
-
const parsed = readPresenceFile(candidate);
|
|
117
|
-
if (parsed === null)
|
|
118
|
-
continue;
|
|
119
|
-
return { skill: parsed.skill, path: candidate };
|
|
120
|
-
}
|
|
78
|
+
function tryDetectBrokenGraph(_projectRoot) {
|
|
121
79
|
return null;
|
|
122
80
|
}
|
|
123
81
|
function messageHasMarker(message) {
|
|
@@ -128,16 +86,18 @@ function messageHasMarker(message) {
|
|
|
128
86
|
/**
|
|
129
87
|
* Pure read-only presence-marker detection. No I/O side effects.
|
|
130
88
|
*
|
|
131
|
-
* Slice 4.0.
|
|
132
|
-
*
|
|
133
|
-
* `
|
|
134
|
-
* canonical
|
|
135
|
-
*
|
|
89
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: the deprecated
|
|
90
|
+
* `.peaks/_runtime/active-skill.json` (and legacy
|
|
91
|
+
* `.peaks/.active-skill.json`) read paths are removed. The
|
|
92
|
+
* canonical sid-scoped lease projection at
|
|
93
|
+
* `.peaks/_runtime/<sid>/leases/presence-*.json` is the only source.
|
|
94
|
+
* The `warning` field is preserved for downstream consumers
|
|
95
|
+
* (statusline, doctor, hooks).
|
|
136
96
|
*/
|
|
137
97
|
export function detectPresenceMarker(input) {
|
|
138
98
|
const project = input.project;
|
|
139
99
|
const message = input.latestAssistantMessage ?? '';
|
|
140
|
-
const presence =
|
|
100
|
+
const presence = readCanonicalLease(project);
|
|
141
101
|
if (presence === null) {
|
|
142
102
|
return { active: false, markerFound: false };
|
|
143
103
|
}
|
|
@@ -42,9 +42,7 @@ const SKIP_DIRS = new Set([
|
|
|
42
42
|
'caller',
|
|
43
43
|
'callers',
|
|
44
44
|
'sop-state',
|
|
45
|
-
'system'
|
|
46
|
-
'active-skill.json',
|
|
47
|
-
'.active-skill.json'
|
|
45
|
+
'system'
|
|
48
46
|
]);
|
|
49
47
|
const SESSION_DIR_RE = /^\d{4}-\d{2}-\d{2}-session-/;
|
|
50
48
|
const TECH_DOC_MARKERS = ['## Architecture', '## Component', '## API', '## Dependencies'];
|
|
@@ -53,10 +53,10 @@ export type CommitBoundary = {
|
|
|
53
53
|
};
|
|
54
54
|
/**
|
|
55
55
|
* Resolution sources for `resolveArtifactSession`, in priority order.
|
|
56
|
-
* - `active-skill`: the
|
|
57
|
-
* (`.peaks/_runtime/
|
|
58
|
-
*
|
|
59
|
-
* session dir that owns the slice's marker artifact.
|
|
56
|
+
* - `active-skill`: the canonical sid-scoped lease projection
|
|
57
|
+
* (`.peaks/_runtime/<sid>/leases/presence-*.json`) for the bound
|
|
58
|
+
* session id. When at least one in-flight lease exists under the
|
|
59
|
+
* session dir, that session owns the slice's marker artifact.
|
|
60
60
|
* - `session-json`: the workspace binding in
|
|
61
61
|
* `.peaks/_runtime/session.json` (with back-compat fallback to
|
|
62
62
|
* `.peaks/.session.json`) points to a session dir that owns the
|
|
@@ -74,9 +74,13 @@ export type ResolvedArtifactSession = {
|
|
|
74
74
|
* Resolve the session id that owns the slice's artifacts using a 3-tier
|
|
75
75
|
* precedence:
|
|
76
76
|
*
|
|
77
|
-
* 1.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
77
|
+
* 1. The canonical sid-scoped lease projection under the bound
|
|
78
|
+
* session id (workspace binding + at least one in-flight lease
|
|
79
|
+
* in `.peaks/_runtime/<sid>/leases/`). Slice 4.0.11 statusline-
|
|
80
|
+
* sid-scoped-lease C collapsed the previous
|
|
81
|
+
* `.peaks/_runtime/active-skill.json` reader into this tier —
|
|
82
|
+
* the session id is now read from the canonical workspace
|
|
83
|
+
* binding (was tier 2), gated on a live lease.
|
|
80
84
|
* 2. `.peaks/_runtime/session.json` `sessionId` (with back-compat
|
|
81
85
|
* fallback to `.peaks/.session.json`) if it points to a real
|
|
82
86
|
* session that owns the slice.
|
|
@@ -5,6 +5,7 @@ import { isInsidePath } from '../../shared/path-utils.js';
|
|
|
5
5
|
import { getWorkspaceConfigForPath } from '../config/config-service.js';
|
|
6
6
|
import { getArtifactRemoteRepo, getArtifactWorkspaceStatus, getLocalArtifactPath } from '../artifacts/workspace-service.js';
|
|
7
7
|
import { getSessionId } from '../session/session-manager.js';
|
|
8
|
+
import { listPresenceLeases } from '../skills/presence-lease-service.js';
|
|
8
9
|
const REQUIRED_ARTIFACTS = [
|
|
9
10
|
{ name: 'retention-boundary.md', path: ['sc', 'retention-boundary.md'] },
|
|
10
11
|
{ name: 'change-impact.json', path: ['sc', 'change-impact.json'] },
|
|
@@ -120,33 +121,31 @@ function isRetainedArtifactFile(filePath, artifactWorkspacePath, changesRoot, ch
|
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
/**
|
|
123
|
-
*
|
|
124
|
-
* `
|
|
124
|
+
* Resolve the canonical sid-scoped lease session id (replaces the
|
|
125
|
+
* removed `.peaks/_runtime/active-skill.json` single-slot marker
|
|
126
|
+
* reader). Reads the workspace session binding
|
|
127
|
+
* (`.peaks/_runtime/session.json`, with back-compat fallback to
|
|
128
|
+
* `.peaks/.session.json`) and returns its `sessionId` when at least
|
|
129
|
+
* one in-flight canonical lease exists under
|
|
130
|
+
* `.peaks/_runtime/<sid>/leases/`.
|
|
125
131
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
+
* Slice 4.0.11 statusline-sid-scoped-lease C: the project-level
|
|
133
|
+
* `active-skill.json` is removed; the canonical sid-scoped lease
|
|
134
|
+
* projection (`.peaks/_runtime/<sid>/leases/presence-*.json`) is the
|
|
135
|
+
* authoritative source. The session-id is now read from the
|
|
136
|
+
* workspace binding (which was already tier 2 in the old resolver),
|
|
137
|
+
* gated on the existence of an in-flight lease so a stale binding
|
|
138
|
+
* with no live presence does not produce a false `active-skill`
|
|
139
|
+
* tier hit. Returns null when the session binding is missing /
|
|
140
|
+
* malformed, or when no in-flight lease exists.
|
|
132
141
|
*/
|
|
133
142
|
function readActiveSkillSessionId(projectRoot) {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const pathToRead = existsSync(newPath) ? newPath : legacyPath;
|
|
137
|
-
if (!existsSync(pathToRead))
|
|
138
|
-
return null;
|
|
139
|
-
try {
|
|
140
|
-
const raw = readFileSync(pathToRead, 'utf8');
|
|
141
|
-
const parsed = JSON.parse(raw);
|
|
142
|
-
if (typeof parsed?.sessionId === 'string' && parsed.sessionId.length > 0) {
|
|
143
|
-
return parsed.sessionId;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
143
|
+
const sessionId = readSessionJsonBinding(projectRoot);
|
|
144
|
+
if (sessionId === null)
|
|
147
145
|
return null;
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
const leases = listPresenceLeases(projectRoot, sessionId);
|
|
147
|
+
const hasInFlight = leases.some((l) => l.status === 'running' || l.status === 'preparing');
|
|
148
|
+
return hasInFlight ? sessionId : null;
|
|
150
149
|
}
|
|
151
150
|
/**
|
|
152
151
|
* Read the workspace session binding and return its `sessionId`,
|
|
@@ -284,9 +283,13 @@ function readdirSyncSafe(dir) {
|
|
|
284
283
|
* Resolve the session id that owns the slice's artifacts using a 3-tier
|
|
285
284
|
* precedence:
|
|
286
285
|
*
|
|
287
|
-
* 1.
|
|
288
|
-
*
|
|
289
|
-
*
|
|
286
|
+
* 1. The canonical sid-scoped lease projection under the bound
|
|
287
|
+
* session id (workspace binding + at least one in-flight lease
|
|
288
|
+
* in `.peaks/_runtime/<sid>/leases/`). Slice 4.0.11 statusline-
|
|
289
|
+
* sid-scoped-lease C collapsed the previous
|
|
290
|
+
* `.peaks/_runtime/active-skill.json` reader into this tier —
|
|
291
|
+
* the session id is now read from the canonical workspace
|
|
292
|
+
* binding (was tier 2), gated on a live lease.
|
|
290
293
|
* 2. `.peaks/_runtime/session.json` `sessionId` (with back-compat
|
|
291
294
|
* fallback to `.peaks/.session.json`) if it points to a real
|
|
292
295
|
* session that owns the slice.
|
|
@@ -24,14 +24,14 @@ export declare const InstanceRecordSchema: z.ZodObject<{
|
|
|
24
24
|
callerId: z.ZodString;
|
|
25
25
|
lastHeartbeat: z.ZodString;
|
|
26
26
|
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
lastHeartbeat: string;
|
|
27
28
|
startedAt: string;
|
|
28
29
|
roles: string[];
|
|
29
30
|
callerId: string;
|
|
30
|
-
lastHeartbeat: string;
|
|
31
31
|
}, {
|
|
32
|
+
lastHeartbeat: string;
|
|
32
33
|
startedAt: string;
|
|
33
34
|
callerId: string;
|
|
34
|
-
lastHeartbeat: string;
|
|
35
35
|
roles?: string[] | undefined;
|
|
36
36
|
}>;
|
|
37
37
|
export declare const BindingSchema: z.ZodObject<{
|
|
@@ -45,14 +45,14 @@ export declare const BindingSchema: z.ZodObject<{
|
|
|
45
45
|
callerId: z.ZodString;
|
|
46
46
|
lastHeartbeat: z.ZodString;
|
|
47
47
|
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
lastHeartbeat: string;
|
|
48
49
|
startedAt: string;
|
|
49
50
|
roles: string[];
|
|
50
51
|
callerId: string;
|
|
51
|
-
lastHeartbeat: string;
|
|
52
52
|
}, {
|
|
53
|
+
lastHeartbeat: string;
|
|
53
54
|
startedAt: string;
|
|
54
55
|
callerId: string;
|
|
55
|
-
lastHeartbeat: string;
|
|
56
56
|
roles?: string[] | undefined;
|
|
57
57
|
}>>;
|
|
58
58
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -61,10 +61,10 @@ export declare const BindingSchema: z.ZodObject<{
|
|
|
61
61
|
pid: number;
|
|
62
62
|
scope: string;
|
|
63
63
|
instances: Record<string, {
|
|
64
|
+
lastHeartbeat: string;
|
|
64
65
|
startedAt: string;
|
|
65
66
|
roles: string[];
|
|
66
67
|
callerId: string;
|
|
67
|
-
lastHeartbeat: string;
|
|
68
68
|
}>;
|
|
69
69
|
}, {
|
|
70
70
|
lastHeartbeat: string;
|
|
@@ -72,9 +72,9 @@ export declare const BindingSchema: z.ZodObject<{
|
|
|
72
72
|
pid: number;
|
|
73
73
|
scope: string;
|
|
74
74
|
instances: Record<string, {
|
|
75
|
+
lastHeartbeat: string;
|
|
75
76
|
startedAt: string;
|
|
76
77
|
callerId: string;
|
|
77
|
-
lastHeartbeat: string;
|
|
78
78
|
roles?: string[] | undefined;
|
|
79
79
|
}>;
|
|
80
80
|
}>;
|
|
@@ -67,7 +67,7 @@ export type HookInstallOptions = {
|
|
|
67
67
|
/** Sentinel substring identifying a Claude-Code gate-enforce hook entry. */
|
|
68
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
|
-
export declare const HOOK_ENFORCE_COMMAND = "peaks gate enforce --project \"${CLAUDE_PROJECT_DIR}\"";
|
|
70
|
+
export declare const HOOK_ENFORCE_COMMAND = "peaks gate enforce --project \"${CLAUDE_PROJECT_DIR}\" --json";
|
|
71
71
|
export type HookInstallPlan = {
|
|
72
72
|
scope: HookScope;
|
|
73
73
|
settingsPath: string;
|
|
@@ -11,7 +11,7 @@ import { getAdapter } from '../ide/ide-registry.js';
|
|
|
11
11
|
/** Sentinel substring identifying a Claude-Code gate-enforce hook entry. */
|
|
12
12
|
export const HOOK_ENFORCE_SENTINEL = 'peaks gate enforce';
|
|
13
13
|
/** Default (claude-code) hook command — kept as a stable export for tests. */
|
|
14
|
-
export const HOOK_ENFORCE_COMMAND = `peaks gate enforce --project "\${CLAUDE_PROJECT_DIR}"`;
|
|
14
|
+
export const HOOK_ENFORCE_COMMAND = `peaks gate enforce --project "\${CLAUDE_PROJECT_DIR}" --json`;
|
|
15
15
|
/**
|
|
16
16
|
* Per-IDE hook command + sentinel. The default (Claude Code) uses the
|
|
17
17
|
* legacy `peaks gate enforce` surface; Trae / Cursor / Codex (Cursor-style
|
|
@@ -54,7 +54,6 @@ export type SkillPresence = {
|
|
|
54
54
|
* fallback (slice 2026-06-26-unknown-sid-fallback-fix).
|
|
55
55
|
*/
|
|
56
56
|
export declare function getCurrentSessionId(projectRootOverride?: string): string | null;
|
|
57
|
-
export declare function exportSkillPresence(projectRootOverride?: string): string;
|
|
58
57
|
/**
|
|
59
58
|
* Write the per-caller active-skill marker to
|
|
60
59
|
* `.peaks/_runtime/<peakSid>/active-skill-<callerId>.json` (D6). Returns
|