@principles/pd-cli 1.73.0
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 +90 -0
- package/dist/commands/artifact.d.ts +14 -0
- package/dist/commands/artifact.d.ts.map +1 -0
- package/dist/commands/artifact.js +67 -0
- package/dist/commands/artifact.js.map +1 -0
- package/dist/commands/candidate.d.ts +83 -0
- package/dist/commands/candidate.d.ts.map +1 -0
- package/dist/commands/candidate.js +891 -0
- package/dist/commands/candidate.js.map +1 -0
- package/dist/commands/central-sync.d.ts +10 -0
- package/dist/commands/central-sync.d.ts.map +1 -0
- package/dist/commands/central-sync.js +32 -0
- package/dist/commands/central-sync.js.map +1 -0
- package/dist/commands/console.d.ts +9 -0
- package/dist/commands/console.d.ts.map +1 -0
- package/dist/commands/console.js +114 -0
- package/dist/commands/console.js.map +1 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +55 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/demo-story-a.d.ts +12 -0
- package/dist/commands/demo-story-a.d.ts.map +1 -0
- package/dist/commands/demo-story-a.js +175 -0
- package/dist/commands/demo-story-a.js.map +1 -0
- package/dist/commands/diagnose.d.ts +35 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +390 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/evolution-tasks-list.d.ts +15 -0
- package/dist/commands/evolution-tasks-list.d.ts.map +1 -0
- package/dist/commands/evolution-tasks-list.js +34 -0
- package/dist/commands/evolution-tasks-list.js.map +1 -0
- package/dist/commands/evolution-tasks-show.d.ts +14 -0
- package/dist/commands/evolution-tasks-show.d.ts.map +1 -0
- package/dist/commands/evolution-tasks-show.js +52 -0
- package/dist/commands/evolution-tasks-show.js.map +1 -0
- package/dist/commands/flow.d.ts +7 -0
- package/dist/commands/flow.d.ts.map +1 -0
- package/dist/commands/flow.js +57 -0
- package/dist/commands/flow.js.map +1 -0
- package/dist/commands/health.d.ts +16 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +150 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/history.d.ts +11 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +50 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/legacy-cleanup.d.ts +27 -0
- package/dist/commands/legacy-cleanup.d.ts.map +1 -0
- package/dist/commands/legacy-cleanup.js +171 -0
- package/dist/commands/legacy-cleanup.js.map +1 -0
- package/dist/commands/legacy-import.d.ts +7 -0
- package/dist/commands/legacy-import.d.ts.map +1 -0
- package/dist/commands/legacy-import.js +86 -0
- package/dist/commands/legacy-import.js.map +1 -0
- package/dist/commands/pain-record.d.ts +10 -0
- package/dist/commands/pain-record.d.ts.map +1 -0
- package/dist/commands/pain-record.js +162 -0
- package/dist/commands/pain-record.js.map +1 -0
- package/dist/commands/proven-channel-baseline.d.ts +12 -0
- package/dist/commands/proven-channel-baseline.d.ts.map +1 -0
- package/dist/commands/proven-channel-baseline.js +97 -0
- package/dist/commands/proven-channel-baseline.js.map +1 -0
- package/dist/commands/remediation-output.d.ts +40 -0
- package/dist/commands/remediation-output.d.ts.map +1 -0
- package/dist/commands/remediation-output.js +23 -0
- package/dist/commands/remediation-output.js.map +1 -0
- package/dist/commands/run.d.ts +10 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +68 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/runtime-activation.d.ts +11 -0
- package/dist/commands/runtime-activation.d.ts.map +1 -0
- package/dist/commands/runtime-activation.js +150 -0
- package/dist/commands/runtime-activation.js.map +1 -0
- package/dist/commands/runtime-canary.d.ts +30 -0
- package/dist/commands/runtime-canary.d.ts.map +1 -0
- package/dist/commands/runtime-canary.js +343 -0
- package/dist/commands/runtime-canary.js.map +1 -0
- package/dist/commands/runtime-diagnostics-export.d.ts +20 -0
- package/dist/commands/runtime-diagnostics-export.d.ts.map +1 -0
- package/dist/commands/runtime-diagnostics-export.js +177 -0
- package/dist/commands/runtime-diagnostics-export.js.map +1 -0
- package/dist/commands/runtime-features.d.ts +26 -0
- package/dist/commands/runtime-features.d.ts.map +1 -0
- package/dist/commands/runtime-features.js +70 -0
- package/dist/commands/runtime-features.js.map +1 -0
- package/dist/commands/runtime-gfi-snapshot.d.ts +7 -0
- package/dist/commands/runtime-gfi-snapshot.d.ts.map +1 -0
- package/dist/commands/runtime-gfi-snapshot.js +101 -0
- package/dist/commands/runtime-gfi-snapshot.js.map +1 -0
- package/dist/commands/runtime-health-snapshot.d.ts +7 -0
- package/dist/commands/runtime-health-snapshot.d.ts.map +1 -0
- package/dist/commands/runtime-health-snapshot.js +93 -0
- package/dist/commands/runtime-health-snapshot.js.map +1 -0
- package/dist/commands/runtime-idle-trigger.d.ts +12 -0
- package/dist/commands/runtime-idle-trigger.d.ts.map +1 -0
- package/dist/commands/runtime-idle-trigger.js +102 -0
- package/dist/commands/runtime-idle-trigger.js.map +1 -0
- package/dist/commands/runtime-internalization-enqueue-successors.d.ts +9 -0
- package/dist/commands/runtime-internalization-enqueue-successors.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-enqueue-successors.js +393 -0
- package/dist/commands/runtime-internalization-enqueue-successors.js.map +1 -0
- package/dist/commands/runtime-internalization-integrity-repair.d.ts +9 -0
- package/dist/commands/runtime-internalization-integrity-repair.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-integrity-repair.js +54 -0
- package/dist/commands/runtime-internalization-integrity-repair.js.map +1 -0
- package/dist/commands/runtime-internalization-integrity.d.ts +7 -0
- package/dist/commands/runtime-internalization-integrity.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-integrity.js +53 -0
- package/dist/commands/runtime-internalization-integrity.js.map +1 -0
- package/dist/commands/runtime-internalization-queue.d.ts +7 -0
- package/dist/commands/runtime-internalization-queue.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-queue.js +85 -0
- package/dist/commands/runtime-internalization-queue.js.map +1 -0
- package/dist/commands/runtime-internalization-run-once.d.ts +12 -0
- package/dist/commands/runtime-internalization-run-once.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-run-once.js +546 -0
- package/dist/commands/runtime-internalization-run-once.js.map +1 -0
- package/dist/commands/runtime-internalization-wake-once.d.ts +8 -0
- package/dist/commands/runtime-internalization-wake-once.d.ts.map +1 -0
- package/dist/commands/runtime-internalization-wake-once.js +72 -0
- package/dist/commands/runtime-internalization-wake-once.js.map +1 -0
- package/dist/commands/runtime-pain-flood-simulation.d.ts +10 -0
- package/dist/commands/runtime-pain-flood-simulation.d.ts.map +1 -0
- package/dist/commands/runtime-pain-flood-simulation.js +104 -0
- package/dist/commands/runtime-pain-flood-simulation.js.map +1 -0
- package/dist/commands/runtime-pruning.d.ts +45 -0
- package/dist/commands/runtime-pruning.d.ts.map +1 -0
- package/dist/commands/runtime-pruning.js +355 -0
- package/dist/commands/runtime-pruning.js.map +1 -0
- package/dist/commands/runtime-recovery.d.ts +9 -0
- package/dist/commands/runtime-recovery.d.ts.map +1 -0
- package/dist/commands/runtime-recovery.js +94 -0
- package/dist/commands/runtime-recovery.js.map +1 -0
- package/dist/commands/runtime-synthetic-baseline.d.ts +7 -0
- package/dist/commands/runtime-synthetic-baseline.d.ts.map +1 -0
- package/dist/commands/runtime-synthetic-baseline.js +59 -0
- package/dist/commands/runtime-synthetic-baseline.js.map +1 -0
- package/dist/commands/runtime-uat.d.ts +52 -0
- package/dist/commands/runtime-uat.d.ts.map +1 -0
- package/dist/commands/runtime-uat.js +274 -0
- package/dist/commands/runtime-uat.js.map +1 -0
- package/dist/commands/runtime.d.ts +20 -0
- package/dist/commands/runtime.d.ts.map +1 -0
- package/dist/commands/runtime.js +256 -0
- package/dist/commands/runtime.js.map +1 -0
- package/dist/commands/samples-list.d.ts +11 -0
- package/dist/commands/samples-list.d.ts.map +1 -0
- package/dist/commands/samples-list.js +37 -0
- package/dist/commands/samples-list.js.map +1 -0
- package/dist/commands/samples-review.d.ts +14 -0
- package/dist/commands/samples-review.d.ts.map +1 -0
- package/dist/commands/samples-review.js +22 -0
- package/dist/commands/samples-review.js.map +1 -0
- package/dist/commands/task.d.ts +14 -0
- package/dist/commands/task.d.ts.map +1 -0
- package/dist/commands/task.js +92 -0
- package/dist/commands/task.js.map +1 -0
- package/dist/commands/trace.d.ts +19 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +154 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/trajectory.d.ts +11 -0
- package/dist/commands/trajectory.d.ts.map +1 -0
- package/dist/commands/trajectory.js +47 -0
- package/dist/commands/trajectory.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +736 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy/legacy-import.d.ts +15 -0
- package/dist/legacy/legacy-import.d.ts.map +1 -0
- package/dist/legacy/legacy-import.js +141 -0
- package/dist/legacy/legacy-import.js.map +1 -0
- package/dist/legacy/session-history-import.d.ts +26 -0
- package/dist/legacy/session-history-import.d.ts.map +1 -0
- package/dist/legacy/session-history-import.js +151 -0
- package/dist/legacy/session-history-import.js.map +1 -0
- package/dist/principle-tree-ledger-adapter.d.ts +12 -0
- package/dist/principle-tree-ledger-adapter.d.ts.map +1 -0
- package/dist/principle-tree-ledger-adapter.js +12 -0
- package/dist/principle-tree-ledger-adapter.js.map +1 -0
- package/dist/resolve-workspace.d.ts +12 -0
- package/dist/resolve-workspace.d.ts.map +1 -0
- package/dist/resolve-workspace.js +20 -0
- package/dist/resolve-workspace.js.map +1 -0
- package/dist/services/demo-story-a-runner.d.ts +8 -0
- package/dist/services/demo-story-a-runner.d.ts.map +1 -0
- package/dist/services/demo-story-a-runner.js +369 -0
- package/dist/services/demo-story-a-runner.js.map +1 -0
- package/dist/services/feature-flag-loader.d.ts +6 -0
- package/dist/services/feature-flag-loader.d.ts.map +1 -0
- package/dist/services/feature-flag-loader.js +54 -0
- package/dist/services/feature-flag-loader.js.map +1 -0
- package/dist/services/pain-flood-simulation-runner.d.ts +10 -0
- package/dist/services/pain-flood-simulation-runner.d.ts.map +1 -0
- package/dist/services/pain-flood-simulation-runner.js +289 -0
- package/dist/services/pain-flood-simulation-runner.js.map +1 -0
- package/dist/services/proven-channel-baseline-runner.d.ts +12 -0
- package/dist/services/proven-channel-baseline-runner.d.ts.map +1 -0
- package/dist/services/proven-channel-baseline-runner.js +114 -0
- package/dist/services/proven-channel-baseline-runner.js.map +1 -0
- package/dist/services/synthetic-baseline-runner.d.ts +8 -0
- package/dist/services/synthetic-baseline-runner.d.ts.map +1 -0
- package/dist/services/synthetic-baseline-runner.js +251 -0
- package/dist/services/synthetic-baseline-runner.js.map +1 -0
- package/package.json +35 -0
- package/src/commands/artifact.ts +82 -0
- package/src/commands/candidate.ts +1117 -0
- package/src/commands/central-sync.ts +44 -0
- package/src/commands/console.ts +121 -0
- package/src/commands/context.ts +72 -0
- package/src/commands/demo-story-a.ts +195 -0
- package/src/commands/diagnose.ts +452 -0
- package/src/commands/evolution-tasks-list.ts +44 -0
- package/src/commands/evolution-tasks-show.ts +60 -0
- package/src/commands/flow.ts +60 -0
- package/src/commands/health.ts +189 -0
- package/src/commands/history.ts +63 -0
- package/src/commands/legacy-cleanup.ts +206 -0
- package/src/commands/legacy-import.ts +104 -0
- package/src/commands/pain-record.ts +167 -0
- package/src/commands/proven-channel-baseline.ts +113 -0
- package/src/commands/remediation-output.ts +66 -0
- package/src/commands/run.ts +89 -0
- package/src/commands/runtime-activation.ts +176 -0
- package/src/commands/runtime-canary.ts +371 -0
- package/src/commands/runtime-diagnostics-export.ts +229 -0
- package/src/commands/runtime-features.ts +103 -0
- package/src/commands/runtime-gfi-snapshot.ts +135 -0
- package/src/commands/runtime-health-snapshot.ts +106 -0
- package/src/commands/runtime-internalization-enqueue-successors.ts +479 -0
- package/src/commands/runtime-internalization-integrity-repair.ts +69 -0
- package/src/commands/runtime-internalization-integrity.ts +63 -0
- package/src/commands/runtime-internalization-queue.ts +106 -0
- package/src/commands/runtime-internalization-run-once.ts +658 -0
- package/src/commands/runtime-internalization-wake-once.ts +87 -0
- package/src/commands/runtime-pain-flood-simulation.ts +121 -0
- package/src/commands/runtime-pruning.ts +438 -0
- package/src/commands/runtime-recovery.ts +107 -0
- package/src/commands/runtime-synthetic-baseline.ts +70 -0
- package/src/commands/runtime-uat.ts +339 -0
- package/src/commands/runtime.ts +281 -0
- package/src/commands/samples-list.ts +43 -0
- package/src/commands/samples-review.ts +32 -0
- package/src/commands/task.ts +130 -0
- package/src/commands/trace.ts +174 -0
- package/src/commands/trajectory.ts +64 -0
- package/src/index.ts +829 -0
- package/src/legacy/legacy-import.ts +179 -0
- package/src/legacy/session-history-import.ts +231 -0
- package/src/principle-tree-ledger-adapter.ts +13 -0
- package/src/resolve-workspace.ts +20 -0
- package/src/services/demo-story-a-runner.ts +472 -0
- package/src/services/feature-flag-loader.ts +73 -0
- package/src/services/pain-flood-simulation-runner.ts +354 -0
- package/src/services/proven-channel-baseline-runner.ts +150 -0
- package/src/services/synthetic-baseline-runner.ts +291 -0
- package/tests/commands/candidate-audit-repair.test.ts +338 -0
- package/tests/commands/candidate-intake.test.ts +589 -0
- package/tests/commands/candidate-internalization-backfill.test.ts +480 -0
- package/tests/commands/candidate-internalize.test.ts +272 -0
- package/tests/commands/candidate-route.test.ts +328 -0
- package/tests/commands/candidate-show.test.ts +95 -0
- package/tests/commands/cli-command-tree.test.ts +64 -0
- package/tests/commands/context.test.ts +114 -0
- package/tests/commands/demo-story-a.test.ts +255 -0
- package/tests/commands/diagnose.test.ts +792 -0
- package/tests/commands/health.test.ts +330 -0
- package/tests/commands/pain-record.test.ts +316 -0
- package/tests/commands/plugin-config-resolution-cutover.test.ts +220 -0
- package/tests/commands/proven-channel-baseline.test.ts +441 -0
- package/tests/commands/runtime-activation.test.ts +168 -0
- package/tests/commands/runtime-canary.test.ts +369 -0
- package/tests/commands/runtime-diagnostics-export.test.ts +170 -0
- package/tests/commands/runtime-features.test.ts +114 -0
- package/tests/commands/runtime-health-snapshot.test.ts +357 -0
- package/tests/commands/runtime-internalization-enqueue-successors.test.ts +803 -0
- package/tests/commands/runtime-internalization-integrity-repair.test.ts +169 -0
- package/tests/commands/runtime-internalization-integrity.test.ts +102 -0
- package/tests/commands/runtime-internalization-queue.test.ts +252 -0
- package/tests/commands/runtime-internalization-run-once.test.ts +1318 -0
- package/tests/commands/runtime-internalization-wake-once.test.ts +170 -0
- package/tests/commands/runtime-internalization.test.ts +52 -0
- package/tests/commands/runtime-pain-flood-simulation.test.ts +418 -0
- package/tests/commands/runtime-pruning.test.ts +693 -0
- package/tests/commands/runtime-recovery.test.ts +96 -0
- package/tests/commands/runtime-synthetic-baseline.test.ts +249 -0
- package/tests/commands/runtime-uat.test.ts +397 -0
- package/tests/commands/runtime.test.ts +262 -0
- package/tests/commands/trace.test.ts +314 -0
- package/tests/e2e/candidate-intake-e2e.test.ts +316 -0
- package/tests/services/feature-flag-loader.test.ts +207 -0
- package/tests/services/proven-channel-baseline-runner.test.ts +30 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd health command implementation — Runtime V2 edition.
|
|
3
|
+
*
|
|
4
|
+
* Usage: pd health [--workspace <path>] [--json]
|
|
5
|
+
*
|
|
6
|
+
* Reads workspace/.pd/state.db and workspace/.state/principle_training_state.json
|
|
7
|
+
* to provide Runtime V2 health diagnostics.
|
|
8
|
+
* Uses read models from @principles/core/runtime-v2 (no direct ledger access).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import Database from 'better-sqlite3';
|
|
14
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
15
|
+
import { PruningReadModel, PainChainReadModel, auditCandidateLedgerConsistency, getLedgerFilePathPublic } from '@principles/core/runtime-v2';
|
|
16
|
+
import type { PainChainTrace } from '@principles/core/runtime-v2';
|
|
17
|
+
|
|
18
|
+
interface LastSuccessfulChain {
|
|
19
|
+
painId?: string;
|
|
20
|
+
taskId: string;
|
|
21
|
+
runId: string;
|
|
22
|
+
artifactId: string;
|
|
23
|
+
candidateIds: string[];
|
|
24
|
+
ledgerEntryIds: string[];
|
|
25
|
+
latencyMs?: { totalMs?: number };
|
|
26
|
+
failureCategory: string | null;
|
|
27
|
+
checkedAt: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface WorkspaceHealth {
|
|
31
|
+
generatedAt: string;
|
|
32
|
+
workspace: string;
|
|
33
|
+
partialHealth?: boolean;
|
|
34
|
+
pdStateDb: { path: string; exists: boolean };
|
|
35
|
+
ledger: { path: string; exists: boolean; totalPrinciples: number; byStatus: Record<string, number> };
|
|
36
|
+
candidates: { total: number; consumed: number; pending: number };
|
|
37
|
+
tasks: { total: number; byStatus: Record<string, number> };
|
|
38
|
+
candidateLedgerConsistency: { status: 'ok' | 'degraded'; missing: number };
|
|
39
|
+
lastSuccessfulChain?: LastSuccessfulChain;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface HealthOptions {
|
|
43
|
+
workspace?: string;
|
|
44
|
+
json?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function painChainTraceToLastSuccessfulChain(trace: PainChainTrace): LastSuccessfulChain {
|
|
48
|
+
const totalMs = (trace.latencyMs.painToTask ?? 0)
|
|
49
|
+
+ (trace.latencyMs.taskToRun ?? 0)
|
|
50
|
+
+ (trace.latencyMs.runToArtifact ?? 0);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
painId: trace.painId,
|
|
54
|
+
taskId: trace.taskId,
|
|
55
|
+
runId: trace.runId ?? '',
|
|
56
|
+
artifactId: trace.artifactId ?? '',
|
|
57
|
+
candidateIds: trace.candidateIds,
|
|
58
|
+
ledgerEntryIds: trace.ledgerEntryIds,
|
|
59
|
+
latencyMs: { totalMs: totalMs > 0 ? totalMs : undefined },
|
|
60
|
+
failureCategory: trace.failureCategory,
|
|
61
|
+
checkedAt: trace.checkedAt,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function handleHealth(opts: HealthOptions = {}): Promise<void> {
|
|
66
|
+
const workspaceDir = opts.workspace
|
|
67
|
+
? path.resolve(opts.workspace)
|
|
68
|
+
: resolveWorkspaceDir();
|
|
69
|
+
|
|
70
|
+
const generatedAt = new Date().toISOString();
|
|
71
|
+
const pdDbPath = path.join(workspaceDir, '.pd', 'state.db');
|
|
72
|
+
const ledgerStateDir = path.join(workspaceDir, '.state');
|
|
73
|
+
const ledgerPath = getLedgerFilePathPublic(ledgerStateDir);
|
|
74
|
+
|
|
75
|
+
const pruningModel = new PruningReadModel({ workspaceDir });
|
|
76
|
+
const healthSummary = pruningModel.getHealthSummary();
|
|
77
|
+
const ledgerByStatus = healthSummary.byStatus;
|
|
78
|
+
|
|
79
|
+
const { missingLedgerCount } = await auditCandidateLedgerConsistency(workspaceDir);
|
|
80
|
+
|
|
81
|
+
let candidatesTotal = 0, candidatesConsumed = 0, candidatesPending = 0;
|
|
82
|
+
let tasksTotal = 0;
|
|
83
|
+
const tasksByStatus: Record<string, number> = {};
|
|
84
|
+
let pdDbExists = false;
|
|
85
|
+
let lastSuccessfulChain: LastSuccessfulChain | undefined = undefined;
|
|
86
|
+
let partialHealth = false;
|
|
87
|
+
|
|
88
|
+
function buildHealth(): WorkspaceHealth {
|
|
89
|
+
return {
|
|
90
|
+
generatedAt,
|
|
91
|
+
workspace: workspaceDir,
|
|
92
|
+
partialHealth,
|
|
93
|
+
pdStateDb: { path: pdDbPath, exists: pdDbExists },
|
|
94
|
+
ledger: {
|
|
95
|
+
path: ledgerPath,
|
|
96
|
+
exists: fs.existsSync(ledgerPath),
|
|
97
|
+
totalPrinciples: healthSummary.totalPrinciples,
|
|
98
|
+
byStatus: ledgerByStatus,
|
|
99
|
+
},
|
|
100
|
+
candidates: { total: candidatesTotal, consumed: candidatesConsumed, pending: candidatesPending },
|
|
101
|
+
tasks: { total: tasksTotal, byStatus: tasksByStatus },
|
|
102
|
+
candidateLedgerConsistency: {
|
|
103
|
+
status: missingLedgerCount === 0 ? 'ok' : 'degraded',
|
|
104
|
+
missing: missingLedgerCount,
|
|
105
|
+
},
|
|
106
|
+
lastSuccessfulChain,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function writeHealth(): void {
|
|
111
|
+
const health = buildHealth();
|
|
112
|
+
|
|
113
|
+
if (opts.json) {
|
|
114
|
+
console.log(JSON.stringify(health, null, 2));
|
|
115
|
+
if (health.candidateLedgerConsistency.status === 'degraded') process.exit(1);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(`generatedAt: ${health.generatedAt}`);
|
|
120
|
+
console.log(`workspace: ${health.workspace}`);
|
|
121
|
+
console.log(`pdStateDb.exists: ${health.pdStateDb.exists}`);
|
|
122
|
+
console.log(`pdStateDb.path: ${health.pdStateDb.path}`);
|
|
123
|
+
console.log(`ledger.exists: ${health.ledger.exists}`);
|
|
124
|
+
console.log(`ledger.path: ${health.ledger.path}`);
|
|
125
|
+
console.log(`ledger.totalPrinciples: ${health.ledger.totalPrinciples}`);
|
|
126
|
+
console.log(`ledger.byStatus: ${JSON.stringify(health.ledger.byStatus)}`);
|
|
127
|
+
console.log(`candidates.total: ${health.candidates.total}`);
|
|
128
|
+
console.log(`candidates.consumed: ${health.candidates.consumed}`);
|
|
129
|
+
console.log(`candidates.pending: ${health.candidates.pending}`);
|
|
130
|
+
console.log(`tasks.total: ${health.tasks.total}`);
|
|
131
|
+
console.log(`tasks.byStatus: ${JSON.stringify(health.tasks.byStatus)}`);
|
|
132
|
+
console.log(`candidateLedgerConsistency.status: ${health.candidateLedgerConsistency.status}`);
|
|
133
|
+
console.log(`candidateLedgerConsistency.missing: ${health.candidateLedgerConsistency.missing}`);
|
|
134
|
+
if (health.lastSuccessfulChain) {
|
|
135
|
+
console.log('lastSuccessfulChain:');
|
|
136
|
+
console.log(` taskId: ${health.lastSuccessfulChain.taskId}`);
|
|
137
|
+
console.log(` runId: ${health.lastSuccessfulChain.runId}`);
|
|
138
|
+
console.log(` artifactId: ${health.lastSuccessfulChain.artifactId}`);
|
|
139
|
+
console.log(` candidateIds: ${health.lastSuccessfulChain.candidateIds.join(', ')}`);
|
|
140
|
+
console.log(` ledgerEntries: ${health.lastSuccessfulChain.ledgerEntryIds.join(', ')}`);
|
|
141
|
+
}
|
|
142
|
+
console.log('');
|
|
143
|
+
|
|
144
|
+
if (health.candidateLedgerConsistency.status === 'degraded') {
|
|
145
|
+
console.warn('⚠️ Candidate/ledger consistency is DEGRADED. Run: pd candidate audit --workspace "' + workspaceDir + '" --json');
|
|
146
|
+
console.warn(' To repair missing entries: pd candidate repair --candidate-id <id> --workspace "' + workspaceDir + '" --json');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (fs.existsSync(pdDbPath)) {
|
|
152
|
+
pdDbExists = true;
|
|
153
|
+
const db = Database(pdDbPath, { readonly: true });
|
|
154
|
+
try {
|
|
155
|
+
const cRow = db.prepare('SELECT COUNT(*) as total, status FROM principle_candidates GROUP BY status').all() as { total: number; status: string }[];
|
|
156
|
+
for (const r of cRow) {
|
|
157
|
+
candidatesTotal += r.total;
|
|
158
|
+
if (r.status === 'consumed') candidatesConsumed = r.total;
|
|
159
|
+
if (r.status === 'pending') candidatesPending = r.total;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const tRows = db.prepare('SELECT COUNT(*) as total, status FROM tasks GROUP BY status').all() as { total: number; status: string }[];
|
|
163
|
+
for (const r of tRows) {
|
|
164
|
+
tasksTotal += r.total;
|
|
165
|
+
tasksByStatus[r.status] = r.total;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const painChainModel = new PainChainReadModel({ workspaceDir });
|
|
169
|
+
try {
|
|
170
|
+
const chain = await painChainModel.getLastSuccessfulChain();
|
|
171
|
+
if (chain) {
|
|
172
|
+
lastSuccessfulChain = painChainTraceToLastSuccessfulChain(chain);
|
|
173
|
+
}
|
|
174
|
+
} catch {
|
|
175
|
+
partialHealth = true;
|
|
176
|
+
} finally {
|
|
177
|
+
await painChainModel.close();
|
|
178
|
+
}
|
|
179
|
+
} catch (err) {
|
|
180
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
181
|
+
console.warn(`Warning: could not read full state.db metrics — partial health data: ${msg}`);
|
|
182
|
+
partialHealth = true;
|
|
183
|
+
} finally {
|
|
184
|
+
db.close();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
writeHealth();
|
|
189
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd history query — Query run history for a task with pagination.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* pd history query <taskId> [--limit N] [--cursor <cursor>]
|
|
6
|
+
* pd history query <taskId> --from <date> --to <date>
|
|
7
|
+
*/
|
|
8
|
+
import { SqliteConnection, SqliteHistoryQuery } from '@principles/core';
|
|
9
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
10
|
+
|
|
11
|
+
interface HistoryQueryOptions {
|
|
12
|
+
limit?: number;
|
|
13
|
+
cursor?: string;
|
|
14
|
+
from?: string;
|
|
15
|
+
to?: string;
|
|
16
|
+
json?: boolean;
|
|
17
|
+
workspace?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function handleHistoryQuery(taskId: string, opts: HistoryQueryOptions): Promise<void> {
|
|
21
|
+
const workspaceDir = resolveWorkspaceDir(opts.workspace);
|
|
22
|
+
const connection = new SqliteConnection(workspaceDir);
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const historyQuery = new SqliteHistoryQuery(connection);
|
|
26
|
+
|
|
27
|
+
const queryOpts = opts.limit || opts.from || opts.to
|
|
28
|
+
? {
|
|
29
|
+
limit: opts.limit,
|
|
30
|
+
timeWindowStart: opts.from,
|
|
31
|
+
timeWindowEnd: opts.to,
|
|
32
|
+
}
|
|
33
|
+
: undefined;
|
|
34
|
+
const result = await historyQuery.query(taskId, opts.cursor, queryOpts);
|
|
35
|
+
|
|
36
|
+
if (opts.json) {
|
|
37
|
+
console.log(JSON.stringify(result, null, 2));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (result.entries.length === 0) {
|
|
42
|
+
console.log('No history entries found.');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log(`\nHistory for ${taskId} (${result.entries.length} entries${result.truncated ? ', truncated' : ''}):\n`);
|
|
47
|
+
for (const entry of result.entries) {
|
|
48
|
+
const text = entry.text ? (entry.text.length > 60 ? entry.text.substring(0, 57) + '...' : entry.text) : '<empty>';
|
|
49
|
+
console.log(' [%s] %-8s %s', entry.ts.substring(11, 19), entry.role, text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (result.nextCursor) {
|
|
53
|
+
console.log(`\n nextCursor: ${result.nextCursor}`);
|
|
54
|
+
}
|
|
55
|
+
console.log('');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
58
|
+
console.error(`Error: ${message}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
} finally {
|
|
61
|
+
connection.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd legacy cleanup
|
|
3
|
+
*
|
|
4
|
+
* Cleans legacy artifacts from workspaces:
|
|
5
|
+
* - .state/pd_tasks.json (removes empathy-optimizer entries)
|
|
6
|
+
* - .state/sessions/*.json (archives sessions with cron:pd-empathy-optimizer)
|
|
7
|
+
* - .state/diagnostician_tasks.json (archives)
|
|
8
|
+
* - .state/.evolution_complete_* (archives)
|
|
9
|
+
* - .state/.diagnostician_report_* (archives)
|
|
10
|
+
* - ~/.openclaw/cron/jobs.json (removes pd-empathy-optimizer cron jobs)
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* pd legacy cleanup --workspace <path> --dry-run
|
|
14
|
+
* pd legacy cleanup --workspace <path> --apply
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import * as os from 'os';
|
|
20
|
+
|
|
21
|
+
interface CleanupTarget {
|
|
22
|
+
path: string;
|
|
23
|
+
action: 'remove' | 'archive';
|
|
24
|
+
reason: string;
|
|
25
|
+
archivePath?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface CronJobRecord {
|
|
29
|
+
id?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface _CronStore {
|
|
35
|
+
jobs: CronJobRecord[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface TaskRecord {
|
|
39
|
+
id?: string;
|
|
40
|
+
name?: string;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function glob(pattern: string): string[] {
|
|
45
|
+
const results: string[] = [];
|
|
46
|
+
const baseDir = path.dirname(pattern);
|
|
47
|
+
const filePattern = path.basename(pattern).replace(/\*/g, '');
|
|
48
|
+
|
|
49
|
+
if (!fs.existsSync(baseDir)) return [];
|
|
50
|
+
|
|
51
|
+
for (const file of fs.readdirSync(baseDir)) {
|
|
52
|
+
if (file.startsWith(filePattern) || filePattern === '') {
|
|
53
|
+
const fullPath = path.join(baseDir, file);
|
|
54
|
+
const stat = fs.statSync(fullPath);
|
|
55
|
+
if (stat.isFile()) results.push(fullPath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function findLegacyTargets(workspacePath: string): CleanupTarget[] {
|
|
62
|
+
const targets: CleanupTarget[] = [];
|
|
63
|
+
const stateDir = path.join(workspacePath, '.state');
|
|
64
|
+
const archiveTimestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
65
|
+
const archiveDir = path.join(stateDir, 'legacy-archive', archiveTimestamp);
|
|
66
|
+
|
|
67
|
+
// 1. pd_tasks.json — remove empathy-optimizer entries
|
|
68
|
+
const pdTasksPath = path.join(stateDir, 'pd_tasks.json');
|
|
69
|
+
if (fs.existsSync(pdTasksPath)) {
|
|
70
|
+
try {
|
|
71
|
+
const content = fs.readFileSync(pdTasksPath, 'utf-8');
|
|
72
|
+
const tasks = JSON.parse(content);
|
|
73
|
+
const filtered = tasks.filter((t: TaskRecord) =>
|
|
74
|
+
!t.id?.includes('empathy-optimizer') && !t.name?.includes('Empathy Optimizer')
|
|
75
|
+
);
|
|
76
|
+
if (filtered.length !== tasks.length) {
|
|
77
|
+
targets.push({
|
|
78
|
+
path: pdTasksPath,
|
|
79
|
+
action: 'archive',
|
|
80
|
+
reason: 'Removed empathy-optimizer entries from pd_tasks.json',
|
|
81
|
+
archivePath: path.join(archiveDir, 'pd_tasks.json.backup'),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
} catch { /* skip invalid JSON */ }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 2. sessions/*.json — archive empathy cron sessions
|
|
88
|
+
const sessionsDir = path.join(stateDir, 'sessions');
|
|
89
|
+
if (fs.existsSync(sessionsDir)) {
|
|
90
|
+
for (const file of fs.readdirSync(sessionsDir)) {
|
|
91
|
+
if (!file.endsWith('.json')) continue;
|
|
92
|
+
const filePath = path.join(sessionsDir, file);
|
|
93
|
+
try {
|
|
94
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
95
|
+
const session = JSON.parse(content);
|
|
96
|
+
if (session.sessionKey?.includes('cron:pd-empathy-optimizer') ||
|
|
97
|
+
session.sessionKey?.includes('cron:empathy-optimizer')) {
|
|
98
|
+
targets.push({
|
|
99
|
+
path: filePath,
|
|
100
|
+
action: 'archive',
|
|
101
|
+
reason: `Legacy empathy cron session: ${session.sessionKey}`,
|
|
102
|
+
archivePath: path.join(archiveDir, 'sessions', file),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
} catch { /* skip */ }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 3. diagnostician_tasks.json
|
|
110
|
+
const diagPath = path.join(stateDir, 'diagnostician_tasks.json');
|
|
111
|
+
if (fs.existsSync(diagPath)) {
|
|
112
|
+
targets.push({
|
|
113
|
+
path: diagPath,
|
|
114
|
+
action: 'archive',
|
|
115
|
+
reason: 'Legacy diagnostician task store',
|
|
116
|
+
archivePath: path.join(archiveDir, 'diagnostician_tasks.json'),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 4. .evolution_complete_* markers
|
|
121
|
+
for (const marker of glob(path.join(stateDir, '.evolution_complete_*'))) {
|
|
122
|
+
targets.push({
|
|
123
|
+
path: marker,
|
|
124
|
+
action: 'archive',
|
|
125
|
+
reason: 'Legacy evolution marker',
|
|
126
|
+
archivePath: path.join(archiveDir, path.basename(marker)),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 5. .diagnostician_report_* markers
|
|
131
|
+
for (const marker of glob(path.join(stateDir, '.diagnostician_report_*'))) {
|
|
132
|
+
targets.push({
|
|
133
|
+
path: marker,
|
|
134
|
+
action: 'archive',
|
|
135
|
+
reason: 'Legacy diagnostician report marker',
|
|
136
|
+
archivePath: path.join(archiveDir, path.basename(marker)),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 6. OpenClaw cron jobs.json
|
|
141
|
+
const cronPath = path.join(os.homedir(), '.openclaw', 'cron', 'jobs.json');
|
|
142
|
+
if (fs.existsSync(cronPath)) {
|
|
143
|
+
try {
|
|
144
|
+
const content = fs.readFileSync(cronPath, 'utf-8');
|
|
145
|
+
const store = JSON.parse(content) as _CronStore;
|
|
146
|
+
const filtered = store.jobs.filter((j: CronJobRecord) =>
|
|
147
|
+
!j.id?.includes('pd-empathy-optimizer') && !j.name?.includes('Empathy Optimizer')
|
|
148
|
+
);
|
|
149
|
+
if (filtered.length !== store.jobs.length) {
|
|
150
|
+
targets.push({
|
|
151
|
+
path: cronPath,
|
|
152
|
+
action: 'archive',
|
|
153
|
+
reason: 'Removed pd-empathy-optimizer cron jobs',
|
|
154
|
+
archivePath: path.join(os.homedir(), '.openclaw', 'cron', `jobs.json.backup-${archiveTimestamp}`),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
} catch { /* skip */ }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return targets;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function handleLegacyCleanup(
|
|
164
|
+
workspacePath: string,
|
|
165
|
+
dryRun: boolean
|
|
166
|
+
): Promise<{ targets: CleanupTarget[]; applied: number }> {
|
|
167
|
+
const targets = findLegacyTargets(workspacePath);
|
|
168
|
+
let applied = 0;
|
|
169
|
+
|
|
170
|
+
if (dryRun) {
|
|
171
|
+
console.log(`\n=== DRY RUN: Would process ${targets.length} target(s) ===`);
|
|
172
|
+
for (const t of targets) {
|
|
173
|
+
console.log(` ${t.action}: ${t.path}`);
|
|
174
|
+
console.log(` Reason: ${t.reason}`);
|
|
175
|
+
if (t.archivePath) {
|
|
176
|
+
console.log(` Archive: ${t.archivePath}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (targets.length === 0) {
|
|
180
|
+
console.log(' No legacy artifacts found.');
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
console.log(`\n=== Applying ${targets.length} cleanup(s) ===`);
|
|
184
|
+
for (const t of targets) {
|
|
185
|
+
try {
|
|
186
|
+
if (t.action === 'archive' && t.archivePath) {
|
|
187
|
+
const archiveDir = path.dirname(t.archivePath);
|
|
188
|
+
if (!fs.existsSync(archiveDir)) {
|
|
189
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
190
|
+
}
|
|
191
|
+
fs.copyFileSync(t.path, t.archivePath);
|
|
192
|
+
fs.unlinkSync(t.path);
|
|
193
|
+
console.log(` Archived: ${t.path} -> ${t.archivePath}`);
|
|
194
|
+
} else {
|
|
195
|
+
fs.unlinkSync(t.path);
|
|
196
|
+
console.log(` Removed: ${t.path}`);
|
|
197
|
+
}
|
|
198
|
+
applied++;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
console.error(` ERROR processing ${t.path}: ${String(err)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { targets, applied };
|
|
206
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd legacy import openclaw — Import OpenClaw legacy data into PD runtime-v2 store.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* pd legacy import openclaw --workspace <path>
|
|
6
|
+
*
|
|
7
|
+
* This command is the formal operator path for migrating OpenClaw workspace data
|
|
8
|
+
* into PD runtime-v2 SQLite. It must be run before trajectory/history/context commands
|
|
9
|
+
* can return results on a workspace that only has OpenClaw legacy data.
|
|
10
|
+
*
|
|
11
|
+
* Two import stages:
|
|
12
|
+
* 1. Task/Run metadata from .state/diagnostician_tasks.json
|
|
13
|
+
* 2. Session history from .state/trajectory.db (assistant_turns, user_turns, tool_calls)
|
|
14
|
+
*/
|
|
15
|
+
import { SqliteConnection } from '@principles/core';
|
|
16
|
+
import { syncOpenClawWorkspace } from '../legacy/legacy-import.js';
|
|
17
|
+
import { importSessionHistory } from '../legacy/session-history-import.js';
|
|
18
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
19
|
+
|
|
20
|
+
interface LegacyImportOptions {
|
|
21
|
+
workspace?: string;
|
|
22
|
+
json?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function handleLegacyImportOpenClaw(opts: LegacyImportOptions): Promise<void> {
|
|
26
|
+
const workspaceDir = resolveWorkspaceDir(opts.workspace);
|
|
27
|
+
const connection = new SqliteConnection(workspaceDir);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const openclawWorkspace = workspaceDir; // same workspace for now
|
|
31
|
+
|
|
32
|
+
// Stage 1: Task/Run metadata import
|
|
33
|
+
if (opts.json) {
|
|
34
|
+
console.log(JSON.stringify({ stage: 1, source: '.state/diagnostician_tasks.json' }));
|
|
35
|
+
} else {
|
|
36
|
+
console.log('Stage 1: Importing diagnostician tasks and runs...');
|
|
37
|
+
}
|
|
38
|
+
const syncResult = await syncOpenClawWorkspace(workspaceDir, connection);
|
|
39
|
+
|
|
40
|
+
if (opts.json) {
|
|
41
|
+
console.log(
|
|
42
|
+
JSON.stringify({
|
|
43
|
+
stage: 1,
|
|
44
|
+
tasksImported: syncResult.tasksSynced,
|
|
45
|
+
runsImported: syncResult.runsSynced,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
} else {
|
|
49
|
+
console.log(` → ${syncResult.tasksSynced} tasks, ${syncResult.runsSynced} runs synced`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Stage 2: Session history import (if better-sqlite3 is available)
|
|
53
|
+
try {
|
|
54
|
+
if (opts.json) {
|
|
55
|
+
console.log(JSON.stringify({ stage: 2, source: '.state/trajectory.db' }));
|
|
56
|
+
} else {
|
|
57
|
+
console.log('Stage 2: Importing session history from trajectory.db...');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
const historyResult = await importSessionHistory(
|
|
62
|
+
openclawWorkspace,
|
|
63
|
+
workspaceDir,
|
|
64
|
+
() => connection.getDb(),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (opts.json) {
|
|
68
|
+
console.log(
|
|
69
|
+
JSON.stringify({
|
|
70
|
+
stage: 2,
|
|
71
|
+
sessionsProcessed: historyResult.sessionsProcessed,
|
|
72
|
+
entriesImported: historyResult.entriesImported,
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
} else {
|
|
76
|
+
console.log(
|
|
77
|
+
` → ${historyResult.sessionsProcessed} sessions, ${historyResult.entriesImported} entries imported`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
} catch (historyError) {
|
|
81
|
+
const msg = historyError instanceof Error ? historyError.message : String(historyError);
|
|
82
|
+
if (opts.json) {
|
|
83
|
+
console.log(
|
|
84
|
+
JSON.stringify({
|
|
85
|
+
stage: 2,
|
|
86
|
+
skipped: true,
|
|
87
|
+
reason: `better-sqlite3 not available: ${msg}`,
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
console.log(` → Stage 2 skipped (better-sqlite3 not available: ${msg})`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!opts.json) {
|
|
96
|
+
console.log('\nImport complete. You can now run:');
|
|
97
|
+
console.log(' pd trajectory locate --task <id> --workspace <path>');
|
|
98
|
+
console.log(' pd history query <id> --workspace <path>');
|
|
99
|
+
console.log(' pd context build <id> --workspace <path>');
|
|
100
|
+
}
|
|
101
|
+
} finally {
|
|
102
|
+
connection.close();
|
|
103
|
+
}
|
|
104
|
+
}
|