@principles/pd-cli 1.145.2 → 1.146.1
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/README.md +11 -2
- package/dist/commands/build-trajectory-evidence.d.ts +25 -6
- package/dist/commands/build-trajectory-evidence.d.ts.map +1 -1
- package/dist/commands/build-trajectory-evidence.js +174 -114
- package/dist/commands/build-trajectory-evidence.js.map +1 -1
- package/dist/commands/console.d.ts +13 -0
- package/dist/commands/console.d.ts.map +1 -1
- package/dist/commands/console.js +104 -0
- package/dist/commands/console.js.map +1 -1
- package/dist/commands/pain-record.d.ts.map +1 -1
- package/dist/commands/pain-record.js +212 -17
- package/dist/commands/pain-record.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/build-trajectory-evidence.ts +211 -122
- package/src/commands/console.ts +105 -0
- package/src/commands/pain-record.ts +224 -16
- package/src/index.ts +1 -1
- package/tests/commands/build-trajectory-evidence.test.ts +226 -161
- package/tests/commands/console-open.test.ts +175 -0
- package/tests/commands/pain-record-async.test.ts +36 -30
- package/tests/commands/pain-record-session-parser.test.ts +127 -0
- package/tests/commands/pain-record.test.ts +205 -37
package/README.md
CHANGED
|
@@ -15,13 +15,22 @@ npm install -g @principles/pd-cli
|
|
|
15
15
|
Record a pain signal to the workspace's trajectory database via `PainToPrincipleService`.
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
pd pain record --reason "edited file without reading first" --score 75
|
|
18
|
+
pd pain record --reason "edited file without reading first" --score 75 --session "<session-id>"
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Options:
|
|
22
22
|
- `--reason, -r` — Pain reason (required)
|
|
23
23
|
- `--score, -s` — Pain score 0-100 (default: 80)
|
|
24
|
-
- `--session
|
|
24
|
+
- `--session` — Session ID recorded in this workspace's trajectory; validated
|
|
25
|
+
up front (a missing session fails with `session_not_found` before anything
|
|
26
|
+
is written). Binding a session attaches real trajectory evidence.
|
|
27
|
+
- `--workspace, -w` — Workspace directory
|
|
28
|
+
- `--wait` — Diagnose synchronously (overrides the async CLI flag)
|
|
29
|
+
- `--json` — Machine-readable output
|
|
30
|
+
|
|
31
|
+
Without `--session` the record is an honest unbound Owner report: it carries
|
|
32
|
+
no trajectory evidence and candidates will likely be gated by the admission
|
|
33
|
+
threshold (`needs_evidence`); the output discloses this explicitly.
|
|
25
34
|
|
|
26
35
|
## Production Canary Validation
|
|
27
36
|
|
|
@@ -10,12 +10,31 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { PainEvidenceEntry } from '@principles/core/runtime-v2';
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* PRI-642 (SPEC §7.3): discriminated acquisition result. `unavailable` carries
|
|
14
|
+
* a distinct reasonCode so `pd pain record --session` can fail/degrade
|
|
15
|
+
* explicitly BEFORE any LLM/task/candidate mutation, without placeholder
|
|
16
|
+
* evidence.
|
|
17
|
+
*/
|
|
18
|
+
export type TrajectoryEvidenceAcquisition = {
|
|
19
|
+
status: 'available';
|
|
20
|
+
entries: PainEvidenceEntry[];
|
|
21
|
+
} | {
|
|
22
|
+
status: 'unavailable';
|
|
23
|
+
reasonCode: 'trajectory_unavailable' | 'session_not_found' | 'empty_trajectory' | 'evidence_read_failed';
|
|
24
|
+
detail: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* PRI-642 Scope A typed acquisition from trajectory.db (SPEC §7.3).
|
|
14
28
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
29
|
+
* Validates that the requested session exists in the trajectory `sessions`
|
|
30
|
+
* table (every recorded turn/tool call upserts its session row, so an absent
|
|
31
|
+
* row means the session was never seen) and classifies the outcome:
|
|
32
|
+
* - `available` — session bound, ≥1 real behavior-trace entry;
|
|
33
|
+
* - `session_not_found` — session absent from the sessions table (or a
|
|
34
|
+
* `cli`/`unknown` sentinel — never a real session);
|
|
35
|
+
* - `trajectory_unavailable` — no trajectory.db in this workspace;
|
|
36
|
+
* - `evidence_read_failed` — the DB exists but cannot be opened/read;
|
|
37
|
+
* - `empty_trajectory` — real session, no usable evidence rows.
|
|
19
38
|
*/
|
|
20
|
-
export declare function
|
|
39
|
+
export declare function acquireTrajectoryEvidenceFromDb(stateDir: string, sessionId: string | undefined, workspaceDir?: string): TrajectoryEvidenceAcquisition;
|
|
21
40
|
//# sourceMappingURL=build-trajectory-evidence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-trajectory-evidence.d.ts","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE
|
|
1
|
+
{"version":3,"file":"build-trajectory-evidence.d.ts","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,6BAA6B,GACrC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,GACrD;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,wBAAwB,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,sBAAsB,CAAC;IACzG,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA6JN;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,6BAA6B,CAoE/B"}
|
|
@@ -12,110 +12,90 @@ import Database from 'better-sqlite3';
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { MAX_EVIDENCE_ENTRIES, MAX_EVIDENCE_NOTE_CHARS, sanitizeString, } from '@principles/core/runtime-v2';
|
|
15
|
+
/** SourceRef markers that carry no real behavior trace (placeholder shapes). */
|
|
16
|
+
const PLACEHOLDER_SOURCE_REFS = new Set([
|
|
17
|
+
'owner_reported:cli',
|
|
18
|
+
'owner_message:unavailable',
|
|
19
|
+
'agent_turn:unavailable',
|
|
20
|
+
'tool_call_failure:unavailable',
|
|
21
|
+
'trajectory:empty',
|
|
22
|
+
]);
|
|
15
23
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* @param sessionId - The session ID to query turns for
|
|
20
|
-
* @param workspaceDir - Workspace directory for path redaction (sanitizeString)
|
|
21
|
-
* @returns Array of PainEvidenceEntry (never empty; degraded entries on failure)
|
|
24
|
+
* Collect evidence entries from an open trajectory.db for one session.
|
|
25
|
+
* Shared by the typed acquisition API and the legacy array wrapper so the
|
|
26
|
+
* two can never drift.
|
|
22
27
|
*/
|
|
23
|
-
|
|
28
|
+
function collectEvidenceFromDb(db, sessionId, workspaceDir) {
|
|
24
29
|
const evidence = [];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
evidence.push({
|
|
28
|
-
sourceRef: 'owner_reported:cli',
|
|
29
|
-
note: 'No session context available',
|
|
30
|
-
});
|
|
31
|
-
return evidence;
|
|
32
|
-
}
|
|
33
|
-
const dbPath = path.join(stateDir, 'trajectory.db');
|
|
34
|
-
if (!fs.existsSync(dbPath)) {
|
|
35
|
-
evidence.push({
|
|
36
|
-
sourceRef: 'owner_reported:cli',
|
|
37
|
-
note: 'No session context available',
|
|
38
|
-
});
|
|
39
|
-
return evidence;
|
|
40
|
-
}
|
|
41
|
-
let db;
|
|
42
|
-
try {
|
|
43
|
-
db = new Database(dbPath, { readonly: true });
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
evidence.push({
|
|
47
|
-
sourceRef: 'owner_reported:cli',
|
|
48
|
-
note: 'No session context available',
|
|
49
|
-
});
|
|
50
|
-
return evidence;
|
|
51
|
-
}
|
|
30
|
+
let readFailed = false;
|
|
31
|
+
// Try to read user turns with correction detection
|
|
52
32
|
try {
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
const userTurns = db.prepare(`
|
|
33
|
+
const userTurns = db.prepare(`
|
|
56
34
|
SELECT id, raw_excerpt, correction_detected, correction_cue, created_at
|
|
57
35
|
FROM user_turns
|
|
58
36
|
WHERE session_id = ?
|
|
59
37
|
ORDER BY id ASC
|
|
60
38
|
`).all(sessionId);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
39
|
+
const lastCorrectionTurn = [...userTurns].reverse().find(t => Boolean(t.correction_detected));
|
|
40
|
+
if (lastCorrectionTurn) {
|
|
41
|
+
const rawExcerpt = typeof lastCorrectionTurn.raw_excerpt === 'string'
|
|
42
|
+
? lastCorrectionTurn.raw_excerpt
|
|
43
|
+
: '';
|
|
44
|
+
const sanitizedNote = sanitizeString(rawExcerpt.slice(0, MAX_EVIDENCE_NOTE_CHARS), workspaceDir);
|
|
45
|
+
evidence.push({
|
|
46
|
+
sourceRef: `owner_message:${String(lastCorrectionTurn.created_at ?? 'unknown')}`,
|
|
47
|
+
note: sanitizedNote,
|
|
48
|
+
});
|
|
72
49
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
readFailed = true;
|
|
53
|
+
// user_turns table may not exist — degrade gracefully
|
|
54
|
+
if (evidence.length < MAX_EVIDENCE_ENTRIES) {
|
|
55
|
+
evidence.push({
|
|
56
|
+
sourceRef: 'owner_message:unavailable',
|
|
57
|
+
note: 'trajectory_user_turns_unavailable',
|
|
58
|
+
});
|
|
81
59
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
}
|
|
61
|
+
// Try to read assistant turns (last 3)
|
|
62
|
+
try {
|
|
63
|
+
const assistantTurns = db.prepare(`
|
|
85
64
|
SELECT id, sanitized_text, stop_reason, created_at
|
|
86
65
|
FROM assistant_turns
|
|
87
66
|
WHERE session_id = ?
|
|
88
67
|
ORDER BY id ASC
|
|
89
68
|
`).all(sessionId);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
69
|
+
const recentAssistant = assistantTurns.slice(-3);
|
|
70
|
+
for (const turn of recentAssistant) {
|
|
71
|
+
if (evidence.length >= MAX_EVIDENCE_ENTRIES)
|
|
72
|
+
break;
|
|
73
|
+
const sanitizedText = typeof turn.sanitized_text === 'string'
|
|
74
|
+
? turn.sanitized_text
|
|
75
|
+
: '';
|
|
76
|
+
const sanitizedNote = sanitizeString(sanitizedText.slice(0, MAX_EVIDENCE_NOTE_CHARS), workspaceDir);
|
|
77
|
+
// Enhanced: append truncation warning when stop_reason=length
|
|
78
|
+
const stopReason = typeof turn.stop_reason === 'string' ? turn.stop_reason : null;
|
|
79
|
+
const truncationWarning = stopReason === 'length' ? ' [TRUNCATED: output cut off by length limit]' : '';
|
|
80
|
+
evidence.push({
|
|
81
|
+
sourceRef: `agent_turn:${String(turn.created_at ?? 'unknown')}`,
|
|
82
|
+
note: sanitizedNote + truncationWarning,
|
|
83
|
+
});
|
|
106
84
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
readFailed = true;
|
|
88
|
+
// assistant_turns table may not exist — degrade gracefully
|
|
89
|
+
if (evidence.length < MAX_EVIDENCE_ENTRIES) {
|
|
90
|
+
evidence.push({
|
|
91
|
+
sourceRef: 'agent_turn:unavailable',
|
|
92
|
+
note: 'trajectory_assistant_turns_unavailable',
|
|
93
|
+
});
|
|
115
94
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
95
|
+
}
|
|
96
|
+
// PRI-358: Try to read failed tool_calls (last 3 failures, chronological order)
|
|
97
|
+
try {
|
|
98
|
+
const failedToolCalls = db.prepare(`
|
|
119
99
|
SELECT tool_name, error_type, exit_code, result_preview, created_at
|
|
120
100
|
FROM (
|
|
121
101
|
SELECT tool_name, error_type, exit_code, result_preview, created_at
|
|
@@ -126,39 +106,119 @@ export function buildTrajectoryEvidenceFromDb(stateDir, sessionId, workspaceDir)
|
|
|
126
106
|
)
|
|
127
107
|
ORDER BY created_at ASC
|
|
128
108
|
`).all(sessionId);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// tool_calls table may not exist — degrade gracefully (only when no other evidence)
|
|
147
|
-
if (evidence.length === 0) {
|
|
148
|
-
evidence.push({
|
|
149
|
-
sourceRef: 'tool_call_failure:unavailable',
|
|
150
|
-
note: 'trajectory_tool_calls_unavailable',
|
|
151
|
-
});
|
|
152
|
-
}
|
|
109
|
+
for (const tc of failedToolCalls) {
|
|
110
|
+
if (evidence.length >= MAX_EVIDENCE_ENTRIES)
|
|
111
|
+
break;
|
|
112
|
+
const toolName = typeof tc.tool_name === 'string' ? tc.tool_name : 'unknown';
|
|
113
|
+
const errorType = typeof tc.error_type === 'string' ? tc.error_type : 'unknown';
|
|
114
|
+
const exitCode = tc.exit_code != null ? String(tc.exit_code) : 'N/A';
|
|
115
|
+
// Enhanced: append resultPreview when available
|
|
116
|
+
const resultPreview = typeof tc.result_preview === 'string' ? tc.result_preview : null;
|
|
117
|
+
const previewSuffix = resultPreview ? ` | ${resultPreview.slice(0, 200)}` : '';
|
|
118
|
+
const note = `Tool ${toolName} failed: ${errorType} (exitCode: ${exitCode})${previewSuffix}`;
|
|
119
|
+
evidence.push({
|
|
120
|
+
sourceRef: `tool_call_failure:${String(tc.created_at ?? 'unknown')}`,
|
|
121
|
+
note: sanitizeString(note.slice(0, MAX_EVIDENCE_NOTE_CHARS), workspaceDir),
|
|
122
|
+
});
|
|
153
123
|
}
|
|
154
|
-
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
readFailed = true;
|
|
127
|
+
// tool_calls table may not exist — degrade gracefully (only when no other evidence)
|
|
155
128
|
if (evidence.length === 0) {
|
|
156
129
|
evidence.push({
|
|
157
|
-
sourceRef: '
|
|
158
|
-
note: '
|
|
130
|
+
sourceRef: 'tool_call_failure:unavailable',
|
|
131
|
+
note: 'trajectory_tool_calls_unavailable',
|
|
159
132
|
});
|
|
160
133
|
}
|
|
161
|
-
|
|
134
|
+
}
|
|
135
|
+
// If no evidence at all from trajectory, provide a meaningful placeholder
|
|
136
|
+
if (evidence.length === 0) {
|
|
137
|
+
evidence.push({
|
|
138
|
+
sourceRef: 'trajectory:empty',
|
|
139
|
+
note: 'trajectory_available_but_empty: no user correction or assistant turns found',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const bounded = evidence.slice(0, MAX_EVIDENCE_ENTRIES);
|
|
143
|
+
const realEntryCount = bounded.reduce((count, entry) => count + (PLACEHOLDER_SOURCE_REFS.has(entry.sourceRef) ? 0 : 1), 0);
|
|
144
|
+
return { entries: bounded, realEntryCount, readFailed };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* PRI-642 Scope A typed acquisition from trajectory.db (SPEC §7.3).
|
|
148
|
+
*
|
|
149
|
+
* Validates that the requested session exists in the trajectory `sessions`
|
|
150
|
+
* table (every recorded turn/tool call upserts its session row, so an absent
|
|
151
|
+
* row means the session was never seen) and classifies the outcome:
|
|
152
|
+
* - `available` — session bound, ≥1 real behavior-trace entry;
|
|
153
|
+
* - `session_not_found` — session absent from the sessions table (or a
|
|
154
|
+
* `cli`/`unknown` sentinel — never a real session);
|
|
155
|
+
* - `trajectory_unavailable` — no trajectory.db in this workspace;
|
|
156
|
+
* - `evidence_read_failed` — the DB exists but cannot be opened/read;
|
|
157
|
+
* - `empty_trajectory` — real session, no usable evidence rows.
|
|
158
|
+
*/
|
|
159
|
+
export function acquireTrajectoryEvidenceFromDb(stateDir, sessionId, workspaceDir) {
|
|
160
|
+
if (!sessionId || sessionId === 'cli' || sessionId === 'unknown') {
|
|
161
|
+
return {
|
|
162
|
+
status: 'unavailable',
|
|
163
|
+
reasonCode: 'session_not_found',
|
|
164
|
+
detail: sessionId ? `sentinel_session_id:${sessionId}` : 'missing_session_id',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const dbPath = path.join(stateDir, 'trajectory.db');
|
|
168
|
+
if (!fs.existsSync(dbPath)) {
|
|
169
|
+
return {
|
|
170
|
+
status: 'unavailable',
|
|
171
|
+
reasonCode: 'trajectory_unavailable',
|
|
172
|
+
detail: 'trajectory_db_missing',
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
let db;
|
|
176
|
+
try {
|
|
177
|
+
db = new Database(dbPath, { readonly: true });
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
return {
|
|
181
|
+
status: 'unavailable',
|
|
182
|
+
reasonCode: 'evidence_read_failed',
|
|
183
|
+
detail: `trajectory_db_unreadable: ${err instanceof Error ? err.message : String(err)}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
// Session existence: rows are upserted by every turn/tool-call write, so
|
|
188
|
+
// an absent row means the trajectory never saw this session.
|
|
189
|
+
let sessionExists = false;
|
|
190
|
+
try {
|
|
191
|
+
const row = db.prepare('SELECT 1 FROM sessions WHERE session_id = ?').get(sessionId);
|
|
192
|
+
sessionExists = row !== undefined;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// sessions table missing → cannot validate existence; fall through and
|
|
196
|
+
// let the evidence rows decide (legacy DBs may lack the table).
|
|
197
|
+
sessionExists = true;
|
|
198
|
+
}
|
|
199
|
+
if (!sessionExists) {
|
|
200
|
+
return {
|
|
201
|
+
status: 'unavailable',
|
|
202
|
+
reasonCode: 'session_not_found',
|
|
203
|
+
detail: 'session_not_present_in_trajectory',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const collection = collectEvidenceFromDb(db, sessionId, workspaceDir);
|
|
207
|
+
if (collection.realEntryCount > 0) {
|
|
208
|
+
return { status: 'available', entries: collection.entries };
|
|
209
|
+
}
|
|
210
|
+
if (collection.readFailed) {
|
|
211
|
+
return {
|
|
212
|
+
status: 'unavailable',
|
|
213
|
+
reasonCode: 'evidence_read_failed',
|
|
214
|
+
detail: 'trajectory_tables_unreadable',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
status: 'unavailable',
|
|
219
|
+
reasonCode: 'empty_trajectory',
|
|
220
|
+
detail: 'session_present_but_no_usable_evidence',
|
|
221
|
+
};
|
|
162
222
|
}
|
|
163
223
|
finally {
|
|
164
224
|
db.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-trajectory-evidence.js","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,cAAc,GACf,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"build-trajectory-evidence.js","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,19 @@ interface ConsoleOptions {
|
|
|
15
15
|
noAuth?: boolean;
|
|
16
16
|
json?: boolean;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Verify the console server's runtime dependency slots are resolvable.
|
|
20
|
+
*
|
|
21
|
+
* The console's dist statically imports `@principles/core/runtime-v2` and
|
|
22
|
+
* `@principles/host-runtime`, and reads plugin governance exports from
|
|
23
|
+
* `principles-disciple`. Each slot must be a real package (package.json present
|
|
24
|
+
* AND dist/index.js present) — a dangling junction or an empty shell (package.json
|
|
25
|
+
* without dist) makes the server crash with ERR_MODULE_NOT_FOUND at startup.
|
|
26
|
+
*
|
|
27
|
+
* Returns a human-readable description of the first broken slot, or undefined
|
|
28
|
+
* when everything is resolvable.
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkConsoleRuntimeDependencies(consoleDir: string): string | undefined;
|
|
18
31
|
export declare function handleConsole(opts?: ConsoleOptions): Promise<void>;
|
|
19
32
|
/**
|
|
20
33
|
* Launch (or reuse) the PD Console with seed-friendly defaults:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/commands/console.ts"],"names":[],"mappings":"AAwBA,UAAU,kBAAkB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAuBD,wBAAsB,aAAa,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/commands/console.ts"],"names":[],"mappings":"AAwBA,UAAU,kBAAkB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAuBD;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAqCtF;AAED,wBAAsB,aAAa,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyI5E;AAID;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0fpF"}
|
package/dist/commands/console.js
CHANGED
|
@@ -30,6 +30,56 @@ function getConsoleDir() {
|
|
|
30
30
|
const dir = resolved.mode === 'canonical' ? paths.consoleDir : path.join(paths.openClawExtensionDir, 'console');
|
|
31
31
|
return { dir, mode: resolved.mode };
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Verify the console server's runtime dependency slots are resolvable.
|
|
35
|
+
*
|
|
36
|
+
* The console's dist statically imports `@principles/core/runtime-v2` and
|
|
37
|
+
* `@principles/host-runtime`, and reads plugin governance exports from
|
|
38
|
+
* `principles-disciple`. Each slot must be a real package (package.json present
|
|
39
|
+
* AND dist/index.js present) — a dangling junction or an empty shell (package.json
|
|
40
|
+
* without dist) makes the server crash with ERR_MODULE_NOT_FOUND at startup.
|
|
41
|
+
*
|
|
42
|
+
* Returns a human-readable description of the first broken slot, or undefined
|
|
43
|
+
* when everything is resolvable.
|
|
44
|
+
*/
|
|
45
|
+
export function checkConsoleRuntimeDependencies(consoleDir) {
|
|
46
|
+
// These are the exact entry files the console server resolves at startup,
|
|
47
|
+
// derived from each package's real `exports` map (not assumed dist/index.js):
|
|
48
|
+
// @principles/core/principle-tree-ledger → dist/principle-tree-ledger.js
|
|
49
|
+
// @principles/core/runtime-v2 → dist/runtime-v2/index.js
|
|
50
|
+
// @principles/host-runtime → dist/index.js
|
|
51
|
+
// @principles/install-layout → dist/index.js
|
|
52
|
+
// principles-disciple/governance-audit → dist/governance-audit.js
|
|
53
|
+
// Checking the real resolved entries (not just dist/index.js) catches broken
|
|
54
|
+
// shells where package.json exists but the actual import target is missing.
|
|
55
|
+
// One package can have multiple required entries (@principles/core).
|
|
56
|
+
const slots = [
|
|
57
|
+
{
|
|
58
|
+
pkg: '@principles/core',
|
|
59
|
+
entries: [
|
|
60
|
+
path.join('dist', 'principle-tree-ledger.js'),
|
|
61
|
+
path.join('dist', 'runtime-v2', 'index.js'),
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{ pkg: '@principles/host-runtime', entries: [path.join('dist', 'index.js')] },
|
|
65
|
+
{ pkg: '@principles/install-layout', entries: [path.join('dist', 'index.js')] },
|
|
66
|
+
{ pkg: 'principles-disciple', entries: [path.join('dist', 'governance-audit.js')] },
|
|
67
|
+
];
|
|
68
|
+
for (const slot of slots) {
|
|
69
|
+
const base = path.join(consoleDir, 'node_modules', slot.pkg);
|
|
70
|
+
const pkgJson = path.join(base, 'package.json');
|
|
71
|
+
if (!fs.existsSync(pkgJson)) {
|
|
72
|
+
return `console/node_modules/${slot.pkg}/package.json is missing`;
|
|
73
|
+
}
|
|
74
|
+
for (const entry of slot.entries) {
|
|
75
|
+
const entryFile = path.join(base, entry);
|
|
76
|
+
if (!fs.existsSync(entryFile)) {
|
|
77
|
+
return `console/node_modules/${slot.pkg}/${entry.replaceAll('\\', '/')} is missing (incomplete package)`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
33
83
|
export async function handleConsole(opts = {}) {
|
|
34
84
|
const workspaceDir = opts.workspace
|
|
35
85
|
? path.resolve(opts.workspace)
|
|
@@ -73,6 +123,27 @@ export async function handleConsole(opts = {}) {
|
|
|
73
123
|
process.exit(1);
|
|
74
124
|
return;
|
|
75
125
|
}
|
|
126
|
+
// Runtime dependency integrity check: the console server statically imports
|
|
127
|
+
// @principles/core/runtime-v2 and @principles/host-runtime, and the console
|
|
128
|
+
// reads plugin governance exports from principles-disciple. When the OpenClaw
|
|
129
|
+
// upgrade path refreshes the plugin bundle without re-running the PD installer
|
|
130
|
+
// (2026-09: console_cli_exited_before_result), these node_modules slots can be
|
|
131
|
+
// left as an empty shell (package.json without dist) or a dangling junction.
|
|
132
|
+
// The server then crashes with ERR_MODULE_NOT_FOUND at startup, which the
|
|
133
|
+
// Companion reports as the opaque console_cli_exited_before_result. Fail loud
|
|
134
|
+
// here with the actionable repair command instead.
|
|
135
|
+
const integrityError = checkConsoleRuntimeDependencies(consoleLocation.dir);
|
|
136
|
+
if (integrityError) {
|
|
137
|
+
const msg = `Console runtime dependency broken: ${integrityError}. Re-run installer to repair.`;
|
|
138
|
+
if (opts.json) {
|
|
139
|
+
console.log(JSON.stringify({ success: false, reason: msg, nextAction: 'npx create-principles-disciple' }));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
console.error(msg);
|
|
143
|
+
}
|
|
144
|
+
process.exit(1);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
76
147
|
const port = opts.port || '3100';
|
|
77
148
|
const host = '127.0.0.1';
|
|
78
149
|
const args = [serverEntry, '--workspace', workspaceDir, '--port', port, '--host', host];
|
|
@@ -456,6 +527,39 @@ export async function handleConsoleOpen(opts = {}) {
|
|
|
456
527
|
return;
|
|
457
528
|
}
|
|
458
529
|
// 5) Fresh spawn path
|
|
530
|
+
// Runtime dependency integrity check — only here, NOT before the reuse
|
|
531
|
+
// probe above. A healthy console already running (reused) has its modules
|
|
532
|
+
// loaded in memory; broken disk slots (dangling junction / empty shell left
|
|
533
|
+
// by an interrupted update) must not prevent reusing it. Only when we are
|
|
534
|
+
// about to execute the local console bytes do the local bytes need to be
|
|
535
|
+
// resolvable. The server statically imports @principles/core/runtime-v2 and
|
|
536
|
+
// @principles/host-runtime, and reads plugin governance exports from
|
|
537
|
+
// principles-disciple; without this check a broken install crashes with
|
|
538
|
+
// ERR_MODULE_NOT_FOUND which the Companion reports as the opaque
|
|
539
|
+
// console_cli_exited_before_result.
|
|
540
|
+
const integrityError = checkConsoleRuntimeDependencies(consoleLocation.dir);
|
|
541
|
+
if (integrityError) {
|
|
542
|
+
const result = {
|
|
543
|
+
status: 'failed',
|
|
544
|
+
url: '',
|
|
545
|
+
port: plan.port,
|
|
546
|
+
host: plan.host,
|
|
547
|
+
workspaceDir,
|
|
548
|
+
reused: false,
|
|
549
|
+
browserOpened: false,
|
|
550
|
+
reason: 'console_runtime_dependency_broken',
|
|
551
|
+
nextAction: `Re-run installer: npx create-principles-disciple (${integrityError})`,
|
|
552
|
+
};
|
|
553
|
+
if (opts.json) {
|
|
554
|
+
console.log(JSON.stringify(result, null, 2));
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
console.error(`error: ${result.reason}`);
|
|
558
|
+
console.error(`next: ${result.nextAction}`);
|
|
559
|
+
}
|
|
560
|
+
process.exit(1);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
459
563
|
const args = [serverEntry, '--workspace', workspaceDir, '--port', String(plan.port), '--host', plan.host];
|
|
460
564
|
if (opts.noAuth)
|
|
461
565
|
args.push('--no-auth');
|