@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,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd runtime probe command — Runtime health and capabilities inspection.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* pd runtime probe --runtime openclaw-cli [--openclaw-local|--openclaw-gateway] [--json]
|
|
6
|
+
* pd runtime probe --runtime pi-ai --provider <name> --model <id> --apiKeyEnv <name> [--baseUrl <url>] [--json]
|
|
7
|
+
*
|
|
8
|
+
* HG-01 HARD GATE: This command must deliver.
|
|
9
|
+
*/
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { probeRuntime } from '@principles/core/runtime-v2';
|
|
12
|
+
import { PDRuntimeError } from '@principles/core/runtime-v2';
|
|
13
|
+
|
|
14
|
+
interface RuntimeProbeOptions {
|
|
15
|
+
runtime: string;
|
|
16
|
+
openclawLocal?: boolean;
|
|
17
|
+
openclawGateway?: boolean;
|
|
18
|
+
agent?: string;
|
|
19
|
+
provider?: string;
|
|
20
|
+
model?: string;
|
|
21
|
+
apiKeyEnv?: string;
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
maxRetries?: number;
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
workspace?: string;
|
|
26
|
+
json?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Format capabilities as a key-value table for console output.
|
|
31
|
+
*/
|
|
32
|
+
function formatCapabilitiesTable(capabilities: Record<string, unknown>): string {
|
|
33
|
+
const lines: string[] = [];
|
|
34
|
+
for (const [key, value] of Object.entries(capabilities)) {
|
|
35
|
+
const displayValue = typeof value === 'boolean' ? (value ? 'yes' : 'no') : String(value);
|
|
36
|
+
lines.push(` ${key.padEnd(40)} ${displayValue}`);
|
|
37
|
+
}
|
|
38
|
+
return lines.join('\n');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* openclaw-cli probe branch (existing behavior, unchanged).
|
|
43
|
+
*/
|
|
44
|
+
async function handleOpenClawProbe(opts: RuntimeProbeOptions): Promise<void> {
|
|
45
|
+
// Validate mutually exclusive flags (HG-03)
|
|
46
|
+
if (opts.openclawLocal && opts.openclawGateway) {
|
|
47
|
+
console.error('error: --openclaw-local and --openclaw-gateway are mutually exclusive');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Require explicit runtime mode (HG-03, DPB-09)
|
|
52
|
+
if (!opts.openclawLocal && !opts.openclawGateway) {
|
|
53
|
+
console.error('error: --openclaw-local or --openclaw-gateway is required for --runtime openclaw-cli');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const runtimeMode = opts.openclawLocal ? 'local' : 'gateway';
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const result = await probeRuntime({
|
|
61
|
+
runtimeKind: 'openclaw-cli',
|
|
62
|
+
runtimeMode,
|
|
63
|
+
agentId: opts.agent,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Per finding #2: status must reflect actual health
|
|
67
|
+
// healthy=false → status=failed, exit 1
|
|
68
|
+
// healthy=true + degraded=true → status=degraded
|
|
69
|
+
// healthy=true + degraded=false → status=succeeded
|
|
70
|
+
let exitCode = 0;
|
|
71
|
+
const status = !result.health.healthy ? 'failed'
|
|
72
|
+
: result.health.degraded ? 'degraded'
|
|
73
|
+
: 'succeeded';
|
|
74
|
+
if (!result.health.healthy) exitCode = 1;
|
|
75
|
+
|
|
76
|
+
if (opts.json) {
|
|
77
|
+
console.log(JSON.stringify({
|
|
78
|
+
status,
|
|
79
|
+
runtimeKind: result.runtimeKind,
|
|
80
|
+
health: result.health,
|
|
81
|
+
capabilities: result.capabilities,
|
|
82
|
+
}, null, 2));
|
|
83
|
+
if (exitCode !== 0) {
|
|
84
|
+
process.exit(exitCode);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Human-readable output
|
|
90
|
+
console.log(`\nRuntime: ${result.runtimeKind}`);
|
|
91
|
+
console.log(`Mode: ${runtimeMode}`);
|
|
92
|
+
console.log(`Status: ${status}`);
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log('Health:');
|
|
95
|
+
console.log(` healthy: ${result.health.healthy ? 'yes' : 'no'}`);
|
|
96
|
+
console.log(` degraded: ${result.health.degraded ? 'yes' : 'no'}`);
|
|
97
|
+
if (result.health.warnings.length > 0) {
|
|
98
|
+
console.log(` warnings:`);
|
|
99
|
+
for (const w of result.health.warnings) {
|
|
100
|
+
console.log(` - ${w}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
console.log(` lastCheckedAt: ${result.health.lastCheckedAt}`);
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log('Capabilities:');
|
|
106
|
+
console.log(formatCapabilitiesTable(result.capabilities));
|
|
107
|
+
console.log('');
|
|
108
|
+
|
|
109
|
+
if (exitCode !== 0) {
|
|
110
|
+
process.exit(exitCode);
|
|
111
|
+
}
|
|
112
|
+
} catch (error: unknown) {
|
|
113
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
114
|
+
let errorCategory = 'execution_failed';
|
|
115
|
+
if (error instanceof PDRuntimeError) {
|
|
116
|
+
errorCategory = error.category;
|
|
117
|
+
}
|
|
118
|
+
if (opts.json) {
|
|
119
|
+
console.log(JSON.stringify({
|
|
120
|
+
status: 'failed',
|
|
121
|
+
errorCategory,
|
|
122
|
+
message,
|
|
123
|
+
runtimeKind: 'openclaw-cli',
|
|
124
|
+
}, null, 2));
|
|
125
|
+
} else {
|
|
126
|
+
console.error(`error: ${message} (${errorCategory})`);
|
|
127
|
+
}
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* pi-ai probe branch — validates flags, calls probeRuntime, formats output.
|
|
134
|
+
*/
|
|
135
|
+
async function handlePiAiProbe(opts: RuntimeProbeOptions): Promise<void> {
|
|
136
|
+
// D-01: flags are required for pi-ai probe unless --workspace is provided (policy fallback)
|
|
137
|
+
const workspaceDir = opts.workspace ? path.resolve(opts.workspace) : undefined;
|
|
138
|
+
let provider = opts.provider ?? '';
|
|
139
|
+
let model = opts.model ?? '';
|
|
140
|
+
let apiKeyEnv = opts.apiKeyEnv ?? '';
|
|
141
|
+
let baseUrl = opts.baseUrl ?? '';
|
|
142
|
+
let {timeoutMs} = opts;
|
|
143
|
+
|
|
144
|
+
// D-01: always load workspace policy; CLI values take priority as override
|
|
145
|
+
if (workspaceDir) {
|
|
146
|
+
try {
|
|
147
|
+
const { resolveRuntimeConfig, isRuntimeConfigError } = await import('@principles/core/runtime-v2');
|
|
148
|
+
const configResult = resolveRuntimeConfig(path.join(workspaceDir, '.state'));
|
|
149
|
+
if (isRuntimeConfigError(configResult)) {
|
|
150
|
+
console.warn(`Warning: could not load workspace runtime config — ${configResult.message}`);
|
|
151
|
+
} else {
|
|
152
|
+
const config = configResult;
|
|
153
|
+
provider = provider || config.provider || '';
|
|
154
|
+
model = model || config.model || '';
|
|
155
|
+
apiKeyEnv = apiKeyEnv || config.apiKeyEnv || '';
|
|
156
|
+
baseUrl = baseUrl || config.baseUrl || '';
|
|
157
|
+
timeoutMs = timeoutMs ?? config.timeoutMs;
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.warn(`Warning: could not load workspace runtime config — policy fallback disabled: ${err instanceof Error ? err.message : String(err)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!provider) {
|
|
165
|
+
console.error("error: --provider is required for --runtime pi-ai (or set in --workspace workflows.yaml)");
|
|
166
|
+
console.error(" e.g.: pd runtime probe --runtime pi-ai --provider openrouter --model anthropic/claude-sonnet-4 --apiKeyEnv OPENROUTER_API_KEY");
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
if (!model) {
|
|
170
|
+
console.error("error: --model is required for --runtime pi-ai (or set in --workspace workflows.yaml)");
|
|
171
|
+
console.error(" e.g.: pd runtime probe --runtime pi-ai --provider openrouter --model anthropic/claude-sonnet-4 --apiKeyEnv OPENROUTER_API_KEY");
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
if (!apiKeyEnv) {
|
|
175
|
+
console.error("error: --apiKeyEnv is required for --runtime pi-ai (or set in --workspace workflows.yaml)");
|
|
176
|
+
console.error(" e.g.: pd runtime probe --runtime pi-ai --provider openrouter --model anthropic/claude-sonnet-4 --apiKeyEnv OPENROUTER_API_KEY");
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// D-09: check env var exists before calling probeRuntime
|
|
181
|
+
if (!process.env[apiKeyEnv]) {
|
|
182
|
+
console.error(`error: environment variable '${apiKeyEnv}' is not set`);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
const result = await probeRuntime({
|
|
188
|
+
runtimeKind: 'pi-ai',
|
|
189
|
+
provider,
|
|
190
|
+
model,
|
|
191
|
+
apiKeyEnv,
|
|
192
|
+
baseUrl,
|
|
193
|
+
maxRetries: opts.maxRetries,
|
|
194
|
+
timeoutMs: timeoutMs ?? 120_000, // D-04: probe timeout 120s (matches Runtime defaults)
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Narrow to pi-ai result (TypeScript can't infer from input args alone)
|
|
198
|
+
if (result.runtimeKind !== 'pi-ai') {
|
|
199
|
+
throw new Error('unexpected: probeRuntime returned non-pi-ai result');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Determine status from health
|
|
203
|
+
let exitCode = 0;
|
|
204
|
+
const status = !result.health.healthy ? 'failed'
|
|
205
|
+
: result.health.degraded ? 'degraded'
|
|
206
|
+
: 'succeeded';
|
|
207
|
+
if (!result.health.healthy) exitCode = 1;
|
|
208
|
+
|
|
209
|
+
if (opts.json) {
|
|
210
|
+
console.log(JSON.stringify({
|
|
211
|
+
status,
|
|
212
|
+
runtimeKind: result.runtimeKind,
|
|
213
|
+
provider: result.provider,
|
|
214
|
+
model: result.model,
|
|
215
|
+
baseUrlPresent: !!baseUrl,
|
|
216
|
+
health: result.health,
|
|
217
|
+
capabilities: result.capabilities,
|
|
218
|
+
}, null, 2));
|
|
219
|
+
if (exitCode !== 0) process.exit(exitCode);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// D-05: human-readable output
|
|
224
|
+
console.log(`\nRuntime: ${result.runtimeKind}`);
|
|
225
|
+
console.log(`Provider: ${result.provider}`);
|
|
226
|
+
console.log(`Model: ${result.model}`);
|
|
227
|
+
if (baseUrl) console.log(`BaseUrl: ${baseUrl}`);
|
|
228
|
+
console.log(`Status: ${status}`);
|
|
229
|
+
console.log('');
|
|
230
|
+
console.log('Health:');
|
|
231
|
+
console.log(` healthy: ${result.health.healthy ? 'yes' : 'no'}`);
|
|
232
|
+
console.log(` degraded: ${result.health.degraded ? 'yes' : 'no'}`);
|
|
233
|
+
if (result.health.warnings.length > 0) {
|
|
234
|
+
console.log(' warnings:');
|
|
235
|
+
for (const w of result.health.warnings) {
|
|
236
|
+
console.log(` - ${w}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
console.log(` lastCheckedAt: ${result.health.lastCheckedAt}`);
|
|
240
|
+
console.log('');
|
|
241
|
+
console.log('Capabilities:');
|
|
242
|
+
console.log(formatCapabilitiesTable(result.capabilities));
|
|
243
|
+
console.log('');
|
|
244
|
+
|
|
245
|
+
if (exitCode !== 0) process.exit(exitCode);
|
|
246
|
+
} catch (error: unknown) {
|
|
247
|
+
// D-10: test complete failure → error category + raw error
|
|
248
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
249
|
+
let errorCategory = 'execution_failed';
|
|
250
|
+
if (error instanceof PDRuntimeError) {
|
|
251
|
+
errorCategory = error.category;
|
|
252
|
+
}
|
|
253
|
+
if (opts.json) {
|
|
254
|
+
console.log(JSON.stringify({
|
|
255
|
+
status: 'failed',
|
|
256
|
+
errorCategory,
|
|
257
|
+
message,
|
|
258
|
+
runtimeKind: 'pi-ai',
|
|
259
|
+
}, null, 2));
|
|
260
|
+
} else {
|
|
261
|
+
console.error(`error: ${message} (${errorCategory})`);
|
|
262
|
+
}
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* pd runtime probe — dispatches to openclaw-cli or pi-ai branch.
|
|
269
|
+
*/
|
|
270
|
+
export async function handleRuntimeProbe(opts: RuntimeProbeOptions): Promise<void> {
|
|
271
|
+
if (opts.runtime === 'openclaw-cli') {
|
|
272
|
+
return handleOpenClawProbe(opts);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (opts.runtime === 'pi-ai') {
|
|
276
|
+
return handlePiAiProbe(opts);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.error(`error: unsupported --runtime '${opts.runtime}' (supported: openclaw-cli, pi-ai)`);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd samples list command implementation.
|
|
3
|
+
*
|
|
4
|
+
* Usage: pd samples list [--status pending|approved|rejected]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { listCorrectionSamples } from '@principles/core/trajectory-store';
|
|
8
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
9
|
+
|
|
10
|
+
interface SamplesListOptions {
|
|
11
|
+
status?: 'pending' | 'approved' | 'rejected';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function handleSamplesList(opts: SamplesListOptions): Promise<void> {
|
|
15
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
16
|
+
const status = opts.status ?? 'pending';
|
|
17
|
+
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
19
|
+
let samples;
|
|
20
|
+
try {
|
|
21
|
+
samples = listCorrectionSamples(workspaceDir, status);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24
|
+
if (message.includes('ENOENT') || message.includes('SQLITE_CANTOPEN') || message.includes('SQLITE_NOTADB')) {
|
|
25
|
+
console.log('No correction samples found.');
|
|
26
|
+
} else {
|
|
27
|
+
console.error('Failed to list samples:', message);
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (samples.length === 0) {
|
|
34
|
+
console.log('No correction samples found.');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log(`Correction Samples (${status}):`);
|
|
39
|
+
for (const sample of samples) {
|
|
40
|
+
console.log(` [${sample.sampleId}] session=${sample.sessionId} score=${sample.qualityScore} created=${sample.createdAt}`);
|
|
41
|
+
}
|
|
42
|
+
console.log(`${samples.length} sample(s)`);
|
|
43
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd samples review command implementation.
|
|
3
|
+
*
|
|
4
|
+
* Usage: pd samples review <sample-id> approve|reject [note]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { reviewCorrectionSample } from '@principles/core/trajectory-store';
|
|
8
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
9
|
+
|
|
10
|
+
type ReviewDecision = 'approved' | 'rejected';
|
|
11
|
+
|
|
12
|
+
interface SamplesReviewOptions {
|
|
13
|
+
sampleId: string;
|
|
14
|
+
decision: ReviewDecision;
|
|
15
|
+
note?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function handleSamplesReview(opts: SamplesReviewOptions): Promise<void> {
|
|
19
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
reviewCorrectionSample(opts.sampleId, opts.decision, opts.note, workspaceDir);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (err instanceof Error && err.message.includes('Sample not found')) {
|
|
25
|
+
console.error(`Error: Sample not found: ${opts.sampleId}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`Sample ${opts.sampleId} marked as ${opts.decision}`);
|
|
32
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd task list/show commands — Runtime v2 task inspection.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* pd task list [--status <status>] [--kind <kind>] [--limit <n>]
|
|
6
|
+
* pd task show <taskId>
|
|
7
|
+
*/
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { RuntimeStateManager } from '@principles/core';
|
|
10
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
11
|
+
|
|
12
|
+
interface TaskListOptions {
|
|
13
|
+
status?: string;
|
|
14
|
+
kind?: string;
|
|
15
|
+
limit?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function handleTaskList(opts: TaskListOptions): Promise<void> {
|
|
19
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
20
|
+
const stateManager = new RuntimeStateManager({ workspaceDir });
|
|
21
|
+
await stateManager.initialize();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const filter: Record<string, string | number> = {};
|
|
25
|
+
if (opts.status) filter.status = opts.status;
|
|
26
|
+
if (opts.kind) filter.taskKind = opts.kind;
|
|
27
|
+
if (opts.limit) filter.limit = opts.limit;
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const tasks = await stateManager.listTasks(Object.keys(filter).length > 0 ? filter : undefined);
|
|
31
|
+
|
|
32
|
+
if (tasks.length === 0) {
|
|
33
|
+
console.log('No tasks found.');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(`\nTasks (${tasks.length}):\n`);
|
|
38
|
+
console.log(
|
|
39
|
+
'%-22s %-12s %-10s %-4s/%-4s %-15s %s',
|
|
40
|
+
'TASK_ID', 'KIND', 'STATUS', 'ATT', 'MAX', 'LEASE_OWNER', 'LEASE_EXPIRES',
|
|
41
|
+
);
|
|
42
|
+
console.log('-'.repeat(90));
|
|
43
|
+
|
|
44
|
+
for (const task of tasks) {
|
|
45
|
+
const expiresAt = task.leaseExpiresAt
|
|
46
|
+
? new Date(task.leaseExpiresAt).toLocaleString()
|
|
47
|
+
: '-';
|
|
48
|
+
console.log(
|
|
49
|
+
'%-22s %-12s %-10s %-4s %-4s %-15s %s',
|
|
50
|
+
task.taskId.substring(0, 22),
|
|
51
|
+
task.taskKind.substring(0, 12),
|
|
52
|
+
task.status,
|
|
53
|
+
task.attemptCount,
|
|
54
|
+
task.maxAttempts,
|
|
55
|
+
task.leaseOwner ?? '-',
|
|
56
|
+
expiresAt.substring(0, 19),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
console.log('');
|
|
60
|
+
} finally {
|
|
61
|
+
await stateManager.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface TaskShowOptions {
|
|
66
|
+
id: string;
|
|
67
|
+
json?: boolean;
|
|
68
|
+
workspace?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function handleTaskShow(opts: TaskShowOptions): Promise<void> {
|
|
72
|
+
const workspaceDir = opts.workspace ? path.resolve(opts.workspace) : resolveWorkspaceDir();
|
|
73
|
+
const stateManager = new RuntimeStateManager({ workspaceDir });
|
|
74
|
+
await stateManager.initialize();
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const task = await stateManager.getTask(opts.id);
|
|
78
|
+
|
|
79
|
+
if (!task) {
|
|
80
|
+
console.error(`Task not found: ${opts.id}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const runs = await stateManager.getRunsByTask(opts.id);
|
|
85
|
+
|
|
86
|
+
if (opts.json) {
|
|
87
|
+
console.log(JSON.stringify({ task, runs }, null, 2));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log(`\nTask: ${task.taskId}\n`);
|
|
92
|
+
console.log(` Kind: ${task.taskKind}`);
|
|
93
|
+
console.log(` Status: ${task.status}`);
|
|
94
|
+
console.log(` Attempts: ${task.attemptCount} / ${task.maxAttempts}`);
|
|
95
|
+
if (task.leaseOwner) {
|
|
96
|
+
console.log(` Lease Owner: ${task.leaseOwner}`);
|
|
97
|
+
console.log(` Lease Expires: ${task.leaseExpiresAt ? new Date(task.leaseExpiresAt).toLocaleString() : '-'}`);
|
|
98
|
+
}
|
|
99
|
+
if (task.lastError) {
|
|
100
|
+
console.log(` Last Error: ${task.lastError}`);
|
|
101
|
+
}
|
|
102
|
+
if (task.inputRef) {
|
|
103
|
+
console.log(` Input Ref: ${task.inputRef}`);
|
|
104
|
+
}
|
|
105
|
+
if (task.resultRef) {
|
|
106
|
+
console.log(` Result Ref: ${task.resultRef}`);
|
|
107
|
+
}
|
|
108
|
+
console.log(` Created: ${new Date(task.createdAt).toLocaleString()}`);
|
|
109
|
+
console.log(` Updated: ${new Date(task.updatedAt).toLocaleString()}`);
|
|
110
|
+
console.log('');
|
|
111
|
+
|
|
112
|
+
if (runs.length > 0) {
|
|
113
|
+
console.log(`Runs (${runs.length}):`);
|
|
114
|
+
console.log(' %-22s %-12s %-6s %s', 'RUN_ID', 'STATUS', 'ATT', 'STARTED');
|
|
115
|
+
console.log(' ' + '-'.repeat(65));
|
|
116
|
+
for (const run of runs) {
|
|
117
|
+
console.log(
|
|
118
|
+
' %-22s %-12s %-6s %s',
|
|
119
|
+
run.runId.substring(0, 22),
|
|
120
|
+
run.executionStatus,
|
|
121
|
+
run.attemptNumber,
|
|
122
|
+
new Date(run.startedAt).toLocaleString(),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
console.log('');
|
|
126
|
+
}
|
|
127
|
+
} finally {
|
|
128
|
+
await stateManager.close();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd runtime trace show command — full pain-to-ledger chain trace.
|
|
3
|
+
*
|
|
4
|
+
* Usage: pd runtime trace show --pain-id <id> [--workspace <path>] [--json]
|
|
5
|
+
*
|
|
6
|
+
* Traces the complete pain→task→run→artifact→candidate→ledger chain
|
|
7
|
+
* and reports consistency, latency, and failure classification.
|
|
8
|
+
*
|
|
9
|
+
* PRI-129: Migrated from direct store/ledger usage
|
|
10
|
+
* to PainChainReadModel (ADR-0001 boundary compliance).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
15
|
+
import { PainChainReadModel } from '@principles/core/runtime-v2';
|
|
16
|
+
import type { PainChainTrace, PainChainTraceLatencyMs } from '@principles/core/runtime-v2';
|
|
17
|
+
|
|
18
|
+
interface TraceResult {
|
|
19
|
+
painId: string;
|
|
20
|
+
taskId: string;
|
|
21
|
+
runId?: string;
|
|
22
|
+
artifactId?: string;
|
|
23
|
+
candidateIds: string[];
|
|
24
|
+
ledgerEntryIds: string[];
|
|
25
|
+
status: string;
|
|
26
|
+
latencyMs: PainChainTraceLatencyMs;
|
|
27
|
+
failureCategory: string | null;
|
|
28
|
+
checkedAt: string;
|
|
29
|
+
missingLinks: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface TraceOptions {
|
|
33
|
+
painId: string;
|
|
34
|
+
workspace?: string;
|
|
35
|
+
json?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function formatNoTaskResult(opts: TraceOptions, workspaceDir: string, checkedAt: string) {
|
|
39
|
+
const taskId = `diagnosis_${opts.painId}`;
|
|
40
|
+
return {
|
|
41
|
+
painId: opts.painId,
|
|
42
|
+
taskId,
|
|
43
|
+
status: 'not_found' as const,
|
|
44
|
+
failureCategory: 'runtime_unavailable' as const,
|
|
45
|
+
message: `No task found for painId: ${opts.painId}`,
|
|
46
|
+
workspace: workspaceDir,
|
|
47
|
+
checkedAt,
|
|
48
|
+
missingLinks: ['task' as const],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function outputResult(result: TraceResult, opts: TraceOptions): void {
|
|
53
|
+
if (opts.json) {
|
|
54
|
+
console.log(JSON.stringify(result, null, 2));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log(`Pain ID: ${result.painId}`);
|
|
59
|
+
console.log(`Task ID: ${result.taskId}`);
|
|
60
|
+
console.log(`Status: ${result.status}`);
|
|
61
|
+
if (result.runId) console.log(`Run ID: ${result.runId}`);
|
|
62
|
+
if (result.artifactId) console.log(`Artifact ID: ${result.artifactId}`);
|
|
63
|
+
if (result.candidateIds.length > 0) console.log(`Candidate IDs: ${result.candidateIds.join(', ')}`);
|
|
64
|
+
if (result.ledgerEntryIds.length > 0) console.log(`Ledger Entries: ${result.ledgerEntryIds.join(', ')}`);
|
|
65
|
+
if (result.failureCategory) console.log(`Failure: ${result.failureCategory}`);
|
|
66
|
+
console.log(`Checked at: ${result.checkedAt}`);
|
|
67
|
+
|
|
68
|
+
if (Object.keys(result.latencyMs).length > 0) {
|
|
69
|
+
console.log('\nLatency:');
|
|
70
|
+
if (result.latencyMs.painToTask) console.log(` pain→task: ${result.latencyMs.painToTask}ms`);
|
|
71
|
+
if (result.latencyMs.taskToRun) console.log(` task→run: ${result.latencyMs.taskToRun}ms`);
|
|
72
|
+
if (result.latencyMs.runToArtifact) console.log(` run→artifact: ${result.latencyMs.runToArtifact}ms`);
|
|
73
|
+
if (result.latencyMs.artifactToCandidate) console.log(` artifact→candidate: ${result.latencyMs.artifactToCandidate}ms`);
|
|
74
|
+
if (result.latencyMs.candidateToLedger) console.log(` candidate→ledger: ${result.latencyMs.candidateToLedger}ms`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (result.missingLinks.length > 0) {
|
|
78
|
+
console.log(`\nMissing links (${result.missingLinks.length}):`);
|
|
79
|
+
for (const link of result.missingLinks) {
|
|
80
|
+
console.log(` - ${link}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function handleTraceShow(opts: TraceOptions): Promise<void> {
|
|
86
|
+
if (!opts.painId) {
|
|
87
|
+
console.error('Error: --pain-id <id> is required');
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const workspaceDir = opts.workspace
|
|
93
|
+
? path.resolve(opts.workspace)
|
|
94
|
+
: resolveWorkspaceDir();
|
|
95
|
+
|
|
96
|
+
const readModel = new PainChainReadModel({ workspaceDir });
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const trace: PainChainTrace = await readModel.traceByPainId(opts.painId);
|
|
100
|
+
|
|
101
|
+
if (trace.status === 'not_found') {
|
|
102
|
+
const noTaskResult = formatNoTaskResult(opts, workspaceDir, trace.checkedAt);
|
|
103
|
+
if (opts.json) {
|
|
104
|
+
console.log(JSON.stringify(noTaskResult, null, 2));
|
|
105
|
+
} else {
|
|
106
|
+
console.error(`Error: No task found for painId: ${opts.painId}`);
|
|
107
|
+
console.error(` Derived taskId: ${noTaskResult.taskId}`);
|
|
108
|
+
console.error(` Workspace: ${workspaceDir}`);
|
|
109
|
+
}
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (trace.status === 'error') {
|
|
115
|
+
const isConfigError = trace.failureCategory === 'config_missing';
|
|
116
|
+
if (opts.json) {
|
|
117
|
+
console.log(JSON.stringify({
|
|
118
|
+
painId: trace.painId,
|
|
119
|
+
taskId: trace.taskId,
|
|
120
|
+
status: 'error',
|
|
121
|
+
failureCategory: trace.failureCategory,
|
|
122
|
+
message: isConfigError
|
|
123
|
+
? 'Failed to initialize state manager'
|
|
124
|
+
: 'Internal error during trace',
|
|
125
|
+
checkedAt: trace.checkedAt,
|
|
126
|
+
missingLinks: trace.missingLinks,
|
|
127
|
+
}, null, 2));
|
|
128
|
+
} else {
|
|
129
|
+
console.error(`Error: ${isConfigError ? 'Failed to open workspace' : 'Internal error during trace'}`);
|
|
130
|
+
console.error(` Workspace: ${workspaceDir}`);
|
|
131
|
+
}
|
|
132
|
+
process.exitCode = 1;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const result: TraceResult = {
|
|
137
|
+
painId: trace.painId,
|
|
138
|
+
taskId: trace.taskId,
|
|
139
|
+
runId: trace.runId,
|
|
140
|
+
artifactId: trace.artifactId,
|
|
141
|
+
candidateIds: trace.candidateIds,
|
|
142
|
+
ledgerEntryIds: trace.ledgerEntryIds,
|
|
143
|
+
status: trace.status,
|
|
144
|
+
latencyMs: trace.latencyMs,
|
|
145
|
+
failureCategory: trace.failureCategory,
|
|
146
|
+
checkedAt: trace.checkedAt,
|
|
147
|
+
missingLinks: trace.missingLinks,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
outputResult(result, opts);
|
|
151
|
+
|
|
152
|
+
if (result.status === 'error' || result.status === 'failed' || result.status === 'degraded') {
|
|
153
|
+
process.exitCode = 1;
|
|
154
|
+
}
|
|
155
|
+
} catch (err) {
|
|
156
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
157
|
+
if (opts.json) {
|
|
158
|
+
console.log(JSON.stringify({
|
|
159
|
+
painId: opts.painId,
|
|
160
|
+
taskId: `diagnosis_${opts.painId}`,
|
|
161
|
+
status: 'error',
|
|
162
|
+
failureCategory: 'runtime_unavailable',
|
|
163
|
+
message: msg,
|
|
164
|
+
checkedAt: new Date().toISOString(),
|
|
165
|
+
missingLinks: ['internal_error'],
|
|
166
|
+
}, null, 2));
|
|
167
|
+
} else {
|
|
168
|
+
console.error(`Error: ${msg}`);
|
|
169
|
+
}
|
|
170
|
+
process.exitCode = 1;
|
|
171
|
+
} finally {
|
|
172
|
+
await readModel.close();
|
|
173
|
+
}
|
|
174
|
+
}
|